summaryrefslogtreecommitdiff
path: root/filesys/miniFilter/avscan/filter/utility.h
blob: 0f137f23175ac46545e8016e8c77d9d19df63d4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*++

Copyright (c) 2011  Microsoft Corporation

Module Name:

    utility.h

Abstract:

    Header file which contains the structures, type definitions,
    constants, global variables and function prototypes that are
    only visible within the kernel. The functions include
    generic table routines.

Environment:

    Kernel mode

--*/
#ifndef __UTILITY_H__
#define __UTILITY_H__

#define AV_STRING_TAG                        'tSvA'
#define AV_RESOURCE_TAG                      'cRvA'
#define AV_KEVENT_TAG                        'eKvA'
#define AV_TABLE_ENTRY_TAG                   'eTvA'

//////////////////////////////////////////////////////////////////////////////
//  ReFS Compatibility Helpers                                              //
//////////////////////////////////////////////////////////////////////////////

//
//  This helps us deal with ReFS 128-bit file IDs and NTFS 64-bit file IDs.
//

#define AV_INVALID_FILE_REFERENCE( _fileid_ ) \
    (((_fileid_).FileId64.UpperZeroes == 0ll) && \
     ((_fileid_).FileId64.Value == (ULONGLONG)FILE_INVALID_FILE_ID))

#define AV_SET_INVALID_FILE_REFERENCE( _fileid_ ) \
      (_fileid_).FileId64.UpperZeroes = 0ll;\
      (_fileid_).FileId64.Value = (ULONGLONG)FILE_INVALID_FILE_ID;

typedef union _AV_FILE_REFERENCE {

    struct {
        ULONGLONG   Value;
        ULONGLONG   UpperZeroes;
    } FileId64;

    FILE_ID_128     FileId128;

} AV_FILE_REFERENCE, *PAV_FILE_REFERENCE;


//
//  The generic table entry data structure.
//

typedef struct _AV_GENERIC_TABLE_ENTRY {

    AV_FILE_REFERENCE FileId;
    ULONG      InfectedState;

    //
    // Revision numbers for files on CSVFS
    //
    LONGLONG   VolumeRevision;
    LONGLONG   CacheRevision;
    LONGLONG   FileRevision;

} AV_GENERIC_TABLE_ENTRY, *PAV_GENERIC_TABLE_ENTRY;

#define AV_GENERIC_TABLE_ENTRY_SIZE         sizeof( AV_GENERIC_TABLE_ENTRY )

/*
_IRQL_requires_same_
_Function_class_(RTL_GENERIC_COMPARE_ROUTINE)
RTL_GENERIC_COMPARE_RESULTS
AvCompareEntry (
    _In_ PRTL_GENERIC_TABLE Table,
    _In_ PVOID FirstStruct,
    _In_ PVOID SecondStruct
    );

_IRQL_requires_same_
__drv_allocatesMem(Mem)
_Function_class_(RTL_GENERIC_ALLOCATE_ROUTINE)
PVOID
NTAPI
AvAllocateGenericTableEntry (
    _In_ PRTL_GENERIC_TABLE Table,
    _In_ CLONG ByteSize
    );

_IRQL_requires_same_
_Function_class_(RTL_GENERIC_FREE_ROUTINE)
VOID
NTAPI
AvFreeGenericTableEntry (
    _In_ PRTL_GENERIC_TABLE Table,
    _In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Entry
    );
*/

RTL_GENERIC_COMPARE_ROUTINE AvCompareEntry;

RTL_GENERIC_ALLOCATE_ROUTINE AvAllocateGenericTableEntry;

RTL_GENERIC_FREE_ROUTINE AvFreeGenericTableEntry;

//
// NTFS supports a file state cache. Since CSVFS is built on top of
// NTFS, it can also support the cache.
//
#define FS_SUPPORTS_FILE_STATE_CACHE(VolumeFilesystemType) \
  ( ((VolumeFilesystemType) == FLT_FSTYPE_NTFS) || \
    ((VolumeFilesystemType) == FLT_FSTYPE_CSVFS) || \
    ((VolumeFilesystemType) == FLT_FSTYPE_REFS) )


FORCEINLINE
PERESOURCE
AvAllocateResource (
    VOID
    )
{
    //
    //  eResource by its rule has to be in the non-paged pool
    //  NonPagedPoolNx: non-executable non-paged pool
    //

    return ExAllocatePoolZero( NonPagedPoolNx,
                               sizeof( ERESOURCE ),
                               AV_RESOURCE_TAG );
}

FORCEINLINE
VOID
AvFreeResource (
    _In_ PERESOURCE Resource
    )
{

    ExFreePoolWithTag( Resource,
                       AV_RESOURCE_TAG );
}

FORCEINLINE
PKEVENT
AvAllocateKevent (
    VOID
    )
{
    //
    //  KEVENT has to be in the non-paged pool
    //

    return ExAllocatePoolZero( NonPagedPoolNx,
                               sizeof( KEVENT ),
                               AV_KEVENT_TAG );
}

FORCEINLINE
VOID
AvFreeKevent (
    _In_ PKEVENT Event
    )
{

    ExFreePoolWithTag( Event,
                       AV_KEVENT_TAG );
}

NTSTATUS
AvGetFileId (
    _In_    PFLT_INSTANCE Instance,
    _In_    PFILE_OBJECT FileObject,
    _Out_   PAV_FILE_REFERENCE FileId
    );

NTSTATUS
AvGetFileSize (
    _In_    PFLT_INSTANCE Instance,
    _In_    PFILE_OBJECT FileObject,
    _Out_   PLONGLONG Size
    );

NTSTATUS
AvGetFileEncrypted (
    _In_   PFLT_INSTANCE Instance,
    _In_   PFILE_OBJECT FileObject,
    _Out_  PBOOLEAN  Encrypted
    );

LONG
AvExceptionFilter (
    _In_ PEXCEPTION_POINTERS ExceptionPointer,
    _In_ BOOLEAN AccessingUserBuffer
    );

FORCEINLINE
VOID
_Acquires_lock_(_Global_critical_region_)
AvAcquireResourceExclusive (
    _Inout_ _Acquires_exclusive_lock_(*Resource) PERESOURCE Resource
    )
{
    FLT_ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
    FLT_ASSERT(ExIsResourceAcquiredExclusiveLite(Resource) ||
               !ExIsResourceAcquiredSharedLite(Resource));

    KeEnterCriticalRegion();
    (VOID)ExAcquireResourceExclusiveLite( Resource, TRUE );
}

FORCEINLINE
VOID
_Acquires_lock_(_Global_critical_region_)
AvAcquireResourceShared (
    _Inout_ _Acquires_shared_lock_(*Resource) PERESOURCE Resource
    )
{
    FLT_ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

    KeEnterCriticalRegion();
    (VOID)ExAcquireResourceSharedLite( Resource, TRUE );
}

FORCEINLINE
VOID
_Releases_lock_(_Global_critical_region_)
_Requires_lock_held_(_Global_critical_region_)
AvReleaseResource (
    _Inout_ _Requires_lock_held_(*Resource) _Releases_lock_(*Resource) PERESOURCE Resource
    )
{
    FLT_ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
    FLT_ASSERT(ExIsResourceAcquiredExclusiveLite(Resource) ||
               ExIsResourceAcquiredSharedLite(Resource));

    ExReleaseResourceLite(Resource);
    KeLeaveCriticalRegion();
}

#define LIST_FOR_EACH_SAFE(curr, n, head) \
        for (curr = (head)->Flink , n = curr->Flink ; curr != (head); \
             curr = n, n = curr->Flink )

#endif