[ros-diffs] [mjmartin] 41254: IopCreateObjectTypes: Add a DeleteProcedure for Device Objects. IopUnloadDevice: After calling the drivers Unload routine, make the DriverObject temporary and dereference it. IopUnloadDriver: Check that the driver is not already unloading before trying to call unload routine. If any failure, dereference the DriverObject before returning STATUS code. On an attempt to unload the driver, loop through each DeviceObject and set DOE_UNLOAD_PENDING in device extensions flags. Before calling the driver's unload routine set DRVO_UNLOAD_INVOKED in DriverObject's flags. Fixes Bugchecks when attempting to load driver a second time and when unloading a driver that has upper level device attached.

mjmartin at svn.reactos.org mjmartin at svn.reactos.org
Tue Jun 2 14:10:18 CEST 2009


Author: mjmartin
Date: Tue Jun  2 16:10:17 2009
New Revision: 41254

URL: http://svn.reactos.org/svn/reactos?rev=41254&view=rev
Log:
IopCreateObjectTypes: Add a DeleteProcedure for Device Objects.
IopUnloadDevice: After calling the drivers Unload routine, make the DriverObject temporary and dereference it.
IopUnloadDriver: Check that the driver is not already unloading before trying to call unload routine.
If any failure, dereference the DriverObject before returning STATUS code.
On an attempt to unload the driver, loop through each DeviceObject and set DOE_UNLOAD_PENDING in device extensions flags.
Before calling the driver's unload routine set DRVO_UNLOAD_INVOKED in DriverObject's flags.
Fixes Bugchecks when attempting to load driver a second time and when unloading a driver that has upper level device attached.

Modified:
    trunk/reactos/ntoskrnl/include/internal/io.h
    trunk/reactos/ntoskrnl/io/iomgr/device.c
    trunk/reactos/ntoskrnl/io/iomgr/driver.c
    trunk/reactos/ntoskrnl/io/iomgr/iomgr.c

Modified: trunk/reactos/ntoskrnl/include/internal/io.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/io.h?rev=41254&r1=41253&r2=41254&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] Tue Jun  2 16:10:17 2009
@@ -938,6 +938,10 @@
 //
 // File Routines
 //
+VOID
+NTAPI
+IopDeleteDevice(IN PVOID ObjectBody);
+
 NTSTATUS
 NTAPI
 IopParseDevice(

Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/device.c?rev=41254&r1=41253&r2=41254&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/device.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/device.c [iso-8859-1] Tue Jun  2 16:10:17 2009
@@ -22,6 +22,21 @@
 KSPIN_LOCK ShutdownListLock;
 
 /* PRIVATE FUNCTIONS **********************************************************/
+
+VOID
+NTAPI
+IopDeleteDevice(IN PVOID ObjectBody)
+{
+    PDEVICE_OBJECT DeviceObject = ObjectBody;
+    PAGED_CODE();
+ 
+    /* TODO: Delete Device Node */
+
+    /* Dereference the driver object, referenced in IoCreateDevice */
+    if (DeviceObject->DriverObject);
+        ObDereferenceObject(DeviceObject->DriverObject);
+}
+
 
 PDEVICE_OBJECT
 NTAPI
@@ -356,6 +371,13 @@
 
     /* Unload it */
     if (DriverObject->DriverUnload) DriverObject->DriverUnload(DriverObject);
+
+    /* Make object temporary so it can be deleted */
+    ObMakeTemporaryObject(DriverObject);
+
+    /* Dereference once more, referenced at driver object creation */
+    ObDereferenceObject(DriverObject);
+
 }
 
 VOID

Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c?rev=41254&r1=41253&r2=41254&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/driver.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/driver.c [iso-8859-1] Tue Jun  2 16:10:17 2009
@@ -977,9 +977,12 @@
    UNICODE_STRING ServiceName;
    UNICODE_STRING ObjectName;
    PDRIVER_OBJECT DriverObject;
+   PDEVICE_OBJECT DeviceObject;
+   PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
    LOAD_UNLOAD_PARAMS LoadParams;
    NTSTATUS Status;
    LPWSTR Start;
+   BOOLEAN SafeToUnload = TRUE;
 
    DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers);
 
@@ -1031,6 +1034,14 @@
       return Status;
    }
 
+   /* Check that driver is not already unloading */
+   if (DriverObject->Flags & DRVO_UNLOAD_INVOKED)
+   {
+       DPRINT1("Driver deletion pending\n");
+       ObDereferenceObject(DriverObject);
+       return STATUS_DELETE_PENDING;
+   }
+
    /*
     * Get path of service...
     */
@@ -1049,6 +1060,7 @@
    if (!NT_SUCCESS(Status))
    {
       DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
+      ObDereferenceObject(DriverObject);
       return Status;
    }
 
@@ -1061,6 +1073,7 @@
    if (!NT_SUCCESS(Status))
    {
       DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status);
+      ObDereferenceObject(DriverObject);
       return Status;
    }
 
@@ -1069,6 +1082,35 @@
     */
 
    ExFreePool(ImagePath.Buffer);
+
+   /* Loop through each device object of the driver
+      and set DOE_UNLOAD_PENDING flag */
+   DeviceObject = DriverObject->DeviceObject;
+   while (DeviceObject)
+   {
+      /* Set the unload pending flag for the device */
+      DeviceExtension = IoGetDevObjExtension(DeviceObject);
+      DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING;
+
+      /* Make sure there are no attached devices or no reference counts */
+      if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice))
+      {
+         /* Not safe to unload */
+         DPRINT1("Drivers device object is referenced or has attached devices\n");
+
+         SafeToUnload = FALSE;
+      }
+
+      DeviceObject = DeviceObject->NextDevice;
+   }
+
+   /* If not safe to unload, then return success */
+   if (!SafeToUnload)
+   {
+      ObDereferenceObject(DriverObject);
+      return STATUS_SUCCESS;
+   }
+
 
    /*
     * Unload the module and release the references to the device object
@@ -1077,6 +1119,9 @@
     /* Call the load/unload routine, depending on current process */
    if (DriverObject->DriverUnload && DriverObject->DriverSection)
    {
+      /* Set the unload invoked flag */
+      DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
+
       if (PsGetCurrentProcess() == PsInitialSystemProcess)
       {
          /* Just call right away */

Modified: trunk/reactos/ntoskrnl/io/iomgr/iomgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iomgr.c?rev=41254&r1=41253&r2=41254&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/iomgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/iomgr.c [iso-8859-1] Tue Jun  2 16:10:17 2009
@@ -265,9 +265,10 @@
                                        NULL,
                                        &IoControllerObjectType))) return FALSE;
 
-    /* Do the Device Type. FIXME: Needs Delete Routine! */
+    /* Do the Device Type */
     RtlInitUnicodeString(&Name, L"Device");
     ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
+    ObjectTypeInitializer.DeleteProcedure = IopDeleteDevice;
     ObjectTypeInitializer.ParseProcedure = IopParseDevice;
     ObjectTypeInitializer.SecurityProcedure = IopSecurityFile;
     if (!NT_SUCCESS(ObCreateObjectType(&Name,



More information about the Ros-diffs mailing list