From 8cfc4a3376e5f731bfa4b8a961fc900999dc8b90 Mon Sep 17 00:00:00 2001 From: Victor Perevertkin Date: Mon, 26 Jun 2023 01:26:08 +0300 Subject: [PATCH] [NTOS:PNP] Complete the PlugPlayControlInitializeDevice control class Besides creating the PDO and device node for it, it has to set up the necessary registry keys, and register PDO at PnP root driver properly. CORE-18989 --- ntoskrnl/io/pnpmgr/plugplay.c | 48 ++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/ntoskrnl/io/pnpmgr/plugplay.c b/ntoskrnl/io/pnpmgr/plugplay.c index 461328c8651..9220b30dc9e 100644 --- a/ntoskrnl/io/pnpmgr/plugplay.c +++ b/ntoskrnl/io/pnpmgr/plugplay.c @@ -32,6 +32,9 @@ static KEVENT IopPnpNotifyEvent; /* FUNCTIONS *****************************************************************/ +NTSTATUS +IopSetDeviceInstanceData(HANDLE InstanceKey, PDEVICE_NODE DeviceNode); + CODE_SEG("INIT") NTSTATUS IopInitPlugPlayEvents(VOID) @@ -198,15 +201,16 @@ IopCaptureUnicodeString(PUNICODE_STRING DstName, PUNICODE_STRING SrcName) static NTSTATUS -IopInitializeDevice( +PiControlInitializeDevice( _In_ PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA ControlData) { UNICODE_STRING DeviceInstance; PDEVICE_OBJECT DeviceObject; PDEVICE_NODE DeviceNode; NTSTATUS Status = STATUS_SUCCESS; + HANDLE InstanceKey; - DPRINT("IopInitializeDevice(%p)\n", ControlData); + DPRINT("PiControlInitializeDevice(%p)\n", ControlData); Status = IopCaptureUnicodeString(&DeviceInstance, &ControlData->DeviceInstance); if (!NT_SUCCESS(Status)) @@ -229,13 +233,7 @@ IopInitializeDevice( DPRINT("Device %wZ does not exist!\n", &DeviceInstance); /* Create a device node for the device instance */ - Status = IoCreateDevice(IopRootDriverObject, - 0, - NULL, - FILE_DEVICE_CONTROLLER, - FILE_AUTOGENERATED_DEVICE_NAME, - FALSE, - &DeviceObject); + Status = PnpRootCreateDeviceObject(&DeviceObject); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDevice() failed (Status 0x%08lx)\n", Status); @@ -252,8 +250,12 @@ IopInitializeDevice( goto done; } - /* Set the device instance of the device node */ - Status = RtlDuplicateUnicodeString(0, &DeviceInstance, &DeviceNode->InstancePath); + // Set the device instance of the device node + // NOTE: a NULL-terminated string is required for PnpRootRegisterDevice + Status = RtlDuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &DeviceInstance, + &DeviceNode->InstancePath); if (!NT_SUCCESS(Status)) { DPRINT1("RtlDuplicateUnicodeString() failed (Status 0x%08lx)\n", Status); @@ -262,9 +264,31 @@ IopInitializeDevice( goto done; } + DeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE; + DeviceNode->Flags |= DNF_MADEUP | DNF_IDS_QUERIED | DNF_ENUMERATED; + PiSetDevNodeState(DeviceNode, DeviceNodeInitialized); + + Status = IopCreateDeviceKeyPath(&DeviceInstance, REG_OPTION_NON_VOLATILE, &InstanceKey); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create the instance key! (Status %lx)\n", Status); + IopFreeDeviceNode(DeviceNode); + IoDeleteDevice(DeviceObject); + goto done; + } + + /* Write the resource information to the registry */ + IopSetDeviceInstanceData(InstanceKey, DeviceNode); + + // Finish the root device registration + PnpRootRegisterDevice(DeviceObject); + /* Insert as a root enumerated device node */ PiInsertDevNode(DeviceNode, IopRootDeviceNode); + IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED, &DeviceInstance); + + ZwClose(InstanceKey); done: ExFreePool(DeviceInstance.Buffer); @@ -1431,7 +1455,7 @@ NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, case PlugPlayControlInitializeDevice: if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)) return STATUS_INVALID_PARAMETER; - return IopInitializeDevice((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer); + return PiControlInitializeDevice((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer); case PlugPlayControlStartDevice: case PlugPlayControlResetDevice: