xref: /reactos/drivers/filters/fltmgr/Interface.c (revision 81db5e1d)
1 /*
2 * PROJECT:         Filesystem Filter Manager
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * FILE:            drivers/filters/fltmgr/interface.c
5 * PURPOSE:         Implements the driver interface
6 * PROGRAMMERS:     Ged Murphy (gedmurphy@reactos.org)
7 */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include "fltmgr.h"
12 #include "fltmgrint.h"
13 
14 //#define NDEBUG
15 #include <debug.h>
16 
17 
18 /* DATA *********************************************************************/
19 
20 #define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName) \
21     (((_FastIoDispatchPtr) != NULL) && \
22      (((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \
23             (FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && \
24      ((_FastIoDispatchPtr)->_FieldName != NULL))
25 
26 #define IS_MY_DEVICE_OBJECT(_devObj) \
27     (((_devObj) != NULL) && \
28     ((_devObj)->DriverObject == Dispatcher::DriverObject) && \
29       ((_devObj)->DeviceExtension != NULL))
30 
31 extern PDEVICE_OBJECT CommsDeviceObject;
32 extern LIST_ENTRY FilterList;
33 extern ERESOURCE FilterListLock;
34 
35 DRIVER_DATA DriverData;
36 
37 typedef struct _DETACH_DEVICE_WORK_ITEM
38 {
39     WORK_QUEUE_ITEM WorkItem;
40     PDEVICE_OBJECT SourceDevice;
41     PDEVICE_OBJECT TargetDevice;
42 
43 } DETACH_DEVICE_WORK_ITEM, *PDETACH_DEVICE_WORK_ITEM;
44 
45 /* LOCAL FUNCTIONS ****************************************/
46 
47 static
48 VOID
49 FltpCleanupDeviceObject(_In_ PDEVICE_OBJECT DeviceObject)
50 {
51     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
52 
53     DeviceExtension = DeviceObject->DeviceExtension;
54     if (DeviceExtension)
55     {
56         // cleanup device extension
57     }
58 }
59 
60 CODE_SEG("PAGE")
61 static
62 NTSTATUS
63 FltpAttachDeviceObject(_In_ PDEVICE_OBJECT SourceDevice,
64                        _In_ PDEVICE_OBJECT TargetDevice,
65                        _Out_ PDEVICE_OBJECT *AttachedToDeviceObject)
66 {
67     NTSTATUS Status;
68 
69     PAGED_CODE();
70 
71     /* Before attaching, copy the flags from the device we're going to attach to */
72     if (FlagOn(SourceDevice->Flags, DO_BUFFERED_IO))
73     {
74         SetFlag(TargetDevice->Flags, DO_BUFFERED_IO);
75     }
76     if (FlagOn(SourceDevice->Flags, DO_DIRECT_IO))
77     {
78         SetFlag(TargetDevice->Flags, DO_DIRECT_IO);
79     }
80     if (FlagOn(SourceDevice->Flags, DO_SYSTEM_BOOT_PARTITION))
81     {
82         SetFlag(TargetDevice->Characteristics, FILE_DEVICE_SECURE_OPEN);
83     }
84 
85     /* Attach this device to the top of the driver stack */
86     Status = IoAttachDeviceToDeviceStackSafe(SourceDevice,
87                                              TargetDevice,
88                                              AttachedToDeviceObject);
89 
90     return Status;
91 }
92 
93 CODE_SEG("PAGE")
94 static
95 BOOLEAN
96 FltpIsAttachedToDevice(_In_ PDEVICE_OBJECT DeviceObject,
97                        _In_opt_ PDEVICE_OBJECT *AttachedDeviceObject)
98 {
99     PDEVICE_OBJECT CurrentDeviceObject;
100     PDEVICE_OBJECT NextDeviceObject;
101 
102     PAGED_CODE();
103 
104     /* Initialize the return pointer */
105     if (AttachedDeviceObject) *AttachedDeviceObject = NULL;
106 
107     /* Start by getting the top level device in the chain */
108     CurrentDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
109 
110     /* Loop while there are attached devices */
111     while (CurrentDeviceObject)
112     {
113         /* Check if this device driver matches ours */
114         if (CurrentDeviceObject->DriverObject == DriverData.DriverObject)
115         {
116             FLT_ASSERT(CurrentDeviceObject->DeviceExtension != NULL);
117 
118             /* We're attached, return the device object if the caller asked for it */
119             if (AttachedDeviceObject)
120             {
121                 *AttachedDeviceObject = CurrentDeviceObject;
122             }
123             else
124             {
125                 /* We aren't returning the reference, so decrement the count */
126                 ObDereferenceObject(CurrentDeviceObject);
127             }
128 
129             return TRUE;
130         }
131 
132         /* Get the next device in the chain */
133         NextDeviceObject = IoGetLowerDeviceObject(CurrentDeviceObject);
134 
135         /* Decrement the count on the last device before we update the pointer */
136         ObDereferenceObject(CurrentDeviceObject);
137         CurrentDeviceObject = NextDeviceObject;
138     }
139 
140     return FALSE;
141 }
142 
143 CODE_SEG("PAGE")
144 static
145 NTSTATUS
146 FltpEnumerateFileSystemVolumes(_In_ PDEVICE_OBJECT DeviceObject)
147 {
148     PFLTMGR_DEVICE_EXTENSION NewDeviceExtension;
149     PDEVICE_OBJECT BaseDeviceObject;
150     PDEVICE_OBJECT NewDeviceObject;
151     PDEVICE_OBJECT *DeviceList;
152     PDEVICE_OBJECT StorageStackDeviceObject;
153     UNICODE_STRING DeviceName;
154     ULONG NumDevices;
155     ULONG i;
156     NTSTATUS Status;
157 
158     PAGED_CODE();
159 
160     /* Get the base device */
161     BaseDeviceObject = IoGetDeviceAttachmentBaseRef(DeviceObject);
162 
163     /* get the number of device object linked to the base file system */
164     Status = IoEnumerateDeviceObjectList(BaseDeviceObject->DriverObject,
165                                          NULL,
166                                          0,
167                                          &NumDevices);
168     if (Status != STATUS_BUFFER_TOO_SMALL) return Status;
169 
170     /* Add a few more slots in case the size changed between calls and allocate some memory to hold the pointers */
171     NumDevices += 4;
172     DeviceList = ExAllocatePoolWithTag(NonPagedPool,
173                                        (NumDevices * sizeof(PDEVICE_OBJECT)),
174                                        FM_TAG_DEV_OBJ_PTRS);
175     if (DeviceList == NULL) return STATUS_INSUFFICIENT_RESOURCES;
176 
177     /* Now get all the device objects that this base driver has created */
178     Status = IoEnumerateDeviceObjectList(BaseDeviceObject->DriverObject,
179                                          DeviceList,
180                                          (NumDevices * sizeof(PDEVICE_OBJECT)),
181                                          &NumDevices);
182     if (!NT_SUCCESS(Status))
183     {
184         ExFreePoolWithTag(DeviceList, FM_TAG_DEV_OBJ_PTRS);
185         return Status;
186     }
187 
188     /* Loop through all the devices looking for ones to attach to */
189     for (i = 0; i < NumDevices; i++)
190     {
191         RtlInitUnicodeString(&DeviceName, NULL);
192         StorageStackDeviceObject = NULL;
193         NewDeviceObject = NULL;
194 
195         /* Ignore the device we passed in, and devices of the wrong type */
196         if ((DeviceList[i] == BaseDeviceObject) ||
197             (DeviceList[i]->DeviceType != BaseDeviceObject->DeviceType))
198         {
199             goto CleanupAndNext;
200         }
201 
202         /* Ignore this device if we're already attached to it */
203         if (FltpIsAttachedToDevice(DeviceList[i], NULL) == FALSE)
204         {
205             goto CleanupAndNext;
206         }
207 
208 
209         /*
210          * If the device has a name, it must be a control device.
211          * This handles drivers with more then one control device (like FastFat)
212          */
213         FltpGetBaseDeviceObjectName(DeviceList[i], &DeviceName);
214         if (NT_SUCCESS(Status) && DeviceName.Length > 0)
215         {
216             goto CleanupAndNext;
217         }
218 
219         /*
220          * Try to get the storage stack (disk) device object associated with
221          * this file system device object. Ignore the device if we don't have one
222          */
223         Status = IoGetDiskDeviceObject(DeviceList[i],
224                                        &StorageStackDeviceObject);
225         if (!NT_SUCCESS(Status))
226         {
227             goto CleanupAndNext;
228         }
229 
230 
231         /*
232          * TODO: Don't attach to shadow copy volumes,
233          * ros doesn't have any so it's not an issues yet
234          */
235 
236         /*
237          * We're far enough to be ready to attach, create a device
238          * object which we'll use to do so
239          */
240         Status = IoCreateDevice(DriverData.DriverObject,
241                                 sizeof(FLTMGR_DEVICE_EXTENSION),
242                                 NULL,
243                                 DeviceList[i]->DeviceType,
244                                 0,
245                                 FALSE,
246                                 &NewDeviceObject);
247         if (!NT_SUCCESS(Status))
248         {
249             goto CleanupAndNext;
250         }
251 
252         /* Get the device extension for this new object and store our disk object there */
253         NewDeviceExtension = NewDeviceObject->DeviceExtension;
254         NewDeviceExtension->StorageStackDeviceObject = StorageStackDeviceObject;
255 
256         /* Lookup and store the device name for the storage stack */
257         RtlInitEmptyUnicodeString(&NewDeviceExtension->DeviceName,
258                                   NewDeviceExtension->DeviceNameBuffer,
259                                   sizeof(NewDeviceExtension->DeviceNameBuffer));
260         FltpGetObjectName(StorageStackDeviceObject,
261                           &NewDeviceExtension->DeviceName);
262 
263 
264         /* Grab the attach lock before we attempt to attach */
265         ExAcquireFastMutex(&DriverData.FilterAttachLock);
266 
267         /* Check again that we aren't already attached. It may have changed since our last check */
268         if (FltpIsAttachedToDevice(DeviceList[i], NULL) == FALSE)
269         {
270             FLT_ASSERT(NewDeviceObject->DriverObject == DriverData.DriverObject);
271 
272             /* Finally, attach to the volume */
273             Status = FltpAttachDeviceObject(DeviceList[i],
274                                             NewDeviceObject,
275                                             &NewDeviceExtension->AttachedToDeviceObject);
276             if (NT_SUCCESS(Status))
277             {
278                 /* Clean the initializing flag so other filters can attach to our device object */
279                 ClearFlag(NewDeviceObject->Flags, DO_DEVICE_INITIALIZING);
280             }
281         }
282         else
283         {
284             /* We're already attached. Just cleanup */
285             Status = STATUS_DEVICE_ALREADY_ATTACHED;
286         }
287 
288         ExReleaseFastMutex(&DriverData.FilterAttachLock);
289 
290 CleanupAndNext:
291 
292         if (!NT_SUCCESS(Status))
293         {
294             if (NewDeviceObject)
295             {
296                 FltpCleanupDeviceObject(NewDeviceObject);
297                 IoDeleteDevice(NewDeviceObject);
298             }
299         }
300 
301         if (StorageStackDeviceObject)
302         {
303             /* A ref was added for us when we attached, so we can deref ours now */
304             ObDereferenceObject(StorageStackDeviceObject);
305         }
306 
307         /* Remove the ref which was added by IoEnumerateDeviceObjectList */
308         ObDereferenceObject(DeviceList[i]);
309 
310         /* Free the buffer that FltpGetBaseDeviceObjectName added */
311         FltpFreeUnicodeString(&DeviceName);
312 
313     }
314 
315     /* Free the memory we allocated for the list */
316     ExFreePoolWithTag(DeviceList, FM_TAG_DEV_OBJ_PTRS);
317 
318     return STATUS_SUCCESS;
319 }
320 
321 CODE_SEG("PAGE")
322 static
323 NTSTATUS
324 FltpAttachToFileSystemDevice(_In_ PDEVICE_OBJECT DeviceObject,
325                              _In_ PUNICODE_STRING DeviceName)
326 {
327     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
328     PDEVICE_OBJECT NewDeviceObject;
329     WCHAR Buffer[MAX_DEVNAME_LENGTH];
330     UNICODE_STRING FileSystemDeviceName;
331     UNICODE_STRING FsRecDeviceName;
332     NTSTATUS Status;
333 
334     PAGED_CODE();
335 
336     /* Only handle device types we're interested in */
337     if (DeviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
338         DeviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM &&
339         DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM)
340     {
341         return STATUS_SUCCESS;
342     }
343 
344     /* Setup the buffer to hold the device name */
345     RtlInitEmptyUnicodeString(&FileSystemDeviceName,
346                               Buffer,
347                               MAX_DEVNAME_LENGTH * sizeof(WCHAR));
348 
349     /* Get the the name of the file system device */
350     Status = FltpGetObjectName(DeviceObject->DriverObject, &FileSystemDeviceName);
351     if (!NT_SUCCESS(Status)) return Status;
352 
353     DPRINT("Found device %wZ, checking if we need to attach...\n", &FileSystemDeviceName);
354 
355     /* Build up the name of the file system recognizer device */
356     RtlInitUnicodeString(&FsRecDeviceName, L"\\FileSystem\\Fs_Rec");
357 
358     /* We don't attach to recognizer devices, so bail if this is one */
359     if (RtlCompareUnicodeString(&FileSystemDeviceName, &FsRecDeviceName, TRUE) == 0)
360     {
361         return STATUS_SUCCESS;
362     }
363 
364     /* Create a device object which we can attach to this file system */
365     Status = IoCreateDevice(DriverData.DriverObject,
366                             sizeof(FLTMGR_DEVICE_EXTENSION),
367                             NULL,
368                             DeviceObject->DeviceType,
369                             0,
370                             FALSE,
371                             &NewDeviceObject);
372     if (!NT_SUCCESS(Status))
373     {
374         DPRINT1("Failed to create a DO for attaching to a FS : 0x%X\n", Status);
375         return Status;
376     }
377 
378     /* Cast the device extension to something we understand */
379     DeviceExtension = NewDeviceObject->DeviceExtension;
380 
381     /* Attach this device to the top of the driver stack and store the DO we attached to in the DE */
382     Status = FltpAttachDeviceObject(NewDeviceObject,
383                                     DeviceObject,
384                                     &DeviceExtension->AttachedToDeviceObject);
385     if (NT_SUCCESS(Status))
386     {
387         DPRINT("Attached to %wZ\n", &FileSystemDeviceName);
388     }
389     else
390     {
391         DPRINT1("Failed to attach to the driver stack : 0x%X\n", Status);
392         goto Cleanup;
393     }
394 
395     /* Setup the unicode string buffer and copy the device name to the device extension */
396     RtlInitEmptyUnicodeString(&DeviceExtension->DeviceName,
397                               DeviceExtension->DeviceNameBuffer,
398                               MAX_DEVNAME_LENGTH * sizeof(WCHAR));
399     RtlCopyUnicodeString(&DeviceExtension->DeviceName, DeviceName);
400 
401     /* We're done, remove the initializing flag */
402     ClearFlag(NewDeviceObject->Flags, DO_DEVICE_INITIALIZING);
403 
404     /* Look for existing mounted devices for this file system */
405     Status = FltpEnumerateFileSystemVolumes(DeviceObject);
406     if (!NT_SUCCESS(Status))
407     {
408         DPRINT1("Failed to enumerate file system volumes for this file system : 0x%X\n", Status);
409         IoDetachDevice(DeviceExtension->AttachedToDeviceObject);
410     }
411 
412 Cleanup:
413 
414     if (!NT_SUCCESS(Status))
415     {
416         IoDeleteDevice(NewDeviceObject);
417     }
418 
419     return Status;
420 }
421 
422 CODE_SEG("PAGE")
423 static
424 LONG_PTR
425 FltpDetachFromFileSystemDevice(_In_ PDEVICE_OBJECT DeviceObject)
426 {
427     PDEVICE_OBJECT AttachedDevice, NextDevice;
428     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
429     LONG_PTR Count;
430 
431     PAGED_CODE();
432 
433     /* Get the top device in the chain and increment the ref count on it */
434     AttachedDevice = IoGetAttachedDeviceReference(DeviceObject);
435 
436     /* Loop all attached devices looking for our file system driver */
437     while (AttachedDevice->DriverObject != DriverData.DriverObject)
438     {
439         FLT_ASSERT(AttachedDevice != NULL);
440 
441         /* Get the next lower device object. This adds a ref on NextDevice */
442         NextDevice = IoGetLowerDeviceObject(AttachedDevice);
443 
444         /* Remove the reference we added */
445         Count = ObDereferenceObject(AttachedDevice);
446 
447         /* Bail if this is the last one */
448         if (NextDevice == NULL) return Count;
449 
450         /* Try the next one */
451         AttachedDevice = NextDevice;
452     }
453 
454 
455     DeviceExtension = AttachedDevice->DeviceExtension;
456     if (DeviceExtension)
457     {
458         //
459         // FIXME: Put any device extension cleanup code here
460         //
461     }
462 
463     /* Detach the device from the chain and delete the object */
464     IoDetachDevice(DeviceObject);
465     IoDeleteDevice(AttachedDevice);
466 
467     /* Remove the reference we added so the delete can complete */
468     return ObDereferenceObject(AttachedDevice);
469 }
470 
471 
472 /* DISPATCH ROUTINES **********************************************/
473 
474 NTSTATUS
475 NTAPI
476 FltpPreFsFilterOperation(_In_ PFS_FILTER_CALLBACK_DATA Data,
477                          _Out_ PVOID *CompletionContext)
478 {
479     UNREFERENCED_PARAMETER(Data);
480     UNREFERENCED_PARAMETER(CompletionContext);
481     __debugbreak();
482     return STATUS_SUCCESS;
483 }
484 
485 VOID
486 NTAPI
487 FltpPostFsFilterOperation(_In_ PFS_FILTER_CALLBACK_DATA Data,
488                           _In_ NTSTATUS OperationStatus,
489                           _In_ PVOID CompletionContext)
490 {
491     UNREFERENCED_PARAMETER(Data);
492     UNREFERENCED_PARAMETER(OperationStatus);
493     UNREFERENCED_PARAMETER(CompletionContext);
494     __debugbreak();
495 }
496 
497 NTSTATUS
498 NTAPI
499 FltpDispatch(_In_ PDEVICE_OBJECT DeviceObject,
500              _Inout_ PIRP Irp)
501 {
502     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
503     PIO_STACK_LOCATION StackPtr;
504     NTSTATUS Status;
505 
506     DeviceExtension = DeviceObject->DeviceExtension;
507 
508     /* Check if this is a request for us */
509     if (DeviceObject == DriverData.DeviceObject)
510     {
511         FLT_ASSERT(DeviceObject->DriverObject == DriverData.DriverObject);
512         FLT_ASSERT(DeviceExtension == NULL);
513 
514         /* Hand it off to our internal handler */
515         Status = FltpDispatchHandler(DeviceObject, Irp);
516         if (Status != STATUS_REPARSE)
517         {
518             Irp->IoStatus.Status = Status;
519             Irp->IoStatus.Information = 0;
520             IoCompleteRequest(Irp, 0);
521         }
522         return Status;
523     }
524 
525     /* Check if this is a request for a the messaging device */
526     if (DeviceObject == CommsDeviceObject)
527     {
528         /* Hand off to our internal routine */
529         return FltpMsgDispatch(DeviceObject, Irp);
530     }
531 
532     FLT_ASSERT(DeviceExtension &&
533                DeviceExtension->AttachedToDeviceObject);
534 
535     StackPtr = IoGetCurrentIrpStackLocation(Irp);
536     if (StackPtr->MajorFunction == IRP_MJ_SHUTDOWN)
537     {
538         // handle shutdown request
539     }
540 
541     DPRINT1("Received %X from %wZ\n", StackPtr->MajorFunction, &DeviceExtension->DeviceName);
542 
543     /* Just pass the IRP down the stack */
544     IoSkipCurrentIrpStackLocation(Irp);
545     return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
546 }
547 
548 CODE_SEG("PAGE")
549 NTSTATUS
550 NTAPI
551 FltpCreate(_In_ PDEVICE_OBJECT DeviceObject,
552            _Inout_ PIRP Irp)
553 {
554     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
555 
556     PAGED_CODE();
557 
558     DeviceExtension = DeviceObject->DeviceExtension;
559 
560     /* Check if this is a request for us */
561     if (DeviceObject == DriverData.DeviceObject)
562     {
563         FLT_ASSERT(DeviceObject->DriverObject == DriverData.DriverObject);
564         FLT_ASSERT(DeviceExtension == NULL);
565 
566         /* Someone wants a handle to the fltmgr, allow it */
567         Irp->IoStatus.Status = STATUS_SUCCESS;
568         Irp->IoStatus.Information = 0;
569         IofCompleteRequest(Irp, 0);
570         return STATUS_SUCCESS;
571     }
572 
573     /* Check if this is a request for a the new comms connection */
574     if (DeviceObject == CommsDeviceObject)
575     {
576         /* Hand off to our internal routine */
577         return FltpMsgCreate(DeviceObject, Irp);
578     }
579 
580     FLT_ASSERT(DeviceExtension &&
581                DeviceExtension->AttachedToDeviceObject);
582 
583     DPRINT1("Received create from %wZ (%lu)\n", &DeviceExtension->DeviceName, PsGetCurrentProcessId());
584 
585     /* Just pass the IRP down the stack */
586     IoSkipCurrentIrpStackLocation(Irp);
587     return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
588 }
589 
590 CODE_SEG("PAGE")
591 NTSTATUS
592 NTAPI
593 FltpFsControl(_In_ PDEVICE_OBJECT DeviceObject,
594               _Inout_ PIRP Irp)
595 {
596     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
597 
598     PAGED_CODE();
599 
600     /* Check if this is a request for us */
601     if (DeviceObject == DriverData.DeviceObject)
602     {
603         /* We don't handle this request */
604         Irp->IoStatus.Information = 0;
605         Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
606         IofCompleteRequest(Irp, 0);
607         return STATUS_INVALID_DEVICE_REQUEST;
608     }
609 
610     DeviceExtension = DeviceObject->DeviceExtension;
611 
612     FLT_ASSERT(DeviceExtension &&
613                DeviceExtension->AttachedToDeviceObject);
614 
615     /* Just pass the IRP down the stack */
616     IoSkipCurrentIrpStackLocation(Irp);
617     return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
618 }
619 
620 NTSTATUS
621 NTAPI
622 FltpDeviceControl(_In_ PDEVICE_OBJECT DeviceObject,
623                   _Inout_ PIRP Irp)
624 {
625     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
626     NTSTATUS Status;
627 
628     /* Check if the request was meant for us */
629     if (DeviceObject == DriverData.DeviceObject)
630     {
631         Status = FltpDeviceControlHandler(DeviceObject, Irp);
632         if (Status != STATUS_REPARSE)
633         {
634             Irp->IoStatus.Status = Status;
635             Irp->IoStatus.Information = 0;
636             IoCompleteRequest(Irp, 0);
637         }
638 
639         return Status;
640     }
641 
642     DeviceExtension = DeviceObject->DeviceExtension;
643 
644     FLT_ASSERT(DeviceExtension &&
645                DeviceExtension->AttachedToDeviceObject);
646 
647     /* Just pass the IRP down the stack */
648     IoSkipCurrentIrpStackLocation(Irp);
649     return IoCallDriver(DeviceExtension->AttachedToDeviceObject, Irp);
650 }
651 
652 
653 
654 /* FASTIO ROUTINES ************************************************/
655 
656 CODE_SEG("PAGE")
657 BOOLEAN
658 NTAPI
659 FltpFastIoCheckIfPossible(_In_ PFILE_OBJECT FileObject,
660                           _In_ PLARGE_INTEGER FileOffset,
661                           _In_ ULONG Length,
662                           _In_ BOOLEAN Wait,
663                           _In_ ULONG LockKey,
664                           _In_ BOOLEAN CheckForReadOperation,
665                           _Out_ PIO_STATUS_BLOCK IoStatus,
666                           _In_ PDEVICE_OBJECT DeviceObject)
667 
668 {
669     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
670     PDEVICE_OBJECT AttachedDeviceObject;
671     PFAST_IO_DISPATCH FastIoDispatch;
672 
673     PAGED_CODE();
674 
675     /* If it doesn't have a device extension, then it's not our device object */
676     if (DeviceObject->DeviceExtension == NULL)
677     {
678         /* Fail the call */
679         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
680         IoStatus->Information = 0;
681         return TRUE;
682     }
683 
684     DeviceExtension = DeviceObject->DeviceExtension;
685     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
686 
687     /* Get the device that we attached to */
688     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
689     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
690 
691     /* Make sure our FastIo table is valid */
692     if (FastIoDispatch && FastIoDispatch->FastIoCheckIfPossible)
693     {
694         /* Forward the call onto the device we attached to */
695         return FastIoDispatch->FastIoCheckIfPossible(FileObject,
696                                                      FileOffset,
697                                                      Length,
698                                                      Wait,
699                                                      LockKey,
700                                                      CheckForReadOperation,
701                                                      IoStatus,
702                                                      AttachedDeviceObject);
703     }
704 
705     /* We failed to handle the request, send it down the slow path */
706     FLT_ASSERT(FALSE);
707     return FALSE;
708 }
709 
710 CODE_SEG("PAGE")
711 BOOLEAN
712 NTAPI
713 FltpFastIoRead(_In_ PFILE_OBJECT FileObject,
714                _In_ PLARGE_INTEGER FileOffset,
715                _In_ ULONG Length,
716                _In_ BOOLEAN Wait,
717                _In_ ULONG LockKey,
718                _Out_ PVOID Buffer,
719                _Out_ PIO_STATUS_BLOCK IoStatus,
720                _In_ PDEVICE_OBJECT DeviceObject)
721 {
722     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
723     PDEVICE_OBJECT AttachedDeviceObject;
724     PFAST_IO_DISPATCH FastIoDispatch;
725 
726     PAGED_CODE();
727 
728     /* If it doesn't have a device extension, then it's not our device object */
729     if (DeviceObject->DeviceExtension == NULL)
730     {
731         /* Fail the call */
732         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
733         IoStatus->Information = 0;
734         return TRUE;
735     }
736 
737     DeviceExtension = DeviceObject->DeviceExtension;
738     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
739 
740     /* Get the device that we attached to */
741     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
742     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
743 
744     /* Make sure our FastIo table is valid */
745     if (FastIoDispatch && FastIoDispatch->FastIoRead)
746     {
747         /* Forward the call onto the device we attached to */
748         return FastIoDispatch->FastIoRead(FileObject,
749                                           FileOffset,
750                                           Length,
751                                           Wait,
752                                           LockKey,
753                                           Buffer,
754                                           IoStatus,
755                                           AttachedDeviceObject);
756     }
757 
758     /* We failed to handle the request, send it down the slow path */
759     FLT_ASSERT(FALSE);
760     return FALSE;
761 }
762 
763 CODE_SEG("PAGE")
764 BOOLEAN
765 NTAPI
766 FltpFastIoWrite(_In_ PFILE_OBJECT FileObject,
767                 _In_ PLARGE_INTEGER FileOffset,
768                  _In_ ULONG Length,
769                  _In_ BOOLEAN Wait,
770                  _In_ ULONG LockKey,
771                  _In_ PVOID Buffer,
772                  _Out_ PIO_STATUS_BLOCK IoStatus,
773                  _In_ PDEVICE_OBJECT DeviceObject)
774 {
775     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
776     PDEVICE_OBJECT AttachedDeviceObject;
777     PFAST_IO_DISPATCH FastIoDispatch;
778 
779     PAGED_CODE();
780 
781     /* If it doesn't have a device extension, then it's not our device object */
782     if (DeviceObject->DeviceExtension == NULL)
783     {
784         /* Fail the call */
785         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
786         IoStatus->Information = 0;
787         return TRUE;
788     }
789 
790     DeviceExtension = DeviceObject->DeviceExtension;
791     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
792 
793     /* Get the device that we attached to */
794     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
795     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
796 
797     /* Make sure our FastIo table is valid */
798     if (FastIoDispatch && FastIoDispatch->FastIoWrite)
799     {
800         /* Forward the call onto the device we attached to */
801         return FastIoDispatch->FastIoWrite(FileObject,
802                                            FileOffset,
803                                            Length,
804                                            Wait,
805                                            LockKey,
806                                            Buffer,
807                                            IoStatus,
808                                            AttachedDeviceObject);
809     }
810 
811     /* We failed to handle the request, send it down the slow path */
812     FLT_ASSERT(FALSE);
813     return FALSE;
814 }
815 
816 CODE_SEG("PAGE")
817 BOOLEAN
818 NTAPI
819 FltpFastIoQueryBasicInfo(_In_ PFILE_OBJECT FileObject,
820                          _In_ BOOLEAN Wait,
821                          _Out_ PFILE_BASIC_INFORMATION Buffer,
822                          _Out_ PIO_STATUS_BLOCK IoStatus,
823                          _In_ PDEVICE_OBJECT DeviceObject)
824 {
825     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
826     PDEVICE_OBJECT AttachedDeviceObject;
827     PFAST_IO_DISPATCH FastIoDispatch;
828 
829     PAGED_CODE();
830 
831     /* If it doesn't have a device extension, then it's not our device object */
832     if (DeviceObject->DeviceExtension == NULL)
833     {
834         /* Fail the call */
835         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
836         IoStatus->Information = 0;
837         return TRUE;
838     }
839 
840     DeviceExtension = DeviceObject->DeviceExtension;
841     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
842 
843     /* Get the device that we attached to */
844     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
845     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
846 
847     /* Make sure our FastIo table is valid */
848     if (FastIoDispatch && FastIoDispatch->FastIoQueryBasicInfo)
849     {
850         /* Forward the call onto the device we attached to */
851         return FastIoDispatch->FastIoQueryBasicInfo(FileObject,
852                                                     Wait,
853                                                     Buffer,
854                                                     IoStatus,
855                                                     AttachedDeviceObject);
856     }
857 
858     /* We failed to handle the request, send it down the slow path */
859     FLT_ASSERT(FALSE);
860     return FALSE;
861 }
862 
863 CODE_SEG("PAGE")
864 BOOLEAN
865 NTAPI
866 FltpFastIoQueryStandardInfo(_In_ PFILE_OBJECT FileObject,
867                             _In_ BOOLEAN Wait,
868                             _Out_ PFILE_STANDARD_INFORMATION Buffer,
869                             _Out_ PIO_STATUS_BLOCK IoStatus,
870                             _In_ PDEVICE_OBJECT DeviceObject)
871 {
872     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
873     PDEVICE_OBJECT AttachedDeviceObject;
874     PFAST_IO_DISPATCH FastIoDispatch;
875 
876     PAGED_CODE();
877 
878     /* If it doesn't have a device extension, then it's not our device object */
879     if (DeviceObject->DeviceExtension == NULL)
880     {
881         /* Fail the call */
882         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
883         IoStatus->Information = 0;
884         return TRUE;
885     }
886 
887     DeviceExtension = DeviceObject->DeviceExtension;
888     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
889 
890     /* Get the device that we attached to */
891     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
892     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
893 
894     /* Make sure our FastIo table is valid */
895     if (FastIoDispatch && FastIoDispatch->FastIoQueryStandardInfo)
896     {
897         /* Forward the call onto the device we attached to */
898         return FastIoDispatch->FastIoQueryStandardInfo(FileObject,
899                                                        Wait,
900                                                        Buffer,
901                                                        IoStatus,
902                                                        AttachedDeviceObject);
903     }
904 
905     /* We failed to handle the request, send it down the slow path */
906     FLT_ASSERT(FALSE);
907     return FALSE;
908 }
909 
910 CODE_SEG("PAGE")
911 BOOLEAN
912 NTAPI
913 FltpFastIoLock(_In_ PFILE_OBJECT FileObject,
914                _In_ PLARGE_INTEGER FileOffset,
915                _In_ PLARGE_INTEGER Length,
916                _In_ PEPROCESS ProcessId,
917                _In_ ULONG Key,
918                _In_ BOOLEAN FailImmediately,
919                _In_ BOOLEAN ExclusiveLock,
920                _Out_ PIO_STATUS_BLOCK IoStatus,
921                _In_ PDEVICE_OBJECT DeviceObject)
922 {
923     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
924     PDEVICE_OBJECT AttachedDeviceObject;
925     PFAST_IO_DISPATCH FastIoDispatch;
926 
927     PAGED_CODE();
928 
929     /* If it doesn't have a device extension, then it's not our device object */
930     if (DeviceObject->DeviceExtension == NULL)
931     {
932         /* Fail the call */
933         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
934         IoStatus->Information = 0;
935         return TRUE;
936     }
937 
938     DeviceExtension = DeviceObject->DeviceExtension;
939     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
940 
941     /* Get the device that we attached to */
942     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
943     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
944 
945     /* Make sure our FastIo table is valid */
946     if (FastIoDispatch && FastIoDispatch->FastIoLock)
947     {
948         /* Forward the call onto the device we attached to */
949         return FastIoDispatch->FastIoLock(FileObject,
950                                           FileOffset,
951                                           Length,
952                                           ProcessId,
953                                           Key,
954                                           FailImmediately,
955                                           ExclusiveLock,
956                                           IoStatus,
957                                           AttachedDeviceObject);
958     }
959 
960     /* We failed to handle the request, send it down the slow path */
961     FLT_ASSERT(FALSE);
962     return FALSE;
963 }
964 
965 CODE_SEG("PAGE")
966 BOOLEAN
967 NTAPI
968 FltpFastIoUnlockSingle(_In_ PFILE_OBJECT FileObject,
969                        _In_ PLARGE_INTEGER FileOffset,
970                        _In_ PLARGE_INTEGER Length,
971                        _In_ PEPROCESS ProcessId,
972                        _In_ ULONG Key,
973                        _Out_ PIO_STATUS_BLOCK IoStatus,
974                        _In_ PDEVICE_OBJECT DeviceObject)
975 {
976     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
977     PDEVICE_OBJECT AttachedDeviceObject;
978     PFAST_IO_DISPATCH FastIoDispatch;
979 
980     PAGED_CODE();
981 
982     /* If it doesn't have a device extension, then it's not our device object */
983     if (DeviceObject->DeviceExtension == NULL)
984     {
985         /* Fail the call */
986         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
987         IoStatus->Information = 0;
988         return TRUE;
989     }
990 
991     DeviceExtension = DeviceObject->DeviceExtension;
992     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
993 
994     /* Get the device that we attached to */
995     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
996     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
997 
998     /* Make sure our FastIo table is valid */
999     if (FastIoDispatch && FastIoDispatch->FastIoUnlockSingle)
1000     {
1001         /* Forward the call onto the device we attached to */
1002         return FastIoDispatch->FastIoUnlockSingle(FileObject,
1003                                                   FileOffset,
1004                                                   Length,
1005                                                   ProcessId,
1006                                                   Key,
1007                                                   IoStatus,
1008                                                   AttachedDeviceObject);
1009     }
1010 
1011     /* We failed to handle the request, send it down the slow path */
1012     FLT_ASSERT(FALSE);
1013     return FALSE;
1014 }
1015 
1016 CODE_SEG("PAGE")
1017 BOOLEAN
1018 NTAPI
1019 FltpFastIoUnlockAll(_In_ PFILE_OBJECT FileObject,
1020                     _In_ PEPROCESS ProcessId,
1021                     _Out_ PIO_STATUS_BLOCK IoStatus,
1022                     _In_ PDEVICE_OBJECT DeviceObject)
1023 
1024 {
1025     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1026     PDEVICE_OBJECT AttachedDeviceObject;
1027     PFAST_IO_DISPATCH FastIoDispatch;
1028 
1029     PAGED_CODE();
1030 
1031     /* If it doesn't have a device extension, then it's not our device object */
1032     if (DeviceObject->DeviceExtension == NULL)
1033     {
1034         /* Fail the call */
1035         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
1036         IoStatus->Information = 0;
1037         return TRUE;
1038     }
1039 
1040     DeviceExtension = DeviceObject->DeviceExtension;
1041     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1042 
1043     /* Get the device that we attached to */
1044     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1045     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1046 
1047     /* Make sure our FastIo table is valid */
1048     if (FastIoDispatch && FastIoDispatch->FastIoUnlockAll)
1049     {
1050         /* Forward the call onto the device we attached to */
1051         return FastIoDispatch->FastIoUnlockAll(FileObject,
1052                                                ProcessId,
1053                                                IoStatus,
1054                                                AttachedDeviceObject);
1055     }
1056 
1057     /* We failed to handle the request, send it down the slow path */
1058     FLT_ASSERT(FALSE);
1059     return FALSE;
1060 }
1061 
1062 CODE_SEG("PAGE")
1063 BOOLEAN
1064 NTAPI
1065 FltpFastIoUnlockAllByKey(_In_ PFILE_OBJECT FileObject,
1066                          _In_ PVOID ProcessId,
1067                          _In_ ULONG Key,
1068                          _Out_ PIO_STATUS_BLOCK IoStatus,
1069                          _In_ PDEVICE_OBJECT DeviceObject)
1070 {
1071     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1072     PDEVICE_OBJECT AttachedDeviceObject;
1073     PFAST_IO_DISPATCH FastIoDispatch;
1074 
1075     PAGED_CODE();
1076 
1077     /* If it doesn't have a device extension, then it's not our device object */
1078     if (DeviceObject->DeviceExtension == NULL)
1079     {
1080         /* Fail the call */
1081         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
1082         IoStatus->Information = 0;
1083         return TRUE;
1084     }
1085 
1086     DeviceExtension = DeviceObject->DeviceExtension;
1087     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1088 
1089     /* Get the device that we attached to */
1090     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1091     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1092 
1093     /* Make sure our FastIo table is valid */
1094     if (FastIoDispatch && FastIoDispatch->FastIoUnlockAllByKey)
1095     {
1096         /* Forward the call onto the device we attached to */
1097         return FastIoDispatch->FastIoUnlockAllByKey(FileObject,
1098                                                     ProcessId,
1099                                                     Key,
1100                                                     IoStatus,
1101                                                     AttachedDeviceObject);
1102     }
1103 
1104     /* We failed to handle the request, send it down the slow path */
1105     FLT_ASSERT(FALSE);
1106     return FALSE;
1107 }
1108 
1109 CODE_SEG("PAGE")
1110 BOOLEAN
1111 NTAPI
1112 FltpFastIoDeviceControl(_In_ PFILE_OBJECT FileObject,
1113                         _In_ BOOLEAN Wait,
1114                         _In_opt_ PVOID InputBuffer,
1115                         _In_ ULONG InputBufferLength,
1116                         _Out_opt_ PVOID OutputBuffer,
1117                         _In_ ULONG OutputBufferLength,
1118                         _In_ ULONG IoControlCode,
1119                         _Out_ PIO_STATUS_BLOCK IoStatus,
1120                         _In_ PDEVICE_OBJECT DeviceObject)
1121 {
1122     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1123     PDEVICE_OBJECT AttachedDeviceObject;
1124     PFAST_IO_DISPATCH FastIoDispatch;
1125 
1126     PAGED_CODE();
1127 
1128     /* If it doesn't have a device extension, then it's not our device object */
1129     if (DeviceObject->DeviceExtension == NULL)
1130     {
1131         /* Fail the request, send it down the slow path */
1132         return FALSE;
1133     }
1134 
1135     DeviceExtension = DeviceObject->DeviceExtension;
1136     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1137 
1138     /* Get the device that we attached to */
1139     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1140     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1141 
1142     /* Make sure our FastIo table is valid */
1143     if (FastIoDispatch && FastIoDispatch->FastIoDeviceControl)
1144     {
1145         /* Forward the call onto the device we attached to */
1146         return FastIoDispatch->FastIoDeviceControl(FileObject,
1147                                                    Wait,
1148                                                    InputBuffer,
1149                                                    InputBufferLength,
1150                                                    OutputBuffer,
1151                                                    OutputBufferLength,
1152                                                    IoControlCode,
1153                                                    IoStatus,
1154                                                    AttachedDeviceObject);
1155     }
1156 
1157     /* We failed to handle the request, send it down the slow path */
1158     FLT_ASSERT(FALSE);
1159     return FALSE;
1160 }
1161 
1162 VOID
1163 NTAPI
1164 FltpFastIoDetachDeviceWorker(_In_ PVOID Parameter)
1165 {
1166     PDETACH_DEVICE_WORK_ITEM DetachDeviceWorkItem = Parameter;
1167 
1168     /* Run any cleanup routines */
1169     FltpCleanupDeviceObject(DetachDeviceWorkItem->SourceDevice);
1170 
1171     /* Detach from the target device */
1172     IoDetachDevice(DetachDeviceWorkItem->TargetDevice);
1173 
1174     /* Delete the source */
1175     IoDeleteDevice(DetachDeviceWorkItem->SourceDevice);
1176 
1177     /* Free the pool we allocated in FltpFastIoDetachDevice */
1178     ExFreePoolWithTag(DetachDeviceWorkItem, 0x1234);
1179 }
1180 
1181 CODE_SEG("PAGE")
1182 VOID
1183 NTAPI
1184 FltpFastIoDetachDevice(_In_ PDEVICE_OBJECT SourceDevice,
1185                      _In_ PDEVICE_OBJECT TargetDevice)
1186 {
1187     PDETACH_DEVICE_WORK_ITEM DetachDeviceWorkItem;
1188 
1189     PAGED_CODE();
1190 
1191     /*
1192      * Detaching and deleting devices is a lot of work and takes too long
1193      * to be a worthwhile FastIo candidate, so we defer this call to speed
1194      * it up. There's no return value so we're okay to do this.
1195      */
1196 
1197     /* Allocate the work item and it's corresponding data */
1198     DetachDeviceWorkItem = ExAllocatePoolWithTag(NonPagedPool,
1199                                                  sizeof(DETACH_DEVICE_WORK_ITEM),
1200                                                  0x1234);
1201     if (DetachDeviceWorkItem)
1202     {
1203         /* Initialize the work item */
1204         ExInitializeWorkItem(&DetachDeviceWorkItem->WorkItem,
1205                              FltpFastIoDetachDeviceWorker,
1206                              DetachDeviceWorkItem);
1207 
1208         /* Queue the work item and return the call */
1209         ExQueueWorkItem(&DetachDeviceWorkItem->WorkItem,
1210                         DelayedWorkQueue);
1211     }
1212     else
1213     {
1214         /* We failed to defer, just cleanup here */
1215         FltpCleanupDeviceObject(SourceDevice);
1216         IoDetachDevice(TargetDevice);
1217         IoDeleteDevice(SourceDevice);
1218     }
1219 
1220 }
1221 
1222 CODE_SEG("PAGE")
1223 BOOLEAN
1224 NTAPI
1225 FltpFastIoQueryNetworkOpenInfo(_In_ PFILE_OBJECT FileObject,
1226                                _In_ BOOLEAN Wait,
1227                                _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
1228                                _Out_ PIO_STATUS_BLOCK IoStatus,
1229                                _In_ PDEVICE_OBJECT DeviceObject)
1230 {
1231     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1232     PDEVICE_OBJECT AttachedDeviceObject;
1233     PFAST_IO_DISPATCH FastIoDispatch;
1234 
1235     PAGED_CODE();
1236 
1237     /* If it doesn't have a device extension, then it's not our device object */
1238     if (DeviceObject->DeviceExtension == NULL)
1239     {
1240         /* Fail the call */
1241         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
1242         IoStatus->Information = 0;
1243         return TRUE;
1244     }
1245 
1246     DeviceExtension = DeviceObject->DeviceExtension;
1247     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1248 
1249     /* Get the device that we attached to */
1250     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1251     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1252 
1253     /* Make sure our FastIo table is valid */
1254     if (FastIoDispatch && FastIoDispatch->FastIoQueryNetworkOpenInfo)
1255     {
1256         /* Forward the call onto the device we attached to */
1257         return FastIoDispatch->FastIoQueryNetworkOpenInfo(FileObject,
1258                                                           Wait,
1259                                                           Buffer,
1260                                                           IoStatus,
1261                                                           AttachedDeviceObject);
1262     }
1263 
1264     /* We failed to handle the request, send it down the slow path */
1265     FLT_ASSERT(FALSE);
1266     return FALSE;
1267 }
1268 
1269 CODE_SEG("PAGE")
1270 BOOLEAN
1271 NTAPI
1272 FltpFastIoMdlRead(_In_ PFILE_OBJECT FileObject,
1273                   _In_ PLARGE_INTEGER FileOffset,
1274                   _In_ ULONG Length,
1275                   _In_ ULONG LockKey,
1276                   _Out_ PMDL *MdlChain,
1277                   _Out_ PIO_STATUS_BLOCK IoStatus,
1278                   _In_ PDEVICE_OBJECT DeviceObject)
1279 {
1280     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1281     PDEVICE_OBJECT AttachedDeviceObject;
1282     PFAST_IO_DISPATCH FastIoDispatch;
1283 
1284     PAGED_CODE();
1285 
1286     /* If it doesn't have a device extension, then it's not our device object */
1287     if (DeviceObject->DeviceExtension == NULL)
1288     {
1289         /* Fail the call */
1290         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
1291         IoStatus->Information = 0;
1292         return TRUE;
1293     }
1294 
1295     DeviceExtension = DeviceObject->DeviceExtension;
1296     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1297 
1298     /* Get the device that we attached to */
1299     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1300     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1301 
1302     /* Make sure our FastIo table is valid */
1303     if (FastIoDispatch && FastIoDispatch->MdlRead)
1304     {
1305         /* Forward the call onto the device we attached to */
1306         return FastIoDispatch->MdlRead(FileObject,
1307                                        FileOffset,
1308                                        Length,
1309                                        LockKey,
1310                                        MdlChain,
1311                                        IoStatus,
1312                                        AttachedDeviceObject);
1313     }
1314 
1315     /* We failed to handle the request, send it down the slow path */
1316     FLT_ASSERT(FALSE);
1317     return FALSE;
1318 }
1319 
1320 CODE_SEG("PAGE")
1321 BOOLEAN
1322 NTAPI
1323 FltpFastIoMdlReadComplete(_In_ PFILE_OBJECT FileObject,
1324                           _In_ PMDL MdlChain,
1325                           _In_ PDEVICE_OBJECT DeviceObject)
1326 
1327 {
1328     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1329     PDEVICE_OBJECT AttachedDeviceObject;
1330     PFAST_IO_DISPATCH FastIoDispatch;
1331 
1332     PAGED_CODE();
1333 
1334     /* If it doesn't have a device extension, then it's not our device object */
1335     if (DeviceObject->DeviceExtension == NULL)
1336     {
1337         /* Fail the request, send it down the slow path */
1338         return FALSE;
1339     }
1340 
1341     DeviceExtension = DeviceObject->DeviceExtension;
1342     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1343 
1344     /* Get the device that we attached to */
1345     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1346     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1347 
1348     /* Make sure our FastIo table is valid */
1349     if (FastIoDispatch && FastIoDispatch->MdlReadComplete)
1350     {
1351         /* Forward the call onto the device we attached to */
1352         return FastIoDispatch->MdlReadComplete(FileObject,
1353                                                MdlChain,
1354                                                AttachedDeviceObject);
1355     }
1356 
1357     /* We failed to handle the request, send it down the slow path */
1358     FLT_ASSERT(FALSE);
1359     return FALSE;
1360 }
1361 
1362 CODE_SEG("PAGE")
1363 BOOLEAN
1364 NTAPI
1365 FltpFastIoPrepareMdlWrite(_In_ PFILE_OBJECT FileObject,
1366                           _In_ PLARGE_INTEGER FileOffset,
1367                           _In_ ULONG Length,
1368                           _In_ ULONG LockKey,
1369                           _Out_ PMDL *MdlChain,
1370                           _Out_ PIO_STATUS_BLOCK IoStatus,
1371                           _In_ PDEVICE_OBJECT DeviceObject)
1372 {
1373     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1374     PDEVICE_OBJECT AttachedDeviceObject;
1375     PFAST_IO_DISPATCH FastIoDispatch;
1376 
1377     PAGED_CODE();
1378 
1379     /* If it doesn't have a device extension, then it's not our device object */
1380     if (DeviceObject->DeviceExtension == NULL)
1381     {
1382         /* Fail the call */
1383         IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
1384         IoStatus->Information = 0;
1385         return TRUE;
1386     }
1387 
1388     DeviceExtension = DeviceObject->DeviceExtension;
1389     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1390 
1391     /* Get the device that we attached to */
1392     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1393     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1394 
1395     /* Make sure our FastIo table is valid */
1396     if (FastIoDispatch && FastIoDispatch->PrepareMdlWrite)
1397     {
1398         /* Forward the call onto the device we attached to */
1399         return FastIoDispatch->PrepareMdlWrite(FileObject,
1400                                                FileOffset,
1401                                                Length,
1402                                                LockKey,
1403                                                MdlChain,
1404                                                IoStatus,
1405                                                AttachedDeviceObject);
1406     }
1407 
1408     /* We failed to handle the request, send it down the slow path */
1409     FLT_ASSERT(FALSE);
1410     return FALSE;
1411 }
1412 
1413 CODE_SEG("PAGE")
1414 BOOLEAN
1415 NTAPI
1416 FltpFastIoMdlWriteComplete(_In_ PFILE_OBJECT FileObject,
1417                            _In_ PLARGE_INTEGER FileOffset,
1418                            _In_ PMDL MdlChain,
1419                            _In_ PDEVICE_OBJECT DeviceObject)
1420 {
1421     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1422     PDEVICE_OBJECT AttachedDeviceObject;
1423     PFAST_IO_DISPATCH FastIoDispatch;
1424 
1425     PAGED_CODE();
1426 
1427     /* If it doesn't have a device extension, then it's not our device object */
1428     if (DeviceObject->DeviceExtension == NULL)
1429     {
1430         /* Fail the request, send it down the slow path */
1431         return FALSE;
1432     }
1433 
1434     DeviceExtension = DeviceObject->DeviceExtension;
1435     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1436 
1437     /* Get the device that we attached to */
1438     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1439     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1440 
1441     /* Make sure our FastIo table is valid */
1442     if (FastIoDispatch && FastIoDispatch->MdlWriteComplete)
1443     {
1444         /* Forward the call onto the device we attached to */
1445         return FastIoDispatch->MdlWriteComplete(FileObject,
1446                                                FileOffset,
1447                                                MdlChain,
1448                                                AttachedDeviceObject);
1449     }
1450 
1451     /* We failed to handle the request, send it down the slow path */
1452     FLT_ASSERT(FALSE);
1453     return FALSE;
1454 }
1455 
1456 CODE_SEG("PAGE")
1457 BOOLEAN
1458 NTAPI
1459 FltpFastIoReadCompressed(_In_ PFILE_OBJECT FileObject,
1460                          _In_ PLARGE_INTEGER FileOffset,
1461                          _In_ ULONG Length,
1462                          _In_ ULONG LockKey,
1463                          _Out_ PVOID Buffer,
1464                          _Out_ PMDL *MdlChain,
1465                          _Out_ PIO_STATUS_BLOCK IoStatus,
1466                          _Out_ PCOMPRESSED_DATA_INFO CompressedDataInfo,
1467                          _In_ ULONG CompressedDataInfoLength,
1468                          _In_ PDEVICE_OBJECT DeviceObject)
1469 {
1470     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1471     PDEVICE_OBJECT AttachedDeviceObject;
1472     PFAST_IO_DISPATCH FastIoDispatch;
1473 
1474     PAGED_CODE();
1475 
1476     /* If it doesn't have a device extension, then it's not our device object */
1477     if (DeviceObject->DeviceExtension == NULL)
1478     {
1479         /* Fail the request, send it down the slow path */
1480         return FALSE;
1481     }
1482 
1483     DeviceExtension = DeviceObject->DeviceExtension;
1484     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1485 
1486     /* Get the device that we attached to */
1487     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1488     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1489 
1490     /* Make sure our FastIo table is valid */
1491     if (FastIoDispatch && FastIoDispatch->FastIoReadCompressed)
1492     {
1493         /* Forward the call onto the device we attached to */
1494         return FastIoDispatch->FastIoReadCompressed(FileObject,
1495                                                     FileOffset,
1496                                                     Length,
1497                                                     LockKey,
1498                                                     Buffer,
1499                                                     MdlChain,
1500                                                     IoStatus,
1501                                                     CompressedDataInfo,
1502                                                     CompressedDataInfoLength,
1503                                                     AttachedDeviceObject);
1504     }
1505 
1506     /* We failed to handle the request, send it down the slow path */
1507     FLT_ASSERT(FALSE);
1508     return FALSE;
1509 }
1510 
1511 CODE_SEG("PAGE")
1512 BOOLEAN
1513 NTAPI
1514 FltpFastIoWriteCompressed(_In_ PFILE_OBJECT FileObject,
1515                           _In_ PLARGE_INTEGER FileOffset,
1516                           _In_ ULONG Length,
1517                           _In_ ULONG LockKey,
1518                           _In_ PVOID Buffer,
1519                           _Out_ PMDL *MdlChain,
1520                           _Out_ PIO_STATUS_BLOCK IoStatus,
1521                           _In_ PCOMPRESSED_DATA_INFO CompressedDataInfo,
1522                           _In_ ULONG CompressedDataInfoLength,
1523                           _In_ PDEVICE_OBJECT DeviceObject)
1524 {
1525     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1526     PDEVICE_OBJECT AttachedDeviceObject;
1527     PFAST_IO_DISPATCH FastIoDispatch;
1528 
1529     PAGED_CODE();
1530 
1531     /* If it doesn't have a device extension, then it's not our device object */
1532     if (DeviceObject->DeviceExtension == NULL)
1533     {
1534         /* Fail the request, send it down the slow path */
1535         return FALSE;
1536     }
1537 
1538     DeviceExtension = DeviceObject->DeviceExtension;
1539     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1540 
1541     /* Get the device that we attached to */
1542     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1543     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1544 
1545     /* Make sure our FastIo table is valid */
1546     if (FastIoDispatch && FastIoDispatch->FastIoWriteCompressed)
1547     {
1548         /* Forward the call onto the device we attached to */
1549         return FastIoDispatch->FastIoWriteCompressed(FileObject,
1550                                                      FileOffset,
1551                                                      Length,
1552                                                      LockKey,
1553                                                      Buffer,
1554                                                      MdlChain,
1555                                                      IoStatus,
1556                                                      CompressedDataInfo,
1557                                                      CompressedDataInfoLength,
1558                                                      AttachedDeviceObject);
1559     }
1560 
1561     /* We failed to handle the request, send it down the slow path */
1562     FLT_ASSERT(FALSE);
1563     return FALSE;
1564 }
1565 
1566 CODE_SEG("PAGE")
1567 BOOLEAN
1568 NTAPI
1569 FltpFastIoMdlReadCompleteCompressed(_In_ PFILE_OBJECT FileObject,
1570                                     _In_ PMDL MdlChain,
1571                                     _In_ PDEVICE_OBJECT DeviceObject)
1572 {
1573     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1574     PDEVICE_OBJECT AttachedDeviceObject;
1575     PFAST_IO_DISPATCH FastIoDispatch;
1576 
1577     PAGED_CODE();
1578 
1579     /* If it doesn't have a device extension, then it's not our device object */
1580     if (DeviceObject->DeviceExtension == NULL)
1581     {
1582         return FALSE;
1583     }
1584 
1585     DeviceExtension = DeviceObject->DeviceExtension;
1586     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1587 
1588     /* Get the device that we attached to */
1589     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1590     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1591 
1592     /* Make sure our FastIo table is valid */
1593     if (FastIoDispatch && FastIoDispatch->MdlReadCompleteCompressed)
1594     {
1595         /* Forward the call onto the device we attached to */
1596         return FastIoDispatch->MdlReadCompleteCompressed(FileObject,
1597                                                          MdlChain,
1598                                                          AttachedDeviceObject);
1599     }
1600 
1601     /* We failed to handle the request, send it down the slow path */
1602     FLT_ASSERT(FALSE);
1603     return FALSE;
1604 }
1605 
1606 CODE_SEG("PAGE")
1607 BOOLEAN
1608 NTAPI
1609 FltpFastIoMdlWriteCompleteCompressed(_In_ PFILE_OBJECT FileObject,
1610                                      _In_ PLARGE_INTEGER FileOffset,
1611                                      _In_ PMDL MdlChain,
1612                                      _In_ PDEVICE_OBJECT DeviceObject)
1613 {
1614     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1615     PDEVICE_OBJECT AttachedDeviceObject;
1616     PFAST_IO_DISPATCH FastIoDispatch;
1617 
1618     PAGED_CODE();
1619 
1620     /* If it doesn't have a device extension, then it's not our device object */
1621     if (DeviceObject->DeviceExtension == NULL)
1622     {
1623         return FALSE;
1624     }
1625 
1626     DeviceExtension = DeviceObject->DeviceExtension;
1627     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1628 
1629     /* Get the device that we attached to */
1630     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1631     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1632 
1633     /* Make sure our FastIo table is valid */
1634     if (FastIoDispatch && FastIoDispatch->MdlWriteCompleteCompressed)
1635     {
1636         /* Forward the call onto the device we attached to */
1637         return FastIoDispatch->MdlWriteCompleteCompressed(FileObject,
1638                                                           FileOffset,
1639                                                           MdlChain,
1640                                                           AttachedDeviceObject);
1641     }
1642 
1643     /* We failed to handle the request, send it down the slow path */
1644     FLT_ASSERT(FALSE);
1645     return FALSE;
1646 }
1647 
1648 CODE_SEG("PAGE")
1649 BOOLEAN
1650 NTAPI
1651 FltpFastIoQueryOpen(_Inout_ PIRP Irp,
1652                     _Out_ PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
1653                     _In_ PDEVICE_OBJECT DeviceObject)
1654 {
1655     PFLTMGR_DEVICE_EXTENSION DeviceExtension;
1656     PDEVICE_OBJECT AttachedDeviceObject;
1657     PFAST_IO_DISPATCH FastIoDispatch;
1658     BOOLEAN Success;
1659 
1660     PAGED_CODE();
1661 
1662     /* If it doesn't have a device extension, then it's not our device object */
1663     if (DeviceObject->DeviceExtension == NULL)
1664     {
1665         return FALSE;
1666     }
1667 
1668     DeviceExtension = DeviceObject->DeviceExtension;
1669     FLT_ASSERT(DeviceExtension->AttachedToDeviceObject);
1670 
1671     /* Get the device that we attached to */
1672     AttachedDeviceObject = DeviceExtension->AttachedToDeviceObject;
1673     FastIoDispatch = AttachedDeviceObject->DriverObject->FastIoDispatch;
1674 
1675     /* Make sure our FastIo table is valid */
1676     if (FastIoDispatch && FastIoDispatch->FastIoQueryOpen)
1677     {
1678         PIO_STACK_LOCATION StackPtr = IoGetCurrentIrpStackLocation(Irp);
1679 
1680         /* Update the stack to contain the correct device for the next filter */
1681         StackPtr->DeviceObject = AttachedDeviceObject;
1682 
1683         /* Now forward the call */
1684         Success = FastIoDispatch->FastIoQueryOpen(Irp,
1685                                                   NetworkInformation,
1686                                                   AttachedDeviceObject);
1687 
1688         /* Restore the DeviceObject as we found it */
1689         StackPtr->DeviceObject = DeviceObject;
1690         return Success;
1691     }
1692 
1693     /* We failed to handle the request, send it down the slow path */
1694     FLT_ASSERT(FALSE);
1695     return FALSE;
1696 }
1697 
1698 CODE_SEG("PAGE")
1699 DRIVER_FS_NOTIFICATION FltpFsNotification;
1700 
1701 CODE_SEG("PAGE")
1702 VOID
1703 NTAPI
1704 FltpFsNotification(_In_ PDEVICE_OBJECT DeviceObject,
1705                    _In_ BOOLEAN FsActive)
1706 {
1707     UNICODE_STRING DeviceName;
1708     NTSTATUS Status;
1709 
1710     PAGED_CODE();
1711 
1712     /* Set an empty string */
1713     RtlInitUnicodeString(&DeviceName, NULL);
1714 
1715     /* Get the name of the lowest device object on the stack */
1716     Status = FltpGetBaseDeviceObjectName(DeviceObject, &DeviceName);
1717     if (NT_SUCCESS(Status))
1718     {
1719         /* Check if it's attaching or detaching */
1720         if (FsActive)
1721         {
1722             /* Run the attach routine */
1723             FltpAttachToFileSystemDevice(DeviceObject, &DeviceName);
1724         }
1725         else
1726         {
1727             /* Run the detach routine */
1728             FltpDetachFromFileSystemDevice(DeviceObject);
1729         }
1730 
1731         /* Free the buffer which FltpGetBaseDeviceObjectName allocated */
1732         FltpFreeUnicodeString(&DeviceName);
1733     }
1734 }
1735 
1736 static
1737 CODE_SEG("INIT")
1738 NTSTATUS
1739 SetupDispatchAndCallbacksTables(_In_ PDRIVER_OBJECT DriverObject)
1740 {
1741     PFAST_IO_DISPATCH FastIoDispatch;
1742     FS_FILTER_CALLBACKS Callbacks;
1743     ULONG i;
1744 
1745     /* Plug all the IRPs */
1746     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1747     {
1748         DriverObject->MajorFunction[i] = FltpDispatch;
1749     }
1750 
1751     /* Override the ones we're interested in */
1752     DriverObject->MajorFunction[IRP_MJ_CREATE] = FltpCreate;
1753     DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = FltpCreate;
1754     DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = FltpCreate;
1755     DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FltpFsControl;
1756     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FltpDeviceControl;
1757 
1758     /* The FastIo dispatch table is stored in the pool along with a tag */
1759     FastIoDispatch = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_IO_DISPATCH), FM_TAG_DISPATCH_TABLE);
1760     if (FastIoDispatch == NULL) return STATUS_INSUFFICIENT_RESOURCES;
1761 
1762     /* Fill out the FastIo table  */
1763     RtlZeroMemory(FastIoDispatch, sizeof(FAST_IO_DISPATCH));
1764     FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
1765     FastIoDispatch->FastIoCheckIfPossible = FltpFastIoCheckIfPossible;
1766     FastIoDispatch->FastIoRead = FltpFastIoRead;
1767     FastIoDispatch->FastIoWrite = FltpFastIoWrite;
1768     FastIoDispatch->FastIoQueryBasicInfo = FltpFastIoQueryBasicInfo;
1769     FastIoDispatch->FastIoQueryStandardInfo = FltpFastIoQueryStandardInfo;
1770     FastIoDispatch->FastIoLock = FltpFastIoLock;
1771     FastIoDispatch->FastIoUnlockSingle = FltpFastIoUnlockSingle;
1772     FastIoDispatch->FastIoUnlockAll = FltpFastIoUnlockAll;
1773     FastIoDispatch->FastIoUnlockAllByKey = FltpFastIoUnlockAllByKey;
1774     FastIoDispatch->FastIoDeviceControl = FltpFastIoDeviceControl;
1775     FastIoDispatch->FastIoDetachDevice = FltpFastIoDetachDevice;
1776     FastIoDispatch->FastIoQueryNetworkOpenInfo = FltpFastIoQueryNetworkOpenInfo;
1777     FastIoDispatch->MdlRead = FltpFastIoMdlRead;
1778     FastIoDispatch->MdlReadComplete = FltpFastIoMdlReadComplete;
1779     FastIoDispatch->PrepareMdlWrite = FltpFastIoPrepareMdlWrite;
1780     FastIoDispatch->MdlWriteComplete = FltpFastIoMdlWriteComplete;
1781     FastIoDispatch->FastIoReadCompressed = FltpFastIoReadCompressed;
1782     FastIoDispatch->FastIoWriteCompressed = FltpFastIoWriteCompressed;
1783     FastIoDispatch->MdlReadCompleteCompressed = FltpFastIoMdlReadCompleteCompressed;
1784     FastIoDispatch->MdlWriteCompleteCompressed = FltpFastIoMdlWriteCompleteCompressed;
1785     FastIoDispatch->FastIoQueryOpen = FltpFastIoQueryOpen;
1786 
1787     /* Store the FastIo table for internal and our access */
1788     DriverObject->FastIoDispatch = FastIoDispatch;
1789     DriverData.FastIoDispatch = FastIoDispatch;
1790 
1791     /* Initialize the callback table */
1792     Callbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
1793     Callbacks.PreAcquireForSectionSynchronization = FltpPreFsFilterOperation;
1794     Callbacks.PostAcquireForSectionSynchronization = FltpPostFsFilterOperation;
1795     Callbacks.PreReleaseForSectionSynchronization = FltpPreFsFilterOperation;
1796     Callbacks.PostReleaseForSectionSynchronization = FltpPostFsFilterOperation;
1797     Callbacks.PreAcquireForCcFlush = FltpPreFsFilterOperation;
1798     Callbacks.PostAcquireForCcFlush = FltpPostFsFilterOperation;
1799     Callbacks.PreReleaseForCcFlush = FltpPreFsFilterOperation;
1800     Callbacks.PostReleaseForCcFlush = FltpPostFsFilterOperation;
1801     Callbacks.PreAcquireForModifiedPageWriter = FltpPreFsFilterOperation;
1802     Callbacks.PostAcquireForModifiedPageWriter = FltpPostFsFilterOperation;
1803     Callbacks.PreReleaseForModifiedPageWriter = FltpPreFsFilterOperation;
1804     Callbacks.PostReleaseForModifiedPageWriter = FltpPostFsFilterOperation;
1805 
1806     /* Register our callbacks */
1807     return FsRtlRegisterFileSystemFilterCallbacks(DriverObject, &Callbacks);
1808 }
1809 
1810 CODE_SEG("INIT") DRIVER_INITIALIZE DriverEntry;
1811 
1812 CODE_SEG("INIT")
1813 NTSTATUS
1814 NTAPI
1815 DriverEntry(_In_ PDRIVER_OBJECT DriverObject,
1816             _In_ PUNICODE_STRING RegistryPath)
1817 {
1818     UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\FileSystem\\Filters\\"DRIVER_NAME);
1819     PDEVICE_OBJECT RawDeviceObject;
1820     PDEVICE_OBJECT DeviceObject;
1821     PFILE_OBJECT RawFileObject;
1822     UNICODE_STRING ObjectName;
1823     UNICODE_STRING SymLink;
1824 
1825     NTSTATUS Status;
1826 
1827     RtlZeroMemory(&DriverData, sizeof(DRIVER_DATA));
1828     DriverData.DriverObject = DriverObject;
1829 
1830     /* Save the registry key for this driver */
1831     DriverData.ServiceKey.Length = RegistryPath->Length;
1832     DriverData.ServiceKey.MaximumLength = RegistryPath->MaximumLength;
1833     DriverData.ServiceKey.Buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool,
1834                                                                  RegistryPath->MaximumLength,
1835                                                                  FM_TAG_REGISTRY_DATA);
1836     if (!DriverData.ServiceKey.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
1837     RtlCopyUnicodeString(&DriverData.ServiceKey, RegistryPath);
1838 
1839     /* Do some initialization */
1840     ExInitializeFastMutex(&DriverData.FilterAttachLock);
1841 
1842     /* Create the main filter manager device object */
1843     Status = IoCreateDevice(DriverObject,
1844                             0,
1845                             &DeviceName,
1846                             FILE_DEVICE_DISK_FILE_SYSTEM,
1847                             FILE_DEVICE_SECURE_OPEN,
1848                             FALSE,
1849                             &DeviceObject);
1850     if (!NT_SUCCESS(Status))
1851     {
1852         DPRINT1("fltmgr IoCreateDevice failed.  Status = %X\n", Status);
1853         goto Cleanup;
1854     }
1855 
1856     /* Store a global reference so we can access from callbacks */
1857     DriverData.DeviceObject = DeviceObject;
1858 
1859     /* Generate the symbolic link name */
1860     RtlInitUnicodeString(&SymLink, L"\\??\\"DRIVER_NAME);
1861     Status = IoCreateSymbolicLink(&SymLink, &DeviceName);
1862     if (!NT_SUCCESS(Status)) goto Cleanup;
1863 
1864     /* Create the callbacks for the dispatch table, FastIo and FS callbacks */
1865     Status = SetupDispatchAndCallbacksTables(DriverObject);
1866     if (!NT_SUCCESS(Status)) goto Cleanup;
1867 
1868     /* Initialize the comms objects */
1869     Status = FltpSetupCommunicationObjects(DriverObject);
1870     if (!NT_SUCCESS(Status)) goto Cleanup;
1871 
1872     /* Register for notifications when a new file system is loaded. This also enumerates any existing file systems */
1873     Status = IoRegisterFsRegistrationChange(DriverObject, FltpFsNotification);
1874     FLT_ASSERT(Status != STATUS_DEVICE_ALREADY_ATTACHED); // Windows checks for this, I'm not sure how it can happen. Needs investigation??
1875     if (!NT_SUCCESS(Status))  goto Cleanup;
1876 
1877     InitializeListHead(&FilterList);
1878     ExInitializeResourceLite(&FilterListLock);
1879 
1880     /* IoRegisterFsRegistrationChange isn't notified about the raw  file systems, so we attach to them manually */
1881     RtlInitUnicodeString(&ObjectName, L"\\Device\\RawDisk");
1882     Status = IoGetDeviceObjectPointer(&ObjectName,
1883                                       FILE_READ_ATTRIBUTES,
1884                                       &RawFileObject,
1885                                       &RawDeviceObject);
1886     if (NT_SUCCESS(Status))
1887     {
1888         FltpFsNotification(RawDeviceObject, TRUE);
1889         ObDereferenceObject(RawFileObject);
1890     }
1891 
1892     RtlInitUnicodeString(&ObjectName, L"\\Device\\RawCdRom");
1893     Status = IoGetDeviceObjectPointer(&ObjectName,
1894                                       FILE_READ_ATTRIBUTES,
1895                                       &RawFileObject,
1896                                       &RawDeviceObject);
1897     if (NT_SUCCESS(Status))
1898     {
1899         FltpFsNotification(RawDeviceObject, TRUE);
1900         ObDereferenceObject(RawFileObject);
1901     }
1902 
1903     /* We're done, clear the initializing flag */
1904     ClearFlag(DeviceObject->Flags, DO_DEVICE_INITIALIZING);
1905     Status = STATUS_SUCCESS;
1906 
1907 Cleanup:
1908 
1909     if (!NT_SUCCESS(Status))
1910     {
1911         if (DriverData.FastIoDispatch)
1912         {
1913             DriverObject->FastIoDispatch = NULL;
1914             ExFreePoolWithTag(DriverData.FastIoDispatch, FM_TAG_DISPATCH_TABLE);
1915         }
1916 
1917         IoDeleteSymbolicLink(&SymLink);
1918 
1919         if (DeviceObject)
1920             IoDeleteDevice(DeviceObject);
1921 
1922         if (DriverData.ServiceKey.Buffer)
1923             ExFreePoolWithTag(DriverData.ServiceKey.Buffer, FM_TAG_REGISTRY_DATA);
1924     }
1925 
1926     return Status;
1927 }
1928