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