From acd07e725e723ab62ea8bcd2251e93746b9dc569 Mon Sep 17 00:00:00 2001 From: Victor Perevertkin Date: Fri, 21 Aug 2020 08:20:59 +0300 Subject: [PATCH] [NTOS:IO] Do device reset inside the PipDeviceActionWorker This make the operation synchonized with the other device tree actions CORE-10456 CORE-17150 --- ntoskrnl/include/internal/io.h | 3 +- ntoskrnl/io/pnpmgr/devaction.c | 57 ++++++++++++++++++++++++++++++++++ ntoskrnl/io/pnpmgr/plugplay.c | 46 ++------------------------- 3 files changed, 61 insertions(+), 45 deletions(-) diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h index 4e810bc34fe..73f862c003d 100644 --- a/ntoskrnl/include/internal/io.h +++ b/ntoskrnl/include/internal/io.h @@ -544,7 +544,8 @@ typedef enum _SECURITY_DESCRIPTOR_TYPE typedef enum _DEVICE_ACTION { PiActionEnumDeviceTree, - PiActionEnumRootDevices + PiActionEnumRootDevices, + PiActionResetDevice } DEVICE_ACTION; // diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c index 77b9990f35b..0351bec4dbd 100644 --- a/ntoskrnl/io/pnpmgr/devaction.c +++ b/ntoskrnl/io/pnpmgr/devaction.c @@ -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; diff --git a/ntoskrnl/io/pnpmgr/plugplay.c b/ntoskrnl/io/pnpmgr/plugplay.c index 968c6804b86..933e514d9f9 100644 --- a/ntoskrnl/io/pnpmgr/plugplay.c +++ b/ntoskrnl/io/pnpmgr/plugplay.c @@ -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);