[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / io / iomgr / driver.c
index 7dcb035..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;
@@ -191,7 +196,7 @@ IopSuffixUnicodeString(
  * Display 'Loading XXX...' message.
  */
 
-VOID 
+VOID
 FASTCALL
 INIT_FUNCTION
 IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
@@ -232,13 +237,17 @@ 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;
 
+   DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
+
    RtlCopyMemory(
       &InputImagePath,
       ImagePath,
@@ -273,6 +282,8 @@ IopNormalizeImagePath(
       ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY);
    }
 
+   DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
+
    return STATUS_SUCCESS;
 }
 
@@ -310,51 +321,65 @@ IopLoadServiceModule(
       return STATUS_UNSUCCESSFUL;
    }
 
-   /* Open CurrentControlSet */
-   RtlInitUnicodeString(&CCSName,
-                        L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
-   Status = IopOpenRegistryKeyEx(&CCSKey, NULL, &CCSName, KEY_READ);
-   if (!NT_SUCCESS(Status))
+   if (ExpInTextModeSetup)
    {
-       DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
-       return Status;
-   }
+       /* We have no registry, but luckily we know where all the drivers are */
 
-   /* Open service key */
-   Status = IopOpenRegistryKeyEx(&ServiceKey, CCSKey, ServiceName, KEY_READ);
-   if (!NT_SUCCESS(Status))
-   {
-       DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
-       ZwClose(CCSKey);
-       return Status;
+       /* ServiceStart < 4 is all that matters */
+       ServiceStart = 0;
+
+       /* IopNormalizeImagePath will do all of the work for us if we give it an empty string */
+       ServiceImagePath.Length = ServiceImagePath.MaximumLength = 0;
+       ServiceImagePath.Buffer = NULL;
    }
+   else
+   {
+       /* Open CurrentControlSet */
+       RtlInitUnicodeString(&CCSName,
+                            L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
+       Status = IopOpenRegistryKeyEx(&CCSKey, NULL, &CCSName, KEY_READ);
+       if (!NT_SUCCESS(Status))
+       {
+           DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
+           return Status;
+       }
 
-   /*
-    * Get information about the service.
-    */
+       /* Open service key */
+       Status = IopOpenRegistryKeyEx(&ServiceKey, CCSKey, ServiceName, KEY_READ);
+       if (!NT_SUCCESS(Status))
+       {
+           DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
+           ZwClose(CCSKey);
+           return Status;
+       }
 
-   RtlZeroMemory(QueryTable, sizeof(QueryTable));
+       /*
+        * Get information about the service.
+        */
 
-   RtlInitUnicodeString(&ServiceImagePath, NULL);
+       RtlZeroMemory(QueryTable, sizeof(QueryTable));
 
-   QueryTable[0].Name = L"Start";
-   QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
-   QueryTable[0].EntryContext = &ServiceStart;
+       RtlInitUnicodeString(&ServiceImagePath, NULL);
 
-   QueryTable[1].Name = L"ImagePath";
-   QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
-   QueryTable[1].EntryContext = &ServiceImagePath;
+       QueryTable[0].Name = L"Start";
+       QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+       QueryTable[0].EntryContext = &ServiceStart;
 
-   Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
-      (PWSTR)ServiceKey, QueryTable, NULL, NULL);
+       QueryTable[1].Name = L"ImagePath";
+       QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+       QueryTable[1].EntryContext = &ServiceImagePath;
 
-   ZwClose(ServiceKey);
-   ZwClose(CCSKey);
+       Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+          (PWSTR)ServiceKey, QueryTable, NULL, NULL);
 
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
-      return Status;
+       ZwClose(ServiceKey);
+       ZwClose(CCSKey);
+
+       if (!NT_SUCCESS(Status))
+       {
+          DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
+          return Status;
+       }
    }
 
    /*
@@ -369,20 +394,24 @@ IopLoadServiceModule(
       return Status;
    }
 
-      /*
-       * Case for disabled drivers
-       */
-
-  if (ServiceStart >= 4)
-  {
-     /* FIXME: Check if it is the right status code */
-     Status = STATUS_PLUGPLAY_NO_DEVICE;
-  }
-  else
-  {
-     DPRINT("Loading module\n");
-     Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, &BaseAddress);
-  }
+   /*
+    * Case for disabled drivers
+    */
+
+   if (ServiceStart >= 4)
+   {
+      /* We can't load this */
+      Status = STATUS_DRIVER_UNABLE_TO_LOAD;
+   }
+   else
+   {
+      DPRINT("Loading module from %wZ\n", &ServiceImagePath);
+      Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, &BaseAddress);
+      if (NT_SUCCESS(Status))
+      {
+          IopDisplayLoadingMessage(ServiceName);
+      }
+   }
 
    ExFreePool(ServiceImagePath.Buffer);
 
@@ -400,6 +429,10 @@ IopLoadServiceModule(
    return Status;
 }
 
+VOID
+NTAPI
+MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
+
 /*
  * IopInitializeDriverModule
  *
@@ -481,8 +514,7 @@ IopInitializeDriverModule(
        DriverName.Length > 0 ? &DriverName : NULL,
        DriverEntry,
        &RegistryKey,
-       ModuleObject->DllBase,
-       ModuleObject->SizeOfImage,
+       ModuleObject,
        &Driver);
    RtlFreeUnicodeString(&RegistryKey);
 
@@ -493,6 +525,8 @@ IopInitializeDriverModule(
       return Status;
    }
 
+   MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)Driver->DriverSection);
+
    /* Set the driver as initialized */
    IopReadyDeviceObjects(Driver);
 
@@ -529,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 = wcslen(Filters) * sizeof(WCHAR);
+      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);
 
-      Status = IopInitializeDevice(DeviceNode, DriverObject);
-      if (!NT_SUCCESS(Status))
-         continue;
+       /* Remove extra reference */
+       ObDereferenceObject(DriverObject);
    }
 
    return STATUS_SUCCESS;
@@ -710,12 +736,12 @@ MiResolveImageReferences(IN PVOID ImageBase,
 //
 NTSTATUS
 NTAPI
+INIT_FUNCTION
 LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,
                        PUNICODE_STRING FileName,
                        PLDR_DATA_TABLE_ENTRY *ModuleObject)
 {
     NTSTATUS Status;
-    PLDR_DATA_TABLE_ENTRY NewEntry;
     UNICODE_STRING BaseName, BaseDirectory;
     PLOAD_IMPORTS LoadedImports = (PVOID)-2;
     PCHAR MissingApiName, Buffer;
@@ -763,8 +789,6 @@ LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,
     BaseDirectory.Length -= BaseName.Length;
     BaseDirectory.MaximumLength = BaseDirectory.Length;
 
-    NewEntry = LdrEntry;
-
     /* Resolve imports */
     MissingApiName = Buffer;
     Status = MiResolveImageReferences(DriverBase,
@@ -773,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 */
@@ -788,6 +817,7 @@ LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,
 
 NTSTATUS
 NTAPI
+INIT_FUNCTION
 IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
 {
     PDEVICE_NODE DeviceNode;
@@ -824,7 +854,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
    FileExtension = wcsrchr(ServiceName.Buffer, '.');
    if (FileExtension != NULL)
    {
-      ServiceName.Length -= wcslen(FileExtension) * sizeof(WCHAR);
+      ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR);
       FileExtension[0] = 0;
    }
 
@@ -838,7 +868,6 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
       DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status);
       return(Status);
    }
-   DeviceNode->ServiceName = ServiceName;
 
    /*
     * Initialize the driver
@@ -858,6 +887,9 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
       Status = IopStartDevice(DeviceNode);
    }
 
+   /* Remove extra reference from IopInitializeDriverModule */
+   ObDereferenceObject(DriverObject);
+
    return Status;
 }
 
@@ -874,6 +906,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
  */
 VOID
 FASTCALL
+INIT_FUNCTION
 IopInitializeBootDrivers(VOID)
 {
     PLIST_ENTRY ListHead, NextEntry, NextEntry2;
@@ -918,6 +951,7 @@ IopInitializeBootDrivers(VOID)
     {
         /* Fail */
         IopFreeDeviceNode(DeviceNode);
+        ObDereferenceObject(DriverObject);
         return;
     }
 
@@ -927,22 +961,23 @@ IopInitializeBootDrivers(VOID)
     {
         /* Fail */
         IopFreeDeviceNode(DeviceNode);
+        ObDereferenceObject(DriverObject);
         return;
     }
 
     /* Get highest group order index */
     IopGroupIndex = PpInitGetGroupOrderIndex(NULL);
     if (IopGroupIndex == 0xFFFF) ASSERT(FALSE);
-    
+
     /* Allocate the group table */
     IopGroupTable = ExAllocatePoolWithTag(PagedPool,
                                           IopGroupIndex * sizeof(LIST_ENTRY),
                                           TAG_IO);
     if (IopGroupTable == NULL) ASSERT(FALSE);
-    
+
     /* Initialize the group table lists */
     for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
-    
+
     /* Loop the boot modules */
     ListHead = &KeLoaderBlock->LoadOrderListHead;
     NextEntry = ListHead->Flink;
@@ -952,18 +987,18 @@ IopInitializeBootDrivers(VOID)
         LdrEntry = CONTAINING_RECORD(NextEntry,
                                      LDR_DATA_TABLE_ENTRY,
                                      InLoadOrderLinks);
-                                     
+
         /* Check if the DLL needs to be initialized */
         if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
         {
             /* Call its entrypoint */
             MmCallDllInitialize(LdrEntry, NULL);
         }
-        
+
         /* Go to the next driver */
         NextEntry = NextEntry->Flink;
     }
-    
+
     /* Loop the boot drivers */
     ListHead = &KeLoaderBlock->BootDriverListHead;
     NextEntry = ListHead->Flink;
@@ -973,10 +1008,10 @@ IopInitializeBootDrivers(VOID)
         BootEntry = CONTAINING_RECORD(NextEntry,
                                       BOOT_DRIVER_LIST_ENTRY,
                                       Link);
-        
+
         /* Get the driver loader entry */
         LdrEntry = BootEntry->LdrEntry;
-        
+
         /* Allocate our internal accounting structure */
         DriverInfo = ExAllocatePoolWithTag(PagedPool,
                                            sizeof(DRIVER_INFORMATION),
@@ -987,24 +1022,24 @@ IopInitializeBootDrivers(VOID)
             RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION));
             InitializeListHead(&DriverInfo->Link);
             DriverInfo->DataTableEntry = BootEntry;
-            
+
             /* Open the registry key */
             Status = IopOpenRegistryKeyEx(&KeyHandle,
                                           NULL,
                                           &BootEntry->RegistryPath,
                                           KEY_READ);
             if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */
-                ((KeLoaderBlock->SetupLdrBlock) && (KeyHandle = (PVOID)1)))
+                ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment!
             {
                 /* Save the handle */
                 DriverInfo->ServiceHandle = KeyHandle;
-                
+
                 /* Get the group oder index */
                 Index = PpInitGetGroupOrderIndex(KeyHandle);
-                
+
                 /* Get the tag position */
                 DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle);
-                
+
                 /* Insert it into the list, at the right place */
                 ASSERT(Index < IopGroupIndex);
                 NextEntry2 = IopGroupTable[Index].Flink;
@@ -1014,18 +1049,18 @@ IopInitializeBootDrivers(VOID)
                     DriverInfoTag = CONTAINING_RECORD(NextEntry2,
                                                       DRIVER_INFORMATION,
                                                       Link);
-                    
+
                     /* Check if we found the right tag position */
                     if (DriverInfoTag->TagPosition > DriverInfo->TagPosition)
                     {
                         /* We're done */
                         break;
                     }
-                    
+
                     /* Next entry */
                     NextEntry2 = NextEntry2->Flink;
                 }
-                
+
                 /* Insert us right before the next entry */
                 NextEntry2 = NextEntry2->Blink;
                 InsertHeadList(NextEntry2, &DriverInfo->Link);
@@ -1047,45 +1082,46 @@ IopInitializeBootDrivers(VOID)
             DriverInfo = CONTAINING_RECORD(NextEntry,
                                            DRIVER_INFORMATION,
                                            Link);
-            
+
             /* Get the driver loader entry */
             LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
-            
+
             /* Initialize it */
             IopInitializeBuiltinDriver(LdrEntry);
-            
+
             /* Next entry */
             NextEntry = NextEntry->Flink;
         }
     }
-    
+
     /* In old ROS, the loader list became empty after this point. Simulate. */
     InitializeListHead(&KeLoaderBlock->LoadOrderListHead);
 }
 
 VOID
 FASTCALL
+INIT_FUNCTION
 IopInitializeSystemDrivers(VOID)
 {
     PUNICODE_STRING *DriverList, *SavedList;
-    
+
     /* No system drivers on the boot cd */
     if (KeLoaderBlock->SetupLdrBlock) return;
-    
+
     /* Get the driver list */
     SavedList = DriverList = CmGetSystemDriverList();
     ASSERT(DriverList);
-    
+
     /* Loop it */
     while (*DriverList)
     {
         /* Load the driver */
         ZwLoadDriver(*DriverList);
-        
+
         /* Free the entry */
         RtlFreeUnicodeString(*DriverList);
         ExFreePool(*DriverList);
-        
+
         /* Next entry */
         InbvIndicateProgress();
         DriverList++;
@@ -1151,7 +1187,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
     * Construct the driver object name
     */
 
-   ObjectName.Length = (wcslen(Start) + 8) * sizeof(WCHAR);
+   ObjectName.Length = ((USHORT)wcslen(Start) + 8) * sizeof(WCHAR);
    ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR);
    ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength);
    if (!ObjectName.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
@@ -1237,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 */
@@ -1267,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;
 
@@ -1306,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);
 
