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