From: Zebediah Figura zfigura@codeweavers.com
wineusb enumerates new devices and completes IRPs from the same thread (as if it were an IRQ thread). On the other hand, the Hauppauge cx231xx USB driver performs I/O from within IRP_MN_START_DEVICE. If the wineusb "IRQ" thread is currently trying to report a new device, it won't be able to report I/O completion, resulting in a deadlock.
Although wineusb could be modified to use more threads, these tests show that calling IoInvalidateDeviceRelations() should not block in this situation. --- dlls/ntoskrnl.exe/tests/driver_pnp.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index a3e7329ae72..4b269f00bfc 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -275,6 +275,8 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) todo_wine ok(!status, "Failed to wait for child plug event, status %#lx.\n", status); status = ZwSetEvent(device->plug_event2, NULL); ok(!status, "Failed to set event, status %#lx.\n", status); + status = ZwWaitForSingleObject(device->plug_event, TRUE, &wait_time); + todo_wine ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
ret = STATUS_SUCCESS; break; @@ -648,6 +650,10 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code) ok(!status, "Failed to set event, status %#lx.\n", status); status = ZwWaitForSingleObject(device->plug_event2, TRUE, &wait_time); ok(!status, "Failed to wait for child plug event, status %#lx.\n", status); + /* IoInvalidateDeviceRelations() here shouldn't deadlock either. */ + IoInvalidateDeviceRelations(bus_pdo, BusRelations); + status = ZwSetEvent(device->plug_event, NULL); + ok(!status, "Failed to set event, status %#lx.\n", status);
return STATUS_SUCCESS; }