From 23081e8ebdf57757aa8c149fede66d19f05e94bd Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 24 Apr 2020 11:44:01 -0500 Subject: [PATCH] wineusb.sys: Correctly implement device removal. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/wineusb.sys/wineusb.c | 39 ++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c index 55bd84ea308..d79112b4796 100644 --- a/dlls/wineusb.sys/wineusb.c +++ b/dlls/wineusb.sys/wineusb.c @@ -69,6 +69,7 @@ static struct list device_list = LIST_INIT(device_list); struct usb_device { struct list entry; + BOOL removed; DEVICE_OBJECT *device_obj; @@ -126,6 +127,7 @@ static void add_usb_device(libusb_device *libusb_device) EnterCriticalSection(&wineusb_cs); list_add_tail(&device_list, &device->entry); + device->removed = FALSE; LeaveCriticalSection(&wineusb_cs); IoInvalidateDeviceRelations(bus_pdo, BusRelations); @@ -142,15 +144,14 @@ static void remove_usb_device(libusb_device *libusb_device) { if (device->libusb_device == libusb_device) { - libusb_unref_device(device->libusb_device); - libusb_close(device->handle); list_remove(&device->entry); - IoInvalidateDeviceRelations(bus_pdo, BusRelations); - IoDeleteDevice(device->device_obj); + device->removed = TRUE; break; } } LeaveCriticalSection(&wineusb_cs); + + IoInvalidateDeviceRelations(bus_pdo, BusRelations); } static BOOL thread_shutdown; @@ -378,9 +379,39 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) case IRP_MN_START_DEVICE: case IRP_MN_QUERY_CAPABILITIES: + case IRP_MN_SURPRISE_REMOVAL: ret = STATUS_SUCCESS; break; + case IRP_MN_REMOVE_DEVICE: + { + LIST_ENTRY *entry; + + EnterCriticalSection(&wineusb_cs); + while ((entry = RemoveHeadList(&device->irp_list)) != &device->irp_list) + { + irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry); + irp->IoStatus.Status = STATUS_CANCELLED; + irp->IoStatus.Information = 0; + IoCompleteRequest(irp, IO_NO_INCREMENT); + } + LeaveCriticalSection(&wineusb_cs); + + if (device->removed) + { + libusb_unref_device(device->libusb_device); + libusb_close(device->handle); + + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + IoDeleteDevice(device->device_obj); + return STATUS_SUCCESS; + } + + ret = STATUS_SUCCESS; + break; + } + default: FIXME("Unhandled minor function %#x.\n", stack->MinorFunction); }