https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0358fcf9e4197106854e5…
commit 0358fcf9e4197106854e59bb637f6cef80dfda85
Author: Hervé Poussineau <hpoussin(a)reactos.org>
AuthorDate: Mon Dec 13 23:27:01 2021 +0100
Commit: Hervé Poussineau <hpoussin(a)reactos.org>
CommitDate: Thu Dec 16 16:14:21 2021 +0100
[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
---
ntoskrnl/io/pnpmgr/pnproot.c | 171 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 145 insertions(+), 26 deletions(-)
diff --git a/ntoskrnl/io/pnpmgr/pnproot.c b/ntoskrnl/io/pnpmgr/pnproot.c
index cc489c98670..c41844b64d3 100644
--- a/ntoskrnl/io/pnpmgr/pnproot.c
+++ b/ntoskrnl/io/pnpmgr/pnproot.c
@@ -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 CreateDeviceFromRegistry didn't take ownership and zero this,
+ * we need to free it
+ */
+ RtlFreeUnicodeString(&DevicePath);
- if (!NT_SUCCESS(Status))
+ 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;
}