Instead of sending both IRP_MN_SURPRISE_REMOVAL and IRP_MN_REMOVE_DEVICE to all children first, which may have pending IRPs sent to their parent PDO driver, which need to be cancelled before IRP_MN_REMOVE_DEVICE can complete.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/pnp.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index e425712d738..0b4e4ef4613 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -350,12 +350,26 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set ) start_device( device, set, &sp_device ); }
+static void send_surprise_removal( DEVICE_OBJECT *device ) +{ + struct wine_device *impl = CONTAINING_RECORD(device, struct wine_device, device_obj); + ULONG i; + + if (impl->children) + for (i = 0; i < impl->children->Count; ++i) + send_surprise_removal( impl->children->Objects[i] ); + + send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL ); +} + static void remove_device( DEVICE_OBJECT *device ) { struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj);
TRACE("Removing device %p.\n", device);
+ send_surprise_removal( device ); + if (wine_device->children) { ULONG i; @@ -363,7 +377,6 @@ static void remove_device( DEVICE_OBJECT *device ) remove_device( wine_device->children->Objects[i] ); }
- send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL ); send_pnp_irp( device, IRP_MN_REMOVE_DEVICE ); }