https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e18a32df3afc77e06cb8cb71010017b3780d3d34

commit e18a32df3afc77e06cb8cb71010017b3780d3d34
Author:     Victor Perevertkin <[email protected]>
AuthorDate: Fri Nov 20 17:18:43 2020 +0300
Commit:     Victor Perevertkin <[email protected]>
CommitDate: Mon Jan 4 16:50:32 2021 +0300

    [NTOS:IO] Refactoring of the driver initialization code
    
    - Remove IopCreateDriver and put its code into IoCreateDriver and
      IopInitializeDriverModule. It's hard to extract a meaningful common
      part from it
    - Refactor IopInitializeDriverModule. Extend and put the DriverName
      generation logic into it. Now this function frees the ModuleObject in
      case of failure and returns STATUS_FAILED_DRIVER_ENTRY in case of
      DriverInit failure (will be used later)
---
 ntoskrnl/include/internal/io.h |  19 +-
 ntoskrnl/include/internal/mm.h |   4 +
 ntoskrnl/io/iomgr/driver.c     | 431 ++++++++++++++++++++++++++++-------------
 ntoskrnl/io/pnpmgr/devaction.c |   5 +-
 4 files changed, 306 insertions(+), 153 deletions(-)

diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h
index 4e81a6f1c83..47d587d413c 100644
--- a/ntoskrnl/include/internal/io.h
+++ b/ntoskrnl/include/internal/io.h
@@ -1116,15 +1116,6 @@ IopInitializeSystemDrivers(
     VOID
 );
 
-NTSTATUS
-NTAPI
-IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
-                IN PDRIVER_INITIALIZE InitializationFunction,
-                IN PUNICODE_STRING RegistryPath OPTIONAL,
-                IN PCUNICODE_STRING ServiceName,
-                IN PLDR_DATA_TABLE_ENTRY ModuleObject OPTIONAL,
-                OUT PDRIVER_OBJECT *pDriverObject);
-
 VOID
 NTAPI
 IopDeleteDriver(
@@ -1154,13 +1145,11 @@ IopLoadUnloadDriver(
 );
 
 NTSTATUS
-FASTCALL
 IopInitializeDriverModule(
-    IN PLDR_DATA_TABLE_ENTRY ModuleObject,
-    IN PUNICODE_STRING ServiceName,
-    IN BOOLEAN FileSystemDriver,
-    OUT PDRIVER_OBJECT *DriverObject
-);
+    _In_ PLDR_DATA_TABLE_ENTRY ModuleObject,
+    _In_ PUNICODE_STRING ServiceName,
+    _Out_ PDRIVER_OBJECT *DriverObject,
+    _Out_ NTSTATUS *DriverEntryStatus);
 
 NTSTATUS
 FASTCALL
diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h
index 4ef728cd25b..e34f2fbb856 100644
--- a/ntoskrnl/include/internal/mm.h
+++ b/ntoskrnl/include/internal/mm.h
@@ -1401,6 +1401,10 @@ MmCallDllInitialize(
     IN PLIST_ENTRY ListHead
 );
 
+VOID
+NTAPI
+MmFreeDriverInitialization(
+    IN PLDR_DATA_TABLE_ENTRY LdrEntry);
 
 /* procsup.c *****************************************************************/
 
diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c
index f3f4c5a79a8..0451064f6bc 100644
--- a/ntoskrnl/io/iomgr/driver.c
+++ b/ntoskrnl/io/iomgr/driver.c
@@ -455,113 +455,320 @@ IopLoadServiceModule(
     return Status;
 }
 
-VOID
-NTAPI
-MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
-
-/*
- * IopInitializeDriverModule
+/**
+ * @brief      Initialize a loaded driver
  *
- * Initialize a loaded driver.
+ * @param[in]  ModuleObject
+ *     Module object representing the driver. It can be retrieved by 
IopLoadServiceModule.
+ *     Freed on failure, so in a such case this should not be accessed anymore
  *
- *    ModuleObject
- *       Module object representing the driver. It can be retrieve by
- *       IopLoadServiceModule.
+ * @param[in]  ServiceName
+ *     Name of the service (as in the registry)
  *
- *    ServiceName
- *       Name of the service (as in registry).
+ * @param[out] DriverObject
+ *     This contains the driver object if it was created (even with 
unsuccessfull result)
  *
- *    FileSystemDriver
- *       Set to TRUE for file system drivers.
+ * @param[out] DriverEntryStatus
+ *     This contains the status value returned by the driver's DriverEntry 
routine
+ *     (will not be valid of the return value is not STATUS_SUCCESS or 
STATUS_FAILED_DRIVER_ENTRY)
  *
- *    DriverObject
- *       On successful return this contains the driver object representing
- *       the loaded driver.
+ * @return     Status of the operation
  */
 NTSTATUS
