return "PiActionResetDevice";
case PiActionAddBootDevices:
return "PiActionAddBootDevices";
+ case PiActionStartDevice:
+ return "PiActionStartDevice";
default:
return "(request unknown)";
}
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;
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.
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)
{
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);
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:
// 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: