https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4c0585f96a2a8642d2319...
commit c4c0585f96a2a8642d2319e17b4bb834f2b943b7 Author: Victor Perevertkin victor.perevertkin@reactos.org AuthorDate: Thu Nov 26 04:39:38 2020 +0300 Commit: Victor Perevertkin victor.perevertkin@reactos.org CommitDate: Mon Jan 4 16:50:33 2021 +0300
[NTOS:IO][NTOS:PNP] Implement PiCallDriverAddDevice
- Move the driver's name obtaining logic into the IopGetDriverNames function - Create a new PiCallDriverAddDevice instead of PipCallDriverAddDevice and move it to pnpmgr/devaction.c file. Move around all its internal helpers too - Support a proper Windows-compatible driver loading order for a PDO (lower filters, main service, upper filters, etc.) - Set a correct Problem for the DeviceNode, in case of an error during driver loading - Check the Start Type for all drivers before loading - Do not try to load drivers during the early boot stage when there is no disk subsystem initialized --- ntoskrnl/include/internal/io.h | 46 ++- ntoskrnl/io/iomgr/driver.c | 603 ++++++++------------------------------- ntoskrnl/io/pnpmgr/devaction.c | 630 ++++++++++++++++++++++++++++++++++------- ntoskrnl/io/pnpmgr/devnode.c | 17 ++ ntoskrnl/io/pnpmgr/pnpinit.c | 139 --------- ntoskrnl/io/pnpmgr/pnpmgr.c | 69 ----- 6 files changed, 673 insertions(+), 831 deletions(-)
diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h index ad51265ba3f..65005373bd2 100644 --- a/ntoskrnl/include/internal/io.h +++ b/ntoskrnl/include/internal/io.h @@ -568,12 +568,9 @@ IopDetectResourceConflict( // PNP Routines // NTSTATUS -NTAPI -PipCallDriverAddDevice( - IN PDEVICE_NODE DeviceNode, - IN BOOLEAN LoadDriver, - IN PDRIVER_OBJECT DriverObject -); +PiCallDriverAddDevice( + _In_ PDEVICE_NODE DeviceNode, + _In_ BOOLEAN LoadDrivers);
NTSTATUS NTAPI @@ -612,6 +609,15 @@ PiInsertDevNode( _In_ PDEVICE_NODE DeviceNode, _In_ PDEVICE_NODE ParentNode);
+VOID +PiSetDevNodeProblem( + _In_ PDEVICE_NODE DeviceNode, + _In_ UINT32 Problem); + +VOID +PiClearDevNodeProblem( + _In_ PDEVICE_NODE DeviceNode); + NTSTATUS IopFreeDeviceNode( IN PDEVICE_NODE DeviceNode @@ -811,13 +817,6 @@ IopReadyDeviceObjects( IN PDRIVER_OBJECT Driver );
-NTSTATUS -FASTCALL -IopInitializeDevice( - IN PDEVICE_NODE DeviceNode, - IN PDRIVER_OBJECT DriverObject -); - NTSTATUS IopStartDevice( IN PDEVICE_NODE DeviceNode @@ -1110,26 +1109,17 @@ IopDeleteDriver( IN PVOID ObjectBody );
-NTSTATUS -FASTCALL -IopGetDriverObject( - OUT PDRIVER_OBJECT *DriverObject, - IN PUNICODE_STRING ServiceName, - IN BOOLEAN FileSystem -); - -NTSTATUS -FASTCALL -IopLoadServiceModule( - IN PUNICODE_STRING ServiceName, - OUT PLDR_DATA_TABLE_ENTRY *ModuleObject -); - NTSTATUS IopLoadDriver( _In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject);
+NTSTATUS +IopGetDriverNames( + _In_ HANDLE ServiceHandle, + _Out_ PUNICODE_STRING DriverName, + _Out_opt_ PUNICODE_STRING ServiceName); + NTSTATUS IopInitializeDriverModule( _In_ PLDR_DATA_TABLE_ENTRY ModuleObject, diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c index 994d7375af8..1e02c1cc213 100644 --- a/ntoskrnl/io/iomgr/driver.c +++ b/ntoskrnl/io/iomgr/driver.c @@ -122,64 +122,127 @@ IopDeleteDriver(IN PVOID ObjectBody) }
NTSTATUS -FASTCALL -IopGetDriverObject( - PDRIVER_OBJECT *DriverObject, - PUNICODE_STRING ServiceName, - BOOLEAN FileSystem) +IopGetDriverNames( + _In_ HANDLE ServiceHandle, + _Out_ PUNICODE_STRING DriverName, + _Out_opt_ PUNICODE_STRING ServiceName) { - PDRIVER_OBJECT Object; - UNICODE_STRING Prefix; - UNICODE_STRING DriverName; - NTSTATUS Status; + UNICODE_STRING driverName = {.Buffer = NULL}, serviceName; + PKEY_VALUE_FULL_INFORMATION kvInfo; + NTSTATUS status;
- DPRINT("IopGetDriverObject(%p '%wZ' %x)\n", - DriverObject, ServiceName, FileSystem); + PAGED_CODE();
- *DriverObject = NULL; + // 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); + return STATUS_ILL_FORMED_SERVICE_ENTRY; + }
- /* Create ModuleName string */ - if (ServiceName == NULL || ServiceName->Buffer == NULL) - /* We don't know which DriverObject we have to open */ - return STATUS_INVALID_PARAMETER_2; + driverName.Length = kvInfo->DataLength - sizeof(WCHAR), + driverName.MaximumLength = kvInfo->DataLength, + driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO); + if (!driverName.Buffer) + { + ExFreePool(kvInfo); + return STATUS_INSUFFICIENT_RESOURCES; + }
- if (FileSystem != FALSE) - RtlInitUnicodeString(&Prefix, FILESYSTEM_ROOT_NAME); - else - RtlInitUnicodeString(&Prefix, DRIVER_ROOT_NAME); + RtlMoveMemory(driverName.Buffer, + (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), + driverName.Length); + ExFreePool(kvInfo); + }
- DriverName.Length = 0; - DriverName.MaximumLength = Prefix.Length + ServiceName->Length + sizeof(UNICODE_NULL); - ASSERT(DriverName.MaximumLength > ServiceName->Length); - DriverName.Buffer = ExAllocatePoolWithTag(PagedPool, DriverName.MaximumLength, TAG_IO); - if (DriverName.Buffer == NULL) + // check if we need to get ServiceName as well + PKEY_BASIC_INFORMATION basicInfo; + if (!NT_SUCCESS(status) || ServiceName != NULL) { - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlAppendUnicodeStringToString(&DriverName, &Prefix); - RtlAppendUnicodeStringToString(&DriverName, ServiceName); + ULONG infoLength; + status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength); + if (status == STATUS_BUFFER_TOO_SMALL) + { + basicInfo = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO); + if (!basicInfo) + { + return STATUS_INSUFFICIENT_RESOURCES; + }
- DPRINT("Driver name: '%wZ'\n", &DriverName); + status = ZwQueryKey(ServiceHandle, KeyBasicInformation, basicInfo, infoLength, &infoLength); + if (!NT_SUCCESS(status)) + { + ExFreePoolWithTag(basicInfo, TAG_IO); + return status; + }
- /* Open driver object */ - Status = ObReferenceObjectByName(&DriverName, - OBJ_OPENIF | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, /* Attributes */ - NULL, /* PassedAccessState */ - 0, /* DesiredAccess */ - IoDriverObjectType, - KernelMode, - NULL, /* ParseContext */ - (PVOID*)&Object); - ExFreePoolWithTag(DriverName.Buffer, TAG_IO); - if (!NT_SUCCESS(Status)) + serviceName.Length = basicInfo->NameLength; + serviceName.MaximumLength = basicInfo->NameLength; + serviceName.Buffer = basicInfo->Name; + } + else + { + return NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status; + } + } + + // 2. there is no "ObjectName" - construct it ourselves. Depending on a driver type, + // it will be either "\Driver<ServiceName>" or "\FileSystem<ServiceName>" + if (driverName.Buffer == NULL) { - DPRINT("Failed to reference driver object, status=0x%08x\n", Status); - return Status; + status = IopGetRegistryValue(ServiceHandle, L"Type", &kvInfo); + if (!NT_SUCCESS(status) || kvInfo->Type != REG_DWORD) + { + ExFreePool(kvInfo); + ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName + return STATUS_ILL_FORMED_SERVICE_ENTRY; + } + + UINT32 driverType; + RtlMoveMemory(&driverType, (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), sizeof(UINT32)); + ExFreePool(kvInfo); + + driverName.Length = 0; + 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) + { + ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER) + RtlAppendUnicodeToString(&driverName, FILESYSTEM_ROOT_NAME); + else + RtlAppendUnicodeToString(&driverName, DRIVER_ROOT_NAME); + + RtlAppendUnicodeStringToString(&driverName, &serviceName); }
- *DriverObject = Object; + if (ServiceName) + { + PWCHAR buf = ExAllocatePoolWithTag(PagedPool, serviceName.Length, TAG_IO); + if (!buf) + { + ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName + ExFreePoolWithTag(driverName.Buffer, TAG_IO); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlMoveMemory(buf, serviceName.Buffer, serviceName.Length); + ServiceName->MaximumLength = serviceName.Length; + ServiceName->Length = serviceName.Length; + ServiceName->Buffer = buf; + } + ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName
- DPRINT("Driver Object: %p\n", Object); + *DriverName = driverName;
return STATUS_SUCCESS; } @@ -317,162 +380,6 @@ IopNormalizeImagePath( return STATUS_SUCCESS; }
-NTSTATUS -IopQueryServiceSettings( - _In_ PUNICODE_STRING ServiceName, - _Out_ PUNICODE_STRING ServiceImagePath, - _Out_ PULONG ServiceStart) -{ - NTSTATUS Status; - RTL_QUERY_REGISTRY_TABLE QueryTable[3]; - UNICODE_STRING CCSName = RTL_CONSTANT_STRING( - L"\Registry\Machine\SYSTEM\CurrentControlSet\Services"); - HANDLE CCSKey, ServiceKey; - - /* Open CurrentControlSet */ - Status = IopOpenRegistryKeyEx(&CCSKey, NULL, &CCSName, KEY_READ); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - &CCSName, Status); - return Status; - } - - /* Open service key */ - Status = IopOpenRegistryKeyEx(&ServiceKey, CCSKey, ServiceName, KEY_READ); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - ServiceName, Status); - ZwClose(CCSKey); - return Status; - } - - /* - * Get information about the service. - */ - RtlZeroMemory(QueryTable, sizeof(QueryTable)); - - RtlInitUnicodeString(ServiceImagePath, NULL); - - QueryTable[0].Name = L"Start"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[0].EntryContext = ServiceStart; - - QueryTable[1].Name = L"ImagePath"; - QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[1].EntryContext = ServiceImagePath; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - (PWSTR)ServiceKey, - QueryTable, - NULL, - NULL); - - ZwClose(ServiceKey); - ZwClose(CCSKey); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlQueryRegistryValues() failed for '%wZ' (Status %lx)\n", ServiceName, Status); - return Status; - } - - return Status; -} - -/* - * IopLoadServiceModule - * - * Load a module specified by registry settings for service. - * - * Parameters - * ServiceName - * Name of the service to load. - * - * Return Value - * Status - */ -NTSTATUS -FASTCALL -IopLoadServiceModule( - IN PUNICODE_STRING ServiceName, - OUT PLDR_DATA_TABLE_ENTRY *ModuleObject) -{ - ULONG ServiceStart; - UNICODE_STRING ServiceImagePath; - NTSTATUS Status; - PVOID BaseAddress; - - ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource)); - ASSERT(ServiceName->Length); - DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject); - - if (ExpInTextModeSetup) - { - /* We have no registry, but luckily we know where all the drivers are */ - DPRINT1("IopLoadServiceModule(%wZ, 0x%p) called in ExpInTextModeSetup mode...\n", ServiceName, ModuleObject); - - /* ServiceStart < 4 is all that matters */ - ServiceStart = 0; - - /* IopNormalizeImagePath will do all of the work for us if we give it an empty string */ - RtlInitEmptyUnicodeString(&ServiceImagePath, NULL, 0); - } - else - { - Status = IopQueryServiceSettings(ServiceName, &ServiceImagePath, &ServiceStart); - if (!NT_SUCCESS(Status)) - { - DPRINT("IopQueryServiceSettings() failed for '%wZ' (Status %lx)\n", ServiceName, Status); - return Status; - } - } - - /* - * Normalize the image path for all later processing. - */ - Status = IopNormalizeImagePath(&ServiceImagePath, ServiceName); - - if (!NT_SUCCESS(Status)) - { - DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); - return Status; - } - - /* - * 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); - - /* - * Now check if the module was loaded successfully. - */ - if (!NT_SUCCESS(Status)) - { - DPRINT("Module loading failed (Status %x)\n", Status); - } - - DPRINT("Module loading (Status %x)\n", Status); - - return Status; -} - /** * @brief Initialize a loaded driver * @@ -504,112 +411,18 @@ IopInitializeDriverModule(
PAGED_CODE();
- // get the ServiceName - PKEY_BASIC_INFORMATION basicInfo; - ULONG infoLength; - Status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength); - if (Status == STATUS_BUFFER_TOO_SMALL) - { - basicInfo = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO); - if (!basicInfo) - { - MmUnloadSystemImage(ModuleObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - Status = ZwQueryKey(ServiceHandle, KeyBasicInformation, basicInfo, infoLength, &infoLength); - if (!NT_SUCCESS(Status)) - { - ExFreePoolWithTag(basicInfo, TAG_IO); - MmUnloadSystemImage(ModuleObject); - return Status; - } - - ServiceName.Length = basicInfo->NameLength; - ServiceName.MaximumLength = basicInfo->NameLength; - ServiceName.Buffer = basicInfo->Name; - } - else + Status = IopGetDriverNames(ServiceHandle, &DriverName, &ServiceName); + if (!NT_SUCCESS(Status)) { MmUnloadSystemImage(ModuleObject); - return NT_SUCCESS(Status) ? STATUS_UNSUCCESSFUL : Status; - } - - // Make the DriverName field of a DRIVER_OBJECT - PKEY_VALUE_FULL_INFORMATION kvInfo; - - // 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); - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName - 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); - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName - MmUnloadSystemImage(ModuleObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlMoveMemory(DriverName.Buffer, - (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), - DriverName.Length); - ExFreePool(kvInfo); - } - else - { - // 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); - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName - MmUnloadSystemImage(ModuleObject); - return STATUS_ILL_FORMED_SERVICE_ENTRY; - } - - UINT32 driverType; - RtlMoveMemory(&driverType, (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), sizeof(UINT32)); - ExFreePool(kvInfo); - - DriverName.Length = 0; - 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) - { - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName - MmUnloadSystemImage(ModuleObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER) - RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME); - else - RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME); - - RtlAppendUnicodeStringToString(&DriverName, &ServiceName); + return Status; }
DPRINT("Driver name: '%wZ'\n", &DriverName);
// obtain the registry path for the DriverInit routine PKEY_NAME_INFORMATION nameInfo; + ULONG infoLength; Status = ZwQueryKey(ServiceHandle, KeyNameInformation, NULL, 0, &infoLength); if (Status == STATUS_BUFFER_TOO_SMALL) { @@ -644,7 +457,7 @@ IopInitializeDriverModule(
if (!NT_SUCCESS(Status)) { - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName + RtlFreeUnicodeString(&ServiceName); RtlFreeUnicodeString(&DriverName); MmUnloadSystemImage(ModuleObject); return Status; @@ -672,7 +485,7 @@ IopInitializeDriverModule( if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName + RtlFreeUnicodeString(&ServiceName); RtlFreeUnicodeString(&DriverName); MmUnloadSystemImage(ModuleObject); DPRINT1("Error while creating driver object "%wZ" status %x\n", &DriverName, Status); @@ -706,7 +519,7 @@ IopInitializeDriverModule( if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(nameInfo, TAG_IO); - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName + RtlFreeUnicodeString(&ServiceName); RtlFreeUnicodeString(&DriverName); return Status; } @@ -725,7 +538,7 @@ IopInitializeDriverModule( if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName + RtlFreeUnicodeString(&ServiceName); RtlFreeUnicodeString(&DriverName); return Status; } @@ -743,14 +556,14 @@ IopInitializeDriverModule( ObMakeTemporaryObject(driverObject); ObDereferenceObject(driverObject); ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName + RtlFreeUnicodeString(&ServiceName); RtlFreeUnicodeString(&DriverName); return STATUS_INSUFFICIENT_RESOURCES; }
/* Copy the name and set it in the driver extension */ RtlCopyUnicodeString(&serviceKeyName, &ServiceName); - ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName + RtlFreeUnicodeString(&ServiceName); driverObject->DriverExtension->ServiceKeyName = serviceKeyName;
/* Make a copy of the driver name to store in the driver object */ @@ -836,186 +649,6 @@ IopInitializeDriverModule( return STATUS_SUCCESS; }
-/* - * IopAttachFilterDriversCallback - * - * Internal routine used by IopAttachFilterDrivers. - */ -NTSTATUS -NTAPI -IopAttachFilterDriversCallback( - PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - PDEVICE_NODE DeviceNode = Context; - UNICODE_STRING ServiceName; - PWCHAR Filters; - PLDR_DATA_TABLE_ENTRY ModuleObject; - PDRIVER_OBJECT DriverObject; - NTSTATUS Status; - - /* No filter value present */ - if (ValueType == REG_NONE) - return STATUS_SUCCESS; - - for (Filters = ValueData; - ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength && - *Filters != 0; - 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); - - UNICODE_STRING RegistryPath; - - // Make the registry path for the driver - RegistryPath.Length = 0; - RegistryPath.MaximumLength = sizeof(ServicesKeyName) + ServiceName.Length; - RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, RegistryPath.MaximumLength, TAG_IO); - if (RegistryPath.Buffer == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlAppendUnicodeToString(&RegistryPath, ServicesKeyName); - RtlAppendUnicodeStringToString(&RegistryPath, &ServiceName); - - HANDLE serviceHandle; - Status = IopOpenRegistryKeyEx(&serviceHandle, NULL, &RegistryPath, KEY_READ); - RtlFreeUnicodeString(&RegistryPath); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - Status = IopGetDriverObject(&DriverObject, - &ServiceName, - FALSE); - if (!NT_SUCCESS(Status)) - { - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); - - /* Load and initialize the filter driver */ - Status = IopLoadServiceModule(&ServiceName, &ModuleObject); - if (!NT_SUCCESS(Status)) - { - ExReleaseResourceLite(&IopDriverLoadResource); - KeLeaveCriticalRegion(); - ZwClose(serviceHandle); - return Status; - } - - NTSTATUS driverEntryStatus; - Status = IopInitializeDriverModule(ModuleObject, - serviceHandle, - &DriverObject, - &driverEntryStatus); - - ExReleaseResourceLite(&IopDriverLoadResource); - KeLeaveCriticalRegion(); - - if (!NT_SUCCESS(Status)) - { - ZwClose(serviceHandle); - return Status; - } - } - - ZwClose(serviceHandle); - - Status = IopInitializeDevice(DeviceNode, DriverObject); - - /* Remove extra reference */ - ObDereferenceObject(DriverObject); - - if (!NT_SUCCESS(Status)) - return Status; - } - - return STATUS_SUCCESS; -} - -/* - * IopAttachFilterDrivers - * - * Load filter drivers for specified device node. - * - * Parameters - * Lower - * Set to TRUE for loading lower level filters or FALSE for upper - * level filters. - */ -NTSTATUS -FASTCALL -IopAttachFilterDrivers( - PDEVICE_NODE DeviceNode, - HANDLE EnumSubKey, - HANDLE ClassKey, - BOOLEAN Lower) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, }; - NTSTATUS Status; - - /* - * First load the device filters - */ - QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; - if (Lower) - QueryTable[0].Name = L"LowerFilters"; - else - QueryTable[0].Name = L"UpperFilters"; - QueryTable[0].Flags = 0; - QueryTable[0].DefaultType = REG_NONE; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - (PWSTR)EnumSubKey, - QueryTable, - DeviceNode, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to load device %s filters: %08X\n", - Lower ? "lower" : "upper", Status); - return Status; - } - - QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; - if (Lower) - QueryTable[0].Name = L"LowerFilters"; - else - QueryTable[0].Name = L"UpperFilters"; - QueryTable[0].EntryContext = NULL; - QueryTable[0].Flags = 0; - QueryTable[0].DefaultType = REG_NONE; - - if (ClassKey == NULL) - { - return STATUS_SUCCESS; - } - - Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - (PWSTR)ClassKey, - QueryTable, - DeviceNode, - NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to load class %s filters: %08X\n", - Lower ? "lower" : "upper", Status); - return Status; - } - - return STATUS_SUCCESS; -} - NTSTATUS NTAPI MiResolveImageReferences(IN PVOID ImageBase, diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c index 17347573216..12f3e443c30 100644 --- a/ntoskrnl/io/pnpmgr/devaction.c +++ b/ntoskrnl/io/pnpmgr/devaction.c @@ -49,6 +49,8 @@ KSPIN_LOCK IopDeviceActionLock; KEVENT PiEnumerationFinished; static const WCHAR ServicesKeyName[] = L"\Registry\Machine\System\CurrentControlSet\Services\";
+#define TAG_PNP_DEVACTION 'aDpP' + /* TYPES *********************************************************************/
typedef struct _DEVICE_ACTION_REQUEST @@ -60,6 +62,29 @@ typedef struct _DEVICE_ACTION_REQUEST DEVICE_ACTION Action; } DEVICE_ACTION_REQUEST, *PDEVICE_ACTION_REQUEST;
+typedef enum _ADD_DEV_DRIVER_TYPE +{ + LowerFilter, + LowerClassFilter, + DeviceDriver, + UpperFilter, + UpperClassFilter +} ADD_DEV_DRIVER_TYPE; + +typedef struct _ADD_DEV_DRIVERS_LIST +{ + LIST_ENTRY ListEntry; + PDRIVER_OBJECT DriverObject; + ADD_DEV_DRIVER_TYPE DriverType; +} ADD_DEV_DRIVERS_LIST, *PADD_DEV_DRIVERS_LIST; + +typedef struct _ATTACH_FILTER_DRIVERS_CONTEXT +{ + ADD_DEV_DRIVER_TYPE DriverType; + PDEVICE_NODE DeviceNode; + PLIST_ENTRY DriversListHead; +} ATTACH_FILTER_DRIVERS_CONTEXT, *PATTACH_FILTER_DRIVERS_CONTEXT; + /* FUNCTIONS *****************************************************************/
PDEVICE_OBJECT @@ -325,6 +350,500 @@ IopCreateDeviceInstancePath( return STATUS_SUCCESS; }
+/** + * @brief Loads and/or returns the driver associated with the registry entry if the driver + * is enabled. In case of an error, sets up a corresponding Problem to the DeviceNode + */ +static +NTSTATUS +NTAPI +PiAttachFilterDriversCallback( + PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Ctx, + PVOID EntryContext) +{ + PATTACH_FILTER_DRIVERS_CONTEXT context = Ctx; + PDRIVER_OBJECT DriverObject; + NTSTATUS Status; + BOOLEAN loadDrivers = (BOOLEAN)(ULONG_PTR)EntryContext; + + PAGED_CODE(); + + // No filter value present + if (ValueType != REG_SZ) + return STATUS_SUCCESS; + + if (ValueLength <= sizeof(WCHAR)) + return STATUS_OBJECT_NAME_NOT_FOUND; + + // open the service registry key + UNICODE_STRING serviceName = { .Length = 0 }, servicesKeyName; + RtlInitUnicodeString(&serviceName, ValueData); + RtlInitUnicodeString(&servicesKeyName, ServicesKeyName); + + HANDLE ccsServicesHandle, serviceHandle = NULL; + + Status = IopOpenRegistryKeyEx(&ccsServicesHandle, NULL, &servicesKeyName, KEY_READ); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open a registry key for "%wZ" (status %x)\n", &serviceName, Status); + return Status; + } + + Status = IopOpenRegistryKeyEx(&serviceHandle, ccsServicesHandle, &serviceName, KEY_READ); + ZwClose(ccsServicesHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open a registry key for "%wZ" (status %x)\n", &serviceName, Status); + return Status; + } + + PADD_DEV_DRIVERS_LIST driverEntry = ExAllocatePoolWithTag(PagedPool, + sizeof(*driverEntry), + TAG_PNP_DEVACTION); + + if (!driverEntry) + { + DPRINT1("Failed to allocate driverEntry for "%wZ"\n", &serviceName); + ZwClose(serviceHandle); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // check if the driver is disabled + PKEY_VALUE_FULL_INFORMATION kvInfo; + SERVICE_LOAD_TYPE startType = DisableLoad; + + Status = IopGetRegistryValue(serviceHandle, L"Start", &kvInfo); + if (NT_SUCCESS(Status) && kvInfo->Type == REG_DWORD) + { + RtlMoveMemory(&startType, + (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), + sizeof(startType)); + ExFreePool(kvInfo); + } + + // TODO: take into account other start types (like SERVICE_DEMAND_START) + if (startType >= DisableLoad) + { + if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM)) + { + PiSetDevNodeProblem(context->DeviceNode, CM_PROB_DISABLED_SERVICE); + } + + DPRINT("Service "%wZ" is disabled (start type %u)\n", &serviceName, startType); + Status = STATUS_UNSUCCESSFUL; + goto Cleanup; + } + + // check if the driver is already loaded + UNICODE_STRING driverName; + Status = IopGetDriverNames(serviceHandle, &driverName, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unable to obtain the driver name for "%wZ"\n", &serviceName); + goto Cleanup; + } + + // try to open it + Status = ObReferenceObjectByName(&driverName, + OBJ_OPENIF | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, /* PassedAccessState */ + 0, /* DesiredAccess */ + IoDriverObjectType, + KernelMode, + NULL, /* ParseContext */ + (PVOID*)&DriverObject); + RtlFreeUnicodeString(&driverName); + + // the driver was not probably loaded, try to load + if (!NT_SUCCESS(Status)) + { + if (loadDrivers) + { + Status = IopLoadDriver(serviceHandle, &DriverObject); + } + else + { + DPRINT("Service "%wZ" will not be loaded now\n", &serviceName); + // return failure, the driver will be loaded later (in a subsequent call) + Status = STATUS_UNSUCCESSFUL; + goto Cleanup; + } + } + + if (NT_SUCCESS(Status)) + { + driverEntry->DriverObject = DriverObject; + driverEntry->DriverType = context->DriverType; + InsertTailList(context->DriversListHead, &driverEntry->ListEntry); + ZwClose(serviceHandle); + return STATUS_SUCCESS; + } + else + { + if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM)) + { + switch (Status) + { + case STATUS_INSUFFICIENT_RESOURCES: + PiSetDevNodeProblem(context->DeviceNode, CM_PROB_OUT_OF_MEMORY); + break; + case STATUS_FAILED_DRIVER_ENTRY: + PiSetDevNodeProblem(context->DeviceNode, CM_PROB_FAILED_DRIVER_ENTRY); + break; + case STATUS_ILL_FORMED_SERVICE_ENTRY: + PiSetDevNodeProblem(context->DeviceNode, CM_PROB_DRIVER_SERVICE_KEY_INVALID); + break; + default: + PiSetDevNodeProblem(context->DeviceNode, CM_PROB_DRIVER_FAILED_LOAD); + break; + } + } + + DPRINT1("Failed to load driver "%wZ" for %wZ (status %x)\n", + &serviceName, &context->DeviceNode->InstancePath, Status); + } + +Cleanup: + ExFreePoolWithTag(driverEntry, TAG_PNP_DEVACTION); + if (serviceHandle) + { + ZwClose(serviceHandle); + } + return Status; +} + + +/** + * @brief Calls PiAttachFilterDriversCallback for filter drivers (if any) + */ +static +NTSTATUS +PiAttachFilterDrivers( + PLIST_ENTRY DriversListHead, + PDEVICE_NODE DeviceNode, + HANDLE EnumSubKey, + HANDLE ClassKey, + BOOLEAN Lower, + BOOLEAN LoadDrivers) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, }; + ATTACH_FILTER_DRIVERS_CONTEXT routineContext; + NTSTATUS Status; + + PAGED_CODE(); + + routineContext.DriversListHead = DriversListHead; + routineContext.DeviceNode = DeviceNode; + + // First add device filters + routineContext.DriverType = Lower ? LowerFilter : UpperFilter; + QueryTable[0] = (RTL_QUERY_REGISTRY_TABLE){ + .QueryRoutine = PiAttachFilterDriversCallback, + .Name = Lower ? L"LowerFilters" : L"UpperFilters", + .DefaultType = REG_NONE, + .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers + }; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PWSTR)EnumSubKey, + QueryTable, + &routineContext, + NULL); + if (ClassKey == NULL) + { + return Status; + } + + // Then add device class filters + routineContext.DriverType = Lower ? LowerClassFilter : UpperClassFilter; + QueryTable[0] = (RTL_QUERY_REGISTRY_TABLE){ + .QueryRoutine = PiAttachFilterDriversCallback, + .Name = Lower ? L"LowerFilters" : L"UpperFilters", + .DefaultType = REG_NONE, + .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers + }; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PWSTR)ClassKey, + QueryTable, + &routineContext, + NULL); + return Status; +} + +/** + * @brief Loads all drivers for a device node (actual service and filters) + * and calls their AddDevice routine + * + * @param[in] DeviceNode The device node + * @param[in] LoadDrivers Whether to load drivers if they are not loaded yet + * (used when storage subsystem is not yet initialized) + */ +NTSTATUS +PiCallDriverAddDevice( + _In_ PDEVICE_NODE DeviceNode, + _In_ BOOLEAN LoadDrivers) +{ + NTSTATUS Status; + HANDLE EnumRootKey, SubKey; + HANDLE ClassKey = NULL; + UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); + static UNICODE_STRING ccsControlClass = + RTL_CONSTANT_STRING(L"\Registry\Machine\System\CurrentControlSet\Control\Class"); + PKEY_VALUE_FULL_INFORMATION kvInfo = NULL; + + PAGED_CODE(); + + // open the enumeration root key + Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, &EnumRoot, KEY_READ); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IopOpenRegistryKeyEx() failed for "%wZ" (status %x)\n", &EnumRoot, Status); + return Status; + } + + // open an instance subkey + Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, &DeviceNode->InstancePath, KEY_READ); + ZwClose(EnumRootKey); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open a devnode instance key for "%wZ" (status %x)\n", + &DeviceNode->InstancePath, Status); + return Status; + } + + // try to get the class GUID of an instance and its registry key + Status = IopGetRegistryValue(SubKey, REGSTR_VAL_CLASSGUID, &kvInfo); + if (NT_SUCCESS(Status) && kvInfo->Type == REG_SZ && kvInfo->DataLength > sizeof(WCHAR)) + { + UNICODE_STRING classGUID = { + .MaximumLength = kvInfo->DataLength, + .Length = kvInfo->DataLength - sizeof(UNICODE_NULL), + .Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset) + }; + HANDLE ccsControlHandle; + + Status = IopOpenRegistryKeyEx(&ccsControlHandle, NULL, &ccsControlClass, KEY_READ); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IopOpenRegistryKeyEx() failed for "%wZ" (status %x)\n", + &ccsControlClass, Status); + } + else + { + // open the CCS\Constol\Class<ClassGUID> key + Status = IopOpenRegistryKeyEx(&ClassKey, ccsControlHandle, &classGUID, KEY_READ); + ZwClose(ccsControlHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open class key "%wZ" (status %x)\n", &classGUID, Status); + } + } + + if (ClassKey) + { + // Check the Properties key of a class too + // Windows fills some device properties from this key (which is protected) + // TODO: add the device properties from this key + + UNICODE_STRING properties = RTL_CONSTANT_STRING(REGSTR_KEY_DEVICE_PROPERTIES); + HANDLE propertiesHandle; + + Status = IopOpenRegistryKeyEx(&propertiesHandle, ClassKey, &properties, KEY_READ); + if (!NT_SUCCESS(Status)) + { + DPRINT("Properties key failed to open for "%wZ" (status %x)\n", + &classGUID, Status); + } + else + { + ZwClose(propertiesHandle); + } + } + ExFreePool(kvInfo); + } + + // the driver loading order: + // 1. LowerFilters + // 2. LowerClassFilters + // 3. Device driver (only one service!) + // 4. UpperFilters + // 5. UpperClassFilters + + LIST_ENTRY drvListHead; + InitializeListHead(&drvListHead); + + // lower (class) filters + Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, TRUE, LoadDrivers); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + ATTACH_FILTER_DRIVERS_CONTEXT routineContext = { + .DriversListHead = &drvListHead, + .DriverType = DeviceDriver, + .DeviceNode = DeviceNode + }; + + RTL_QUERY_REGISTRY_TABLE queryTable[2] = {{ + .QueryRoutine = PiAttachFilterDriversCallback, + .Name = L"Service", + .Flags = RTL_QUERY_REGISTRY_REQUIRED, + .DefaultType = REG_SZ, // REG_MULTI_SZ is not allowed here + .DefaultData = L"", + .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers + },}; + + // device driver + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PWSTR)SubKey, + queryTable, + &routineContext, + NULL); + if (NT_SUCCESS(Status)) + { + // do nothing + } + // if a driver is not found, but a device allows raw access -> proceed + else if (Status == STATUS_OBJECT_NAME_NOT_FOUND && + (DeviceNode->CapabilityFlags & 0x00000040)) // CM_DEVCAP_RAWDEVICEOK + { + // add a dummy entry to the drivers list (need for later processing) + PADD_DEV_DRIVERS_LIST driverEntry = ExAllocatePoolZero(PagedPool, + sizeof(*driverEntry), + TAG_PNP_DEVACTION); + driverEntry->DriverType = DeviceDriver; + InsertTailList(&drvListHead, &driverEntry->ListEntry); + DPRINT("No service for "%wZ" (RawDeviceOK)\n", &DeviceNode->InstancePath); + } + else + { + if (Status == STATUS_OBJECT_TYPE_MISMATCH && !(DeviceNode->Flags & DNF_HAS_PROBLEM)) + { + PiSetDevNodeProblem(DeviceNode, CM_PROB_REGISTRY); + } + DPRINT("No service for "%wZ" (loadDrv: %u)\n", &DeviceNode->InstancePath, LoadDrivers); + goto Cleanup; + } + + // upper (class) filters + Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, FALSE, LoadDrivers); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + // finally loop through the stack and call AddDevice for every driver + for (PLIST_ENTRY listEntry = drvListHead.Flink; + listEntry != &drvListHead; + listEntry = listEntry->Flink) + { + PADD_DEV_DRIVERS_LIST driverEntry; + driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry); + PDRIVER_OBJECT driverObject = driverEntry->DriverObject; + + // FIXME: ReactOS is not quite ready for this assert + // (legacy drivers should not have AddDevice routine) + // ASSERT(!(DriverObject->Flags & DRVO_LEGACY_DRIVER)); + + if (driverObject && driverObject->DriverExtension->AddDevice) + { + Status = driverObject->DriverExtension->AddDevice(driverEntry->DriverObject, + DeviceNode->PhysicalDeviceObject); + } + else if (driverObject == NULL) + { + // valid only for DeviceDriver + ASSERT(driverEntry->DriverType == DeviceDriver); + ASSERT(DeviceNode->CapabilityFlags & 0x00000040); // CM_DEVCAP_RAWDEVICEOK + Status = STATUS_SUCCESS; + } + else + { + // HACK: the driver doesn't have a AddDevice routine. We shouldn't be here, + // but ReactOS' PnP stack is not that correct yet + DeviceNode->Flags |= DNF_LEGACY_DRIVER; + Status = STATUS_UNSUCCESSFUL; + } + + // for filter drivers we don't care about the AddDevice result + if (driverEntry->DriverType == DeviceDriver) + { + if (NT_SUCCESS(Status)) + { + PDEVICE_OBJECT fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject); + + // HACK: Check if we have a ACPI device (needed for power management) + if (fdo->DeviceType == FILE_DEVICE_ACPI) + { + static BOOLEAN SystemPowerDeviceNodeCreated = FALSE; + + // There can be only one system power device + if (!SystemPowerDeviceNodeCreated) + { + PopSystemPowerDeviceNode = DeviceNode; + ObReferenceObject(PopSystemPowerDeviceNode->PhysicalDeviceObject); + SystemPowerDeviceNodeCreated = TRUE; + } + } + + ObDereferenceObject(fdo); + + IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); + } + else + { + // lower filters (if already started) will be removed upon this request + PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_ADD); + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + IopRemoveDevice(DeviceNode); + break; + } + } + +#if DBG + PDEVICE_OBJECT attachedDO = IoGetAttachedDevice(DeviceNode->PhysicalDeviceObject); + if (attachedDO->Flags & DO_DEVICE_INITIALIZING) + { + DPRINT1("DO_DEVICE_INITIALIZING is not cleared on a device 0x%p!\n", attachedDO); + } +#endif + } + +Cleanup: + while (!IsListEmpty(&drvListHead)) + { + PLIST_ENTRY listEntry = RemoveHeadList(&drvListHead); + PADD_DEV_DRIVERS_LIST driverEntry; + driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry); + + // drivers which don't have any devices (in case of failure) will be cleaned up + if (driverEntry->DriverObject) + { + ObDereferenceObject(driverEntry->DriverObject); + } + ExFreePoolWithTag(driverEntry, TAG_PNP_DEVACTION); + } + + ZwClose(SubKey); + if (ClassKey != NULL) + { + ZwClose(ClassKey); + } + + if (DeviceNode->Flags & DNF_ADDED) + { + IopStartDevice(DeviceNode); + } + + return Status; +} + NTSTATUS NTAPI IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, @@ -1008,8 +1527,6 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode, PVOID Context) { PDEVICE_NODE ParentDeviceNode; - NTSTATUS Status; - BOOLEAN BootDrivers = !PnpSystemInit;
DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode, Context);
@@ -1043,114 +1560,7 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode, IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED)) return STATUS_SUCCESS;
- if (DeviceNode->ServiceName.Buffer == NULL) - { - /* We don't need to worry about loading the driver because we're - * being driven in raw mode so our parent must be loaded to get here */ - Status = IopInitializeDevice(DeviceNode, NULL); - if (NT_SUCCESS(Status)) - { - Status = IopStartDevice(DeviceNode); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n", - &DeviceNode->InstancePath, Status); - } - } - } - else - { - PLDR_DATA_TABLE_ENTRY ModuleObject; - PDRIVER_OBJECT DriverObject; - - /* Get existing DriverObject pointer (in case the driver has - already been loaded and initialized) */ - Status = IopGetDriverObject( - &DriverObject, - &DeviceNode->ServiceName, - FALSE); - - if (!NT_SUCCESS(Status)) - { - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); - - /* Driver is not initialized, try to load it */ - Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject); - - if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED) - { - UNICODE_STRING RegistryPath; - - // obtain a handle for driver's RegistryPath - RegistryPath.Length = 0; - RegistryPath.MaximumLength = sizeof(ServicesKeyName) + DeviceNode->ServiceName.Length; - RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, RegistryPath.MaximumLength, TAG_IO); - if (RegistryPath.Buffer == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto OpenHandleFail; - } - RtlAppendUnicodeToString(&RegistryPath, ServicesKeyName); - RtlAppendUnicodeStringToString(&RegistryPath, &DeviceNode->ServiceName); - - HANDLE serviceHandle; - Status = IopOpenRegistryKeyEx(&serviceHandle, NULL, &RegistryPath, KEY_READ); - RtlFreeUnicodeString(&RegistryPath); - if (!NT_SUCCESS(Status)) - { - goto OpenHandleFail; - } - - /* Initialize the driver */ - NTSTATUS driverEntryStatus; - Status = IopInitializeDriverModule(ModuleObject, - serviceHandle, - &DriverObject, - &driverEntryStatus); - ZwClose(serviceHandle); - - if (!NT_SUCCESS(Status)) - DeviceNode->Problem = CM_PROB_FAILED_DRIVER_ENTRY; - } - else if (Status == STATUS_DRIVER_UNABLE_TO_LOAD) - { - DPRINT1("Service '%wZ' is disabled\n", &DeviceNode->ServiceName); - DeviceNode->Problem = CM_PROB_DISABLED_SERVICE; - } - else - { - DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n", - &DeviceNode->ServiceName, Status); - if (!BootDrivers) - DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD; - } -OpenHandleFail: - ExReleaseResourceLite(&IopDriverLoadResource); - KeLeaveCriticalRegion(); - } - - /* Driver is loaded and initialized at this point */ - if (NT_SUCCESS(Status)) - { - /* Initialize the device, including all filters */ - Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject); - - /* Remove the extra reference */ - ObDereferenceObject(DriverObject); - } - else - { - /* - * Don't disable when trying to load only boot drivers - */ - if (!BootDrivers) - { - IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); - } - } - } - + PiCallDriverAddDevice(DeviceNode, PnPBootDriversLoaded); return STATUS_SUCCESS; }
diff --git a/ntoskrnl/io/pnpmgr/devnode.c b/ntoskrnl/io/pnpmgr/devnode.c index 0442e1765c2..090419f18a9 100644 --- a/ntoskrnl/io/pnpmgr/devnode.c +++ b/ntoskrnl/io/pnpmgr/devnode.c @@ -100,6 +100,23 @@ PiInsertDevNode( DeviceNode->Level = ParentNode->Level + 1; }
+VOID +PiSetDevNodeProblem( + _In_ PDEVICE_NODE DeviceNode, + _In_ UINT32 Problem) +{ + DeviceNode->Flags |= DNF_HAS_PROBLEM; + DeviceNode->Problem = Problem; +} + +VOID +PiClearDevNodeProblem( + _In_ PDEVICE_NODE DeviceNode) +{ + DeviceNode->Flags &= ~DNF_HAS_PROBLEM; + DeviceNode->Problem = 0; +} + /** * @brief Creates a device node * diff --git a/ntoskrnl/io/pnpmgr/pnpinit.c b/ntoskrnl/io/pnpmgr/pnpinit.c index dd33a4b0258..e32c11e930d 100644 --- a/ntoskrnl/io/pnpmgr/pnpinit.c +++ b/ntoskrnl/io/pnpmgr/pnpinit.c @@ -286,145 +286,6 @@ Quickie: return i; }
-NTSTATUS -NTAPI -PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode, - IN BOOLEAN LoadDriver, - IN PDRIVER_OBJECT DriverObject) -{ - NTSTATUS Status; - HANDLE EnumRootKey, SubKey; - HANDLE ControlKey, ClassKey = NULL, PropertiesKey; - UNICODE_STRING ClassGuid, Properties; - UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); - UNICODE_STRING ControlClass = - RTL_CONSTANT_STRING(L"\Registry\Machine\System\CurrentControlSet\Control\Class"); - PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; - PWCHAR Buffer; - - /* Open enumeration root key */ - Status = IopOpenRegistryKeyEx(&EnumRootKey, - NULL, - &EnumRoot, - KEY_READ); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - &EnumRoot, Status); - return Status; - } - - /* Open instance subkey */ - Status = IopOpenRegistryKeyEx(&SubKey, - EnumRootKey, - &DeviceNode->InstancePath, - KEY_READ); - ZwClose(EnumRootKey); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - &DeviceNode->InstancePath, Status); - return Status; - } - - /* Get class GUID */ - Status = IopGetRegistryValue(SubKey, - REGSTR_VAL_CLASSGUID, - &KeyValueInformation); - if (NT_SUCCESS(Status)) - { - /* Convert to unicode string */ - Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); - PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length); - ClassGuid.MaximumLength = (USHORT)KeyValueInformation->DataLength; - ClassGuid.Buffer = Buffer; - - /* Open the key */ - Status = IopOpenRegistryKeyEx(&ControlKey, - NULL, - &ControlClass, - KEY_READ); - if (!NT_SUCCESS(Status)) - { - /* No class key */ - DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - &ControlClass, Status); - } - else - { - /* Open the class key */ - Status = IopOpenRegistryKeyEx(&ClassKey, - ControlKey, - &ClassGuid, - KEY_READ); - ZwClose(ControlKey); - if (!NT_SUCCESS(Status)) - { - /* No class key */ - DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - &ClassGuid, Status); - } - } - - /* Check if we made it till here */ - if (ClassKey) - { - /* Get the device properties */ - RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES); - Status = IopOpenRegistryKeyEx(&PropertiesKey, - ClassKey, - &Properties, - KEY_READ); - if (!NT_SUCCESS(Status)) - { - /* No properties */ - DPRINT("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", - &Properties, Status); - PropertiesKey = NULL; - } - else - { - ZwClose(PropertiesKey); - } - } - - /* Free the registry data */ - ExFreePool(KeyValueInformation); - } - - /* Do ReactOS-style setup */ - Status = IopAttachFilterDrivers(DeviceNode, SubKey, ClassKey, TRUE); - if (!NT_SUCCESS(Status)) - { - IopRemoveDevice(DeviceNode); - goto Exit; - } - - Status = IopInitializeDevice(DeviceNode, DriverObject); - if (!NT_SUCCESS(Status)) - { - goto Exit; - } - - Status = IopAttachFilterDrivers(DeviceNode, SubKey, ClassKey, FALSE); - if (!NT_SUCCESS(Status)) - { - IopRemoveDevice(DeviceNode); - goto Exit; - } - - Status = IopStartDevice(DeviceNode); - -Exit: - /* Close keys and return status */ - ZwClose(SubKey); - if (ClassKey != NULL) - { - ZwClose(ClassKey); - } - return Status; -} - CODE_SEG("INIT") NTSTATUS NTAPI diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c index 1a72481691b..37290335cfd 100644 --- a/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -390,75 +390,6 @@ IopInstallCriticalDevice(PDEVICE_NODE DeviceNode) ZwClose(CriticalDeviceKey); }
-NTSTATUS -FASTCALL -IopInitializeDevice(PDEVICE_NODE DeviceNode, - PDRIVER_OBJECT DriverObject) -{ - PDEVICE_OBJECT Fdo; - NTSTATUS Status; - - if (!DriverObject) - { - /* Special case for bus driven devices */ - DeviceNode->Flags |= DNF_ADDED; - return STATUS_SUCCESS; - } - - if (!DriverObject->DriverExtension->AddDevice) - { - DeviceNode->Flags |= DNF_LEGACY_DRIVER; - } - - if (DeviceNode->Flags & DNF_LEGACY_DRIVER) - { - DeviceNode->Flags |= (DNF_ADDED | DNF_STARTED); - return STATUS_SUCCESS; - } - - /* This is a Plug and Play driver */ - DPRINT("Plug and Play driver found\n"); - ASSERT(DeviceNode->PhysicalDeviceObject); - - DPRINT("Calling %wZ->AddDevice(%wZ)\n", - &DriverObject->DriverName, - &DeviceNode->InstancePath); - Status = DriverObject->DriverExtension->AddDevice(DriverObject, - DeviceNode->PhysicalDeviceObject); - if (!NT_SUCCESS(Status)) - { - DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n", - &DriverObject->DriverName, - &DeviceNode->InstancePath, - Status); - IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); - DeviceNode->Problem = CM_PROB_FAILED_ADD; - return Status; - } - - Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject); - - /* Check if we have a ACPI device (needed for power management) */ - if (Fdo->DeviceType == FILE_DEVICE_ACPI) - { - static BOOLEAN SystemPowerDeviceNodeCreated = FALSE; - - /* There can be only one system power device */ - if (!SystemPowerDeviceNodeCreated) - { - PopSystemPowerDeviceNode = DeviceNode; - ObReferenceObject(PopSystemPowerDeviceNode->PhysicalDeviceObject); - SystemPowerDeviceNodeCreated = TRUE; - } - } - - ObDereferenceObject(Fdo); - - IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); - - return STATUS_SUCCESS; -} - NTSTATUS IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) {