Jacek Caban : hidclass.sys: Support canceling read IRPs.
Alexandre Julliard
julliard at winehq.org
Thu May 9 13:32:43 CDT 2019
Module: wine
Branch: master
Commit: f7bc64959886e585aced90688036a59a907b9743
URL: https://source.winehq.org/git/wine.git/?a=commit;h=f7bc64959886e585aced90688036a59a907b9743
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed May 8 23:09:16 2019 +0200
hidclass.sys: Support canceling read IRPs.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Aric Stewart <aric at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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
{
More information about the wine-cvs
mailing list