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