Module: wine Branch: master Commit: f7bc64959886e585aced90688036a59a907b9743 URL: https://source.winehq.org/git/wine.git/?a=commit;h=f7bc64959886e585aced90688... Author: Jacek Caban <jacek(a)codeweavers.com> Date: Wed May 8 23:09:16 2019 +0200 hidclass.sys: Support canceling read IRPs. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Aric Stewart <aric(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/hidclass.sys/device.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index fcdb1b8..1fb3bbc 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -134,14 +134,44 @@ static IRP *pop_irp_from_queue(BASE_DEVICE_EXTENSION *ext) KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); - entry = RemoveHeadList(&ext->irp_queue); - if (entry != &ext->irp_queue) + while (!irp && (entry = RemoveHeadList(&ext->irp_queue)) != &ext->irp_queue) + { irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); + if (!IoSetCancelRoutine(irp, NULL)) + { + /* cancel routine is already cleared, meaning that it was called. let it handle completion. */ + InitializeListHead(&irp->Tail.Overlay.s.ListEntry); + irp = NULL; + } + } KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); return irp; } +static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) +{ + BASE_DEVICE_EXTENSION *ext; + KIRQL old_irql; + + TRACE("cancel %p IRP on device %p\n", irp, device); + + ext = device->DeviceExtension; + + IoReleaseCancelSpinLock(irp->CancelIrql); + + KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); + + RemoveEntryList(&irp->Tail.Overlay.s.ListEntry); + + KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); + + irp->IoStatus.u.Status = STATUS_CANCELLED; + irp->IoStatus.Information = 0; + IoCompleteRequest(irp, IO_NO_INCREMENT); +} + + void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device) { BASE_DEVICE_EXTENSION *ext; @@ -669,10 +699,20 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp) KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); + IoSetCancelRoutine(irp, read_cancel_routine); + if (irp->Cancel && !IoSetCancelRoutine(irp, NULL)) + { + /* IRP was canceled before we set cancel routine */ + InitializeListHead(&irp->Tail.Overlay.s.ListEntry); + KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); + return STATUS_CANCELLED; + } + InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry); - rc = STATUS_PENDING; + IoMarkIrpPending(irp); KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); + rc = STATUS_PENDING; } else {