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