WDK Mini Filter Example
nccompat.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1999 - 2002 Microsoft Corporation
4 
5 Module Name:
6 
7  nccompat.c
8 
9 Abstract:
10 
11  Contains compatibility routines so that name changer works on
12  all OSes. Functions not available on older OSes are emulated here.
13  We try, wherever possible, to call into newer routines directly and
14  only fall back to emulation if required.
15 
16 Environment:
17 
18  Kernel mode
19 
20 --*/
21 
22 #include "nc.h"
23 
24 //
25 // Prototypes for alternates.
26 //
27 
28 NTSTATUS
30  _In_ PFILE_OBJECT FileObject,
31  _In_reads_bytes_(FileNameLength) PWSTR NewFileName,
32  _In_ USHORT FileNameLength
33  );
34 
35 NTSTATUS
37  _In_ PFLT_INSTANCE Instance,
38  _In_ PFILE_OBJECT FileObject,
39  _In_reads_bytes_(Length) PVOID FileInformation,
40  _In_ ULONG Length,
41  _In_ FILE_INFORMATION_CLASS FileInformationClass,
42  _In_ BOOLEAN ReturnSingleEntry,
43  _In_opt_ PUNICODE_STRING FileName,
44  _In_ BOOLEAN RestartScan,
45  _Out_opt_ PULONG LengthReturned
46  );
47 
48 NTSTATUS
49 FLTAPI
51  _In_ PFLT_FILTER Filter,
52  _In_opt_ PFLT_INSTANCE Instance,
53  _Out_ PHANDLE FileHandle,
54  _Outptr_opt_ PFILE_OBJECT *FileObject,
55  _In_ ACCESS_MASK DesiredAccess,
56  _In_ POBJECT_ATTRIBUTES ObjectAttributes,
57  _Out_ PIO_STATUS_BLOCK IoStatusBlock,
58  _In_opt_ PLARGE_INTEGER AllocationSize,
59  _In_ ULONG FileAttributes,
60  _In_ ULONG ShareAccess,
61  _In_ ULONG CreateDisposition,
62  _In_ ULONG CreateOptions,
63  _In_reads_bytes_opt_(EaLength) PVOID EaBuffer,
64  _In_ ULONG EaLength,
65  _In_ ULONG Flags,
66  _In_opt_ PIO_DRIVER_CREATE_CONTEXT DriverContext
67  );
68 
69 #pragma alloc_text(PAGE, NcCompatInit)
70 #pragma alloc_text(PAGE, NcCreateFileEx2Alternate)
71 #pragma alloc_text(PAGE, NcQueryDirectoryFileAlternate)
72 #pragma alloc_text(PAGE, NcReplaceFileObjectNameAlternate)
73 
74 //
75 // Global variables which hold pointers to the functions we will call.
76 //
77 
82 
83 //
84 // Holder for FltCreateFileEx, if it exists and we need to call it.
85 //
86 
88 
89 //
90 // Alternative routines which are used when on downlevel os'es.
91 //
92 
93 NTSTATUS
95  _In_ PFILE_OBJECT FileObject,
96  _In_reads_bytes_(FileNameLength) PWSTR NewFileName,
97  _In_ USHORT FileNameLength
98  )
99 /*++
100 
101 Routine Description:
102 
103  This routine is used to replace a file object's name with a provided
104  name. On Win7 and forward IoReplaceFileObjectName will be used.
105  If this function is used and verifier is enabled on pre Win7 machines
106  the filter will fail to unload due to a false positive on the leaked
107  pool test.
108 
109 Arguments:
110 
111  FileObject - Pointer to file object whose name is to be replaced.
112 
113  NewFileName - Pointer to buffer containing the new name.
114 
115  FileNameLength - Length of the new name in bytes.
116 
117 Return Value:
118 
119  STATUS_INSUFFICIENT_RESOURCES - No memory to allocate the new buffer.
120 
121  STATUS_SUCCESS otherwise.
122 
123 --*/
124 {
125  PWSTR Buffer;
126  PUNICODE_STRING FileName;
127  USHORT NewMaxLength;
128 
129  PAGED_CODE();
130 
131  FileName = &FileObject->FileName;
132 
133  //
134  // If the new name fits inside the current buffer we simply copy it over
135  // instead of allocating a new buffer (and keep the MaximumLength value
136  // the same).
137  //
138 
139  if (FileNameLength <= FileName->MaximumLength) {
140 
141  goto CopyAndReturn;
142  }
143 
144  NewMaxLength = FileNameLength;
145 
146  Buffer = ExAllocatePoolWithTag( PagedPool,
147  NewMaxLength,
149 
150  if (!Buffer) {
151 
152  return STATUS_INSUFFICIENT_RESOURCES;
153  }
154 
155  if (FileName->Buffer != NULL) {
156 
157  ExFreePool(FileName->Buffer);
158  }
159 
160  FileName->Buffer = Buffer;
161  FileName->MaximumLength = NewMaxLength;
162 
163 CopyAndReturn:
164 
165  RtlZeroMemory(FileName->Buffer, FileName->MaximumLength);
166 
167  FileName->Length = FileNameLength;
168  RtlCopyMemory(FileName->Buffer, NewFileName, FileNameLength);
169 
170  return STATUS_SUCCESS;
171 }
172 
173 NTSTATUS
175  _In_ PFLT_INSTANCE Instance,
176  _In_ PFILE_OBJECT FileObject,
177  _In_reads_bytes_(Length) PVOID FileInformation,
178  _In_ ULONG Length,
179  _In_ FILE_INFORMATION_CLASS FileInformationClass,
180  _In_ BOOLEAN ReturnSingleEntry,
181  _In_opt_ PUNICODE_STRING FileName,
182  _In_ BOOLEAN RestartScan,
183  _Out_opt_ PULONG LengthReturned
184  )
185 /*++
186 
187 Routine Description:
188 
189  This function issues a directory control operation to the filesystem
190 
191 Arguments:
192 
193 
194  Instance - Supplies the Instance initiating this IO.
195 
196  FileObject - Supplies the file object about which the requested
197  Information should be queried.
198 
199  FileInformation - Supplies a buffer to hold the directory control
200  results.
201 
202  Length - Supplies the length, in bytes, of the FileInformation buffer.
203 
204  FileInformationClass - Specifies the file Information class requested.
205 
206  ReturnSingleEntry - Retrieve only one file at a time.
207 
208  FileName - This is the pattern to search for.
209 
210  RestartScan - Restart the directory enumeration from the start.
211 
212  LengthReturned - On success, this is how much Information was placed
213  into the FileInformation buffer.
214 
215 Return Value:
216 
217  The status returned is the final completion Status of the operation.
218 
219 --*/
220 {
221  PFLT_CALLBACK_DATA Info;
222  NTSTATUS Status;
223 
224  PAGED_CODE();
225 
226  Status = FltAllocateCallbackData( Instance, FileObject, &Info );
227 
228  if (!NT_SUCCESS( Status )) {
229 
230  return Status;
231  }
232 
233  Info->Iopb->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
234  Info->Iopb->MinorFunction = IRP_MN_QUERY_DIRECTORY;
235 
236  Info->Iopb->Parameters.DirectoryControl.QueryDirectory.Length = Length;
237  Info->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName = FileName;
238  Info->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass = FileInformationClass;
239  Info->Iopb->Parameters.DirectoryControl.QueryDirectory.FileIndex = 0;
240 
241  Info->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer = FileInformation;
242  Info->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress = NULL;
243 
244  if (RestartScan) {
245 
246  Info->Iopb->OperationFlags |= SL_RESTART_SCAN;
247  }
248 
249  if (ReturnSingleEntry) {
250 
251  Info->Iopb->OperationFlags |= SL_RETURN_SINGLE_ENTRY;
252  }
253 
254  //
255  // Perform the operation
256  //
257 
258  FltPerformSynchronousIo( Info );
259 
260  Status = Info->IoStatus.Status;
261 
262  if (ARGUMENT_PRESENT(LengthReturned) &&
263  NT_SUCCESS( Status )) {
264 
265  *LengthReturned = (ULONG) Info->IoStatus.Information;
266  }
267 
268  FltFreeCallbackData( Info );
269 
270  return Status;
271 }
272 
273 NTSTATUS
274 FLTAPI
276  _In_ PFLT_FILTER Filter,
277  _In_opt_ PFLT_INSTANCE Instance,
278  _Out_ PHANDLE FileHandle,
279  _Outptr_opt_ PFILE_OBJECT *FileObject,
280  _In_ ACCESS_MASK DesiredAccess,
281  _In_ POBJECT_ATTRIBUTES ObjectAttributes,
282  _Out_ PIO_STATUS_BLOCK IoStatusBlock,
283  _In_opt_ PLARGE_INTEGER AllocationSize,
284  _In_ ULONG FileAttributes,
285  _In_ ULONG ShareAccess,
286  _In_ ULONG CreateDisposition,
287  _In_ ULONG CreateOptions,
288  _In_reads_bytes_opt_(EaLength) PVOID EaBuffer,
289  _In_ ULONG EaLength,
290  _In_ ULONG Flags,
291  _In_opt_ PIO_DRIVER_CREATE_CONTEXT DriverContext
292  )
293 {
294  NTSTATUS Status;
295 
296  PAGED_CODE();
297 
298  //
299  // If we are here, FltCreateFileEx2 does not exist. We
300  // cannot open files within the context of a transaction
301  // from here. If Txf exists, so should FltCreateFileEx2.
302  //
303 
304  UNREFERENCED_PARAMETER( DriverContext );
305  FLT_ASSERT( DriverContext == NULL );
306 
307  //
308  // Zero out output parameters.
309  //
310 
311  *FileHandle = INVALID_HANDLE_VALUE;
312 
313  if (ARGUMENT_PRESENT( FileObject )) {
314 
315  *FileObject = NULL;
316  }
317 
318  if (NcCreateFileEx) {
319 
320  //
321  // If the system has FltCreateFileEx, we call that.
322  //
323 
324  Status = NcCreateFileEx( Filter,
325  Instance,
326  FileHandle,
327  FileObject,
328  DesiredAccess,
329  ObjectAttributes,
330  IoStatusBlock,
331  AllocationSize,
332  FileAttributes,
333  ShareAccess,
334  CreateDisposition,
335  CreateOptions,
336  EaBuffer,
337  EaLength,
338  Flags );
339  } else {
340 
341  //
342  // Attempt the open.
343  //
344 
345  Status = FltCreateFile( Filter,
346  Instance,
347  FileHandle,
348  DesiredAccess,
349  ObjectAttributes,
350  IoStatusBlock,
351  AllocationSize,
352  FileAttributes,
353  ShareAccess,
354  CreateDisposition,
355  CreateOptions,
356  EaBuffer,
357  EaLength,
358  Flags );
359 
360  if(!NT_SUCCESS( Status )) {
361 
362  goto NcCreateFileEx2Cleanup;
363  }
364 
365  FLT_ASSERT( *FileHandle != INVALID_HANDLE_VALUE && *FileHandle != NULL );
366 
367  if(ARGUMENT_PRESENT( FileObject )) {
368 
369  //
370  // If the user provided an output FileObject parameter,
371  // then we need to get a reference to the fileobject and return it.
372  //
373 
374  Status = ObReferenceObjectByHandle( *FileHandle,
375  DesiredAccess,
376  *IoFileObjectType,
377  KernelMode,
378  FileObject,
379  NULL );
380 
381  if(!NT_SUCCESS( Status )) {
382 
383  goto NcCreateFileEx2Cleanup;
384  }
385  }
386  }
387 
388 NcCreateFileEx2Cleanup:
389 
390  if (!NT_SUCCESS( Status )) {
391 
392  if (*FileHandle != INVALID_HANDLE_VALUE) {
393 
394  FltClose( *FileHandle );
395  }
396 
397  if (ARGUMENT_PRESENT( FileObject )) {
398 
399  if (*FileObject != NULL) {
400 
401  ObDereferenceObject( *FileObject );
402  }
403  }
404  }
405 
406  return Status;
407 }
408 
409 //
410 // Helper routines which manage importing the functions.
411 //
412 
413 VOID
415 {
416  UNICODE_STRING FuncName;
417  PAGED_CODE();
418 
419  //
420  // Default to NonPagedPoolNx for non paged pool allocations where supported.
421  //
422 
423  ExInitializeDriverRuntime( DrvRtPoolNxOptIn );
424 
425  //
426  // Cast from data pointer to function pointer. This is
427  // somewhat unavoidable when calling MmGetSystemRoutineAddress/
428  // FltGetRoutineAddress etc.
429  //
430 
431 #pragma warning( push )
432 #pragma warning( disable: 4055 )
433 
434  RtlInitUnicodeString( &FuncName, L"IoReplaceFileObjectName" );
435 
436  NcReplaceFileObjectName = (NC_REPLACE_FILEOBJECT_NAME_TYPE)
437  MmGetSystemRoutineAddress( &FuncName );
438 
439  if (NcReplaceFileObjectName == NULL) {
440 
441  NcReplaceFileObjectName = NcReplaceFileObjectNameAlternate;
442  }
443 
444  NcQueryDirectoryFile = (NC_QUERY_DIRECTORY_FILE_TYPE)
445  FltGetRoutineAddress( "FltQueryDirectoryFile" );
446 
447  if (NcQueryDirectoryFile == NULL) {
448 
449  NcQueryDirectoryFile = NcQueryDirectoryFileAlternate;
450  }
451 
452  NcCreateFileEx2 = (NC_CREATE_FILE_EX2_TYPE)
453  FltGetRoutineAddress( "FltCreateFileEx2" );
454 
455  if (NcCreateFileEx2 == NULL) {
456 
457  NcCreateFileEx = (NC_CREATE_FILE_EX_TYPE)
458  FltGetRoutineAddress( "FltCreateFileEx" );
459  NcCreateFileEx2 = NcCreateFileEx2Alternate;
460  }
461 
462  NcGetNewSystemBufferAddress = (NC_GET_NEW_SYSTEM_BUFFER_ADDRESS)
463  FltGetRoutineAddress( "FltGetNewSystemBufferAddress" );
464 
465 #pragma warning( pop )
466 }
467 
468 
NTSTATUS(* NC_CREATE_FILE_EX2_TYPE)(_In_ PFLT_FILTER Filter, _In_opt_ PFLT_INSTANCE Instance, _Out_ PHANDLE FileHandle, _Outptr_opt_ PFILE_OBJECT *FileObject, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_opt_ PLARGE_INTEGER AllocationSize, _In_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions, _In_reads_bytes_opt_(EaLength) PVOID EaBuffer, _In_ ULONG EaLength, _In_ ULONG Flags, _In_opt_ PIO_DRIVER_CREATE_CONTEXT DriverContext)
Definition: nc.h:108
NC_QUERY_DIRECTORY_FILE_TYPE NcQueryDirectoryFile
Definition: nccompat.c:79
NC_CREATE_FILE_EX2_TYPE NcCreateFileEx2
Definition: nccompat.c:80
#define NC_FILE_NAME_TAG
Definition: nc.h:19
_In_ PLARGE_INTEGER _In_ ULONG Length
NC_CREATE_FILE_EX_TYPE NcCreateFileEx
Definition: nccompat.c:87
PVOID(* NC_GET_NEW_SYSTEM_BUFFER_ADDRESS)(_In_ PFLT_CALLBACK_DATA Data)
Definition: nc.h:129
RtlCopyMemory(OutputStringBuffer, TempMappingBuffer->Data, OutputString->MaximumLength)
NTSTATUS NcQueryDirectoryFileAlternate(_In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _In_reads_bytes_(Length) PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass, _In_ BOOLEAN ReturnSingleEntry, _In_opt_ PUNICODE_STRING FileName, _In_ BOOLEAN RestartScan, _Out_opt_ PULONG LengthReturned)
Definition: nccompat.c:174
_In_opt_ PFILE_OBJECT _In_opt_ PFLT_INSTANCE Instance
Definition: nc.h:493
FLT_ASSERT(IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
#define INVALID_HANDLE_VALUE
Definition: nc.h:58
NTSTATUS FLTAPI NcCreateFileEx2Alternate(_In_ PFLT_FILTER Filter, _In_opt_ PFLT_INSTANCE Instance, _Out_ PHANDLE FileHandle, _Outptr_opt_ PFILE_OBJECT *FileObject, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_opt_ PLARGE_INTEGER AllocationSize, _In_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions, _In_reads_bytes_opt_(EaLength) PVOID EaBuffer, _In_ ULONG EaLength, _In_ ULONG Flags, _In_opt_ PIO_DRIVER_CREATE_CONTEXT DriverContext)
Definition: nccompat.c:275
NTSTATUS NcReplaceFileObjectNameAlternate(_In_ PFILE_OBJECT FileObject, _In_reads_bytes_(FileNameLength) PWSTR NewFileName, _In_ USHORT FileNameLength)
Definition: nccompat.c:94
NC_REPLACE_FILEOBJECT_NAME_TYPE NcReplaceFileObjectName
Definition: nccompat.c:78
NTSTATUS(* NC_REPLACE_FILEOBJECT_NAME_TYPE)(_In_ PFILE_OBJECT FileObject, _In_reads_bytes_(FileNameLength) PWSTR NewFileName, _In_ USHORT FileNameLength)
Definition: nc.h:66
_In_ BOOLEAN _Out_ PFILE_BASIC_INFORMATION Buffer
_In_ PLARGE_INTEGER _In_ ULONG _In_ ULONG _In_reads_bytes_(Length)
UNREFERENCED_PARAMETER(FileObject)
NcLoadRegistryStringRetry NULL
Definition: ncinit.c:53
PAGED_CODE()
#define IRP_MN_QUERY_DIRECTORY
Definition: mspyLog.h:318
#define IRP_MJ_DIRECTORY_CONTROL
Definition: mspyLog.h:296
IoStatus Status
NTSTATUS(* NC_QUERY_DIRECTORY_FILE_TYPE)(_In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _Out_writes_bytes_(Length) PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass, _In_ BOOLEAN ReturnSingleEntry, _In_opt_ PUNICODE_STRING FileName, _In_ BOOLEAN RestartScan, _Out_opt_ PULONG LengthReturned)
Definition: nc.h:74
NTSTATUS(* NC_CREATE_FILE_EX_TYPE)(_In_ PFLT_FILTER Filter, _In_opt_ PFLT_INSTANCE Instance, _Out_ PHANDLE FileHandle, _Outptr_opt_ PFILE_OBJECT *FileObject, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_opt_ PLARGE_INTEGER AllocationSize, _In_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions, _In_reads_bytes_opt_(EaLength) PVOID EaBuffer, _In_ ULONG EaLength, _In_ ULONG Flags)
Definition: nc.h:88
VOID NcCompatInit()
Definition: nccompat.c:414
OutputString MaximumLength
Definition: ncinit.c:155
NC_GET_NEW_SYSTEM_BUFFER_ADDRESS NcGetNewSystemBufferAddress
Definition: nccompat.c:81
_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