[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / io / iomgr / driver.c
index 54d7448..82fed8f 100644 (file)
@@ -58,6 +58,11 @@ IopDeleteDriver(IN PVOID ObjectBody)
     PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension;
     PAGED_CODE();
 
+    DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName);
+
+    /* There must be no device objects remaining at this point */
+    ASSERT(!DriverObject->DeviceObject);
+
     /* Get the extension and loop them */
     DriverExtension = IoGetDrvObjExtension(DriverObject)->
                       ClientDriverExtension;
@@ -232,10 +237,12 @@ IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
  *    The input image path isn't freed on error.
  */
 
-NTSTATUS FASTCALL
+NTSTATUS
+FASTCALL
 IopNormalizeImagePath(
-   IN OUT PUNICODE_STRING ImagePath,
-   IN PUNICODE_STRING ServiceName)
+   _Inout_ _When_(return>=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem)))
+        PUNICODE_STRING ImagePath,
+   _In_ PUNICODE_STRING ServiceName)
 {
    UNICODE_STRING InputImagePath;
 
@@ -274,7 +281,7 @@ IopNormalizeImagePath(
       /* Free caller's string */
       ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY);
    }
+
    DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
 
    return STATUS_SUCCESS;
@@ -393,8 +400,8 @@ IopLoadServiceModule(
 
    if (ServiceStart >= 4)
    {
-      /* FIXME: Check if it is the right status code */
-      Status = STATUS_PLUGPLAY_NO_DEVICE;
+      /* We can't load this */
+      Status = STATUS_DRIVER_UNABLE_TO_LOAD;
    }
    else
    {
@@ -517,7 +524,7 @@ IopInitializeDriverModule(
       DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status);
       return Status;
    }
-   
+
    MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)Driver->DriverSection);
 
    /* Set the driver as initialized */
@@ -556,39 +563,31 @@ IopAttachFilterDriversCallback(
         Filters += (ServiceName.Length / sizeof(WCHAR)) + 1)
    {
       DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath);
+
       ServiceName.Buffer = Filters;
       ServiceName.MaximumLength =
       ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR);
 
-      /* Load and initialize the filter driver */
-      Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
-      if (Status != STATUS_IMAGE_ALREADY_LOADED)
-      {
-         if (!NT_SUCCESS(Status))
-            continue;
+       Status = IopGetDriverObject(&DriverObject,
+                                   &ServiceName,
+                                   FALSE);
+       if (!NT_SUCCESS(Status))
+       {
+           /* Load and initialize the filter driver */
+           Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
+           if (!NT_SUCCESS(Status))
+               continue;
 
-         Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
-                                            FALSE, &DriverObject);
-         if (!NT_SUCCESS(Status))
-            continue;
-      }
-      else
-      {
-         /* get existing DriverObject pointer */
-         Status = IopGetDriverObject(
-            &DriverObject,
-            &ServiceName,
-            FALSE);
-         if (!NT_SUCCESS(Status))
-         {
-            DPRINT1("IopGetDriverObject() returned status 0x%08x!\n", Status);
-            continue;
-         }
-      }
+           Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
+                                              FALSE, &DriverObject);
+           if (!NT_SUCCESS(Status))
+               continue;
+       }
 
-      Status = IopInitializeDevice(DeviceNode, DriverObject);
-      if (!NT_SUCCESS(Status))
-         continue;
+       Status = IopInitializeDevice(DeviceNode, DriverObject);
+
+       /* Remove extra reference */
+       ObDereferenceObject(DriverObject);
    }
 
    return STATUS_SUCCESS;
@@ -798,6 +797,11 @@ LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,
                                       &MissingApiName,
                                       &MissingDriverName,
                                       &LoadedImports);
+
+    /* Free the temporary buffer */
+    ExFreePoolWithTag(Buffer, TAG_LDR_WSTR);
+
+    /* Check the result of the imports resolution */
     if (!NT_SUCCESS(Status)) return Status;
 
     /* Return */
@@ -883,6 +887,9 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
       Status = IopStartDevice(DeviceNode);
    }
 
+   /* Remove extra reference from IopInitializeDriverModule */
+   ObDereferenceObject(DriverObject);
+
    return Status;
 }
 
@@ -944,6 +951,7 @@ IopInitializeBootDrivers(VOID)
     {
         /* Fail */
         IopFreeDeviceNode(DeviceNode);
+        ObDereferenceObject(DriverObject);
         return;
     }
 
@@ -953,6 +961,7 @@ IopInitializeBootDrivers(VOID)
     {
         /* Fail */
         IopFreeDeviceNode(DeviceNode);
+        ObDereferenceObject(DriverObject);
         return;
     }
 
@@ -1264,7 +1273,8 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
     */
 
     /* Call the load/unload routine, depending on current process */
-   if (DriverObject->DriverUnload && DriverObject->DriverSection)
+   if (DriverObject->DriverUnload && DriverObject->DriverSection &&
+       (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER)))
    {
       /* Loop through each device object of the driver
          and set DOE_UNLOAD_PENDING flag */
@@ -1294,6 +1304,8 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
          return STATUS_SUCCESS;
       }
 
