Author: pschweitzer Date: Thu Jun 2 17:43:44 2011 New Revision: 52065
URL: http://svn.reactos.org/svn/reactos?rev=52065&view=rev Log: [NTOSKRNL] - renamed Io volumes global to match Windows names (in case of debug) - renamed IopDereferenceVpb() to IopDereferenceVpbAndFree(), IopReferenceVpbForVerify() to IopReferenceVerifyVpb(), IopInitializeVpbForMount() to IopMountInitializeVpb(), IopLoadFileSystem() to IopLoadFileSystemDriver() - implemented IopDecrementDeviceObjectHandleCount(), IopInterlockedIncrementUlong(), IopInterlockedDecrementUlong(), IopNotifyAlreadyRegisteredFileSystems() and IoEnumerateRegisteredFiltersList() - halfplemented IopDecrementDeviceObjectRef() - implemented check for already registrered notification in IoRegisterFsRegistrationChange() - implemented sending notifications for already registered drivers to registrant in IoRegisterFsRegistrationChange() - implemented VPB freeing in IopDereferenceVpbAndFree() - acquire Io volumes lists once and forever for system shutdown, instead of keeping acquiring and releasing - reference device object in IopShutdownBaseFileSystems() before sending it the shutdown IRP. To ensure to keep it valid till the end - added a FS driver registration operations counter - use this counter to handle failed mounts - fixed: release locks before calling driver for mounting and reacquire them after - fixed check for boot partition failure (and associated bugcheck): check we are in boot phase 0 or 1 - simplified lock process by using only one lock (ie removed mutex). Also use only critical region where needed - fixed: ensure that locks are properly released when quitting a function - fixed wrong return in IopCreateVpb() - minor fixes around
Modified: trunk/reactos/ntoskrnl/include/internal/io.h trunk/reactos/ntoskrnl/io/iomgr/device.c trunk/reactos/ntoskrnl/io/iomgr/file.c trunk/reactos/ntoskrnl/io/iomgr/iomgr.c trunk/reactos/ntoskrnl/io/iomgr/volume.c
Modified: trunk/reactos/ntoskrnl/include/internal/io.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] Thu Jun 2 17:43:44 2011 @@ -838,7 +838,7 @@
VOID NTAPI -IopDereferenceVpb( +IopDereferenceVpbAndFree( IN PVPB Vpb );
@@ -869,8 +869,15 @@
NTSTATUS NTAPI -IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, - OUT PDEVICE_OBJECT *DeviceObject +IoGetRelatedTargetDevice( + IN PFILE_OBJECT FileObject, + OUT PDEVICE_OBJECT *DeviceObject +); + +VOID +NTAPI +IopUnloadDevice( + IN PDEVICE_OBJECT DeviceObject );
//
Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/device.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/device.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/iomgr/device.c [iso-8859-1] Thu Jun 2 17:43:44 2011 @@ -19,9 +19,10 @@ ULONG IopDeviceObjectNumber = 0; LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead; KSPIN_LOCK ShutdownListLock; -extern LIST_ENTRY IopDiskFsListHead; -extern LIST_ENTRY IopCdRomFsListHead; -extern LIST_ENTRY IopTapeFsListHead; +extern LIST_ENTRY IopDiskFileSystemQueueHead; +extern LIST_ENTRY IopCdRomFileSystemQueueHead; +extern LIST_ENTRY IopTapeFileSystemQueueHead; +extern ERESOURCE IopDatabaseResource;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -187,14 +188,17 @@ } else if (Phase == 1) { + /* Acquire resource forever */ + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE); + /* Shutdown disk file systems */ - IopShutdownBaseFileSystems(&IopDiskFsListHead); + IopShutdownBaseFileSystems(&IopDiskFileSystemQueueHead);
/* Shutdown cdrom file systems */ - IopShutdownBaseFileSystems(&IopCdRomFsListHead); + IopShutdownBaseFileSystems(&IopCdRomFileSystemQueueHead);
/* Shutdown tape filesystems */ - IopShutdownBaseFileSystems(&IopTapeFsListHead); + IopShutdownBaseFileSystems(&IopTapeFileSystemQueueHead);
/* Loop last-chance shutdown notifications */ ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] Thu Jun 2 17:43:44 2011 @@ -479,7 +479,7 @@ { /* Dereference the device and VPB, then fail */ IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); - if (Vpb) IopDereferenceVpb(Vpb); + if (Vpb) IopDereferenceVpbAndFree(Vpb); return STATUS_INSUFFICIENT_RESOURCES; }
@@ -577,7 +577,7 @@
/* Dereference the device and VPB */ IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); - if (Vpb) IopDereferenceVpb(Vpb); + if (Vpb) IopDereferenceVpbAndFree(Vpb);
/* We failed, return status */ OpenPacket->FinalStatus = Status; @@ -687,7 +687,7 @@
/* Dereference the device object and VPB */ IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); - if (Vpb) IopDereferenceVpb(Vpb); + if (Vpb) IopDereferenceVpbAndFree(Vpb);
/* Clear the FO and dereference it */ FileObject->DeviceObject = NULL; @@ -783,7 +783,7 @@ IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
/* Unless the driver cancelled the open, dereference the VPB */ - if (!(OpenCancelled) && (Vpb)) IopDereferenceVpb(Vpb); + if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
/* Set the status and return */ OpenPacket->FinalStatus = Status; @@ -806,7 +806,7 @@ if (OwnerDevice != DeviceObject) { /* We have to de-reference the VPB we had associated */ - if (Vpb) IopDereferenceVpb(Vpb); + if (Vpb) IopDereferenceVpbAndFree(Vpb);
/* And re-associate with the actual one */ Vpb = FileObject->Vpb;
Modified: trunk/reactos/ntoskrnl/io/iomgr/iomgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iomgr.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iomgr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iomgr.c [iso-8859-1] Thu Jun 2 17:43:44 2011 @@ -52,19 +52,17 @@ extern LIST_ENTRY LastChanceShutdownListHead; extern KSPIN_LOCK ShutdownListLock; extern POBJECT_TYPE IoAdapterObjectType; -ERESOURCE IopDatabaseResource; -extern ERESOURCE FileSystemListLock; +extern ERESOURCE IopDatabaseResource; ERESOURCE IopSecurityResource; -extern KGUARDED_MUTEX FsChangeNotifyListLock; extern KGUARDED_MUTEX PnpNotifyListLock; -extern LIST_ENTRY IopDiskFsListHead; -extern LIST_ENTRY IopCdRomFsListHead; -extern LIST_ENTRY IopTapeFsListHead; -extern LIST_ENTRY IopNetworkFsListHead; +extern LIST_ENTRY IopDiskFileSystemQueueHead; +extern LIST_ENTRY IopCdRomFileSystemQueueHead; +extern LIST_ENTRY IopTapeFileSystemQueueHead; +extern LIST_ENTRY IopNetworkFileSystemQueueHead; extern LIST_ENTRY DriverBootReinitListHead; extern LIST_ENTRY DriverReinitListHead; extern LIST_ENTRY PnpNotifyListHead; -extern LIST_ENTRY FsChangeNotifyListHead; +extern LIST_ENTRY IopFsNotifyChangeQueueHead; extern LIST_ENTRY IopErrorLogListHead; extern LIST_ENTRY IopTimerQueueHead; extern KDPC IopTimerDpc; @@ -450,20 +448,18 @@
/* Initialize all locks and lists */ ExInitializeResource(&IopDatabaseResource); - ExInitializeResource(&FileSystemListLock); ExInitializeResource(&IopSecurityResource); - KeInitializeGuardedMutex(&FsChangeNotifyListLock); KeInitializeGuardedMutex(&PnpNotifyListLock); - InitializeListHead(&IopDiskFsListHead); - InitializeListHead(&IopCdRomFsListHead); - InitializeListHead(&IopTapeFsListHead); - InitializeListHead(&IopNetworkFsListHead); + InitializeListHead(&IopDiskFileSystemQueueHead); + InitializeListHead(&IopCdRomFileSystemQueueHead); + InitializeListHead(&IopTapeFileSystemQueueHead); + InitializeListHead(&IopNetworkFileSystemQueueHead); InitializeListHead(&DriverBootReinitListHead); InitializeListHead(&DriverReinitListHead); InitializeListHead(&PnpNotifyListHead); InitializeListHead(&ShutdownListHead); InitializeListHead(&LastChanceShutdownListHead); - InitializeListHead(&FsChangeNotifyListHead); + InitializeListHead(&IopFsNotifyChangeQueueHead); InitializeListHead(&IopErrorLogListHead); KeInitializeSpinLock(&IoStatisticsLock); KeInitializeSpinLock(&DriverReinitListLock);
Modified: trunk/reactos/ntoskrnl/io/iomgr/volume.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/volume.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/volume.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/iomgr/volume.c [iso-8859-1] Thu Jun 2 17:43:44 2011 @@ -6,6 +6,7 @@ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * Hervé Poussineau (hpoussin@reactos.org) * Eric Kohl + * Pierre Schweitzer (pierre.schweitzer@reactos.org) */
/* INCLUDES *****************************************************************/ @@ -21,14 +22,60 @@
/* GLOBALS ******************************************************************/
-ERESOURCE FileSystemListLock; -LIST_ENTRY IopDiskFsListHead, IopNetworkFsListHead; -LIST_ENTRY IopCdRomFsListHead, IopTapeFsListHead; -KGUARDED_MUTEX FsChangeNotifyListLock; -LIST_ENTRY FsChangeNotifyListHead; +ERESOURCE IopDatabaseResource; +LIST_ENTRY IopDiskFileSystemQueueHead, IopNetworkFileSystemQueueHead; +LIST_ENTRY IopCdRomFileSystemQueueHead, IopTapeFileSystemQueueHead; +LIST_ENTRY IopFsNotifyChangeQueueHead; +ULONG IopFsRegistrationOps;
/* PRIVATE FUNCTIONS *********************************************************/
+/* + * @halfplemented + */ +VOID +NTAPI +IopDecrementDeviceObjectRef(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN UnloadIfUnused) +{ + KIRQL OldIrql; + + /* Acquire lock */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock); + ASSERT(DeviceObject->ReferenceCount > 0); + + if (--DeviceObject->ReferenceCount > 0) + { + KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql); + return; + } + + /* Here, DO is not referenced any longer, check if we have to unload it */ + if (UnloadIfUnused || IoGetDevObjExtension(DeviceObject)->ExtensionFlags & + (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING)) + { + /* Unload the driver */ + IopUnloadDevice(DeviceObject); + } + + /* Release lock */ + KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql); +} + +/* + * @implemented + */ +VOID +NTAPI +IopDecrementDeviceObjectHandleCount(IN PDEVICE_OBJECT DeviceObject) +{ + /* Just decrease reference count */ + IopDecrementDeviceObjectRef(DeviceObject, FALSE); +} + +/* + * @implemented + */ PVPB NTAPI IopCheckVpbMounted(IN POPEN_PACKET OpenPacket, @@ -100,6 +147,9 @@ return Vpb; }
+/* + * @implemented + */ NTSTATUS NTAPI IopCreateVpb(IN PDEVICE_OBJECT DeviceObject) @@ -110,7 +160,7 @@ Vpb = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VPB); - if (!Vpb) return STATUS_UNSUCCESSFUL; + if (!Vpb) return STATUS_INSUFFICIENT_RESOURCES;
/* Clear it so we don't waste time manually */ RtlZeroMemory(Vpb, sizeof(VPB)); @@ -125,9 +175,12 @@ return STATUS_SUCCESS; }
+/* + * @implemented + */ VOID NTAPI -IopDereferenceVpb(IN PVPB Vpb) +IopDereferenceVpbAndFree(IN PVPB Vpb) { KIRQL OldIrql;
@@ -136,21 +189,30 @@ Vpb->ReferenceCount--;
/* Check if we're out of references */ - if (!Vpb->ReferenceCount) - { - /* FIXME: IMPLEMENT CLEANUP! */ - ASSERT(FALSE); - } - - /* Release VPB lock */ - IoReleaseVpbSpinLock(OldIrql); -} - + if (!Vpb->ReferenceCount && Vpb->RealDevice->Vpb == Vpb && + !(Vpb->Flags & VPB_PERSISTENT)) + { + /* Release VPB lock */ + IoReleaseVpbSpinLock(OldIrql); + + /* And free VPB */ + ExFreePoolWithTag(Vpb, TAG_VPB); + } + else + { + /* Release VPB lock */ + IoReleaseVpbSpinLock(OldIrql); + } +} + +/* + * @implemented + */ BOOLEAN NTAPI -IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject, - OUT PDEVICE_OBJECT *FileSystemObject, - OUT PVPB *Vpb) +IopReferenceVerifyVpb(IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_OBJECT *FileSystemObject, + OUT PVPB *Vpb) { KIRQL OldIrql; PVPB LocalVpb; @@ -181,9 +243,9 @@
PVPB NTAPI -IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject, - IN PDEVICE_OBJECT AttachedDeviceObject, - IN BOOLEAN Raw) +IopMountInitializeVpb(IN PDEVICE_OBJECT DeviceObject, + IN PDEVICE_OBJECT AttachedDeviceObject, + IN BOOLEAN Raw) { KIRQL OldIrql; PVPB Vpb; @@ -212,20 +274,20 @@ return Vpb; }
+/* + * @implemented + */ VOID -NTAPI +FORCEINLINE IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN DriverActive) { PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; PLIST_ENTRY ListEntry;
- /* Acquire the notification lock */ - KeAcquireGuardedMutex(&FsChangeNotifyListLock); - /* Loop the list */ - ListEntry = FsChangeNotifyListHead.Flink; - while (ListEntry != &FsChangeNotifyListHead) + ListEntry = IopFsNotifyChangeQueueHead.Flink; + while (ListEntry != &IopFsNotifyChangeQueueHead) { /* Get the entry */ ChangeEntry = CONTAINING_RECORD(ListEntry, @@ -238,11 +300,47 @@ /* Go to the next entry */ ListEntry = ListEntry->Flink; } - - /* Release the lock */ - KeReleaseGuardedMutex(&FsChangeNotifyListLock); -} - +} + +/* + * @implemented + */ +ULONG +FASTCALL +IopInterlockedIncrementUlong(IN KSPIN_LOCK_QUEUE_NUMBER Queue, + IN PULONG Ulong) +{ + KIRQL Irql; + ULONG OldValue; + + Irql = KeAcquireQueuedSpinLock(Queue); + OldValue = (*Ulong)++; + KeReleaseQueuedSpinLock(Queue, Irql); + + return OldValue; +} + +/* + * @implemented + */ +ULONG +FASTCALL +IopInterlockedDecrementUlong(IN KSPIN_LOCK_QUEUE_NUMBER Queue, + IN PULONG Ulong) +{ + KIRQL Irql; + ULONG OldValue; + + Irql = KeAcquireQueuedSpinLock(Queue); + OldValue = (*Ulong)--; + KeReleaseQueuedSpinLock(Queue, Irql); + + return OldValue; +} + +/* + * @implemented + */ VOID NTAPI IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead) @@ -254,9 +352,6 @@ KEVENT Event; NTSTATUS Status;
- /* Lock the FS List and initialize an event to wait on */ - KeEnterCriticalRegion(); - ExAcquireResourceSharedLite(&FileSystemListLock,TRUE); KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Get the first entry and start looping */ @@ -267,6 +362,9 @@ DeviceObject = CONTAINING_RECORD(ListEntry, DEVICE_OBJECT, Queue.ListEntry); + + ObReferenceObject(DeviceObject); + IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
/* Check if we're attached */ if (DeviceObject->AttachedDevice) @@ -293,18 +391,20 @@ /* Reset the event */ KeClearEvent(&Event);
+ IopDecrementDeviceObjectRef(DeviceObject, FALSE); + ObDereferenceObject(DeviceObject); + /* Go to the next entry */ ListEntry = ListEntry->Flink; } - - /* Release the lock */ - ExReleaseResourceLite(&FileSystemListLock); - KeLeaveCriticalRegion(); -} - +} + +/* + * @implemented + */ VOID NTAPI -IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject) +IopLoadFileSystemDriver(IN PDEVICE_OBJECT DeviceObject) { IO_STATUS_BLOCK IoStatusBlock; PIO_STACK_LOCATION StackPtr; @@ -347,8 +447,14 @@ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } } -} - + + /* Dereference DO - FsRec? */ + IopDecrementDeviceObjectRef(AttachedDeviceObject, TRUE); +} + +/* + * @implemented + */ NTSTATUS NTAPI IopMountVolume(IN PDEVICE_OBJECT DeviceObject, @@ -366,7 +472,7 @@ LIST_ENTRY LocalList; PDEVICE_OBJECT AttachedDeviceObject = DeviceObject; PDEVICE_OBJECT FileSystemDeviceObject, ParentFsDeviceObject; - ULONG FsStackOverhead; + ULONG FsStackOverhead, RegistrationOps; PAGED_CODE();
/* Check if the device isn't already locked */ @@ -387,7 +493,7 @@
/* Acquire the FS Lock*/ KeEnterCriticalRegion(); - ExAcquireResourceSharedLite(&FileSystemListLock, TRUE); + ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
/* Make sure we weren't already mounted */ if (!(DeviceObject->Vpb->Flags & (VPB_MOUNTED | VPB_REMOVE_PENDING))) @@ -411,17 +517,17 @@ (DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK)) { /* Use the disk list */ - FsList = &IopDiskFsListHead; + FsList = &IopDiskFileSystemQueueHead; } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM) { /* Use the CD-ROM list */ - FsList = &IopCdRomFsListHead; + FsList = &IopCdRomFileSystemQueueHead; } else { /* It's gotta be a tape... */ - FsList = &IopTapeFsListHead; + FsList = &IopTapeFileSystemQueueHead; }
/* Now loop the fs list until one of the file systems accepts us */ @@ -502,6 +608,13 @@ StackPtr->Parameters.MountVolume.DeviceObject = AttachedDeviceObject;
+ /* Save registration operations */ + RegistrationOps = IopFsRegistrationOps; + + /* Release locks */ + IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount); + ExReleaseResourceLite(&IopDatabaseResource); + /* Call the driver */ Status = IoCallDriver(FileSystemDeviceObject, Irp); if (Status == STATUS_PENDING) @@ -515,14 +628,17 @@ Status = IoStatusBlock.Status; }
+ ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE); + IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount); + /* Check if mounting was successful */ if (NT_SUCCESS(Status)) { /* Mount the VPB */ - *Vpb = IopInitializeVpbForMount(DeviceObject, - AttachedDeviceObject, - (DeviceObject->Vpb->Flags & - VPB_RAW_MOUNT)); + *Vpb = IopMountInitializeVpb(DeviceObject, + AttachedDeviceObject, + (DeviceObject->Vpb->Flags & + VPB_RAW_MOUNT)); } else { @@ -534,11 +650,22 @@ break; }
+ /* If there were registration operations in the meanwhile */ + if (RegistrationOps != IopFsRegistrationOps) + { + /* We need to setup a local list to pickup where we left */ + LocalList.Flink = FsList->Flink; + ListEntry = &LocalList; + + Status = STATUS_UNRECOGNIZED_VOLUME; + } + /* Otherwise, check if we need to load the FS driver */ if (Status == STATUS_FS_DRIVER_REQUIRED) { /* We need to release the lock */ - ExReleaseResourceLite(&FileSystemListLock); + IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount); + ExReleaseResourceLite(&IopDatabaseResource);
/* Release the device lock if we're holding it */ if (!DeviceIsLocked) @@ -546,8 +673,11 @@ KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE); }
+ /* Leave critical section */ + KeLeaveCriticalRegion(); + /* Load the FS */ - IopLoadFileSystem(ParentFsDeviceObject); + IopLoadFileSystemDriver(ParentFsDeviceObject);
/* Check if the device isn't already locked */ if (!DeviceIsLocked) @@ -569,7 +699,8 @@ }
/* Reacquire the lock */ - ExAcquireResourceSharedLite(&FileSystemListLock, TRUE); + KeEnterCriticalRegion(); + ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
/* When we released the lock, make sure nobody beat us */ if (DeviceObject->Vpb->Flags & VPB_MOUNTED) @@ -620,7 +751,7 @@ }
/* Release the FS lock */ - ExReleaseResourceLite(&FileSystemListLock); + ExReleaseResourceLite(&IopDatabaseResource); KeLeaveCriticalRegion();
/* Release the device lock if we're holding it */ @@ -628,7 +759,8 @@
/* Check if we failed to mount the boot partition */ if ((!NT_SUCCESS(Status)) && - (DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION)) + (DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION) && + ExpInitializationPhase < 2) { /* Bugcheck the system */ KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE, @@ -642,19 +774,102 @@ return Status; }
+/* + * @implemented + */ +VOID +NTAPI +IopNotifyAlreadyRegisteredFileSystems(IN PLIST_ENTRY ListHead, + IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine, + BOOLEAN SkipLast) +{ + PLIST_ENTRY ListEntry; + PDEVICE_OBJECT DeviceObject; + + /* Browse the whole list */ + ListEntry = ListHead->Flink; + while (ListEntry != ListHead) + { + /* Check if we reached end and if we have to skip it */ + if (ListEntry->Flink == ListHead && SkipLast) + { + return; + } + + /* Otherwise, get DO and notify */ + DeviceObject = CONTAINING_RECORD(ListEntry, + DEVICE_OBJECT, + Queue.ListEntry); + + DriverNotificationRoutine(DeviceObject, TRUE); + + /* Go to the next entry */ + ListEntry = ListEntry->Flink; + } +} + /* PUBLIC FUNCTIONS **********************************************************/
/* - * @unimplemented + * @implemented */ NTSTATUS NTAPI -IoEnumerateRegisteredFiltersList(IN PDRIVER_OBJECT *DriverObjectList, +IoEnumerateRegisteredFiltersList(OUT PDRIVER_OBJECT *DriverObjectList, IN ULONG DriverObjectListSize, OUT PULONG ActualNumberDriverObjects) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; + USHORT Index = 0; + ULONG ListSize = 0; + PLIST_ENTRY ListEntry; + NTSTATUS Status = STATUS_SUCCESS; + PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; + + /* Acquire the FS lock */ + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE); + + /* First of all, count number of driver objects */ + ListEntry = IopFsNotifyChangeQueueHead.Flink; + while (ListEntry != &IopFsNotifyChangeQueueHead) + { + ListSize++; + + /* Go to the next entry */ + ListEntry = ListEntry->Flink; + } + + /* Return this size */ + *ActualNumberDriverObjects = ListSize; + + /* Then, check if given buffer is big enough to contain list */ + if (ListSize > DriverObjectListSize / sizeof(PDRIVER_OBJECT)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + /* Rebrowse the whole list */ + ListEntry = IopFsNotifyChangeQueueHead.Flink; + while (ListEntry != &IopFsNotifyChangeQueueHead) + { + ChangeEntry = CONTAINING_RECORD(ListEntry, + FS_CHANGE_NOTIFY_ENTRY, + FsChangeNotifyList); + + /* Reference the driver object */ + ObReferenceObject(ChangeEntry->DriverObject); + /* And pass it to the caller */ + DriverObjectList[Index++] = ChangeEntry->DriverObject; + + /* Go to the next entry */ + ListEntry = ListEntry->Flink; + } + } + + /* Release the FS lock */ + ExReleaseResourceLite(&IopDatabaseResource); + + return Status; }
/* @@ -669,20 +884,21 @@ PIO_STACK_LOCATION StackPtr; KEVENT Event; PIRP Irp; - NTSTATUS Status = STATUS_SUCCESS, VpbStatus; + NTSTATUS Status, VpbStatus; PDEVICE_OBJECT FileSystemDeviceObject; PVPB Vpb, NewVpb; BOOLEAN WasNotMounted = TRUE;
/* Wait on the device lock */ - KeWaitForSingleObject(&DeviceObject->DeviceLock, - Executive, - KernelMode, - FALSE, - NULL); + Status = KeWaitForSingleObject(&DeviceObject->DeviceLock, + Executive, + KernelMode, + FALSE, + NULL); + ASSERT(Status == STATUS_SUCCESS);
/* Reference the VPB */ - if (IopReferenceVpbForVerify(DeviceObject, &FileSystemDeviceObject, &Vpb)) + if (IopReferenceVerifyVpb(DeviceObject, &FileSystemDeviceObject, &Vpb)) { /* Initialize the event */ KeInitializeEvent(&Event, NotificationEvent, FALSE); @@ -698,7 +914,11 @@
/* Allocate the IRP */ Irp = IoAllocateIrp(FileSystemDeviceObject->StackSize, FALSE); - if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; + if (!Irp) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Release; + }
/* Set it up */ Irp->UserIosb = &IoStatusBlock; @@ -726,28 +946,37 @@ }
/* Dereference the VPB */ - IopDereferenceVpb(Vpb); + IopDereferenceVpbAndFree(Vpb); }
/* Check if we had the wrong volume or didn't mount at all */ - if ((Status == STATUS_WRONG_VOLUME) || (WasNotMounted)) + if (Status == STATUS_WRONG_VOLUME) { /* Create a VPB */ VpbStatus = IopCreateVpb(DeviceObject); if (NT_SUCCESS(VpbStatus)) { + PoVolumeDevice(DeviceObject); + /* Mount it */ VpbStatus = IopMountVolume(DeviceObject, AllowRawMount, TRUE, FALSE, &NewVpb); + + /* If we got a new VPB, dereference it */ + if (NewVpb) + { + IopInterlockedDecrementUlong(LockQueueIoVpbLock, &NewVpb->ReferenceCount); + } }
/* If we failed, remove the verify flag */ if (!NT_SUCCESS(VpbStatus)) DeviceObject->Flags &= ~DO_VERIFY_VOLUME; }
+Release: /* Signal the device lock and return */ KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE); return Status; @@ -764,29 +993,28 @@ PAGED_CODE();
/* Acquire the FS lock */ - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE); + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
/* Check what kind of FS this is */ if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) { /* Use the disk list */ - FsList = &IopDiskFsListHead; + FsList = &IopDiskFileSystemQueueHead; } else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) { /* Use the network device list */ - FsList = &IopNetworkFsListHead; + FsList = &IopNetworkFileSystemQueueHead; } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) { /* Use the CD-ROM list */ - FsList = &IopCdRomFsListHead; + FsList = &IopCdRomFileSystemQueueHead; } else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) { /* Use the tape list */ - FsList = &IopTapeFsListHead; + FsList = &IopTapeFileSystemQueueHead; }
/* Make sure that we have a valid list */ @@ -805,15 +1033,20 @@ } }
+ /* Update operations counter */ + IopFsRegistrationOps++; + /* Clear the initializing flag */ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
- /* Release the FS Lock */ - ExReleaseResourceLite(&FileSystemListLock); - KeLeaveCriticalRegion(); - /* Notify file systems of the addition */ IopNotifyFileSystemChange(DeviceObject, TRUE); + + /* Release the FS Lock */ + ExReleaseResourceLite(&IopDatabaseResource); + + /* Ensure driver won't be unloaded */ + IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount); }
/* @@ -826,18 +1059,25 @@ PAGED_CODE();
/* Acquire the FS lock */ - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE); - - /* Simply remove the entry */ - RemoveEntryList(&DeviceObject->Queue.ListEntry); + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE); + + /* Simply remove the entry - if queued */ + if (DeviceObject->Queue.ListEntry.Flink) + { + RemoveEntryList(&DeviceObject->Queue.ListEntry); + }
/* And notify all registered file systems */ IopNotifyFileSystemChange(DeviceObject, FALSE);
+ /* Update operations counter */ + IopFsRegistrationOps++; + /* Then release the lock */ - ExReleaseResourceLite(&FileSystemListLock); - KeLeaveCriticalRegion(); + ExReleaseResourceLite(&IopDatabaseResource); + + /* Decrease reference count to allow unload */ + IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount); }
/* @@ -846,25 +1086,60 @@ NTSTATUS NTAPI IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, - IN PDRIVER_FS_NOTIFICATION FSDNotificationProc) + IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine) { PFS_CHANGE_NOTIFY_ENTRY Entry; PAGED_CODE(); + + /* Acquire the list lock */ + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE); + + /* Check if that driver is already registered (successive calls) + * See MSDN note: http://msdn.microsoft.com/en-us/library/ff548499%28v=vs.85%29.aspx + */ + if (!IsListEmpty(&IopFsNotifyChangeQueueHead)) + { + Entry = CONTAINING_RECORD(IopFsNotifyChangeQueueHead.Blink, + FS_CHANGE_NOTIFY_ENTRY, + FsChangeNotifyList); + + if (Entry->DriverObject == DriverObject && + Entry->FSDNotificationProc == DriverNotificationRoutine) + { + /* Release the lock */ + ExReleaseResourceLite(&IopDatabaseResource); + + return STATUS_DEVICE_ALREADY_ATTACHED; + } + }
/* Allocate a notification entry */ Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FS_CHANGE_NOTIFY_ENTRY), TAG_FS_CHANGE_NOTIFY); - if (!Entry) return(STATUS_INSUFFICIENT_RESOURCES); + if (!Entry) + { + /* Release the lock */ + ExReleaseResourceLite(&IopDatabaseResource); + + return STATUS_INSUFFICIENT_RESOURCES; + }
/* Save the driver object and notification routine */ Entry->DriverObject = DriverObject; - Entry->FSDNotificationProc = FSDNotificationProc; + Entry->FSDNotificationProc = DriverNotificationRoutine;
/* Insert it into the notification list */ - KeAcquireGuardedMutex(&FsChangeNotifyListLock); - InsertTailList(&FsChangeNotifyListHead, &Entry->FsChangeNotifyList); - KeReleaseGuardedMutex(&FsChangeNotifyListLock); + InsertTailList(&IopFsNotifyChangeQueueHead, &Entry->FsChangeNotifyList); + + /* Start notifying all already present FS */ + IopNotifyAlreadyRegisteredFileSystems(&IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE); + IopNotifyAlreadyRegisteredFileSystems(&IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE); + IopNotifyAlreadyRegisteredFileSystems(&IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE); + IopNotifyAlreadyRegisteredFileSystems(&IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE); + + /* Release the lock */ + ExReleaseResourceLite(&IopDatabaseResource);
/* Reference the driver */ ObReferenceObject(DriverObject); @@ -884,11 +1159,11 @@ PAGED_CODE();
/* Acquire the list lock */ - KeAcquireGuardedMutex(&FsChangeNotifyListLock); + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
/* Loop the list */ - NextEntry = FsChangeNotifyListHead.Flink; - while (NextEntry != &FsChangeNotifyListHead) + NextEntry = IopFsNotifyChangeQueueHead.Flink; + while (NextEntry != &IopFsNotifyChangeQueueHead) { /* Get the entry */ ChangeEntry = CONTAINING_RECORD(NextEntry, @@ -910,7 +1185,7 @@ }
/* Release the lock and dereference the driver */ - KeReleaseGuardedMutex(&FsChangeNotifyListLock); + ExReleaseResourceLite(&IopDatabaseResource); ObDereferenceObject(DriverObject); }