[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
This commit is contained in:
Victor Perevertkin 2023-06-26 01:26:08 +03:00
parent 6cac5b8c9e
commit 8cfc4a3376
No known key found for this signature in database
GPG key ID: C750B7222E9C7830

View file

@ -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: