Module: wine Branch: master Commit: b065daa600e858823944f996144ed233065da7fd URL: https://source.winehq.org/git/wine.git/?a=commit;h=b065daa600e858823944f9961...
Author: Rémi Bernon rbernon@codeweavers.com Date: Tue Jul 6 11:00:47 2021 +0200
ntoskrnl.exe: Send IRP_MN_SURPRISE_REMOVAL to the device stack first.
Instead of sending both IRP_MN_SURPRISE_REMOVAL and IRP_MN_REMOVE_DEVICE to all children first.
They may have pending IRPs sent to their parent PDO driver, which need to be cancelled before IRP_MN_REMOVE_DEVICE can complete. This is the case for hidclass.sys and its thread calling the lower driver for instance.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntoskrnl.exe/pnp.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index e425712d738..d8eb62bc17a 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -350,21 +350,20 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set ) start_device( device, set, &sp_device ); }
-static void remove_device( DEVICE_OBJECT *device ) +static void send_remove_device_irp( DEVICE_OBJECT *device, UCHAR code ) { struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj);
- TRACE("Removing device %p.\n", device); + TRACE( "Removing device %p, code %x.\n", device, code );
if (wine_device->children) { ULONG i; for (i = 0; i < wine_device->children->Count; ++i) - remove_device( wine_device->children->Objects[i] ); + send_remove_device_irp( wine_device->children->Objects[i], code ); }
- send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL ); - send_pnp_irp( device, IRP_MN_REMOVE_DEVICE ); + send_pnp_irp( device, code ); }
static BOOL device_in_list( const DEVICE_RELATIONS *list, const DEVICE_OBJECT *device ) @@ -441,7 +440,8 @@ static void handle_bus_relations( DEVICE_OBJECT *parent ) if (!device_in_list( relations, child )) { TRACE("Removing device %p.\n", child); - remove_device( child ); + send_remove_device_irp( child, IRP_MN_SURPRISE_REMOVAL ); + send_remove_device_irp( child, IRP_MN_REMOVE_DEVICE ); } ObDereferenceObject( child ); } @@ -1105,7 +1105,10 @@ void pnp_manager_stop_driver( struct wine_driver *driver ) struct root_pnp_device *device, *next;
LIST_FOR_EACH_ENTRY_SAFE( device, next, &driver->root_pnp_devices, struct root_pnp_device, entry ) - remove_device( device->device ); + { + send_remove_device_irp( device->device, IRP_MN_SURPRISE_REMOVAL ); + send_remove_device_irp( device->device, IRP_MN_REMOVE_DEVICE ); + } }
void pnp_manager_stop(void) @@ -1179,7 +1182,8 @@ void CDECL wine_enumerate_root_devices( const WCHAR *driver_name ) { TRACE("Removing device %s.\n", debugstr_w(pnp_device->id));
- remove_device( pnp_device->device ); + send_remove_device_irp( pnp_device->device, IRP_MN_SURPRISE_REMOVAL ); + send_remove_device_irp( pnp_device->device, IRP_MN_REMOVE_DEVICE ); }
list_move_head( &driver->root_pnp_devices, &new_list );