2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/volume.c
5 * PURPOSE: Volume and File System I/O Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES *****************************************************************/
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, IoInitFileSystemImplementation)
19 #pragma alloc_text(INIT, IoInitVpbImplementation)
22 /* GLOBALS ******************************************************************/
24 ERESOURCE FileSystemListLock
;
25 LIST_ENTRY IopDiskFsListHead
, IopNetworkFsListHead
;
26 LIST_ENTRY IopCdRomFsListHead
, IopTapeFsListHead
;
27 KGUARDED_MUTEX FsChangeNotifyListLock
;
28 LIST_ENTRY FsChangeNotifyListHead
;
30 /* PRIVATE FUNCTIONS *********************************************************/
34 IopCheckVpbMounted(IN POPEN_PACKET OpenPacket
,
35 IN PDEVICE_OBJECT DeviceObject
,
36 IN PUNICODE_STRING RemainingName
,
39 BOOLEAN Alertable
, Raw
;
44 IoAcquireVpbSpinLock(&OldIrql
);
46 /* Set VPB mount settings */
47 Raw
= !RemainingName
->Length
&& !OpenPacket
->RelatedFileObject
;
48 Alertable
= (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
) ?
51 /* Start looping until the VPB is mounted */
52 while (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
54 /* Release the lock */
55 IoReleaseVpbSpinLock(OldIrql
);
57 /* Mount the volume */
58 *Status
= IopMountVolume(DeviceObject
,
64 /* Check if we failed or if we were alerted */
65 if (!(NT_SUCCESS(*Status
)) ||
66 (*Status
== STATUS_USER_APC
) ||
67 (*Status
== STATUS_ALERTED
))
69 /* Dereference the device, since IopParseDevice referenced it */
70 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
72 /* Check if it was a total failure */
73 if (!NT_SUCCESS(*Status
)) return NULL
;
75 /* Otherwise we were alerted */
76 *Status
= STATUS_WRONG_VOLUME
;
80 /* Re-acquire the lock */
81 IoAcquireVpbSpinLock(&OldIrql
);
84 /* Make sure the VPB isn't locked */
85 Vpb
= DeviceObject
->Vpb
;
86 if (Vpb
->Flags
& VPB_LOCKED
)
88 /* We're locked, so fail */
89 *Status
= STATUS_ACCESS_DENIED
;
94 /* Success! Reference the VPB */
95 Vpb
->ReferenceCount
++;
98 /* Release the lock and return the VPB */
99 IoReleaseVpbSpinLock(OldIrql
);
105 IopCreateVpb(IN PDEVICE_OBJECT DeviceObject
)
109 /* Allocate the Vpb */
110 Vpb
= ExAllocatePoolWithTag(NonPagedPool
,
113 if (!Vpb
) return STATUS_UNSUCCESSFUL
;
115 /* Clear it so we don't waste time manually */
116 RtlZeroMemory(Vpb
, sizeof(VPB
));
118 /* Set the Header and Device Field */
119 Vpb
->Type
= IO_TYPE_VPB
;
120 Vpb
->Size
= sizeof(VPB
);
121 Vpb
->RealDevice
= DeviceObject
;
123 /* Link it to the Device Object */
124 DeviceObject
->Vpb
= Vpb
;
125 return STATUS_SUCCESS
;
130 IopDereferenceVpb(IN PVPB Vpb
)
134 /* Lock the VPBs and decrease references */
135 IoAcquireVpbSpinLock(&OldIrql
);
136 Vpb
->ReferenceCount
--;
138 /* Check if we're out of references */
139 if (!Vpb
->ReferenceCount
)
141 /* FIXME: IMPLEMENT CLEANUP! */
145 /* Release VPB lock */
146 IoReleaseVpbSpinLock(OldIrql
);
151 IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject
,
152 OUT PDEVICE_OBJECT
*FileSystemObject
,
157 BOOLEAN Result
= FALSE
;
159 /* Lock the VPBs and assume failure */
160 IoAcquireVpbSpinLock(&OldIrql
);
162 *FileSystemObject
= NULL
;
164 /* Get the VPB and make sure it's mounted */
165 LocalVpb
= DeviceObject
->Vpb
;
166 if ((LocalVpb
) && (LocalVpb
->Flags
& VPB_MOUNTED
))
170 *FileSystemObject
= LocalVpb
->DeviceObject
;
173 LocalVpb
->ReferenceCount
++;
177 /* Release the VPB lock and return status */
178 IoReleaseVpbSpinLock(OldIrql
);
184 IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject
,
185 IN PDEVICE_OBJECT AttachedDeviceObject
,
192 IoAcquireVpbSpinLock(&OldIrql
);
193 Vpb
= DeviceObject
->Vpb
;
195 /* Set the VPB as mounted and possibly raw */
196 Vpb
->Flags
|= VPB_MOUNTED
| (Raw
? VPB_RAW_MOUNT
: 0);
198 /* Set the stack size */
199 Vpb
->DeviceObject
->StackSize
= AttachedDeviceObject
->StackSize
;
201 /* Add one for the FS Driver */
202 Vpb
->DeviceObject
->StackSize
++;
204 /* Set the VPB in the device extension */
205 IoGetDevObjExtension(Vpb
->DeviceObject
)->Vpb
= Vpb
;
208 Vpb
->ReferenceCount
++;
210 /* Release the VPB lock and return it */
211 IoReleaseVpbSpinLock(OldIrql
);
217 IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject
,
218 IN BOOLEAN DriverActive
)
220 PFS_CHANGE_NOTIFY_ENTRY ChangeEntry
;
221 PLIST_ENTRY ListEntry
;
223 /* Acquire the notification lock */
224 KeAcquireGuardedMutex(&FsChangeNotifyListLock
);
227 ListEntry
= FsChangeNotifyListHead
.Flink
;
228 while (ListEntry
!= &FsChangeNotifyListHead
)
231 ChangeEntry
= CONTAINING_RECORD(ListEntry
,
232 FS_CHANGE_NOTIFY_ENTRY
,
235 /* Call the notification procedure */
236 ChangeEntry
->FSDNotificationProc(DeviceObject
, DriverActive
);
238 /* Go to the next entry */
239 ListEntry
= ListEntry
->Flink
;
242 /* Release the lock */
243 KeReleaseGuardedMutex(&FsChangeNotifyListLock
);
248 IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead
)
250 PLIST_ENTRY ListEntry
;
251 PDEVICE_OBJECT DeviceObject
;
252 IO_STATUS_BLOCK StatusBlock
;
257 /* Lock the FS List and initialize an event to wait on */
258 KeEnterCriticalRegion();
259 ExAcquireResourceSharedLite(&FileSystemListLock
,TRUE
);
260 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
262 /* Get the first entry and start looping */
263 ListEntry
= ListHead
->Flink
;
264 while (ListEntry
!= ListHead
)
266 /* Get the device object */
267 DeviceObject
= CONTAINING_RECORD(ListEntry
,
271 /* Check if we're attached */
272 if (DeviceObject
->AttachedDevice
)
274 /* Get the attached device */
275 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
278 /* Build the shutdown IRP and call the driver */
279 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
286 Status
= IoCallDriver(DeviceObject
, Irp
);
287 if (Status
== STATUS_PENDING
)
289 /* Wait on the driver */
290 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
293 /* Reset the event */
294 KeClearEvent(&Event
);
296 /* Go to the next entry */
297 ListEntry
= ListEntry
->Flink
;
300 /* Release the lock */
301 ExReleaseResourceLite(&FileSystemListLock
);
302 KeLeaveCriticalRegion();
307 IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject
)
309 IO_STATUS_BLOCK IoStatusBlock
;
310 PIO_STACK_LOCATION StackPtr
;
314 PDEVICE_OBJECT AttachedDeviceObject
= DeviceObject
;
317 /* Loop as long as we're attached */
318 while (AttachedDeviceObject
->AttachedDevice
)
320 /* Get the attached device object */
321 AttachedDeviceObject
= AttachedDeviceObject
->AttachedDevice
;
324 /* Initialize the event and build the IRP */
325 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
326 Irp
= IoBuildDeviceIoControlRequest(IRP_MJ_DEVICE_CONTROL
,
327 AttachedDeviceObject
,
337 /* Set the major and minor functions */
338 StackPtr
= IoGetNextIrpStackLocation(Irp
);
339 StackPtr
->MajorFunction
= IRP_MJ_FILE_SYSTEM_CONTROL
;
340 StackPtr
->MinorFunction
= IRP_MN_LOAD_FILE_SYSTEM
;
342 /* Call the driver */
343 Status
= IoCallDriver(AttachedDeviceObject
, Irp
);
344 if (Status
== STATUS_PENDING
)
347 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
354 IopMountVolume(IN PDEVICE_OBJECT DeviceObject
,
355 IN BOOLEAN AllowRawMount
,
356 IN BOOLEAN DeviceIsLocked
,
357 IN BOOLEAN Alertable
,
362 IO_STATUS_BLOCK IoStatusBlock
;
364 PIO_STACK_LOCATION StackPtr
;
365 PLIST_ENTRY FsList
, ListEntry
;
366 LIST_ENTRY LocalList
;
367 PDEVICE_OBJECT AttachedDeviceObject
= DeviceObject
;
368 PDEVICE_OBJECT FileSystemDeviceObject
, ParentFsDeviceObject
;
369 ULONG FsStackOverhead
;
372 /* Check if the device isn't already locked */
375 /* Lock it ourselves */
376 Status
= KeWaitForSingleObject(&DeviceObject
->DeviceLock
,
381 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
383 /* Don't mount if we were interrupted */
388 /* Acquire the FS Lock*/
389 KeEnterCriticalRegion();
390 ExAcquireResourceSharedLite(&FileSystemListLock
, TRUE
);
392 /* Make sure we weren't already mounted */
393 if (!(DeviceObject
->Vpb
->Flags
& (VPB_MOUNTED
| VPB_REMOVE_PENDING
)))
395 /* Initialize the event to wait on */
396 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
398 /* Remove the verify flag and get the actual device to mount */
399 DeviceObject
->Flags
&= ~DO_VERIFY_VOLUME
;
400 while (AttachedDeviceObject
->AttachedDevice
)
402 /* Get the next one */
403 AttachedDeviceObject
= AttachedDeviceObject
->AttachedDevice
;
407 ObReferenceObject(AttachedDeviceObject
);
409 /* For a mount operation, this can only be a Disk, CD-ROM or tape */
410 if ((DeviceObject
->DeviceType
== FILE_DEVICE_DISK
) ||
411 (DeviceObject
->DeviceType
== FILE_DEVICE_VIRTUAL_DISK
))
413 /* Use the disk list */
414 FsList
= &IopDiskFsListHead
;
416 else if (DeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
)
418 /* Use the CD-ROM list */
419 FsList
= &IopCdRomFsListHead
;
423 /* It's gotta be a tape... */
424 FsList
= &IopTapeFsListHead
;
427 /* Now loop the fs list until one of the file systems accepts us */
428 Status
= STATUS_UNSUCCESSFUL
;
429 ListEntry
= FsList
->Flink
;
430 while ((ListEntry
!= FsList
) && !(NT_SUCCESS(Status
)))
433 * If we're not allowed to mount this volume and this is our last
434 * (but not only) chance to mount it...
436 if (!(AllowRawMount
) &&
437 (ListEntry
->Flink
== FsList
) &&
438 (ListEntry
!= FsList
->Flink
))
440 /* Then fail this mount request */
445 * Also check if this is a raw mount and there are other file
446 * systems on the list.
448 if ((DeviceObject
->Vpb
->Flags
& VPB_RAW_MOUNT
) &&
449 (ListEntry
->Flink
!= FsList
))
451 /* Then skip this entry */
455 /* Get the Device Object for this FS */
456 FileSystemDeviceObject
= CONTAINING_RECORD(ListEntry
,
459 ParentFsDeviceObject
= FileSystemDeviceObject
;
462 * If this file system device is attached to some other device,
463 * then we must make sure to increase the stack size for the IRP.
464 * The default is +1, for the FS device itself.
467 while (FileSystemDeviceObject
->AttachedDevice
)
469 /* Get the next attached device and increase overhead */
470 FileSystemDeviceObject
= FileSystemDeviceObject
->
475 /* Clear the event */
476 KeClearEvent(&Event
);
478 /* Allocate the IRP */
479 Irp
= IoAllocateIrp(AttachedDeviceObject
->StackSize
+
480 (UCHAR
)FsStackOverhead
,
485 Status
= STATUS_INSUFFICIENT_RESOURCES
;
490 Irp
->UserIosb
= &IoStatusBlock
;
491 Irp
->UserEvent
= &Event
;
492 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
493 Irp
->Flags
= IRP_MOUNT_COMPLETION
| IRP_SYNCHRONOUS_PAGING_IO
;
494 Irp
->RequestorMode
= KernelMode
;
496 /* Get the I/O Stack location and set it up */
497 StackPtr
= IoGetNextIrpStackLocation(Irp
);
498 StackPtr
->MajorFunction
= IRP_MJ_FILE_SYSTEM_CONTROL
;
499 StackPtr
->MinorFunction
= IRP_MN_MOUNT_VOLUME
;
500 StackPtr
->Flags
= AllowRawMount
;
501 StackPtr
->Parameters
.MountVolume
.Vpb
= DeviceObject
->Vpb
;
502 StackPtr
->Parameters
.MountVolume
.DeviceObject
=
503 AttachedDeviceObject
;
505 /* Call the driver */
506 Status
= IoCallDriver(FileSystemDeviceObject
, Irp
);
507 if (Status
== STATUS_PENDING
)
510 KeWaitForSingleObject(&Event
,
515 Status
= IoStatusBlock
.Status
;
518 /* Check if mounting was successful */
519 if (NT_SUCCESS(Status
))
522 *Vpb
= IopInitializeVpbForMount(DeviceObject
,
523 AttachedDeviceObject
,
524 (DeviceObject
->Vpb
->Flags
&
529 /* Check if we failed because of the user */
530 if ((IoIsErrorUserInduced(Status
)) &&
531 (IoStatusBlock
.Information
== 1))
533 /* Break out and fail */
537 /* Otherwise, check if we need to load the FS driver */
538 if (Status
== STATUS_FS_DRIVER_REQUIRED
)
540 /* We need to release the lock */
541 ExReleaseResourceLite(&FileSystemListLock
);
543 /* Release the device lock if we're holding it */
546 KeSetEvent(&DeviceObject
->DeviceLock
, 0, FALSE
);
550 IopLoadFileSystem(ParentFsDeviceObject
);
552 /* Check if the device isn't already locked */
555 /* Lock it ourselves */
556 Status
= KeWaitForSingleObject(&DeviceObject
->
562 if ((Status
== STATUS_ALERTED
) ||
563 (Status
== STATUS_USER_APC
))
565 /* Don't mount if we were interrupted */
566 ObDereferenceObject(AttachedDeviceObject
);
571 /* Reacquire the lock */
572 ExAcquireResourceSharedLite(&FileSystemListLock
, TRUE
);
574 /* When we released the lock, make sure nobody beat us */
575 if (DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
)
577 /* Someone did, break out */
578 Status
= STATUS_SUCCESS
;
582 /* Start over by setting a failure */
583 Status
= STATUS_UNRECOGNIZED_VOLUME
;
585 /* We need to setup a local list to pickup where we left */
586 LocalList
.Flink
= FsList
->Flink
;
587 ListEntry
= &LocalList
;
591 * Check if we failed with any other error then an unrecognized
592 * volume, and if this request doesn't allow mounting the raw
595 if (!(AllowRawMount
) &&
596 (Status
!= STATUS_UNRECOGNIZED_VOLUME
) &&
597 (FsRtlIsTotalDeviceFailure(Status
)))
599 /* Break out and give up */
604 /* Go to the next FS entry */
605 ListEntry
= ListEntry
->Flink
;
608 /* Dereference the device if we failed */
609 if (!NT_SUCCESS(Status
)) ObDereferenceObject(AttachedDeviceObject
);
611 else if (DeviceObject
->Vpb
->Flags
& VPB_REMOVE_PENDING
)
613 /* Someone wants to remove us */
614 Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
618 /* Someone already mounted us */
619 Status
= STATUS_SUCCESS
;
622 /* Release the FS lock */
623 ExReleaseResourceLite(&FileSystemListLock
);
624 KeLeaveCriticalRegion();
626 /* Release the device lock if we're holding it */
627 if (!DeviceIsLocked
) KeSetEvent(&DeviceObject
->DeviceLock
, 0, FALSE
);
629 /* Check if we failed to mount the boot partition */
630 if ((!NT_SUCCESS(Status
)) &&
631 (DeviceObject
->Flags
& DO_SYSTEM_BOOT_PARTITION
))
633 /* Bugcheck the system */
634 KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE
,
635 (ULONG_PTR
)DeviceObject
,
641 /* Return the mount status */
645 /* PUBLIC FUNCTIONS **********************************************************/
652 IoEnumerateRegisteredFiltersList(IN PDRIVER_OBJECT
*DriverObjectList
,
653 IN ULONG DriverObjectListSize
,
654 OUT PULONG ActualNumberDriverObjects
)
657 return STATUS_UNSUCCESSFUL
;
665 IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject
,
666 IN BOOLEAN AllowRawMount
)
668 IO_STATUS_BLOCK IoStatusBlock
;
669 PIO_STACK_LOCATION StackPtr
;
672 NTSTATUS Status
= STATUS_SUCCESS
, VpbStatus
;
673 PDEVICE_OBJECT FileSystemDeviceObject
;
675 BOOLEAN WasNotMounted
= TRUE
;
677 /* Wait on the device lock */
678 KeWaitForSingleObject(&DeviceObject
->DeviceLock
,
684 /* Reference the VPB */
685 if (IopReferenceVpbForVerify(DeviceObject
, &FileSystemDeviceObject
, &Vpb
))
687 /* Initialize the event */
688 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
690 /* Find the actual File System DO */
691 WasNotMounted
= FALSE
;
692 FileSystemDeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
693 while (FileSystemDeviceObject
->AttachedDevice
)
695 /* Go to the next one */
696 FileSystemDeviceObject
= FileSystemDeviceObject
->AttachedDevice
;
699 /* Allocate the IRP */
700 Irp
= IoAllocateIrp(FileSystemDeviceObject
->StackSize
, FALSE
);
701 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
704 Irp
->UserIosb
= &IoStatusBlock
;
705 Irp
->UserEvent
= &Event
;
706 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
707 Irp
->Flags
= IRP_MOUNT_COMPLETION
| IRP_SYNCHRONOUS_PAGING_IO
;
708 Irp
->RequestorMode
= KernelMode
;
710 /* Get the I/O Stack location and set it */
711 StackPtr
= IoGetNextIrpStackLocation(Irp
);
712 StackPtr
->MajorFunction
= IRP_MJ_FILE_SYSTEM_CONTROL
;
713 StackPtr
->MinorFunction
= IRP_MN_VERIFY_VOLUME
;
714 StackPtr
->Flags
= AllowRawMount
? SL_ALLOW_RAW_MOUNT
: 0;
715 StackPtr
->Parameters
.VerifyVolume
.Vpb
= Vpb
;
716 StackPtr
->Parameters
.VerifyVolume
.DeviceObject
=
717 DeviceObject
->Vpb
->DeviceObject
;
719 /* Call the driver */
720 Status
= IoCallDriver(FileSystemDeviceObject
, Irp
);
721 if (Status
== STATUS_PENDING
)
724 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
725 Status
= IoStatusBlock
.Status
;
728 /* Dereference the VPB */
729 IopDereferenceVpb(Vpb
);
732 /* Check if we had the wrong volume or didn't mount at all */
733 if ((Status
== STATUS_WRONG_VOLUME
) || (WasNotMounted
))
736 VpbStatus
= IopCreateVpb(DeviceObject
);
737 if (NT_SUCCESS(VpbStatus
))
740 VpbStatus
= IopMountVolume(DeviceObject
,
747 /* If we failed, remove the verify flag */
748 if (!NT_SUCCESS(VpbStatus
)) DeviceObject
->Flags
&= ~DO_VERIFY_VOLUME
;
751 /* Signal the device lock and return */
752 KeSetEvent(&DeviceObject
->DeviceLock
, IO_NO_INCREMENT
, FALSE
);
761 IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject
)
763 PLIST_ENTRY FsList
= NULL
;
766 /* Acquire the FS lock */
767 KeEnterCriticalRegion();
768 ExAcquireResourceExclusiveLite(&FileSystemListLock
, TRUE
);
770 /* Check what kind of FS this is */
771 if (DeviceObject
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
)
773 /* Use the disk list */
774 FsList
= &IopDiskFsListHead
;
776 else if (DeviceObject
->DeviceType
== FILE_DEVICE_NETWORK_FILE_SYSTEM
)
778 /* Use the network device list */
779 FsList
= &IopNetworkFsListHead
;
781 else if (DeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)
783 /* Use the CD-ROM list */
784 FsList
= &IopCdRomFsListHead
;
786 else if (DeviceObject
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
)
788 /* Use the tape list */
789 FsList
= &IopTapeFsListHead
;
792 /* Make sure that we have a valid list */
795 /* Check if we should insert it at the top or bottom of the list */
796 if (DeviceObject
->Flags
& DO_LOW_PRIORITY_FILESYSTEM
)
799 InsertTailList(FsList
->Blink
, &DeviceObject
->Queue
.ListEntry
);
804 InsertHeadList(FsList
, &DeviceObject
->Queue
.ListEntry
);
808 /* Clear the initializing flag */
809 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
811 /* Release the FS Lock */
812 ExReleaseResourceLite(&FileSystemListLock
);
813 KeLeaveCriticalRegion();
815 /* Notify file systems of the addition */
816 IopNotifyFileSystemChange(DeviceObject
, TRUE
);
824 IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject
)
828 /* Acquire the FS lock */
829 KeEnterCriticalRegion();
830 ExAcquireResourceExclusiveLite(&FileSystemListLock
, TRUE
);
832 /* Simply remove the entry */
833 RemoveEntryList(&DeviceObject
->Queue
.ListEntry
);
835 /* And notify all registered file systems */
836 IopNotifyFileSystemChange(DeviceObject
, FALSE
);
838 /* Then release the lock */
839 ExReleaseResourceLite(&FileSystemListLock
);
840 KeLeaveCriticalRegion();
848 IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject
,
849 IN PDRIVER_FS_NOTIFICATION FSDNotificationProc
)
851 PFS_CHANGE_NOTIFY_ENTRY Entry
;
854 /* Allocate a notification entry */
855 Entry
= ExAllocatePoolWithTag(PagedPool
,
856 sizeof(FS_CHANGE_NOTIFY_ENTRY
),
857 TAG_FS_CHANGE_NOTIFY
);
858 if (!Entry
) return(STATUS_INSUFFICIENT_RESOURCES
);
860 /* Save the driver object and notification routine */
861 Entry
->DriverObject
= DriverObject
;
862 Entry
->FSDNotificationProc
= FSDNotificationProc
;
864 /* Insert it into the notification list */
865 KeAcquireGuardedMutex(&FsChangeNotifyListLock
);
866 InsertTailList(&FsChangeNotifyListHead
, &Entry
->FsChangeNotifyList
);
867 KeReleaseGuardedMutex(&FsChangeNotifyListLock
);
869 /* Reference the driver */
870 ObReferenceObject(DriverObject
);
871 return STATUS_SUCCESS
;
879 IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject
,
880 IN PDRIVER_FS_NOTIFICATION FSDNotificationProc
)
882 PFS_CHANGE_NOTIFY_ENTRY ChangeEntry
;
883 PLIST_ENTRY NextEntry
;
886 /* Acquire the list lock */
887 KeAcquireGuardedMutex(&FsChangeNotifyListLock
);
890 NextEntry
= FsChangeNotifyListHead
.Flink
;
891 while (NextEntry
!= &FsChangeNotifyListHead
)
894 ChangeEntry
= CONTAINING_RECORD(NextEntry
,
895 FS_CHANGE_NOTIFY_ENTRY
,
898 /* Check if it matches this de-registration */
899 if ((ChangeEntry
->DriverObject
== DriverObject
) &&
900 (ChangeEntry
->FSDNotificationProc
== FSDNotificationProc
))
902 /* It does, remove it from the list */
903 RemoveEntryList(&ChangeEntry
->FsChangeNotifyList
);
904 ExFreePoolWithTag(ChangeEntry
, TAG_FS_CHANGE_NOTIFY
);
908 /* Go to the next entry */
909 NextEntry
= NextEntry
->Flink
;
912 /* Release the lock and dereference the driver */
913 KeReleaseGuardedMutex(&FsChangeNotifyListLock
);
914 ObDereferenceObject(DriverObject
);
922 IoAcquireVpbSpinLock(OUT PKIRQL Irql
)
924 /* Simply acquire the lock */
925 *Irql
= KeAcquireQueuedSpinLock(LockQueueIoVpbLock
);
933 IoReleaseVpbSpinLock(IN KIRQL Irql
)
935 /* Just release the lock */
936 KeReleaseQueuedSpinLock(LockQueueIoVpbLock
, Irql
);
944 IoSetSystemPartition(IN PUNICODE_STRING VolumeNameString
)
947 return STATUS_NOT_IMPLEMENTED
;
955 IoVolumeDeviceToDosName(IN PVOID VolumeDeviceObject
,
956 OUT PUNICODE_STRING DosName
)
959 return STATUS_NOT_IMPLEMENTED
;