[NTOS:IO] Do device reset inside the PipDeviceActionWorker

This make the operation synchonized with the other device tree actions

CORE-10456 CORE-17150
This commit is contained in:
Victor Perevertkin 2020-08-21 08:20:59 +03:00
parent 8aff2c9de7
commit acd07e725e
No known key found for this signature in database
GPG key ID: C750B7222E9C7830
3 changed files with 61 additions and 45 deletions

View file

@ -544,7 +544,8 @@ typedef enum _SECURITY_DESCRIPTOR_TYPE
typedef enum _DEVICE_ACTION
{
PiActionEnumDeviceTree,
PiActionEnumRootDevices
PiActionEnumRootDevices,
PiActionResetDevice
} DEVICE_ACTION;
//

View file

@ -2324,6 +2324,57 @@ cleanup:
&DeviceNode->InstancePath);
}
static
NTSTATUS
PipResetDevice(
_In_ PDEVICE_NODE DeviceNode)
{
NTSTATUS Status = STATUS_SUCCESS;
ASSERT(DeviceNode->Flags & DNF_ENUMERATED);
ASSERT(DeviceNode->Flags & DNF_PROCESSED);
/* Check if there's already a driver loaded for this device */
if (DeviceNode->Flags & DNF_ADDED)
{
/* FIXME: our drivers do not handle device removal well enough */
#if 0
/* Remove the device node */
Status = IopRemoveDevice(DeviceNode);
if (NT_SUCCESS(Status))
{
/* Invalidate device relations for the parent to reenumerate the device */
DPRINT1("A new driver will be loaded for '%wZ' (FDO above removed)\n", &DeviceNode->InstancePath);
Status = IoInvalidateDeviceRelations(DeviceNode->Parent->PhysicalDeviceObject, BusRelations);
}
else
#endif
{
/* A driver has already been loaded for this device */
DPRINT("A reboot is required for the current driver for '%wZ' to be replaced\n", &DeviceNode->InstancePath);
DeviceNode->Problem = CM_PROB_NEED_RESTART;
}
}
else
{
/* FIXME: What if the device really is disabled? */
DeviceNode->Flags &= ~DNF_DISABLED;
DeviceNode->Problem = 0;
/* Load service data from the registry */
Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
if (NT_SUCCESS(Status))
{
/* Start the service and begin PnP initialization of the device again */
DPRINT("A new driver will be loaded for '%wZ' (no FDO above)\n", &DeviceNode->InstancePath);
Status = IopActionInitChildServices(DeviceNode, DeviceNode->Parent);
}
}
return Status;
}
#ifdef DBG
static
PCSTR
@ -2336,6 +2387,8 @@ ActionToStr(
return "PiActionEnumDeviceTree";
case PiActionEnumRootDevices:
return "PiActionEnumRootDevices";
case PiActionResetDevice:
return "PiActionResetDevice";
default:
return "(request unknown)";
}
@ -2376,6 +2429,10 @@ PipDeviceActionWorker(
status = PipEnumerateDevice(deviceNode);
break;
case PiActionResetDevice:
status = PipResetDevice(deviceNode);
break;
default:
DPRINT1("Unimplemented device action %u\n", Request->Action);
status = STATUS_NOT_IMPLEMENTED;

View file

@ -1037,8 +1037,7 @@ static NTSTATUS
IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_NODE DeviceNode;
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS Status;
UNICODE_STRING DeviceInstance;
Status = IopCaptureUnicodeString(&DeviceInstance, &ResetDeviceData->DeviceInstance);
@ -1060,48 +1059,7 @@ IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
return STATUS_NO_SUCH_DEVICE;
}
/* Get the device node */
DeviceNode = IopGetDeviceNode(DeviceObject);
ASSERT(DeviceNode->Flags & DNF_ENUMERATED);
ASSERT(DeviceNode->Flags & DNF_PROCESSED);
/* Check if there's already a driver loaded for this device */
if (DeviceNode->Flags & DNF_ADDED)
{
#if 0
/* Remove the device node */
Status = IopRemoveDevice(DeviceNode);
if (NT_SUCCESS(Status))
{
/* Invalidate device relations for the parent to reenumerate the device */
DPRINT1("A new driver will be loaded for '%wZ' (FDO above removed)\n", &DeviceNode->InstancePath);
Status = IoSynchronousInvalidateDeviceRelations(DeviceNode->Parent->PhysicalDeviceObject, BusRelations);
}
else
#endif
{
/* A driver has already been loaded for this device */
DPRINT("A reboot is required for the current driver for '%wZ' to be replaced\n", &DeviceNode->InstancePath);
DeviceNode->Problem = CM_PROB_NEED_RESTART;
}
}
else
{
/* FIXME: What if the device really is disabled? */
DeviceNode->Flags &= ~DNF_DISABLED;
DeviceNode->Problem = 0;
/* Load service data from the registry */
Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
if (NT_SUCCESS(Status))
{
/* Start the service and begin PnP initialization of the device again */
DPRINT("A new driver will be loaded for '%wZ' (no FDO above)\n", &DeviceNode->InstancePath);
Status = IopActionInitChildServices(DeviceNode, DeviceNode->Parent);
}
}
Status = PiPerformSyncDeviceAction(DeviceObject, PiActionResetDevice);
ObDereferenceObject(DeviceObject);