@@ -1391,8 +1432,7 @@ NTAPI
 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
                 IN PDRIVER_INITIALIZE InitializationFunction,
                 IN PUNICODE_STRING RegistryPath,
-                IN PVOID DllBase,
-                IN ULONG SizeOfImage,
+                PLDR_DATA_TABLE_ENTRY ModuleObject,
                 OUT PDRIVER_OBJECT *pDriverObject)
 {
     WCHAR NameBuffer[100];
@@ -1450,11 +1490,11 @@ 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;
-
+    DriverObject->DriverSection = ModuleObject;
     /* Loop all Major Functions */
     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
     {
@@ -1516,6 +1556,10 @@ try_again:
                                        KernelMode,
                                        (PVOID*)&DriverObject,
                                        NULL);
+
+    /* Close the extra handle */
+    ZwClose(hDriver);
+
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
@@ -1524,12 +1568,9 @@ try_again:
         return Status;
     }
 
-    /* Close the extra handle */
-    ZwClose(hDriver);
-
     DriverObject->HardwareDatabase = &IopHardwareDatabaseKey;
-    DriverObject->DriverStart = DllBase;
-    DriverObject->DriverSize = SizeOfImage;
+    DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0;
+    DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0;
 
     /* Finally, call its init function */
     DPRINT("RegistryKey: %wZ\n", RegistryPath);
@@ -1539,8 +1580,10 @@ try_again:
     {
         /* If it didn't work, then kill the object */
         DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status);
+        DriverObject->DriverSection = NULL;
         ObMakeTemporaryObject(DriverObject);
         ObDereferenceObject(DriverObject);
+        return Status;
     }
     else
     {
@@ -1548,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++)
     {
@@ -1584,7 +1631,7 @@ IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
                IN PDRIVER_INITIALIZE InitializationFunction)
 {
    PDRIVER_OBJECT DriverObject;
-   return IopCreateDriver(DriverName, InitializationFunction, NULL, 0, 0, &DriverObject);
+   return IopCreateDriver(DriverName, InitializationFunction, NULL, NULL, &DriverObject);
 }
 
 /*
@@ -1725,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;
     }
 
@@ -1820,8 +1867,6 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
       cur--;
    }
 
-   IopDisplayLoadingMessage(&ServiceName);
-
    /*
     * Get service type.
     */
@@ -1868,21 +1913,6 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
    DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
    DPRINT("Type: %lx\n", Type);
 
-   /*
-    * Create device node
-    */
-
-   /* Use IopRootDeviceNode for now */
-   Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
-      LoadParams->Status = Status;
-      (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
-      return;
-   }
-
    /* Get existing DriverObject pointer (in case the driver has
       already been loaded and initialized) */
    Status = IopGetDriverObject(
@@ -1897,48 +1927,47 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
         * Load the driver module
         */
 
+       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);
-           IopFreeDeviceNode(DeviceNode);
            LoadParams->Status = Status;
            (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
            return;
        }
 
-       /*
-        * Set a service name for the device node
-        */
-
-       RtlCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer);
-
        /*
         * 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 = IopInitializeDriverModule(
-               DeviceNode,
-               ModuleObject,
-               &DeviceNode->ServiceName,
-               (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
-               Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
-               &DriverObject);
-
-           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;
-           }
+           DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
+           MmUnloadSystemImage(ModuleObject);
+           LoadParams->Status = Status;
+           (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+           return;
        }
 
-       /* Store its DriverSection, so that it could be unloaded */
-       DriverObject->DriverSection = ModuleObject;
+       IopDisplayLoadingMessage(&DeviceNode->ServiceName);
+
+       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);
@@ -1947,12 +1976,10 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
    else
    {
       DPRINT("DriverObject already exist in ObjectManager\n");
+      Status = STATUS_IMAGE_ALREADY_LOADED;
 
       /* IopGetDriverObject references the DriverObject, so dereference it */
       ObDereferenceObject(DriverObject);
-
-      /* Free device node since driver loading failed */
-      IopFreeDeviceNode(DeviceNode);
    }
 
    /* Pass status to the caller and signal the event */