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