https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e18a32df3afc77e06cb8c…
commit e18a32df3afc77e06cb8cb71010017b3780d3d34
Author: Victor Perevertkin <victor.perevertkin(a)reactos.org>
AuthorDate: Fri Nov 20 17:18:43 2020 +0300
Commit: Victor Perevertkin <victor.perevertkin(a)reactos.org>
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;
}