-FASTCALL
 IopInitializeDriverModule(
-    IN PLDR_DATA_TABLE_ENTRY ModuleObject,
-    IN PUNICODE_STRING ServiceName,
-    IN BOOLEAN FileSystemDriver,
-    OUT PDRIVER_OBJECT *DriverObject)
+    _In_ PLDR_DATA_TABLE_ENTRY ModuleObject,
+    _In_ PUNICODE_STRING ServiceName,
+    _Out_ PDRIVER_OBJECT *OutDriverObject,
+    _Out_ NTSTATUS *DriverEntryStatus)
 {
     static const WCHAR ServicesKeyName[] = 
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
     UNICODE_STRING DriverName;
     UNICODE_STRING RegistryKey;
-    PDRIVER_INITIALIZE DriverEntry;
-    PDRIVER_OBJECT Driver;
     NTSTATUS Status;
 
-    DriverEntry = ModuleObject->EntryPoint;
+    PAGED_CODE();
 
-    if (ServiceName != NULL && ServiceName->Length != 0)
+    ASSERT(ServiceName && ServiceName->Length != 0);
+
+    // Make the registry path for the driver
+    RegistryKey.Length = 0;
+    RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length;
+    RegistryKey.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                               RegistryKey.MaximumLength,
+                                               TAG_IO);
+    if (RegistryKey.Buffer == NULL)
     {
-        RegistryKey.Length = 0;
-        RegistryKey.MaximumLength = sizeof(ServicesKeyName) + 
ServiceName->Length;
-        RegistryKey.Buffer = ExAllocatePoolWithTag(PagedPool,
-                                                   RegistryKey.MaximumLength,
-                                                   TAG_IO);
-        if (RegistryKey.Buffer == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName);
+    RtlAppendUnicodeStringToString(&RegistryKey, ServiceName);
+
+    // Open the registry key for this driver (it has to exist)
+    HANDLE serviceHandle;
+    PKEY_VALUE_FULL_INFORMATION kvInfo;
+
+    Status = IopOpenRegistryKeyEx(&serviceHandle, NULL, &RegistryKey, 
KEY_READ);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeUnicodeString(&RegistryKey);
+        MmUnloadSystemImage(ModuleObject);
+        return Status;
+    }
+
+    // Make the DriverName field of a DRIVER_OBJECT
+
+    // 1. Check the "ObjectName" field in the driver's registry key (it has 
the priority)
+    Status = IopGetRegistryValue(serviceHandle, L"ObjectName", &kvInfo);
+    if (NT_SUCCESS(Status))
+    {
+        // we're got the ObjectName. Use it to create the DRIVER_OBJECT
+        if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0)
+        {
+            ExFreePool(kvInfo);
+            ZwClose(serviceHandle);
+            RtlFreeUnicodeString(&RegistryKey);
+            MmUnloadSystemImage(ModuleObject);
+            return STATUS_ILL_FORMED_SERVICE_ENTRY;
+        }
+
+        DriverName.Length = kvInfo->DataLength - sizeof(WCHAR),
+        DriverName.MaximumLength = kvInfo->DataLength,
+        DriverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 
DriverName.MaximumLength, TAG_IO);
+        if (!DriverName.Buffer)
         {
+            ExFreePool(kvInfo);
+            ZwClose(serviceHandle);
+            RtlFreeUnicodeString(&RegistryKey);
+            MmUnloadSystemImage(ModuleObject);
             return STATUS_INSUFFICIENT_RESOURCES;
         }
-        RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName);
-        RtlAppendUnicodeStringToString(&RegistryKey, ServiceName);
+
+        RtlMoveMemory(DriverName.Buffer,
+                      (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
+                      DriverName.Length);
+        ExFreePool(kvInfo);
     }
     else
     {
-        RtlInitEmptyUnicodeString(&RegistryKey, NULL, 0);
-    }
+        // 2. there is no "ObjectName" - construct it ourselves. Depending on 
a driver type,
+        // it will be either "\Driver\<ServiceName>" or 
"\FileSystem\<ServiceName>"
+
+        Status = IopGetRegistryValue(serviceHandle, L"Type", &kvInfo);
+        if (!NT_SUCCESS(Status) || kvInfo->Type != REG_DWORD)
+        {
+            ExFreePool(kvInfo);
+            ZwClose(serviceHandle);
+            RtlFreeUnicodeString(&RegistryKey);
+            MmUnloadSystemImage(ModuleObject);
+            return STATUS_ILL_FORMED_SERVICE_ENTRY;
+        }
+
+        UINT32 driverType;
+        RtlMoveMemory(&driverType, (PVOID)((ULONG_PTR)kvInfo + 
kvInfo->DataOffset), sizeof(UINT32));
+        ExFreePool(kvInfo);
 
-    /* Create ModuleName string */
-    if (ServiceName && ServiceName->Length > 0)
-    {
         DriverName.Length = 0;
-        DriverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME) + 
ServiceName->Length;
-        DriverName.Buffer = ExAllocatePoolWithTag(PagedPool,
-                                                  DriverName.MaximumLength,
-                                                  TAG_IO);
-        if (DriverName.Buffer == NULL)
+        if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == 
SERVICE_FILE_SYSTEM_DRIVER)
+            DriverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME) + 
ServiceName->Length;
+        else
+            DriverName.MaximumLength = sizeof(DRIVER_ROOT_NAME) + 
ServiceName->Length;
+        DriverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 
DriverName.MaximumLength, TAG_IO);
+        if (!DriverName.Buffer)
         {
+            ZwClose(serviceHandle);
             RtlFreeUnicodeString(&RegistryKey);
+            MmUnloadSystemImage(ModuleObject);
             return STATUS_INSUFFICIENT_RESOURCES;
         }
 
-        if (FileSystemDriver != FALSE)
+        if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == 
SERVICE_FILE_SYSTEM_DRIVER)
             RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME);
         else
             RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME);
+
         RtlAppendUnicodeStringToString(&DriverName, ServiceName);
+    }
+
+    ZwClose(serviceHandle);
+
+    DPRINT("Driver name: '%wZ'\n", &DriverName);
+
+    // create the driver object
+    UINT32 ObjectSize = sizeof(DRIVER_OBJECT) + 
sizeof(EXTENDED_DRIVER_EXTENSION);
+    OBJECT_ATTRIBUTES objAttrs;
+    PDRIVER_OBJECT driverObject;
+    InitializeObjectAttributes(&objAttrs,
+                               &DriverName,
+                               OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | 
OBJ_KERNEL_HANDLE,
+                               NULL,
+                               NULL);
 
-        DPRINT("Driver name: '%wZ'\n", &DriverName);
+    Status = ObCreateObject(KernelMode,
+                            IoDriverObjectType,
+                            &objAttrs,
+                            KernelMode,
+                            NULL,
+                            ObjectSize,
+                            0,
+                            0,
+                            (PVOID*)&driverObject);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeUnicodeString(&RegistryKey);
+        RtlFreeUnicodeString(&DriverName);
+        MmUnloadSystemImage(ModuleObject);
+        DPRINT1("Error while creating driver object \"%wZ\" status %x\n", 
&DriverName, Status);
+        return Status;
     }
-    else
+
+    DPRINT("Created driver object 0x%p for \"%wZ\"\n", driverObject, 
&DriverName);
+
+    RtlZeroMemory(driverObject, ObjectSize);
+    driverObject->Type = IO_TYPE_DRIVER;
+    driverObject->Size = sizeof(DRIVER_OBJECT);
+    driverObject->Flags = DRVO_LEGACY_DRIVER; // TODO: check the WDM_DRIVER 
flag on the module
+    driverObject->DriverSection = ModuleObject;
+    driverObject->DriverStart = ModuleObject->DllBase;
+    driverObject->DriverSize = ModuleObject->SizeOfImage;
+    driverObject->DriverInit = ModuleObject->EntryPoint;
+    driverObject->HardwareDatabase = &IopHardwareDatabaseKey;
+    driverObject->DriverExtension = (PDRIVER_EXTENSION)(driverObject + 1);
+    driverObject->DriverExtension->DriverObject = driverObject;
+
+    /* Loop all Major Functions */
+    for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+    {
+        /* Invalidate each function */
+        driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
+    }
+
+    /* Add the Object and get its handle */
+    HANDLE hDriver;
+    Status = ObInsertObject(driverObject, NULL, FILE_READ_DATA, 0, NULL, 
&hDriver);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeUnicodeString(&RegistryKey);
+        RtlFreeUnicodeString(&DriverName);
+        MmUnloadSystemImage(ModuleObject); // TODO: is it needed here?
+        return Status;
+    }
+
+    /* Now reference it */
+    Status = ObReferenceObjectByHandle(hDriver,
+                                       0,
+                                       IoDriverObjectType,
+                                       KernelMode,
+                                       (PVOID*)&driverObject,
+                                       NULL);
+
+    /* Close the extra handle */
+    ZwClose(hDriver);
+
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeUnicodeString(&RegistryKey);
+        RtlFreeUnicodeString(&DriverName);
+        return Status;
+    }
+
+    /* Set up the service key name buffer */
+    UNICODE_STRING serviceKeyName;
+    serviceKeyName.Length = 0;
+    // put a NULL character at the end for Windows compatibility
+    serviceKeyName.MaximumLength = ServiceName->MaximumLength + 
sizeof(UNICODE_NULL);
+    serviceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                  serviceKeyName.MaximumLength,
+                                                  TAG_IO);
+    if (!serviceKeyName.Buffer)
+    {
+        ObMakeTemporaryObject(driverObject);
+        ObDereferenceObject(driverObject);
+        RtlFreeUnicodeString(&RegistryKey);
+        RtlFreeUnicodeString(&DriverName);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Copy the name and set it in the driver extension */
+    RtlCopyUnicodeString(&serviceKeyName, ServiceName);
+    driverObject->DriverExtension->ServiceKeyName = serviceKeyName;
+
+    /* Make a copy of the driver name to store in the driver object */
+    UNICODE_STRING driverNamePaged;
+    driverNamePaged.Length = 0;
+    // put a NULL character at the end for Windows compatibility
+    driverNamePaged.MaximumLength = DriverName.MaximumLength + 
sizeof(UNICODE_NULL);
+    driverNamePaged.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                   
driverNamePaged.MaximumLength,
+                                                   TAG_IO);
+    if (!driverNamePaged.Buffer)
     {
-        RtlInitEmptyUnicodeString(&DriverName, NULL, 0);
+        ObMakeTemporaryObject(driverObject);
+        ObDereferenceObject(driverObject);
+        RtlFreeUnicodeString(&RegistryKey);
+        RtlFreeUnicodeString(&DriverName);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlCopyUnicodeString(&driverNamePaged, &DriverName);
+    driverObject->DriverName = driverNamePaged;
+
+    /* Finally, call its init function */
+    Status = driverObject->DriverInit(driverObject, &RegistryKey);
+    *DriverEntryStatus = Status;
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", 
&DriverName, Status);
+        // return a special status value in case of failure
+        Status = STATUS_FAILED_DRIVER_ENTRY;
+    }
+
+    /* HACK: 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;
+    }
+
+    // Windows does this fixup - keep it for compatibility
+    for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+    {
+        /*
+         * Make sure the driver didn't set any dispatch entry point to NULL!
+         * Doing so is illegal; drivers shouldn't touch entry points they
+         * do not implement.
+         */
+
+        /* Check if it did so anyway */
+        if (!driverObject->MajorFunction[i])
+        {
+            /* Print a warning in the debug log */
+            DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to 
NULL!\n",
+                    &driverObject->DriverName, i);
+
+            /* Fix it up */
+            driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
+        }
     }
 
-    Status = IopCreateDriver(DriverName.Length > 0 ? &DriverName : NULL,
-                             DriverEntry,
-                             &RegistryKey,
-                             ServiceName,
-                             ModuleObject,
-                             &Driver);
+    // TODO: for legacy drivers, unload the driver if it didn't create any DO
+
     RtlFreeUnicodeString(&RegistryKey);
     RtlFreeUnicodeString(&DriverName);
 
     if (!NT_SUCCESS(Status))
     {
-        DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status);
+        // if the driver entry has been failed, clear the object
+        ObMakeTemporaryObject(driverObject);
+        ObDereferenceObject(driverObject);
         return Status;
     }
 
