[ros-diffs] [pschweitzer] 52065: [NTOSKRNL] - renamed Io volumes global to match Windows names (in case of debug) - renamed IopDereferenceVpb() to IopDereferenceVpbAndFree(), IopReferenceVpbForVerify() to IopR...

pschweitzer at svn.reactos.org pschweitzer at svn.reactos.org
Thu Jun 2 17:43:47 UTC 2011


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/io.h?rev=52065&r1=52064&r2=52065&view=diff
==============================================================================
--- 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?rev=52065&r1=52064&r2=52065&view=diff
==============================================================================
--- 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?rev=52065&r1=52064&r2=52065&view=diff
==============================================================================
--- 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?rev=52065&r1=52064&r2=52065&view=diff
==============================================================================
--- 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?rev=52065&r1=52064&r2=52065&view=diff
==============================================================================
--- 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 at reactos.org)
  *                  Hervé Poussineau (hpoussin at reactos.org)
  *                  Eric Kohl
+ *                  Pierre Schweitzer (pierre.schweitzer at 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);
 }
 




More information about the Ros-diffs mailing list