diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 052d350ea8a..a39e60604b9 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -790,6 +790,16 @@ IopStartDevice( IN PDEVICE_NODE DeviceNode ); +NTSTATUS +IopStopDevice( + IN PDEVICE_NODE DeviceNode +); + +NTSTATUS +IopRemoveDevice( + IN PDEVICE_NODE DeviceNode +); + PVPB NTAPI IopCheckVpbMounted( diff --git a/reactos/ntoskrnl/io/pnpmgr/plugplay.c b/reactos/ntoskrnl/io/pnpmgr/plugplay.c index 9c01544bcbf..52e480e6746 100644 --- a/reactos/ntoskrnl/io/pnpmgr/plugplay.c +++ b/reactos/ntoskrnl/io/pnpmgr/plugplay.c @@ -551,10 +551,18 @@ IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData) DeviceNode = IopGetDeviceNode(DeviceObject); - /* FIXME: we should stop the device, before starting it again */ + /* Remove the device */ + if (DeviceNode->Flags & DNF_ENUMERATED) + { + Status = IopRemoveDevice(DeviceNode); + if (!NT_SUCCESS(Status)) + { + DPRINT1("WARNING: Ignoring failed IopRemoveDevice() for %wZ (likely a driver bug)\n", &DeviceNode->InstancePath); + } + } - /* Start the device */ - IopDeviceNodeClearFlag(DeviceNode, DNF_DISABLED); + /* Reenumerate the device and its children */ + DeviceNode->Flags &= ~DNF_DISABLED; Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent); if (NT_SUCCESS(Status)) diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 0636d812cfd..dd7d6330d21 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -337,6 +337,24 @@ IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode) return Status; } +NTSTATUS +IopStopDevice( + PDEVICE_NODE DeviceNode) +{ + NTSTATUS Status; + + DPRINT("Stopping device: %wZ\n", &DeviceNode->InstancePath); + + Status = IopQueryStopDevice(DeviceNode->PhysicalDeviceObject); + if (!NT_SUCCESS(Status)) + { + IopSendStopDevice(DeviceNode->PhysicalDeviceObject); + return STATUS_SUCCESS; + } + + return Status; +} + NTSTATUS IopStartDevice( PDEVICE_NODE DeviceNode) @@ -420,7 +438,7 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, return Status; } - DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCaps + 4); + DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCaps->Version + sizeof(DeviceCaps->Version));; if (DeviceCaps->NoDisplayInUI) DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI; @@ -3873,6 +3891,12 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject) PDEVICE_RELATIONS DeviceRelations; NTSTATUS Status; ULONG i; + + if (DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) + { + DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath); + return STATUS_UNSUCCESSFUL; + } IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING, &DeviceNode->InstancePath); @@ -3958,6 +3982,23 @@ cleanup: return Status; } +NTSTATUS +IopRemoveDevice(PDEVICE_NODE DeviceNode) +{ + NTSTATUS Status; + + DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath); + + Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject); + if (NT_SUCCESS(Status)) + { + IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject); + return STATUS_SUCCESS; + } + + return Status; +} + /* * @implemented */