-    *DriverObject = Driver;
+    *OutDriverObject = driverObject;
 
-    MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)Driver->DriverSection);
+    
MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)driverObject->DriverSection);
 
     /* Set the driver as initialized */
-    IopReadyDeviceObjects(Driver);
+    IopReadyDeviceObjects(driverObject);
 
     if (PnpSystemInit) IopReinitializeDrivers();
 
@@ -621,10 +828,11 @@ IopAttachFilterDriversCallback(
                 return Status;
             }
 
+            NTSTATUS driverEntryStatus;
             Status = IopInitializeDriverModule(ModuleObject,
                                                &ServiceName,
-                                               FALSE,
-                                               &DriverObject);
+                                               &DriverObject,
+                                               &driverEntryStatus);
             if (!NT_SUCCESS(Status))
             {
                 ExReleaseResourceLite(&IopDriverLoadResource);
@@ -897,10 +1105,11 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY 
BootLdrEntry)
     /*
      * Initialize the driver
      */
+    NTSTATUS driverEntryStatus;
     Status = IopInitializeDriverModule(LdrEntry,
                                        &ServiceName,
-                                       FALSE,
-                                       &DriverObject);
+                                       &DriverObject,
+                                       &driverEntryStatus);
     RtlFreeUnicodeString(&ServiceName);
 
     if (!NT_SUCCESS(Status))
@@ -933,8 +1142,6 @@ IopInitializeBootDrivers(VOID)
 {
     PLIST_ENTRY ListHead, NextEntry, NextEntry2;
     PLDR_DATA_TABLE_ENTRY LdrEntry;
-    PDRIVER_OBJECT DriverObject;
-    LDR_DATA_TABLE_ENTRY ModuleObject;
     NTSTATUS Status;
     UNICODE_STRING DriverName;
     ULONG i, Index;
@@ -943,17 +1150,10 @@ IopInitializeBootDrivers(VOID)
     PBOOT_DRIVER_LIST_ENTRY BootEntry;
     DPRINT("IopInitializeBootDrivers()\n");
 
-    /* Setup the module object for the RAW FS Driver */
-    ModuleObject.DllBase = NULL;
-    ModuleObject.SizeOfImage = 0;
-    ModuleObject.EntryPoint = RawFsDriverEntry;
-    RtlInitUnicodeString(&DriverName, L"RAW");
-
-    /* Initialize it */
-    Status = IopInitializeDriverModule(&ModuleObject,
-                                       &DriverName,
-                                       TRUE,
-                                       &DriverObject);
+    /* Create the RAW FS built-in driver */
+    RtlInitUnicodeString(&DriverName, L"\\FileSystem\\RAW");
+
+    Status = IoCreateDriver(&DriverName, RawFsDriverEntry);
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
@@ -1461,14 +1661,16 @@ IopReinitializeBootDrivers(VOID)
     KeWaitForSingleObject(&PiEnumerationFinished, Executive, KernelMode, 
FALSE, NULL);
 }
 
+/* PUBLIC FUNCTIONS 
***********************************************************/
+
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
-IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
-                IN PDRIVER_INITIALIZE InitializationFunction,
-                IN PUNICODE_STRING RegistryPath OPTIONAL,
-                IN PCUNICODE_STRING ServiceName,
-                IN PLDR_DATA_TABLE_ENTRY ModuleObject OPTIONAL,
-                OUT PDRIVER_OBJECT *pDriverObject)
+IoCreateDriver(
+    _In_opt_ PUNICODE_STRING DriverName,
+    _In_ PDRIVER_INITIALIZE InitializationFunction)
 {
     WCHAR NameBuffer[100];
     USHORT NameLength;
@@ -1525,20 +1727,10 @@ try_again:
     RtlZeroMemory(DriverObject, ObjectSize);
     DriverObject->Type = IO_TYPE_DRIVER;
     DriverObject->Size = sizeof(DRIVER_OBJECT);
-
-    /*
-     * Check whether RegistryPath and ModuleObject are both NULL because
-     * IoCreateDriver() was called to initialize a built-in driver.
-     */
-    if ((RegistryPath != NULL) || (ModuleObject != NULL))
-        DriverObject->Flags = DRVO_LEGACY_DRIVER;
-    else
-        DriverObject->Flags = DRVO_BUILTIN_DRIVER;
-
+    DriverObject->Flags = DRVO_BUILTIN_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++)
     {
@@ -1547,10 +1739,8 @@ try_again:
     }
 
     /* Set up the service key name buffer */
-    ServiceKeyName.MaximumLength = ServiceName->Length + sizeof(UNICODE_NULL);
-    ServiceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
-                                                  ServiceKeyName.MaximumLength,
-                                                  TAG_IO);
+    ServiceKeyName.MaximumLength = LocalDriverName.Length + 
sizeof(UNICODE_NULL);
+    ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, 
LocalDriverName.MaximumLength, TAG_IO);
     if (!ServiceKeyName.Buffer)
     {
         /* Fail */
@@ -1559,9 +1749,9 @@ try_again:
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    /* Copy the name and set it in the driver extension */
-    RtlCopyUnicodeString(&ServiceKeyName,
-                         ServiceName);
+    /* For builtin drivers, the ServiceKeyName is equal to DriverName */
+    RtlCopyUnicodeString(&ServiceKeyName, &LocalDriverName);
+    ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = 
UNICODE_NULL;
     DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
 
     /* Make a copy of the driver name to store in the driver object */
@@ -1577,8 +1767,7 @@ try_again:
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    RtlCopyUnicodeString(&DriverObject->DriverName,
-                         &LocalDriverName);
+    RtlCopyUnicodeString(&DriverObject->DriverName, &LocalDriverName);
 
     /* Add the Object and get its handle */
     Status = ObInsertObject(DriverObject,
@@ -1617,34 +1806,19 @@ try_again:
         return Status;
     }
 
-    DriverObject->HardwareDatabase = &IopHardwareDatabaseKey;
-    DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0;
-    DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0;
-
     /* Finally, call its init function */
-    DPRINT("RegistryKey: %wZ\n", RegistryPath);
     DPRINT("Calling driver entrypoint at %p\n", InitializationFunction);
-    Status = (*InitializationFunction)(DriverObject, RegistryPath);
+    Status = (*InitializationFunction)(DriverObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         /* 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
-    {
-        /* Returns to caller the object */
-        *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 */
+    // Windows does this fixup - keep it for compatibility
     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
     {
         /*
@@ -1669,20 +1843,6 @@ try_again:
     return Status;
 }
 
-/* PUBLIC FUNCTIONS 
***********************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
-               IN PDRIVER_INITIALIZE InitializationFunction)
-{
-    PDRIVER_OBJECT DriverObject;
-    return IopCreateDriver(DriverName, InitializationFunction, NULL, 
DriverName, NULL, &DriverObject);
-}
-
 /*
  * @implemented
  */
@@ -2019,17 +2179,16 @@ IopLoadUnloadDriver(
          */
         IopDisplayLoadingMessage(&ServiceName);
 
+        NTSTATUS driverEntryStatus;
         Status = IopInitializeDriverModule(ModuleObject,
                                            &ServiceName,
-                                           (Type == SERVICE_FILE_SYSTEM_DRIVER 
||
-                                            Type == SERVICE_RECOGNIZER_DRIVER),
-                                           DriverObject);
+                                           DriverObject,
+                                           &driverEntryStatus);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", 
Status);
             ExReleaseResourceLite(&IopDriverLoadResource);
             KeLeaveCriticalRegion();
-            MmUnloadSystemImage(ModuleObject);
             return Status;
         }
 
diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c
index 99e4e2b944d..aebbf1a01c2 100644
--- a/ntoskrnl/io/pnpmgr/devaction.c
+++ b/ntoskrnl/io/pnpmgr/devaction.c
@@ -1079,10 +1079,11 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
             if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
             {
                 /* Initialize the driver */
+                NTSTATUS driverEntryStatus;
                 Status = IopInitializeDriverModule(ModuleObject,
                                                    &DeviceNode->ServiceName,
-                                                   FALSE,
-                                                   &DriverObject);
+                                                   &DriverObject,
+                                                   &driverEntryStatus);
                 if (!NT_SUCCESS(Status))
                     DeviceNode->Problem = CM_PROB_FAILED_DRIVER_ENTRY;
             }

Reply via email to