hidclass.sys: Always wait for the lower driver in hid_device_thread().

Doing otherwise may result in memory corruption. The lower driver should complete its IRPs on device removal anyway.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-04-14 23:22:07 -05:00 committed by Alexandre Julliard
parent 27f40156ba
commit fd25cc3c3b
1 changed files with 9 additions and 11 deletions

View File

@ -288,12 +288,11 @@ static DWORD CALLBACK hid_device_thread(void *args)
IO_STATUS_BLOCK irp_status; IO_STATUS_BLOCK irp_status;
HID_XFER_PACKET *packet; HID_XFER_PACKET *packet;
DWORD rc; DWORD rc;
HANDLE events[2]; HANDLE event;
NTSTATUS ntrc; NTSTATUS ntrc;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
events[0] = CreateEventA(NULL, TRUE, FALSE, NULL); event = CreateEventA(NULL, TRUE, FALSE, NULL);
events[1] = ext->halt_event;
packet = HeapAlloc(GetProcessHeap(), 0, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength); packet = HeapAlloc(GetProcessHeap(), 0, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength);
packet->reportBuffer = (BYTE *)packet + sizeof(*packet); packet->reportBuffer = (BYTE *)packet + sizeof(*packet);
@ -302,7 +301,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
{ {
while(1) while(1)
{ {
ResetEvent(events[0]); ResetEvent(event);
packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength; packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength;
packet->reportId = 0; packet->reportId = 0;
@ -311,11 +310,11 @@ static DWORD CALLBACK hid_device_thread(void *args)
device, NULL, 0, packet, sizeof(*packet), TRUE, NULL, device, NULL, 0, packet, sizeof(*packet), TRUE, NULL,
&irp_status); &irp_status);
IoSetCompletionRoutine(irp, read_Completion, events[0], TRUE, TRUE, TRUE); IoSetCompletionRoutine(irp, read_Completion, event, TRUE, TRUE, TRUE);
ntrc = IoCallDriver(device, irp); ntrc = IoCallDriver(device, irp);
if (ntrc == STATUS_PENDING) if (ntrc == STATUS_PENDING)
WaitForMultipleObjects(2, events, FALSE, INFINITE); WaitForSingleObject(event, INFINITE);
if (irp->IoStatus.u.Status == STATUS_SUCCESS) if (irp->IoStatus.u.Status == STATUS_SUCCESS)
{ {
@ -339,19 +338,19 @@ static DWORD CALLBACK hid_device_thread(void *args)
while(1) while(1)
{ {
ResetEvent(events[0]); ResetEvent(event);
irp = IoBuildDeviceIoControlRequest(IOCTL_HID_READ_REPORT, irp = IoBuildDeviceIoControlRequest(IOCTL_HID_READ_REPORT,
device, NULL, 0, packet->reportBuffer, device, NULL, 0, packet->reportBuffer,
ext->preparseData->caps.InputReportByteLength, TRUE, NULL, ext->preparseData->caps.InputReportByteLength, TRUE, NULL,
&irp_status); &irp_status);
IoSetCompletionRoutine(irp, read_Completion, events[0], TRUE, TRUE, TRUE); IoSetCompletionRoutine(irp, read_Completion, event, TRUE, TRUE, TRUE);
ntrc = IoCallDriver(device, irp); ntrc = IoCallDriver(device, irp);
if (ntrc == STATUS_PENDING) if (ntrc == STATUS_PENDING)
{ {
WaitForMultipleObjects(2, events, FALSE, INFINITE); WaitForSingleObject(event, INFINITE);
} }
rc = WaitForSingleObject(ext->halt_event, 0); rc = WaitForSingleObject(ext->halt_event, 0);
@ -376,8 +375,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
} }
} }
/* FIXME: releasing packet requires IRP cancellation support */ CloseHandle(event);
CloseHandle(events[0]);
TRACE("Device thread exiting\n"); TRACE("Device thread exiting\n");
return 1; return 1;