Compare commits

...

2 Commits

Author SHA1 Message Date
Hervé Poussineau
471ef3ea4e [NTOS:PNP] Let pnproot only report already detected devices
Ignore devices which have DeviceReported=1 in instance key
and not DeviceReported=1 in Control key.

CORE-17874
2021-12-15 17:09:00 +01:00
Hervé Poussineau
491d78b8df [NTOS:PNP] Set DeviceReported=1 in Instance key and Control key of legacy devices at report time
CORE-17874
2021-12-15 17:09:00 +01:00
2 changed files with 183 additions and 27 deletions

View File

@@ -155,15 +155,19 @@ IoReportDetectedDevice(
_In_ BOOLEAN ResourceAssigned,
_Inout_ PDEVICE_OBJECT *DeviceObject)
{
UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control");
UNICODE_STRING DeviceReportedName = RTL_CONSTANT_STRING(L"DeviceReported");
OBJECT_ATTRIBUTES ObjectAttributes;
PDEVICE_NODE DeviceNode;
PDEVICE_OBJECT Pdo;
NTSTATUS Status;
HANDLE InstanceKey;
HANDLE InstanceKey, ControlKey;
UNICODE_STRING ValueName, ServiceLongName, ServiceName;
WCHAR HardwareId[256];
PWCHAR IfString;
ULONG IdLength;
ULONG LegacyValue;
ULONG DeviceReported = 1;
DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
DeviceObject, DeviceObject ? *DeviceObject : NULL);
@@ -266,6 +270,39 @@ IoReportDetectedDevice(
{
DPRINT("Failed to write the Legacy value: 0x%x\n", Status);
}
Status = ZwSetValueKey(InstanceKey, &DeviceReportedName, 0, REG_DWORD, &DeviceReported, sizeof(DeviceReported));
if (!NT_SUCCESS(Status))
{
DPRINT("Failed to write the DeviceReported value: 0x%x\n", Status);
}
/* Set DeviceReported=1 in Control subkey */
InitializeObjectAttributes(&ObjectAttributes,
&Control,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
InstanceKey,
NULL);
Status = ZwCreateKey(&ControlKey,
KEY_SET_VALUE,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
if (NT_SUCCESS(Status))
{
Status = ZwSetValueKey(ControlKey,
&DeviceReportedName,
0,
REG_DWORD,
&DeviceReported,
sizeof(DeviceReported));
ZwClose(ControlKey);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to set ReportedDevice=1 for device %wZ (status 0x%08lx)\n", &instancePath, Status);
}
/* Add DETECTEDInterfaceType\DriverName */
IdLength = 0;

View File

@@ -94,7 +94,7 @@ LocateChildDevice(
IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension,
IN PCUNICODE_STRING DeviceId,
IN PCWSTR InstanceId,
OUT PPNPROOT_DEVICE* ChildDevice)
OUT PPNPROOT_DEVICE* ChildDevice OPTIONAL)
{
PPNPROOT_DEVICE Device;
UNICODE_STRING InstanceIdU;
@@ -116,7 +116,8 @@ LocateChildDevice(
RtlEqualUnicodeString(&InstanceIdU, &Device->InstanceID, TRUE))
{
/* They do, so set the pointer and return success */
*ChildDevice = Device;
if (ChildDevice)
*ChildDevice = Device;
return STATUS_SUCCESS;
}
}
@@ -261,26 +262,23 @@ tryagain:
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
for (NextInstance = 0; NextInstance <= 9999; NextInstance++)
{
for (NextInstance = 0; NextInstance <= 9999; NextInstance++)
{
_snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
Status = LocateChildDevice(DeviceExtension, &Device->DeviceID, InstancePath, &Device);
if (Status == STATUS_NO_SUCH_DEVICE)
break;
}
_snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
Status = LocateChildDevice(DeviceExtension, &Device->DeviceID, InstancePath, NULL);
if (Status == STATUS_NO_SUCH_DEVICE)
break;
}
if (NextInstance > 9999)
{
DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
if (NextInstance > 9999)
{
DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
_snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
Status = LocateChildDevice(DeviceExtension, &Device->DeviceID, InstancePath, &Device);
Status = LocateChildDevice(DeviceExtension, &Device->DeviceID, InstancePath, NULL);
if (Status != STATUS_NO_SUCH_DEVICE || NextInstance > 9999)
{
DPRINT1("NextInstance value is corrupt! (%lu)\n", NextInstance);
@@ -554,6 +552,114 @@ cleanup:
return Status;
}
static NTSTATUS
IopShouldProcessDevice(
IN HANDLE SubKey,
IN PCWSTR InstanceID)
{
UNICODE_STRING DeviceReportedValue = RTL_CONSTANT_STRING(L"DeviceReported");
UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control");
UNICODE_STRING InstanceIDU;
PKEY_VALUE_FULL_INFORMATION pKeyValueFullInformation;
HANDLE InstanceKey, ControlKey;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG Size, DeviceReported, ResultLength;
NTSTATUS Status;
Size = 128;
pKeyValueFullInformation = ExAllocatePool(PagedPool, Size);
if (!pKeyValueFullInformation)
return STATUS_INSUFFICIENT_RESOURCES;
/* Open Instance key */
RtlInitUnicodeString(&InstanceIDU, InstanceID);
InitializeObjectAttributes(&ObjectAttributes,
&InstanceIDU,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
SubKey,
NULL);
Status = ZwOpenKey(&InstanceKey,
KEY_QUERY_VALUE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
ExFreePool(pKeyValueFullInformation);
return Status;
}
/* Read 'DeviceReported' Key */
Status = ZwQueryValueKey(InstanceKey, &DeviceReportedValue, KeyValueFullInformation, pKeyValueFullInformation, Size, &ResultLength);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
ZwClose(InstanceKey);
ExFreePool(pKeyValueFullInformation);
DPRINT("No 'DeviceReported' value\n");
return STATUS_SUCCESS;
}
else if (!NT_SUCCESS(Status))
{
ZwClose(InstanceKey);
ExFreePool(pKeyValueFullInformation);
return Status;
}
if (pKeyValueFullInformation->Type != REG_DWORD || pKeyValueFullInformation->DataLength != sizeof(DeviceReported))
{
ZwClose(InstanceKey);
ExFreePool(pKeyValueFullInformation);
return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(&DeviceReported, (PVOID)((ULONG_PTR)pKeyValueFullInformation + pKeyValueFullInformation->DataOffset), sizeof(DeviceReported));
/* FIXME: Check DeviceReported value? */
ASSERT(DeviceReported == 1);
/* Open Control key */
InitializeObjectAttributes(&ObjectAttributes,
&Control,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
InstanceKey,
NULL);
Status = ZwOpenKey(&ControlKey,
KEY_QUERY_VALUE,
&ObjectAttributes);
ZwClose(InstanceKey);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
DPRINT("No 'Control' key\n");
return STATUS_NO_SUCH_DEVICE;
}
else if (!NT_SUCCESS(Status))
{
ExFreePool(pKeyValueFullInformation);
return Status;
}
/* Read 'DeviceReported' Key */
Status = ZwQueryValueKey(ControlKey, &DeviceReportedValue, KeyValueFullInformation, pKeyValueFullInformation, Size, &ResultLength);
ZwClose(ControlKey);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
ExFreePool(pKeyValueFullInformation);
DPRINT("No 'DeviceReported' value\n");
return STATUS_NO_SUCH_DEVICE;
}
else if (!NT_SUCCESS(Status))
{
ExFreePool(pKeyValueFullInformation);
return Status;
}
if (pKeyValueFullInformation->Type != REG_DWORD || pKeyValueFullInformation->DataLength != sizeof(DeviceReported))
{
ExFreePool(pKeyValueFullInformation);
return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(&DeviceReported, (PVOID)((ULONG_PTR)pKeyValueFullInformation + pKeyValueFullInformation->DataOffset), sizeof(DeviceReported));
/* FIXME: Check DeviceReported value? */
ASSERT(DeviceReported == 1);
ExFreePool(pKeyValueFullInformation);
return STATUS_SUCCESS;
}
static NTSTATUS
EnumerateDevices(
IN PDEVICE_OBJECT DeviceObject)
@@ -725,17 +831,30 @@ EnumerateDevices(
RtlAppendUnicodeToString(&DevicePath, REGSTR_KEY_ROOTENUM L"\\");
RtlAppendUnicodeStringToString(&DevicePath, &SubKeyName);
DPRINT("Found device %wZ\\%S!\n", &DevicePath, SubKeyInfo->Name);
Status = CreateDeviceFromRegistry(DeviceExtension,
&DevicePath,
SubKeyInfo->Name,
SubKeyHandle);
/* If CreateDeviceFromRegistry didn't take ownership and zero this,
* we need to free it
*/
RtlFreeUnicodeString(&DevicePath);
Status = IopShouldProcessDevice(SubKeyHandle, SubKeyInfo->Name);
if (NT_SUCCESS(Status))
{
Status = CreateDeviceFromRegistry(DeviceExtension,
&DevicePath,
SubKeyInfo->Name,
SubKeyHandle);
if (!NT_SUCCESS(Status))
/* If CreateDeviceFromRegistry didn't take ownership and zero this,
* we need to free it
*/
RtlFreeUnicodeString(&DevicePath);
if (!NT_SUCCESS(Status))
{
goto cleanup;
}
}
else if (Status == STATUS_NO_SUCH_DEVICE)
{
DPRINT("Skipping device %wZ\\%S (not reported yet)\n", &DevicePath, SubKeyInfo->Name);
}
else
{
goto cleanup;
}