WDK Mini Filter Example
filter/utility.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 2011 Microsoft Corporation
4 
5 Module Name:
6 
7  utility.c
8 
9 Abstract:
10 
11  Utility module implementation.
12  1) Generic table routines
13  2) Query file information routines
14 
15 Environment:
16 
17  Kernel mode
18 
19 --*/
20 
21 #include "avscan.h"
22 
23 //
24 // Generic table routines.
25 //
26 
27 RTL_GENERIC_COMPARE_RESULTS
28 NTAPI
30  _In_ PRTL_GENERIC_TABLE Table,
31  _In_ PVOID Lhs,
32  _In_ PVOID Rhs
33  )
34 /*++
35 
36 Routine Description:
37 
38  This routine is the callback for the generic table routines.
39 
40 Arguments:
41 
42  Table - Table for which this is invoked.
43 
44  FirstStruct - An element in the table to compare.
45 
46  SecondStruct - Another element in the table to compare.
47 
48 Return Value:
49 
50  RTL_GENERIC_COMPARE_RESULTS.
51 
52 --*/
53 {
56 
57  UNREFERENCED_PARAMETER (Table);
58 
59  //
60  // Compare the 128 bit fileId in 64bit pieces for efficiency.
61  // Compare the lower 64 bits Value first since that is used
62  // in both 128 bit and 64 bit fileIds and doing so eliminates
63  // and unnecessary comparison of the UpperZeros field in the
64  // most common case. Note this comparison is not equivalent
65  // to a memcmp on the 128 bit values but that doesn't matter
66  // here since we just need the tree to be self-consistent.
67  //
68 
69  if (lhs->FileId.FileId64.Value < rhs->FileId.FileId64.Value) {
70 
71  return GenericLessThan;
72 
73  } else if (lhs->FileId.FileId64.Value > rhs->FileId.FileId64.Value) {
74 
75  return GenericGreaterThan;
76 
77  } else if (lhs->FileId.FileId64.UpperZeroes < rhs->FileId.FileId64.UpperZeroes) {
78 
79  return GenericLessThan;
80 
81  } else if (lhs->FileId.FileId64.UpperZeroes > rhs->FileId.FileId64.UpperZeroes) {
82 
83  return GenericGreaterThan;
84  }
85 
86  return GenericEqual;
87 }
88 
89 
90 PVOID
91 NTAPI
93  _In_ PRTL_GENERIC_TABLE Table,
94  _In_ CLONG ByteSize
95  )
96 /*++
97 
98 Routine Description:
99 
100  This routine is the callback for allocation for entries in the generic table.
101 
102 Arguments:
103 
104  Table - Table for which this is invoked.
105 
106  ByteSize - Amount of memory to allocate.
107 
108 Return Value:
109 
110  Pointer to allocated memory if successful, else NULL.
111 
112 --*/
113 {
114 
115  UNREFERENCED_PARAMETER (Table);
116 
117  return ExAllocatePoolWithTag(PagedPool, ByteSize, AV_TABLE_ENTRY_TAG);
118 }
119 
120 VOID
121 NTAPI
123  _In_ PRTL_GENERIC_TABLE Table,
124  _In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Entry
125  )
126 /*++
127 
128 Routine Description:
129 
130  This routine is the callback for releasing memory for entries in the generic
131  table.
132 
133 Arguments:
134 
135  Table - Table for which this is invoked.
136 
137  Entry - Entry to free.
138 
139 Return Value:
140 
141  None.
142 
143 --*/
144 {
145 
146  UNREFERENCED_PARAMETER (Table);
147 
148  ExFreePoolWithTag( Entry, AV_TABLE_ENTRY_TAG );
149 }
150 
151 //
152 // Query File Information Routines
153 //
154 
155 NTSTATUS
157  _In_ PFLT_INSTANCE Instance,
158  _In_ PFILE_OBJECT FileObject,
159  _Out_ PAV_FILE_REFERENCE FileId
160  )
161 /*++
162 
163 Routine Description:
164 
165  This routine obtains the File ID and saves it in the stream context.
166 
167 Arguments:
168 
169  Instance - Opaque filter pointer for the caller. This parameter is required and cannot be NULL.
170 
171  FileObject - File object pointer for the file. This parameter is required and cannot be NULL.
172 
173  pFileId - Pointer to file id. This is the output
174 
175 Return Value:
176 
177  Returns statuses forwarded from FltQueryInformationFile.
178 
179 --*/
180 {
181  NTSTATUS status = STATUS_SUCCESS;
182  FLT_FILESYSTEM_TYPE type;
183 
184  //
185  // Querying for FileInternalInformation gives you the file ID.
186  //
187 
188  status = FltGetFileSystemType( Instance, &type );
189 
190  if (NT_SUCCESS( status )) {
191 
192  if (type == FLT_FSTYPE_REFS) {
193 
194  FILE_ID_INFORMATION fileIdInformation;
195 
196  status = FltQueryInformationFile( Instance,
197  FileObject,
198  &fileIdInformation,
199  sizeof(FILE_ID_INFORMATION),
200  FileIdInformation,
201  NULL );
202 
203  if (NT_SUCCESS( status )) {
204 
205  RtlCopyMemory(&(FileId->FileId128), &(fileIdInformation.FileId), sizeof(FileId->FileId128) );
206  }
207 
208  } else {
209 
210  FILE_INTERNAL_INFORMATION fileInternalInformation;
211 
212  status = FltQueryInformationFile( Instance,
213  FileObject,
214  &fileInternalInformation,
215  sizeof(FILE_INTERNAL_INFORMATION),
216  FileInternalInformation,
217  NULL );
218 
219  if (NT_SUCCESS( status )) {
220 
221  FileId->FileId64.Value = fileInternalInformation.IndexNumber.QuadPart;
222  FileId->FileId64.UpperZeroes = 0ll;
223  }
224  }
225  }
226 
227  return status;
228 }
229 
230 NTSTATUS
232  _In_ PFLT_INSTANCE Instance,
233  _In_ PFILE_OBJECT FileObject,
234  _Out_ PLONGLONG Size
235  )
236 /*++
237 
238 Routine Description:
239 
240  This routine obtains the size.
241 
242 Arguments:
243 
244  Instance - Opaque filter pointer for the caller. This parameter is required and cannot be NULL.
245 
246  FileObject - File object pointer for the file. This parameter is required and cannot be NULL.
247 
248  Size - Pointer to a LONGLONG indicating the file size. This is the output.
249 
250 Return Value:
251 
252  Returns statuses forwarded from FltQueryInformationFile.
253 
254 --*/
255 {
256  NTSTATUS status = STATUS_SUCCESS;
257  FILE_STANDARD_INFORMATION standardInfo;
258 
259  //
260  // Querying for FileStandardInformation gives you the offset of EOF.
261  //
262 
263  status = FltQueryInformationFile( Instance,
264  FileObject,
265  &standardInfo,
266  sizeof(FILE_STANDARD_INFORMATION),
267  FileStandardInformation,
268  NULL );
269 
270  if (NT_SUCCESS( status )) {
271 
272  *Size = standardInfo.EndOfFile.QuadPart;
273  }
274 
275  return status;
276 }
277 
278 NTSTATUS
280  _In_ PFLT_INSTANCE Instance,
281  _In_ PFILE_OBJECT FileObject,
282  _Out_ PBOOLEAN Encrypted
283  )
284 /*++
285 
286 Routine Description:
287 
288  This routine obtains the File ID and saves it in the stream context.
289 
290 Arguments:
291 
292  Instance - Opaque filter pointer for the caller. This parameter is required and cannot be NULL.
293 
294  FileObject - File object pointer for the file. This parameter is required and cannot be NULL.
295 
296  Encrypted - Pointer to a boolean indicating if this file is encrypted or not. This is the output.
297 
298 Return Value:
299 
300  Returns statuses forwarded from FltQueryInformationFile.
301 
302 --*/
303 {
304  NTSTATUS status = STATUS_SUCCESS;
305  FILE_BASIC_INFORMATION basicInfo;
306 
307  //
308  // Querying for basic information to get encryption.
309  //
310 
311  status = FltQueryInformationFile( Instance,
312  FileObject,
313  &basicInfo,
314  sizeof(FILE_BASIC_INFORMATION),
315  FileBasicInformation,
316  NULL );
317 
318  if (NT_SUCCESS( status )) {
319 
320  *Encrypted = BooleanFlagOn( basicInfo.FileAttributes, FILE_ATTRIBUTE_ENCRYPTED );
321  }
322 
323  return status;
324 }
325 
326 LONG
328  _In_ PEXCEPTION_POINTERS ExceptionPointer,
329  _In_ BOOLEAN AccessingUserBuffer
330  )
331 /*++
332 
333 Routine Description:
334 
335  Exception filter to catch errors touching user buffers.
336 
337 Arguments:
338 
339  ExceptionPointer - The exception record.
340 
341  AccessingUserBuffer - If TRUE, overrides FsRtlIsNtStatusExpected to allow
342  the caller to munge the error to a desired status.
343 
344 Return Value:
345 
346  EXCEPTION_EXECUTE_HANDLER - If the exception handler should be run.
347 
348  EXCEPTION_CONTINUE_SEARCH - If a higher exception handler should take care of
349  this exception.
350 
351 --*/
352 {
353  NTSTATUS Status;
354 
355  Status = ExceptionPointer->ExceptionRecord->ExceptionCode;
356 
357  //
358  // Certain exceptions shouldn't be dismissed within the filter
359  // unless we're touching user memory.
360  //
361 
362  if (!FsRtlIsNtstatusExpected( Status ) &&
363  !AccessingUserBuffer) {
364 
365  return EXCEPTION_CONTINUE_SEARCH;
366  }
367 
368  return EXCEPTION_EXECUTE_HANDLER;
369 }
370 
371 
VOID NTAPI AvFreeGenericTableEntry(_In_ PRTL_GENERIC_TABLE Table, _In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Entry)
RtlCopyMemory(OutputStringBuffer, TempMappingBuffer->Data, OutputString->MaximumLength)
_In_opt_ PFILE_OBJECT _In_opt_ PFLT_INSTANCE Instance
Definition: nc.h:493
NTSTATUS AvGetFileSize(_In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _Out_ PLONGLONG Size)
NTSTATUS AvGetFileId(_In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _Out_ PAV_FILE_REFERENCE FileId)
struct _AV_FILE_REFERENCE::@0 FileId64
UNREFERENCED_PARAMETER(FileObject)
NcLoadRegistryStringRetry NULL
Definition: ncinit.c:53
NTSTATUS AvGetFileEncrypted(_In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _Out_ PBOOLEAN Encrypted)
IoStatus Status
struct _AV_GENERIC_TABLE_ENTRY * PAV_GENERIC_TABLE_ENTRY
PVOID NTAPI AvAllocateGenericTableEntry(_In_ PRTL_GENERIC_TABLE Table, _In_ CLONG ByteSize)
#define AV_TABLE_ENTRY_TAG
LONG AvExceptionFilter(_In_ PEXCEPTION_POINTERS ExceptionPointer, _In_ BOOLEAN AccessingUserBuffer)
RTL_GENERIC_COMPARE_RESULTS NTAPI AvCompareEntry(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Lhs, _In_ PVOID Rhs)
_In_opt_ PFILE_OBJECT FileObject
Definition: nc.h:493

Social Network


Services Overview

Architect, implement and test file system filter drivers for a wide range of functionality. We can offer several levels of assistance to meet your specific.

Contact Us

You are welcome to contact us for salse or partnership.

Sales: sales@easefilter.com
Support: support@easefilter.com
Info: info@easefilter.com