hidclass: Combine waits for pending IRP and I/O thread shutdown.

Fixes: 13a4486558
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57158
This commit is contained in:
Rémi Bernon 2024-09-12 11:26:20 +02:00 committed by Alexandre Julliard
parent 5834a6efad
commit 2aecb17285
Notes: Alexandre Julliard 2024-09-12 23:36:48 +02:00
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/wine/merge_requests/6486
3 changed files with 22 additions and 11 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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: