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/…
==============================================================================
--- 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?r…
==============================================================================
--- 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?…
==============================================================================
--- 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(a)reactos.org)
* Hervé Poussineau (hpoussin(a)reactos.org)
* Eric Kohl
+ * Pierre Schweitzer (pierre.schweitzer(a)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);
}