[NTOS:PNP]

- Improve use of local variables in IopCreateDeviceInstancePath and IopActionInterrogateDeviceStack
- Improve debug prints in IopCreateDeviceInstancePath. By Vadim Galyant
- Fix formatting in IopGetParentIdPrefix

svn path=/trunk/; revision=74048
This commit is contained in:
Thomas Faber 2017-03-04 13:20:25 +00:00
parent 3676af8656
commit 54688094ac

View file

@ -1634,98 +1634,108 @@ NTSTATUS
IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
PUNICODE_STRING ParentIdPrefix) PUNICODE_STRING ParentIdPrefix)
{ {
ULONG KeyNameBufferLength; ULONG KeyNameBufferLength;
PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL; PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
UNICODE_STRING KeyName = {0, 0, NULL}; UNICODE_STRING KeyName = {0, 0, NULL};
UNICODE_STRING KeyValue; UNICODE_STRING KeyValue;
UNICODE_STRING ValueName; UNICODE_STRING ValueName;
HANDLE hKey = NULL; HANDLE hKey = NULL;
ULONG crc32; ULONG crc32;
NTSTATUS Status; NTSTATUS Status;
/* HACK: As long as some devices have a NULL device /* HACK: As long as some devices have a NULL device
* instance path, the following test is required :( * instance path, the following test is required :(
*/ */
if (DeviceNode->Parent->InstancePath.Length == 0) if (DeviceNode->Parent->InstancePath.Length == 0)
{ {
DPRINT1("Parent of %wZ has NULL Instance path, please report!\n", DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
&DeviceNode->InstancePath); &DeviceNode->InstancePath);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
/* 1. Try to retrieve ParentIdPrefix from registry */ /* 1. Try to retrieve ParentIdPrefix from registry */
KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR); KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR)); ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR));
if (!ParentIdPrefixInformation) if (!ParentIdPrefixInformation)
{ {
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
KeyName.Buffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length); KeyName.Buffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length);
if (!KeyName.Buffer) if (!KeyName.Buffer)
{ {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup; goto cleanup;
} }
KeyName.Length = 0; KeyName.Length = 0;
KeyName.MaximumLength = (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length; KeyName.MaximumLength = (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length;
RtlAppendUnicodeToString(&KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); RtlAppendUnicodeToString(&KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath); RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath);
Status = IopOpenRegistryKeyEx(&hKey, NULL, &KeyName, KEY_QUERY_VALUE | KEY_SET_VALUE); Status = IopOpenRegistryKeyEx(&hKey, NULL, &KeyName, KEY_QUERY_VALUE | KEY_SET_VALUE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
goto cleanup; {
RtlInitUnicodeString(&ValueName, L"ParentIdPrefix"); goto cleanup;
Status = ZwQueryValueKey( }
hKey, &ValueName, RtlInitUnicodeString(&ValueName, L"ParentIdPrefix");
KeyValuePartialInformation, ParentIdPrefixInformation, Status = ZwQueryValueKey(hKey,
KeyNameBufferLength, &KeyNameBufferLength); &ValueName,
if (NT_SUCCESS(Status)) KeyValuePartialInformation,
{ ParentIdPrefixInformation,
if (ParentIdPrefixInformation->Type != REG_SZ) KeyNameBufferLength,
Status = STATUS_UNSUCCESSFUL; &KeyNameBufferLength);
else if (NT_SUCCESS(Status))
{ {
KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; if (ParentIdPrefixInformation->Type != REG_SZ)
KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; {
} Status = STATUS_UNSUCCESSFUL;
goto cleanup; }
} else
if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
{ KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; }
goto cleanup; goto cleanup;
} }
if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
{
KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
goto cleanup;
}
/* 2. Create the ParentIdPrefix value */ /* 2. Create the ParentIdPrefix value */
crc32 = RtlComputeCrc32(0, crc32 = RtlComputeCrc32(0,
(PUCHAR)DeviceNode->Parent->InstancePath.Buffer, (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
DeviceNode->Parent->InstancePath.Length); DeviceNode->Parent->InstancePath.Length);
swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32); swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32);
RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data); RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data);
/* 3. Try to write the ParentIdPrefix to registry */ /* 3. Try to write the ParentIdPrefix to registry */
Status = ZwSetValueKey(hKey, Status = ZwSetValueKey(hKey,
&ValueName, &ValueName,
0, 0,
REG_SZ, REG_SZ,
(PVOID)KeyValue.Buffer, (PVOID)KeyValue.Buffer,
((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR)); ((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR));
cleanup: cleanup:
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Duplicate the string to return it */ /* Duplicate the string to return it */
Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix); Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
} &KeyValue,
ExFreePool(ParentIdPrefixInformation); ParentIdPrefix);
RtlFreeUnicodeString(&KeyName); }
if (hKey != NULL) ExFreePool(ParentIdPrefixInformation);
ZwClose(hKey); RtlFreeUnicodeString(&KeyName);
return Status; if (hKey != NULL)
{
ZwClose(hKey);
}
return Status;
} }
NTSTATUS NTSTATUS
@ -1850,11 +1860,12 @@ IopQueryCompatibleIds(PDEVICE_NODE DeviceNode,
NTSTATUS NTSTATUS
IopCreateDeviceInstancePath( IopCreateDeviceInstancePath(
_In_ PDEVICE_NODE DeviceNode, _In_ PDEVICE_NODE DeviceNode,
_Out_ PUNICODE_STRING InstancePathU) _Out_ PUNICODE_STRING InstancePath)
{ {
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
PWSTR InformationString; PWSTR DeviceId;
WCHAR InstancePath[MAX_PATH]; PWSTR InstanceId;
WCHAR InstancePathBuffer[MAX_PATH];
IO_STACK_LOCATION Stack; IO_STACK_LOCATION Stack;
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING ParentIdPrefix = { 0, 0, NULL }; UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
@ -1869,27 +1880,27 @@ IopCreateDeviceInstancePath(
&Stack); &Stack);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("IopInitiatePnpIrp() failed (Status %x)\n", Status); DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status);
return Status; return Status;
} }
/* Copy the device id string */ /* Copy the device id string */
InformationString = (PWSTR)IoStatusBlock.Information; DeviceId = (PWSTR)IoStatusBlock.Information;
wcscpy(InstancePath, InformationString); wcscpy(InstancePathBuffer, DeviceId);
/* /*
* FIXME: Check for valid characters, if there is invalid characters * FIXME: Check for valid characters, if there is invalid characters
* then bugcheck. * then bugcheck.
*/ */
ExFreePoolWithTag(InformationString, 0); ExFreePoolWithTag(DeviceId, 0);
DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n"); DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities); Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status); DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status);
return Status; return Status;
} }
@ -1926,22 +1937,22 @@ IopCreateDeviceInstancePath(
&Stack); &Stack);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
InformationString = (PWSTR)IoStatusBlock.Information; InstanceId = (PWSTR)IoStatusBlock.Information;
/* Append the instance id string */ /* Append the instance id string */
wcscat(InstancePath, L"\\"); wcscat(InstancePathBuffer, L"\\");
if (ParentIdPrefix.Length > 0) if (ParentIdPrefix.Length > 0)
{ {
/* Add information from parent bus device to InstancePath */ /* Add information from parent bus device to InstancePath */
wcscat(InstancePath, ParentIdPrefix.Buffer); wcscat(InstancePathBuffer, ParentIdPrefix.Buffer);
if (InformationString && *InformationString) if (InstanceId && *InstanceId)
{ {
wcscat(InstancePath, L"&"); wcscat(InstancePathBuffer, L"&");
} }
} }
if (InformationString) if (InstanceId)
{ {
wcscat(InstancePath, InformationString); wcscat(InstancePathBuffer, InstanceId);
} }
/* /*
@ -1949,18 +1960,18 @@ IopCreateDeviceInstancePath(
* then bugcheck * then bugcheck
*/ */
if (InformationString) if (InstanceId)
{ {
ExFreePoolWithTag(InformationString, 0); ExFreePoolWithTag(InstanceId, 0);
} }
} }
else else
{ {
DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %x)\n", Status);
} }
RtlFreeUnicodeString(&ParentIdPrefix); RtlFreeUnicodeString(&ParentIdPrefix);
if (!RtlCreateUnicodeString(InstancePathU, InstancePath)) if (!RtlCreateUnicodeString(InstancePath, InstancePathBuffer))
{ {
DPRINT1("RtlCreateUnicodeString failed\n"); DPRINT1("RtlCreateUnicodeString failed\n");
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
@ -1991,7 +2002,8 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
PVOID Context) PVOID Context)
{ {
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
PWSTR InformationString; PWSTR DeviceDescription;
PWSTR LocationInformation;
PDEVICE_NODE ParentDeviceNode; PDEVICE_NODE ParentDeviceNode;
IO_STACK_LOCATION Stack; IO_STACK_LOCATION Stack;
NTSTATUS Status; NTSTATUS Status;
@ -2104,14 +2116,14 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
&IoStatusBlock, &IoStatusBlock,
IRP_MN_QUERY_DEVICE_TEXT, IRP_MN_QUERY_DEVICE_TEXT,
&Stack); &Stack);
InformationString = NT_SUCCESS(Status) ? (PWSTR)IoStatusBlock.Information DeviceDescription = NT_SUCCESS(Status) ? (PWSTR)IoStatusBlock.Information
: NULL; : NULL;
/* This key is mandatory, so even if the Irp fails, we still write it */ /* This key is mandatory, so even if the Irp fails, we still write it */
RtlInitUnicodeString(&ValueName, L"DeviceDesc"); RtlInitUnicodeString(&ValueName, L"DeviceDesc");
if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND) if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
{ {
if (InformationString && if (DeviceDescription &&
*InformationString != UNICODE_NULL) *DeviceDescription != UNICODE_NULL)
{ {
/* This key is overriden when a driver is installed. Don't write the /* This key is overriden when a driver is installed. Don't write the
* new description if another one already exists */ * new description if another one already exists */
@ -2119,8 +2131,8 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
&ValueName, &ValueName,
0, 0,
REG_SZ, REG_SZ,
InformationString, DeviceDescription,
((ULONG)wcslen(InformationString) + 1) * sizeof(WCHAR)); ((ULONG)wcslen(DeviceDescription) + 1) * sizeof(WCHAR));
} }
else else
{ {
@ -2141,9 +2153,9 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
} }
} }
if (InformationString) if (DeviceDescription)
{ {
ExFreePoolWithTag(InformationString, 0); ExFreePoolWithTag(DeviceDescription, 0);
} }
DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n"); DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
@ -2156,21 +2168,21 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
&Stack); &Stack);
if (NT_SUCCESS(Status) && IoStatusBlock.Information) if (NT_SUCCESS(Status) && IoStatusBlock.Information)
{ {
InformationString = (PWSTR)IoStatusBlock.Information; LocationInformation = (PWSTR)IoStatusBlock.Information;
DPRINT("LocationInformation: %S\n", InformationString); DPRINT("LocationInformation: %S\n", LocationInformation);
RtlInitUnicodeString(&ValueName, L"LocationInformation"); RtlInitUnicodeString(&ValueName, L"LocationInformation");
Status = ZwSetValueKey(InstanceKey, Status = ZwSetValueKey(InstanceKey,
&ValueName, &ValueName,
0, 0,
REG_SZ, REG_SZ,
InformationString, LocationInformation,
((ULONG)wcslen(InformationString) + 1) * sizeof(WCHAR)); ((ULONG)wcslen(LocationInformation) + 1) * sizeof(WCHAR));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status); DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
} }
ExFreePoolWithTag(InformationString, 0); ExFreePoolWithTag(LocationInformation, 0);
} }
else else
{ {