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