mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 15:18:33 +00:00
![Stanislav Motylkov](/assets/img/avatar_default.png)
Based on a commit by Vadim Galyant:
5ef5c11e7f
Also fix a minor type conversion warning. CORE-18963 CORE-17977
Co-authored-by: Vadim Galyant <vgal@rambler.ru>
727 lines
24 KiB
C
727 lines
24 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
* PURPOSE: PnP manager Firmware Mapper functions
|
|
* COPYRIGHT: Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
|
|
* Copyright 2008-2011 Cameron Gutman <cameron.gutman@reactos.org>
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* TYPES *********************************************************************/
|
|
|
|
typedef struct _PNP_MAPPER_DEVICE_ID
|
|
{
|
|
PCWSTR TypeName;
|
|
PWSTR PnPId;
|
|
} PNP_MAPPER_DEVICE_ID, *PPNP_MAPPER_DEVICE_ID;
|
|
|
|
typedef struct _PNP_DETECT_IDENTIFIER_MAP
|
|
{
|
|
PCWSTR DetectId;
|
|
PWSTR PnPId;
|
|
PPNP_MAPPER_DEVICE_ID PeripheralMap;
|
|
ULONG Counter;
|
|
} PNP_DETECT_IDENTIFIER_MAP;
|
|
|
|
/* DATA **********************************************************************/
|
|
|
|
static UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
|
|
static UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
|
|
static UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data");
|
|
static UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig");
|
|
static UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf");
|
|
|
|
/* FIXME: Trailing \0 in structures below are hacks, should be removed.
|
|
* Hardware identifiers also can be mapped using "LegacyXlate" sections
|
|
* of driver INF files. */
|
|
|
|
DATA_SEG("INITDATA")
|
|
static
|
|
PNP_MAPPER_DEVICE_ID KeyboardMap[] =
|
|
{
|
|
{ L"XT_83KEY", L"*PNP0300\0" },
|
|
{ L"PCAT_86KEY", L"*PNP0301\0" },
|
|
{ L"PCXT_84KEY", L"*PNP0302\0" },
|
|
{ L"XT_84KEY", L"*PNP0302\0" },
|
|
{ L"101-KEY", L"*PNP0303\0" },
|
|
{ L"OLI_83KEY", L"*PNP0304\0" },
|
|
{ L"ATT_301", L"*PNP0304\0" },
|
|
{ L"OLI_102KEY", L"*PNP0305\0" },
|
|
{ L"OLI_86KEY", L"*PNP0306\0" },
|
|
{ L"OLI_A101_102KEY", L"*PNP0309\0" },
|
|
{ L"ATT_302", L"*PNP030a\0" },
|
|
{ L"PCAT_ENHANCED", L"*PNP030b\0" },
|
|
{ L"PC98_106KEY", L"*nEC1300\0" },
|
|
{ L"PC98_LaptopKEY", L"*nEC1300\0" },
|
|
{ L"PC98_N106KEY", L"*PNP0303\0" },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
DATA_SEG("INITDATA")
|
|
static
|
|
PNP_MAPPER_DEVICE_ID PointerMap[] =
|
|
{
|
|
{ L"PS2 MOUSE", L"*PNP0F0E\0" },
|
|
{ L"SERIAL MOUSE", L"*PNP0F0C\0" },
|
|
{ L"MICROSOFT PS2 MOUSE", L"*PNP0F03\0" },
|
|
{ L"LOGITECH PS2 MOUSE", L"*PNP0F12\0" },
|
|
{ L"MICROSOFT INPORT MOUSE", L"*PNP0F02\0" },
|
|
{ L"MICROSOFT SERIAL MOUSE", L"*PNP0F01\0" },
|
|
{ L"MICROSOFT BALLPOINT SERIAL MOUSE", L"*PNP0F09\0" },
|
|
{ L"LOGITECH SERIAL MOUSE", L"*PNP0F08\0" },
|
|
{ L"MICROSOFT BUS MOUSE", L"*PNP0F00\0" },
|
|
{ L"NEC PC-9800 BUS MOUSE", L"*nEC1F00\0" },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
DATA_SEG("INITDATA")
|
|
static
|
|
PNP_DETECT_IDENTIFIER_MAP PnPMap[] =
|
|
{
|
|
{ L"SerialController", L"*PNP0501\0", NULL, 0 },
|
|
//{ L"KeyboardController", L"*PNP0303\0", NULL, 0 },
|
|
//{ L"PointerController", L"*PNP0F13\0", NULL, 0 },
|
|
{ L"KeyboardPeripheral", NULL, KeyboardMap, 0 },
|
|
{ L"PointerPeripheral", NULL, PointerMap, 0 },
|
|
{ L"ParallelController", L"*PNP0400\0", NULL, 0 },
|
|
{ L"FloppyDiskPeripheral", L"*PNP0700\0", NULL, 0 },
|
|
{ NULL, NULL, NULL, 0 }
|
|
};
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
PWSTR
|
|
IopMapPeripheralId(
|
|
_In_ PCUNICODE_STRING Value,
|
|
_In_ PPNP_MAPPER_DEVICE_ID DeviceList)
|
|
{
|
|
ULONG i;
|
|
UNICODE_STRING CmpId;
|
|
|
|
for (i = 0; DeviceList[i].TypeName; i++)
|
|
{
|
|
RtlInitUnicodeString(&CmpId, DeviceList[i].TypeName);
|
|
|
|
if (RtlCompareUnicodeString(Value, &CmpId, FALSE) == 0)
|
|
break;
|
|
}
|
|
|
|
return DeviceList[i].PnPId;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
PWSTR
|
|
IopMapDetectedDeviceId(
|
|
_In_ PUNICODE_STRING DetectId,
|
|
_In_ PUNICODE_STRING Value,
|
|
_Out_ PULONG DeviceIndex)
|
|
{
|
|
ULONG i;
|
|
UNICODE_STRING CmpId;
|
|
|
|
if (!DetectId)
|
|
return NULL;
|
|
|
|
for (i = 0; PnPMap[i].DetectId; i++)
|
|
{
|
|
RtlInitUnicodeString(&CmpId, PnPMap[i].DetectId);
|
|
|
|
if (RtlCompareUnicodeString(DetectId, &CmpId, FALSE) == 0)
|
|
{
|
|
*DeviceIndex = PnPMap[i].Counter++;
|
|
|
|
if (PnPMap[i].PeripheralMap)
|
|
return IopMapPeripheralId(Value, PnPMap[i].PeripheralMap);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return PnPMap[i].PnPId;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
IopEnumerateDetectedDevices(
|
|
_In_ HANDLE hBaseKey,
|
|
_In_opt_ PUNICODE_STRING RelativePath,
|
|
_In_ HANDLE hRootKey,
|
|
_In_ BOOLEAN EnumerateSubKeys,
|
|
_In_opt_ PCM_FULL_RESOURCE_DESCRIPTOR BootResources,
|
|
_In_opt_ ULONG BootResourcesLength,
|
|
_In_ PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources,
|
|
_In_ ULONG ParentBootResourcesLength)
|
|
{
|
|
HANDLE hDevicesKey = NULL;
|
|
ULONG KeyIndex = 0;
|
|
PKEY_BASIC_INFORMATION pDeviceInformation = NULL;
|
|
ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR);
|
|
NTSTATUS Status;
|
|
|
|
if (!BootResources && RelativePath)
|
|
{
|
|
Status = IopOpenRegistryKeyEx(&hDevicesKey, hBaseKey, RelativePath, KEY_ENUMERATE_SUB_KEYS);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
hDevicesKey = hBaseKey;
|
|
|
|
pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength);
|
|
if (!pDeviceInformation)
|
|
{
|
|
DPRINT("ExAllocatePool() failed\n");
|
|
Status = STATUS_NO_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE hDeviceKey = NULL;
|
|
HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf;
|
|
UNICODE_STRING Level2NameU;
|
|
WCHAR Level2Name[5];
|
|
PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
|
|
ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
|
|
UNICODE_STRING DeviceName, ValueName;
|
|
ULONG RequiredSize;
|
|
|
|
UNICODE_STRING HardwareIdKey;
|
|
PWSTR pHardwareId;
|
|
ULONG DeviceIndex = 0;
|
|
|
|
Status = ZwEnumerateKey(hDevicesKey,
|
|
KeyIndex,
|
|
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,
|
|
KeyIndex,
|
|
KeyBasicInformation,
|
|
pDeviceInformation,
|
|
DeviceInfoLength,
|
|
&RequiredSize);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
|
|
goto cleanup;
|
|
}
|
|
KeyIndex++;
|
|
|
|
/* Open device key */
|
|
DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength;
|
|
DeviceName.Buffer = pDeviceInformation->Name;
|
|
|
|
if (BootResources)
|
|
{
|
|
Status = IopEnumerateDetectedDevices(
|
|
hDevicesKey,
|
|
&DeviceName,
|
|
hRootKey,
|
|
TRUE,
|
|
NULL,
|
|
0,
|
|
BootResources,
|
|
BootResourcesLength);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
goto cleanup;
|
|
|
|
continue;
|
|
}
|
|
|
|
pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
|
|
if (!pValueInformation)
|
|
{
|
|
DPRINT("ExAllocatePool() failed\n");
|
|
Status = STATUS_NO_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
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)
|
|
{
|
|
Status = IopEnumerateDetectedDevices(
|
|
hDeviceKey,
|
|
RelativePath,
|
|
hRootKey,
|
|
TRUE,
|
|
BootResources,
|
|
BootResourcesLength,
|
|
ParentBootResources,
|
|
ParentBootResourcesLength);
|
|
|
|
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);
|
|
}
|
|
|
|
pHardwareId = IopMapDetectedDeviceId(RelativePath, &ValueName, &DeviceIndex);
|
|
if (!pHardwareId)
|
|
{
|
|
/* Unknown key path */
|
|
DPRINT("Unknown key path '%wZ' value '%wZ'\n", RelativePath, &ValueName);
|
|
goto nextdevice;
|
|
}
|
|
|
|
/* Prepare hardware id key (hardware id value without final \0) */
|
|
HardwareIdKey.Length = (USHORT)wcslen(pHardwareId) * sizeof(WCHAR);
|
|
HardwareIdKey.MaximumLength = HardwareIdKey.Length + sizeof(UNICODE_NULL) * 2;
|
|
HardwareIdKey.Buffer = pHardwareId;
|
|
|
|
/* 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, HardwareIdKey.Buffer, HardwareIdKey.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))
|
|
{
|
|
PUCHAR CmResourceList;
|
|
ULONG ListCount;
|
|
|
|
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));
|
|
|
|
ExFreePool(CmResourceList);
|
|
|
|
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 (pValueInformation)
|
|
ExFreePool(pValueInformation);
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
cleanup:
|
|
if (hDevicesKey && hDevicesKey != hBaseKey)
|
|
ZwClose(hDevicesKey);
|
|
if (pDeviceInformation)
|
|
ExFreePool(pDeviceInformation);
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
BOOLEAN
|
|
IopIsFirmwareMapperDisabled(VOID)
|
|
{
|
|
UNICODE_STRING KeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
|
|
UNICODE_STRING KeyNameU = RTL_CONSTANT_STRING(L"DisableFirmwareMapper");
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE hPnpKey;
|
|
PKEY_VALUE_PARTIAL_INFORMATION KeyInformation;
|
|
ULONG DesiredLength, Length;
|
|
ULONG KeyValue = 0;
|
|
NTSTATUS Status;
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &KeyPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
Status = ZwOpenKey(&hPnpKey, KEY_QUERY_VALUE, &ObjectAttributes);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = ZwQueryValueKey(hPnpKey,
|
|
&KeyNameU,
|
|
KeyValuePartialInformation,
|
|
NULL,
|
|
0,
|
|
&DesiredLength);
|
|
if ((Status == STATUS_BUFFER_TOO_SMALL) ||
|
|
(Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
Length = DesiredLength;
|
|
KeyInformation = ExAllocatePool(PagedPool, Length);
|
|
if (KeyInformation)
|
|
{
|
|
Status = ZwQueryValueKey(hPnpKey,
|
|
&KeyNameU,
|
|
KeyValuePartialInformation,
|
|
KeyInformation,
|
|
Length,
|
|
&DesiredLength);
|
|
if (NT_SUCCESS(Status) && KeyInformation->DataLength == sizeof(ULONG))
|
|
{
|
|
KeyValue = (ULONG)(*KeyInformation->Data);
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU, &KeyNameU);
|
|
}
|
|
|
|
ExFreePool(KeyInformation);
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("Failed to allocate memory for registry query\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU, &KeyNameU, Status);
|
|
}
|
|
|
|
ZwClose(hPnpKey);
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU, Status);
|
|
}
|
|
|
|
DPRINT("Firmware mapper is %s\n", KeyValue != 0 ? "disabled" : "enabled");
|
|
|
|
return (KeyValue != 0) ? TRUE : FALSE;
|
|
}
|
|
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
NTAPI
|
|
IopUpdateRootKey(VOID)
|
|
{
|
|
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
|
|
UNICODE_STRING RootPathU = RTL_CONSTANT_STRING(L"Root");
|
|
UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE hEnum, hRoot;
|
|
NTSTATUS Status;
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &RootPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hEnum, NULL);
|
|
Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
|
|
ZwClose(hEnum);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
if (!IopIsFirmwareMapperDisabled())
|
|
{
|
|
Status = IopOpenRegistryKeyEx(&hEnum, NULL, &MultiKeyPathU, KEY_ENUMERATE_SUB_KEYS);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Nothing to do, don't return with an error status */
|
|
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
|
ZwClose(hRoot);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
Status = IopEnumerateDetectedDevices(
|
|
hEnum,
|
|
NULL,
|
|
hRoot,
|
|
TRUE,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0);
|
|
ZwClose(hEnum);
|
|
}
|
|
else
|
|
{
|
|
/* Enumeration is disabled */
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
ZwClose(hRoot);
|
|
|
|
return Status;
|
|
}
|