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