https://git.reactos.org/?p=reactos.git;a=commitdiff;h=59a5dba443eaafd7b34d7…
commit 59a5dba443eaafd7b34d7a7920912b3e18b1b2eb
Author: Victor Perevertkin <victor.perevertkin(a)reactos.org>
AuthorDate: Tue Mar 16 02:17:14 2021 +0300
Commit: Victor Perevertkin <victor.perevertkin(a)reactos.org>
CommitDate: Tue Mar 16 03:17:57 2021 +0300
[NTOS:PNP] Implement PlugPlayControlStartDevice control class
This control class is triggered when a driver is being installed for a
non-critical device. The driver info should already be in the registry
so we just need to push the device through the state graph
Meanwhile, combine the code for similar control classes into
PiControlSyncDeviceAction routine
CORE-17463 CORE-17490
---
ntoskrnl/include/internal/io.h | 3 +-
ntoskrnl/io/pnpmgr/devaction.c | 18 +++++++++
ntoskrnl/io/pnpmgr/plugplay.c | 90 +++++++++++++++++++-----------------------
3 files changed, 60 insertions(+), 51 deletions(-)
diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h
index 269264b9e27..5e84f8e120f 100644
--- a/ntoskrnl/include/internal/io.h
+++ b/ntoskrnl/include/internal/io.h
@@ -534,7 +534,8 @@ typedef enum _DEVICE_ACTION
PiActionEnumDeviceTree,
PiActionEnumRootDevices,
PiActionResetDevice,
- PiActionAddBootDevices
+ PiActionAddBootDevices,
+ PiActionStartDevice
} DEVICE_ACTION;
//
diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c
index 7bf77afae3e..5d354ddc62c 100644
--- a/ntoskrnl/io/pnpmgr/devaction.c
+++ b/ntoskrnl/io/pnpmgr/devaction.c
@@ -2482,6 +2482,8 @@ ActionToStr(
return "PiActionResetDevice";
case PiActionAddBootDevices:
return "PiActionAddBootDevices";
+ case PiActionStartDevice:
+ return "PiActionStartDevice";
default:
return "(request unknown)";
}
@@ -2540,6 +2542,22 @@ PipDeviceActionWorker(
status = STATUS_SUCCESS;
break;
+ case PiActionStartDevice:
+ // This action is triggered from usermode, when a driver is installed
+ // for a non-critical PDO
+ if (deviceNode->State == DeviceNodeInitialized &&
+ !(deviceNode->Flags & DNF_HAS_PROBLEM))
+ {
+ PiDevNodeStateMachine(deviceNode);
+ }
+ else
+ {
+ DPRINT1("NOTE: attempt to start an already started/uninitialized
device %wZ\n",
+ &deviceNode->InstancePath);
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+
default:
DPRINT1("Unimplemented device action %u\n",
Request->Action);
status = STATUS_NOT_IMPLEMENTED;
diff --git a/ntoskrnl/io/pnpmgr/plugplay.c b/ntoskrnl/io/pnpmgr/plugplay.c
index 6c0e84fdb92..28e243dcd79 100644
--- a/ntoskrnl/io/pnpmgr/plugplay.c
+++ b/ntoskrnl/io/pnpmgr/plugplay.c
@@ -186,40 +186,6 @@ IopCaptureUnicodeString(PUNICODE_STRING DstName, PUNICODE_STRING
SrcName)
return Status;
}
-static NTSTATUS
-IopPnpEnumerateDevice(PPLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA DeviceData)
-{
- PDEVICE_OBJECT DeviceObject;
- UNICODE_STRING DeviceInstance;
- NTSTATUS Status = STATUS_SUCCESS;
-
- Status = IopCaptureUnicodeString(&DeviceInstance,
&DeviceData->DeviceInstance);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- DPRINT("IopPnpEnumerateDevice(%wZ)\n", &DeviceInstance);
-
- /* Get the device object */
- DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
- if (DeviceInstance.Buffer != NULL)
- {
- ExFreePool(DeviceInstance.Buffer);
- }
- if (DeviceObject == NULL)
- {
- return STATUS_NO_SUCH_DEVICE;
- }
-
- Status = PiPerformSyncDeviceAction(DeviceObject, PiActionEnumDeviceTree);
-
- ObDereferenceObject(DeviceObject);
-
- return Status;
-}
-
-
/*
* Remove the current PnP event from the tail of the event queue
* and signal IopPnpNotifyEvent if there is yet another event in the queue.
@@ -1042,23 +1008,26 @@ IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData)
return Status;
}
-
-static NTSTATUS
-IopResetDevice(PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA ResetDeviceData)
+static
+NTSTATUS
+PiControlSyncDeviceAction(
+ _In_ PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA DeviceData,
+ _In_ PLUGPLAY_CONTROL_CLASS ControlClass)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
UNICODE_STRING DeviceInstance;
- Status = IopCaptureUnicodeString(&DeviceInstance,
&ResetDeviceData->DeviceInstance);
+ ASSERT(ControlClass == PlugPlayControlEnumerateDevice ||
+ ControlClass == PlugPlayControlStartDevice ||
+ ControlClass == PlugPlayControlResetDevice);
+
+ Status = IopCaptureUnicodeString(&DeviceInstance,
&DeviceData->DeviceInstance);
if (!NT_SUCCESS(Status))
{
return Status;
}
- DPRINT("IopResetDevice(%wZ)\n", &DeviceInstance);
-
- /* Get the device object */
DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
if (DeviceInstance.Buffer != NULL)
{
@@ -1069,7 +1038,25 @@ IopResetDevice(PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA
ResetDeviceData)
return STATUS_NO_SUCH_DEVICE;
}
- Status = PiPerformSyncDeviceAction(DeviceObject, PiActionResetDevice);
+ DEVICE_ACTION Action;
+
+ switch (ControlClass)
+ {
+ case PlugPlayControlEnumerateDevice:
+ Action = PiActionEnumDeviceTree;
+ break;
+ case PlugPlayControlStartDevice:
+ Action = PiActionStartDevice;
+ break;
+ case PlugPlayControlResetDevice:
+ Action = PiActionResetDevice;
+ break;
+ default:
+ UNREACHABLE;
+ break;
+ }
+
+ Status = PiPerformSyncDeviceAction(DeviceObject, Action);
ObDereferenceObject(DeviceObject);
@@ -1309,12 +1296,21 @@ NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
case PlugPlayControlEnumerateDevice:
if (!Buffer || BufferLength <
sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA))
return STATUS_INVALID_PARAMETER;
- return
IopPnpEnumerateDevice((PPLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA)Buffer);
+ // the Flags field is not used anyway
+ return
PiControlSyncDeviceAction((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer,
+ PlugPlayControlClass);
// case PlugPlayControlRegisterNewDevice:
// case PlugPlayControlDeregisterDevice:
// case PlugPlayControlInitializeDevice:
-// case PlugPlayControlStartDevice:
+
+ case PlugPlayControlStartDevice:
+ case PlugPlayControlResetDevice:
+ if (!Buffer || BufferLength <
sizeof(PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA))
+ return STATUS_INVALID_PARAMETER;
+ return
PiControlSyncDeviceAction((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer,
+ PlugPlayControlClass);
+
// case PlugPlayControlUnlockDevice:
// case PlugPlayControlQueryAndRemoveDevice:
@@ -1362,12 +1358,6 @@ NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
// case PlugPlayControlTargetDeviceRelation:
// case PlugPlayControlQueryConflictList:
// case PlugPlayControlRetrieveDock:
-
- case PlugPlayControlResetDevice:
- if (!Buffer || BufferLength <
sizeof(PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA))
- return STATUS_INVALID_PARAMETER;
- return IopResetDevice((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer);
-
// case PlugPlayControlHaltDevice:
// case PlugPlayControlGetBlockedDriverList: