Rémi Bernon : dinput/tests: Queue IRP when the expect ret_status is STATUS_PENDING.

Alexandre Julliard julliard at winehq.org
Thu Apr 21 15:21:39 CDT 2022


Module: wine
Branch: master
Commit: c6966b52948190fee25124aa3387e1ea4a0bb675
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c6966b52948190fee25124aa3387e1ea4a0bb675

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Thu Apr 21 19:50:19 2022 +0200

dinput/tests: Queue IRP when the expect ret_status is STATUS_PENDING.

And complete it on the next IOCTL_WINETEST_HID_WAIT_EXPECT ioctl.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dinput/tests/driver_bus.c | 71 ++++++++++++++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 16 deletions(-)

diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c
index 6d7f86d0691..45a984b6c36 100644
--- a/dlls/dinput/tests/driver_bus.c
+++ b/dlls/dinput/tests/driver_bus.c
@@ -95,7 +95,6 @@ static void expect_queue_cleanup( struct expect_queue *queue )
 
     if (irp)
     {
-        irp->IoStatus.Information = 0;
         irp->IoStatus.Status = STATUS_DELETE_PENDING;
         IoCompleteRequest( irp, IO_NO_INCREMENT );
     }
@@ -162,29 +161,64 @@ static void WINAPI wait_cancel_routine( DEVICE_OBJECT *device, IRP *irp )
     IoCompleteRequest( irp, IO_NO_INCREMENT );
 }
 
-static NTSTATUS expect_queue_wait( struct expect_queue *queue, IRP *irp )
+static NTSTATUS expect_queue_add_pending_locked( struct expect_queue *queue, IRP *irp )
+{
+    if (queue->pending_wait) return STATUS_INVALID_PARAMETER;
+
+    IoSetCancelRoutine( irp, wait_cancel_routine );
+    if (irp->Cancel && !IoSetCancelRoutine( irp, NULL ))
+        return STATUS_CANCELLED;
+
+    irp->Tail.Overlay.DriverContext[0] = queue;
+    IoMarkIrpPending( irp );
+    queue->pending_wait = irp;
+
+    return STATUS_PENDING;
+}
+
+static NTSTATUS expect_queue_add_pending( struct expect_queue *queue, IRP *irp )
 {
     NTSTATUS status;
     KIRQL irql;
 
     KeAcquireSpinLock( &queue->lock, &irql );
-    if (queue->pos == queue->end)
-        status = STATUS_SUCCESS;
-    else
+    status = expect_queue_add_pending_locked( queue, irp );
+    KeReleaseSpinLock( &queue->lock, irql );
+
+    return status;
+}
+
+static void expect_queue_clear_pending( struct expect_queue *queue )
+{
+    KIRQL irql;
+    IRP *irp;
+
+    KeAcquireSpinLock( &queue->lock, &irql );
+    if ((irp = queue->pending_wait))
     {
-        IoSetCancelRoutine( irp, wait_cancel_routine );
-        if (irp->Cancel && !IoSetCancelRoutine( irp, NULL ))
-            status = STATUS_CANCELLED;
-        else
-        {
-            irp->Tail.Overlay.DriverContext[0] = queue;
-            IoMarkIrpPending( irp );
-            queue->pending_wait = irp;
-            status = STATUS_PENDING;
-        }
+        queue->pending_wait = NULL;
+        if (!IoSetCancelRoutine( irp, NULL )) irp = NULL;
     }
     KeReleaseSpinLock( &queue->lock, irql );
 
+    if (irp)
+    {
+        irp->IoStatus.Status = STATUS_SUCCESS;
+        IoCompleteRequest( irp, IO_NO_INCREMENT );
+    }
+}
+
+static NTSTATUS expect_queue_wait( struct expect_queue *queue, IRP *irp )
+{
+    NTSTATUS status;
+    KIRQL irql;
+
+    irp->IoStatus.Information = 0;
+    KeAcquireSpinLock( &queue->lock, &irql );
+    if (queue->pos == queue->end) status = STATUS_SUCCESS;
+    else status = expect_queue_add_pending_locked( queue, irp );
+    KeReleaseSpinLock( &queue->lock, irql );
+
     return status;
 }
 
@@ -233,7 +267,6 @@ static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_
 
     if (irp)
     {
-        irp->IoStatus.Information = 0;
         irp->IoStatus.Status = STATUS_SUCCESS;
         IoCompleteRequest( irp, IO_NO_INCREMENT );
     }
@@ -1055,6 +1088,7 @@ static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
 
         irp->IoStatus.Information = expect.ret_length ? expect.ret_length : expect.report_len;
         status = expect.ret_status;
+        if (status == STATUS_PENDING) status = expect_queue_add_pending( &impl->expect_queue, irp );
         break;
     }
 
@@ -1078,6 +1112,7 @@ static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
         irp->IoStatus.Information = expect.ret_length ? expect.ret_length : expect.report_len;
         memcpy( packet->reportBuffer, expect.report_buf, irp->IoStatus.Information );
         status = expect.ret_status;
+        if (status == STATUS_PENDING) status = expect_queue_add_pending( &impl->expect_queue, irp );
         break;
     }
 
@@ -1101,6 +1136,7 @@ static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
 
         irp->IoStatus.Information = expect.ret_length ? expect.ret_length : expect.report_len;
         status = expect.ret_status;
+        if (status == STATUS_PENDING) status = expect_queue_add_pending( &impl->expect_queue, irp );
         break;
     }
 
@@ -1124,6 +1160,7 @@ static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
         irp->IoStatus.Information = expect.ret_length ? expect.ret_length : expect.report_len;
         memcpy( packet->reportBuffer, expect.report_buf, irp->IoStatus.Information );
         status = expect.ret_status;
+        if (status == STATUS_PENDING) status = expect_queue_add_pending( &impl->expect_queue, irp );
         break;
     }
 
@@ -1147,6 +1184,7 @@ static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
 
         irp->IoStatus.Information = expect.ret_length ? expect.ret_length : expect.report_len;
         status = expect.ret_status;
+        if (status == STATUS_PENDING) status = expect_queue_add_pending( &impl->expect_queue, irp );
         break;
     }
 
@@ -1215,6 +1253,7 @@ static NTSTATUS WINAPI pdo_ioctl( DEVICE_OBJECT *device, IRP *irp )
         status = STATUS_SUCCESS;
         break;
     case IOCTL_WINETEST_HID_WAIT_EXPECT:
+        expect_queue_clear_pending( &impl->expect_queue );
         status = expect_queue_wait( &impl->expect_queue, irp );
         break;
     case IOCTL_WINETEST_HID_SEND_INPUT:




More information about the wine-cvs mailing list