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