diff --git a/ntoskrnl/io/pnpmgr/pnpmap.c b/ntoskrnl/io/pnpmgr/pnpmap.c index 795e4a3c2ce..97a170fc46d 100644 --- a/ntoskrnl/io/pnpmgr/pnpmap.c +++ b/ntoskrnl/io/pnpmgr/pnpmap.c @@ -18,68 +18,69 @@ static CODE_SEG("INIT") NTSTATUS IopEnumerateDetectedDevices( - IN HANDLE hBaseKey, - IN PUNICODE_STRING RelativePath OPTIONAL, - IN HANDLE hRootKey, - IN BOOLEAN EnumerateSubKeys, - IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources, - IN ULONG ParentBootResourcesLength) + _In_ HANDLE hBaseKey, + _In_opt_ PUNICODE_STRING RelativePath, + _In_ HANDLE hRootKey, + _In_ BOOLEAN EnumerateSubKeys, + _In_ PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources, + _In_ ULONG ParentBootResourcesLength) { - UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); - UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID"); - UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data"); - UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig"); - UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf"); - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hDevicesKey = NULL; - HANDLE hDeviceKey = NULL; - HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf; - UNICODE_STRING Level2NameU; - WCHAR Level2Name[5]; - ULONG IndexDevice = 0; - ULONG IndexSubKey; - PKEY_BASIC_INFORMATION pDeviceInformation = NULL; - ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR); - PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL; - ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); - UNICODE_STRING DeviceName, ValueName; - ULONG RequiredSize; - PCM_FULL_RESOURCE_DESCRIPTOR BootResources = NULL; - ULONG BootResourcesLength; - NTSTATUS Status; + UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); + UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID"); + UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data"); + UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig"); + UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf"); + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hDevicesKey = NULL; + HANDLE hDeviceKey = NULL; + HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf; + UNICODE_STRING Level2NameU; + WCHAR Level2Name[5]; + ULONG IndexDevice = 0; + ULONG IndexSubKey; + PKEY_BASIC_INFORMATION pDeviceInformation = NULL; + ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR); + PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL; + ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); + UNICODE_STRING DeviceName, ValueName; + ULONG RequiredSize; + PCM_FULL_RESOURCE_DESCRIPTOR BootResources = NULL; + ULONG BootResourcesLength; + NTSTATUS Status; - const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController"); - UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0"); - static ULONG DeviceIndexSerial = 0; - const UNICODE_STRING IdentifierKeyboard = RTL_CONSTANT_STRING(L"KeyboardController"); - UNICODE_STRING HardwareIdKeyboard = RTL_CONSTANT_STRING(L"*PNP0303\0"); - static ULONG DeviceIndexKeyboard = 0; - const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController"); - /* FIXME: IopEnumerateDetectedDevices() should be rewritten. - * The PnP identifiers can either be hardcoded or parsed from a LegacyXlate - * sections of driver INF files. - */ + const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController"); + UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0"); + static ULONG DeviceIndexSerial = 0; + const UNICODE_STRING IdentifierKeyboard = RTL_CONSTANT_STRING(L"KeyboardController"); + UNICODE_STRING HardwareIdKeyboard = RTL_CONSTANT_STRING(L"*PNP0303\0"); + static ULONG DeviceIndexKeyboard = 0; + const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController"); + /* FIXME: IopEnumerateDetectedDevices() should be rewritten. + * The PnP identifiers can either be hardcoded or parsed from a LegacyXlate + * sections of driver INF files. + */ #if defined(SARCH_PC98) - UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*nEC1F00\0"); + UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*nEC1F00\0"); #else - UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0"); + UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0"); #endif - static ULONG DeviceIndexMouse = 0; - const UNICODE_STRING IdentifierParallel = RTL_CONSTANT_STRING(L"ParallelController"); - UNICODE_STRING HardwareIdParallel = RTL_CONSTANT_STRING(L"*PNP0400\0"); - static ULONG DeviceIndexParallel = 0; - const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral"); - UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0"); - static ULONG DeviceIndexFloppy = 0; - UNICODE_STRING HardwareIdKey; - PUNICODE_STRING pHardwareId; - ULONG DeviceIndex = 0; - PUCHAR CmResourceList; - ULONG ListCount; + static ULONG DeviceIndexMouse = 0; + const UNICODE_STRING IdentifierParallel = RTL_CONSTANT_STRING(L"ParallelController"); + UNICODE_STRING HardwareIdParallel = RTL_CONSTANT_STRING(L"*PNP0400\0"); + static ULONG DeviceIndexParallel = 0; + const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral"); + UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0"); + static ULONG DeviceIndexFloppy = 0; + UNICODE_STRING HardwareIdKey; + PUNICODE_STRING pHardwareId; + ULONG DeviceIndex = 0; + PUCHAR CmResourceList; + ULONG ListCount; if (RelativePath) { Status = IopOpenRegistryKeyEx(&hDevicesKey, hBaseKey, RelativePath, KEY_ENUMERATE_SUB_KEYS); + if (!NT_SUCCESS(Status)) { DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); @@ -89,370 +90,444 @@ IopEnumerateDetectedDevices( else hDevicesKey = hBaseKey; - pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); - if (!pDeviceInformation) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_NO_MEMORY; - goto cleanup; - } + pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); + if (!pDeviceInformation) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_NO_MEMORY; + goto cleanup; + } - pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); - if (!pValueInformation) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_NO_MEMORY; - goto cleanup; - } + pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); + if (!pValueInformation) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_NO_MEMORY; + goto cleanup; + } - while (TRUE) - { - Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); - if (Status == STATUS_NO_MORE_ENTRIES) - break; - else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) - { - ExFreePool(pDeviceInformation); - DeviceInfoLength = RequiredSize; - pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); - if (!pDeviceInformation) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_NO_MEMORY; - goto cleanup; - } - Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); - } - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - IndexDevice++; + while (TRUE) + { + Status = ZwEnumerateKey(hDevicesKey, + IndexDevice, + KeyBasicInformation, + pDeviceInformation, + DeviceInfoLength, + &RequiredSize); - /* Open device key */ - DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; - DeviceName.Buffer = pDeviceInformation->Name; + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) + { + ExFreePool(pDeviceInformation); + DeviceInfoLength = RequiredSize; + pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); - Status = IopOpenRegistryKeyEx(&hDeviceKey, hDevicesKey, &DeviceName, - KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0)); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - /* Read boot resources, and add then to parent ones */ - Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); - if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) - { - ExFreePool(pValueInformation); - ValueInfoLength = RequiredSize; - pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); - if (!pValueInformation) - { - DPRINT("ExAllocatePool() failed\n"); - ZwDeleteKey(hLevel2Key); - Status = STATUS_NO_MEMORY; - goto cleanup; - } - Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); - } - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - BootResources = ParentBootResources; - BootResourcesLength = ParentBootResourcesLength; - } - else if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); - goto nextdevice; - } - else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR) - { - DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR); - goto nextdevice; - } - else - { - static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors); - - /* Concatenate current resources and parent ones */ - if (ParentBootResourcesLength == 0) - BootResourcesLength = pValueInformation->DataLength; - else - BootResourcesLength = ParentBootResourcesLength - + pValueInformation->DataLength - - Header; - BootResources = ExAllocatePool(PagedPool, BootResourcesLength); - if (!BootResources) - { - DPRINT("ExAllocatePool() failed\n"); - goto nextdevice; - } - if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) - { - RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); - } - else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific) - { - RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); - RtlCopyMemory( - (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength), - (PVOID)((ULONG_PTR)ParentBootResources + Header), - ParentBootResourcesLength - Header); - BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; - } - else - { - RtlCopyMemory(BootResources, pValueInformation->Data, Header); - RtlCopyMemory( - (PVOID)((ULONG_PTR)BootResources + Header), - (PVOID)((ULONG_PTR)ParentBootResources + Header), - ParentBootResourcesLength - Header); - RtlCopyMemory( - (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength), - pValueInformation->Data + Header, - pValueInformation->DataLength - Header); - BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; - } - } - - if (EnumerateSubKeys) - { - IndexSubKey = 0; - while (TRUE) - { - Status = ZwEnumerateKey(hDeviceKey, IndexSubKey, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); - if (Status == STATUS_NO_MORE_ENTRIES) - break; - else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) + if (!pDeviceInformation) { - ExFreePool(pDeviceInformation); - DeviceInfoLength = RequiredSize; - pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); - if (!pDeviceInformation) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_NO_MEMORY; - goto cleanup; - } - Status = ZwEnumerateKey(hDeviceKey, IndexSubKey, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_NO_MEMORY; + goto cleanup; } - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - IndexSubKey++; - DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; - DeviceName.Buffer = pDeviceInformation->Name; - Status = IopEnumerateDetectedDevices( - hDeviceKey, - &DeviceName, - hRootKey, - TRUE, - BootResources, - BootResourcesLength); - if (!NT_SUCCESS(Status)) - goto cleanup; - } - } + Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); + } - /* Read identifier */ - Status = ZwQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); - if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) - { - ExFreePool(pValueInformation); - ValueInfoLength = RequiredSize; - pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); - if (!pValueInformation) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_NO_MEMORY; + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; - } - Status = ZwQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); - } - if (!NT_SUCCESS(Status)) - { - if (Status != STATUS_OBJECT_NAME_NOT_FOUND) - { + } + IndexDevice++; + + /* Open device key */ + DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; + DeviceName.Buffer = pDeviceInformation->Name; + + Status = IopOpenRegistryKeyEx(&hDeviceKey, hDevicesKey, &DeviceName, + KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0)); + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + /* Read boot resources, and add then to parent ones */ + Status = ZwQueryValueKey(hDeviceKey, + &ConfigurationDataU, + KeyValuePartialInformation, + pValueInformation, + ValueInfoLength, + &RequiredSize); + + if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) + { + ExFreePool(pValueInformation); + ValueInfoLength = RequiredSize; + pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); + + if (!pValueInformation) + { + DPRINT("ExAllocatePool() failed\n"); + ZwDeleteKey(hLevel2Key); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + + Status = ZwQueryValueKey(hDeviceKey, + &ConfigurationDataU, + KeyValuePartialInformation, + pValueInformation, + ValueInfoLength, + &RequiredSize); + } + + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + BootResources = ParentBootResources; + BootResourcesLength = ParentBootResourcesLength; + } + else if (!NT_SUCCESS(Status)) + { DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); goto nextdevice; - } - ValueName.Length = ValueName.MaximumLength = 0; - } - else if (pValueInformation->Type != REG_SZ) - { - DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ); - goto nextdevice; - } - else - { - /* Assign hardware id to this device */ - ValueName.Length = ValueName.MaximumLength = (USHORT)pValueInformation->DataLength; - ValueName.Buffer = (PWCHAR)pValueInformation->Data; - if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) - ValueName.Length -= sizeof(WCHAR); - } - - if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0) - { - pHardwareId = &HardwareIdSerial; - DeviceIndex = DeviceIndexSerial++; - } - else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0) - { - pHardwareId = &HardwareIdKeyboard; - DeviceIndex = DeviceIndexKeyboard++; - } - else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0) - { - pHardwareId = &HardwareIdMouse; - DeviceIndex = DeviceIndexMouse++; - } - else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0) - { - pHardwareId = &HardwareIdParallel; - DeviceIndex = DeviceIndexParallel++; - } - else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0) - { - pHardwareId = &HardwareIdFloppy; - DeviceIndex = DeviceIndexFloppy++; - } - else - { - /* Unknown key path */ - DPRINT("Unknown key path '%wZ'\n", RelativePath); - goto nextdevice; - } - - /* Prepare hardware id key (hardware id value without final \0) */ - HardwareIdKey = *pHardwareId; - HardwareIdKey.Length -= sizeof(UNICODE_NULL); - - /* Add the detected device to Root key */ - InitializeObjectAttributes(&ObjectAttributes, &HardwareIdKey, OBJ_KERNEL_HANDLE, hRootKey, NULL); - Status = ZwCreateKey( - &hLevel1Key, - KEY_CREATE_SUB_KEY, - &ObjectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - goto nextdevice; - } - swprintf(Level2Name, L"%04lu", DeviceIndex); - RtlInitUnicodeString(&Level2NameU, Level2Name); - InitializeObjectAttributes(&ObjectAttributes, &Level2NameU, OBJ_KERNEL_HANDLE, hLevel1Key, NULL); - Status = ZwCreateKey( - &hLevel2Key, - KEY_SET_VALUE | KEY_CREATE_SUB_KEY, - &ObjectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - ZwClose(hLevel1Key); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - goto nextdevice; - } - DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey); - Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; - } - /* Create 'LogConf' subkey */ - InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL); - Status = ZwCreateKey( - &hLogConf, - KEY_SET_VALUE, - &ObjectAttributes, - 0, - NULL, - REG_OPTION_VOLATILE, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; - } - if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) - { - CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG)); - if (!CmResourceList) - { - ZwClose(hLogConf); - ZwDeleteKey(hLevel2Key); + } + else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR) + { + DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR); goto nextdevice; - } + } + else + { + static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors); - /* Add the list count (1st member of CM_RESOURCE_LIST) */ - ListCount = 1; - RtlCopyMemory(CmResourceList, - &ListCount, - sizeof(ULONG)); + /* Concatenate current resources and parent ones */ + if (ParentBootResourcesLength == 0) + BootResourcesLength = pValueInformation->DataLength; + else + BootResourcesLength = ParentBootResourcesLength + + pValueInformation->DataLength + - Header; - /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */ - RtlCopyMemory(CmResourceList + sizeof(ULONG), - BootResources, - BootResourcesLength); + BootResources = ExAllocatePool(PagedPool, BootResourcesLength); + if (!BootResources) + { + DPRINT("ExAllocatePool() failed\n"); + goto nextdevice; + } - /* Save boot resources to 'LogConf\BootConfig' */ - Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_RESOURCE_LIST, CmResourceList, BootResourcesLength + sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { + if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) + { + RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); + } + else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific) + { + RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); + RtlCopyMemory( + (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength), + (PVOID)((ULONG_PTR)ParentBootResources + Header), + ParentBootResourcesLength - Header); + BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; + } + else + { + RtlCopyMemory(BootResources, pValueInformation->Data, Header); + RtlCopyMemory( + (PVOID)((ULONG_PTR)BootResources + Header), + (PVOID)((ULONG_PTR)ParentBootResources + Header), + ParentBootResourcesLength - Header); + RtlCopyMemory( + (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength), + pValueInformation->Data + Header, + pValueInformation->DataLength - Header); + BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; + } + } + + if (EnumerateSubKeys) + { + IndexSubKey = 0; + + while (TRUE) + { + Status = ZwEnumerateKey(hDeviceKey, + IndexSubKey, + KeyBasicInformation, + pDeviceInformation, + DeviceInfoLength, + &RequiredSize); + + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) + { + ExFreePool(pDeviceInformation); + DeviceInfoLength = RequiredSize; + pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); + + if (!pDeviceInformation) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + + Status = ZwEnumerateKey(hDeviceKey, + IndexSubKey, + KeyBasicInformation, + pDeviceInformation, + DeviceInfoLength, + &RequiredSize); + } + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + IndexSubKey++; + DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; + DeviceName.Buffer = pDeviceInformation->Name; + + Status = IopEnumerateDetectedDevices( + hDeviceKey, + &DeviceName, + hRootKey, + TRUE, + BootResources, + BootResourcesLength); + + if (!NT_SUCCESS(Status)) + goto cleanup; + } + } + + /* Read identifier */ + Status = ZwQueryValueKey(hDeviceKey, + &IdentifierU, + KeyValuePartialInformation, + pValueInformation, + ValueInfoLength, + &RequiredSize); + + if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) + { + ExFreePool(pValueInformation); + ValueInfoLength = RequiredSize; + pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); + + if (!pValueInformation) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + + Status = ZwQueryValueKey(hDeviceKey, + &IdentifierU, + KeyValuePartialInformation, + pValueInformation, + ValueInfoLength, + &RequiredSize); + } + + if (!NT_SUCCESS(Status)) + { + if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto nextdevice; + } + ValueName.Length = ValueName.MaximumLength = 0; + } + else if (pValueInformation->Type != REG_SZ) + { + DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ); + goto nextdevice; + } + else + { + /* Assign hardware id to this device */ + ValueName.Length = ValueName.MaximumLength = (USHORT)pValueInformation->DataLength; + ValueName.Buffer = (PWCHAR)pValueInformation->Data; + if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) + ValueName.Length -= sizeof(WCHAR); + } + + if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0) + { + pHardwareId = &HardwareIdSerial; + DeviceIndex = DeviceIndexSerial++; + } + else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0) + { + pHardwareId = &HardwareIdKeyboard; + DeviceIndex = DeviceIndexKeyboard++; + } + else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0) + { + pHardwareId = &HardwareIdMouse; + DeviceIndex = DeviceIndexMouse++; + } + else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0) + { + pHardwareId = &HardwareIdParallel; + DeviceIndex = DeviceIndexParallel++; + } + else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0) + { + pHardwareId = &HardwareIdFloppy; + DeviceIndex = DeviceIndexFloppy++; + } + else + { + /* Unknown key path */ + DPRINT("Unknown key path '%wZ'\n", RelativePath); + goto nextdevice; + } + + /* Prepare hardware id key (hardware id value without final \0) */ + HardwareIdKey = *pHardwareId; + HardwareIdKey.Length -= sizeof(UNICODE_NULL); + + /* Add the detected device to Root key */ + InitializeObjectAttributes(&ObjectAttributes, &HardwareIdKey, OBJ_KERNEL_HANDLE, hRootKey, NULL); + + Status = ZwCreateKey( + &hLevel1Key, + KEY_CREATE_SUB_KEY, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + goto nextdevice; + } + + swprintf(Level2Name, L"%04lu", DeviceIndex); + RtlInitUnicodeString(&Level2NameU, Level2Name); + InitializeObjectAttributes(&ObjectAttributes, &Level2NameU, OBJ_KERNEL_HANDLE, hLevel1Key, NULL); + + Status = ZwCreateKey( + &hLevel2Key, + KEY_SET_VALUE | KEY_CREATE_SUB_KEY, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + ZwClose(hLevel1Key); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + goto nextdevice; + } + + DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey); + Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength); + + if (!NT_SUCCESS(Status)) + { DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ZwClose(hLogConf); ZwDeleteKey(hLevel2Key); goto nextdevice; - } - } - ZwClose(hLogConf); + } + + /* Create 'LogConf' subkey */ + InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL); + + Status = ZwCreateKey( + &hLogConf, + KEY_SET_VALUE, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + ZwDeleteKey(hLevel2Key); + goto nextdevice; + } + + if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) + { + CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG)); + if (!CmResourceList) + { + ZwClose(hLogConf); + ZwDeleteKey(hLevel2Key); + goto nextdevice; + } + + /* Add the list count (1st member of CM_RESOURCE_LIST) */ + ListCount = 1; + RtlCopyMemory(CmResourceList, + &ListCount, + sizeof(ULONG)); + + /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */ + RtlCopyMemory(CmResourceList + sizeof(ULONG), + BootResources, + BootResourcesLength); + + /* Save boot resources to 'LogConf\BootConfig' */ + Status = ZwSetValueKey(hLogConf, + &BootConfigU, + 0, + REG_RESOURCE_LIST, + CmResourceList, + BootResourcesLength + sizeof(ULONG)); + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ZwClose(hLogConf); + ZwDeleteKey(hLevel2Key); + goto nextdevice; + } + } + ZwClose(hLogConf); nextdevice: - if (BootResources && BootResources != ParentBootResources) - { - ExFreePool(BootResources); - BootResources = NULL; - } - if (hLevel2Key) - { - ZwClose(hLevel2Key); - hLevel2Key = NULL; - } - if (hDeviceKey) - { - ZwClose(hDeviceKey); - hDeviceKey = NULL; - } - } + if (BootResources && BootResources != ParentBootResources) + { + ExFreePool(BootResources); + BootResources = NULL; + } + if (hLevel2Key) + { + ZwClose(hLevel2Key); + hLevel2Key = NULL; + } + if (hDeviceKey) + { + ZwClose(hDeviceKey); + hDeviceKey = NULL; + } + } - Status = STATUS_SUCCESS; + Status = STATUS_SUCCESS; cleanup: - if (hDevicesKey && hDevicesKey != hBaseKey) - ZwClose(hDevicesKey); - if (hDeviceKey) - ZwClose(hDeviceKey); - if (pDeviceInformation) - ExFreePool(pDeviceInformation); - if (pValueInformation) - ExFreePool(pValueInformation); - return Status; + if (hDevicesKey && hDevicesKey != hBaseKey) + ZwClose(hDevicesKey); + if (hDeviceKey) + ZwClose(hDeviceKey); + if (pDeviceInformation) + ExFreePool(pDeviceInformation); + if (pValueInformation) + ExFreePool(pValueInformation); + + return Status; } static