+      DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName);
+
       /* Set the unload invoked flag */
       DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
 
@@ -1333,6 +1345,8 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
    }
    else
    {
+      DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
+
       /* Dereference one time (refd inside this function) */
       ObDereferenceObject(DriverObject);
 
@@ -1476,7 +1490,7 @@ try_again:
     RtlZeroMemory(DriverObject, ObjectSize);
     DriverObject->Type = IO_TYPE_DRIVER;
     DriverObject->Size = sizeof(DRIVER_OBJECT);
-    DriverObject->Flags = DRVO_LEGACY_DRIVER;//DRVO_BUILTIN_DRIVER;
+    DriverObject->Flags = DRVO_LEGACY_DRIVER;
     DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
     DriverObject->DriverExtension->DriverObject = DriverObject;
     DriverObject->DriverInit = InitializationFunction;
@@ -1542,6 +1556,10 @@ try_again:
                                        KernelMode,
                                        (PVOID*)&DriverObject,
                                        NULL);
+
+    /* Close the extra handle */
+    ZwClose(hDriver);
+
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
@@ -1550,9 +1568,6 @@ try_again:
         return Status;
     }
 
-    /* Close the extra handle */
-    ZwClose(hDriver);
-
     DriverObject->HardwareDatabase = &IopHardwareDatabaseKey;
     DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0;
     DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0;
@@ -1568,6 +1583,7 @@ try_again:
         DriverObject->DriverSection = NULL;
         ObMakeTemporaryObject(DriverObject);
         ObDereferenceObject(DriverObject);
+        return Status;
     }
     else
     {
@@ -1575,6 +1591,10 @@ try_again:
         *pDriverObject = DriverObject;
     }
 
+    /* We're going to say if we don't have any DOs from DriverEntry, then we're not legacy.
+     * Other parts of the I/O manager depend on this behavior */
+    if (!DriverObject->DeviceObject) DriverObject->Flags &= ~DRVO_LEGACY_DRIVER;
+
     /* Loop all Major Functions */
     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
     {
@@ -1752,7 +1772,7 @@ IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
     if (!Inserted)
     {
         /* Free the entry and fail */
-        ExFreePool(NewDriverExtension);
+        ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION);
         return STATUS_OBJECT_NAME_COLLISION;
     }
 
@@ -1910,7 +1930,7 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
        DPRINT("Loading module from %wZ\n", &ImagePath);
        Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);
 
-       if (!NT_SUCCESS(Status) && Status != STATUS_IMAGE_ALREADY_LOADED)
+       if (!NT_SUCCESS(Status))
        {
            DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
            LoadParams->Status = Status;
@@ -1921,47 +1941,42 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
        /*
         * Initialize the driver module if it's loaded for the first time
         */
-       if (Status != STATUS_IMAGE_ALREADY_LOADED)
+       Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);
+       if (!NT_SUCCESS(Status))
        {
-           Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);
+           DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
+           MmUnloadSystemImage(ModuleObject);
+           LoadParams->Status = Status;
+           (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+           return;
+       }
 
-           if (!NT_SUCCESS(Status))
-           {
-               DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
-               MmUnloadSystemImage(ModuleObject);
-               LoadParams->Status = Status;
-               (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
-               return;
-           }
-
-           IopDisplayLoadingMessage(&DeviceNode->ServiceName);
-
-           Status = IopInitializeDriverModule(
-               DeviceNode,
-               ModuleObject,
-               &DeviceNode->ServiceName,
-               (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
-               Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
-               &DriverObject);
+       IopDisplayLoadingMessage(&DeviceNode->ServiceName);
 
-           if (!NT_SUCCESS(Status))
-           {
-               DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
-               MmUnloadSystemImage(ModuleObject);
-               IopFreeDeviceNode(DeviceNode);
-               LoadParams->Status = Status;
-               (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
-               return;
-           }
-
-           /* Initialize and start device */
-           IopInitializeDevice(DeviceNode, DriverObject);
-           Status = IopStartDevice(DeviceNode);
+       Status = IopInitializeDriverModule(DeviceNode,
+                                          ModuleObject,
+                                          &DeviceNode->ServiceName,
+                                          (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
+                                           Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
+                                          &DriverObject);
+       if (!NT_SUCCESS(Status))
+       {
+           DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
+           MmUnloadSystemImage(ModuleObject);
+           IopFreeDeviceNode(DeviceNode);
+           LoadParams->Status = Status;
+           (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+           return;
        }
+
+       /* Initialize and start device */
+       IopInitializeDevice(DeviceNode, DriverObject);
+       Status = IopStartDevice(DeviceNode);
    }
    else
    {
       DPRINT("DriverObject already exist in ObjectManager\n");
+      Status = STATUS_IMAGE_ALREADY_LOADED;
 
       /* IopGetDriverObject references the DriverObject, so dereference it */
       ObDereferenceObject(DriverObject);