From: Rémi Bernon rbernon@codeweavers.com
Fixes: 13a44865586f7697bb47bb48664ac0a90590a643 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57158 --- dlls/hidclass.sys/device.c | 24 ++++++++++++++++++------ dlls/hidclass.sys/hid.h | 2 +- dlls/hidclass.sys/pnp.c | 7 +++---- 3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 440bf4de24c..8725ca7bba9 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -321,8 +321,9 @@ DWORD CALLBACK hid_device_thread(void *args) HID_XFER_PACKET *packet; HIDP_DEVICE_DESC *desc; IO_STATUS_BLOCK io; + NTSTATUS status; BYTE *buffer; - DWORD res; + IRP *irp;
for (i = 0; i < ext->u.fdo.device_desc.CollectionDescLength; i++) { @@ -340,6 +341,9 @@ DWORD CALLBACK hid_device_thread(void *args)
do { + LARGE_INTEGER delay = {.QuadPart = (LONGLONG)ext->u.fdo.poll_interval * -10000}; + KEVENT irp_event; + packet->reportId = buffer[0] = report_id; packet->reportBuffer = buffer; packet->reportBufferLen = input_length; @@ -350,8 +354,15 @@ DWORD CALLBACK hid_device_thread(void *args) packet->reportBufferLen--; }
- call_minidriver( IOCTL_HID_READ_REPORT, device, NULL, 0, - packet->reportBuffer, packet->reportBufferLen, &io ); + KeInitializeEvent( &irp_event, NotificationEvent, FALSE ); + irp = IoBuildDeviceIoControlRequest( IOCTL_HID_READ_REPORT, device, NULL, 0, packet->reportBuffer, + packet->reportBufferLen, TRUE, &irp_event, &io ); + if (IoCallDriver( device, irp ) == STATUS_PENDING) + { + void *events[2] = {&irp_event, &ext->u.fdo.halt_event}; + status = KeWaitForMultipleObjects( 2, events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL ); + if (status) break; + }
if (io.Status == STATUS_SUCCESS) { @@ -372,10 +383,11 @@ DWORD CALLBACK hid_device_thread(void *args) } }
- res = WaitForSingleObject( ext->u.fdo.halt_event, ext->u.fdo.poll_interval ); - } while (res == WAIT_TIMEOUT); + status = KeWaitForSingleObject( &ext->u.fdo.halt_event, Executive, KernelMode, FALSE, &delay ); + } while (status == STATUS_TIMEOUT);
- TRACE( "device thread exiting, res %#lx\n", res ); + if (status) WARN( "device thread exiting with status %#lx\n", status ); + else TRACE( "device thread exiting\n" ); return 1; }
diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index d58143b34b1..3924c72dcc3 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -53,7 +53,7 @@ typedef struct _BASE_DEVICE_EXTENSION WCHAR serial[256];
ULONG poll_interval; - HANDLE halt_event; + KEVENT halt_event; HANDLE thread;
DEVICE_OBJECT **child_pdos; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index e6ebbb05b32..71fbb8e4205 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -251,7 +251,7 @@ static NTSTATUS initialize_device( minidriver *minidriver, DEVICE_OBJECT *device }
ext->u.fdo.poll_interval = minidriver->minidriver.DevicesArePolled ? DEFAULT_POLL_INTERVAL : 0; - ext->u.fdo.halt_event = CreateEventA(NULL, TRUE, FALSE, NULL); + KeInitializeEvent( &ext->u.fdo.halt_event, NotificationEvent, FALSE ); return STATUS_SUCCESS; }
@@ -377,10 +377,9 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) case IRP_MN_REMOVE_DEVICE: if (ext->u.fdo.thread) { - SetEvent(ext->u.fdo.halt_event); + KeSetEvent( &ext->u.fdo.halt_event, IO_NO_INCREMENT, FALSE ); WaitForSingleObject(ext->u.fdo.thread, INFINITE); } - CloseHandle(ext->u.fdo.halt_event);
status = minidriver->PNPDispatch( device, irp ); HidP_FreeCollectionDescription( &ext->u.fdo.device_desc ); @@ -390,7 +389,7 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) return status;
case IRP_MN_SURPRISE_REMOVAL: - SetEvent(ext->u.fdo.halt_event); + KeSetEvent( &ext->u.fdo.halt_event, IO_NO_INCREMENT, FALSE ); return STATUS_SUCCESS;
default: