Zebediah Figura : ntoskrnl/tests: Add some tests for IRP pending flags.

Alexandre Julliard julliard at winehq.org
Wed Aug 25 15:21:45 CDT 2021


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

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Tue Aug 24 16:11:43 2021 -0500

ntoskrnl/tests: Add some tests for IRP pending flags.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/tests/driver.c | 109 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 102 insertions(+), 7 deletions(-)

diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 7ee48696c09..65c7860e786 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -1737,11 +1737,44 @@ static void test_stack_limits(void)
     ok(low < (ULONG_PTR)&low && (ULONG_PTR)&low < high, "stack variable is not in stack limits\n");
 }
 
-static unsigned int got_completion;
+static unsigned int got_completion, completion_lower_pending, completion_upper_pending;
 
 static NTSTATUS WINAPI completion_cb(DEVICE_OBJECT *device, IRP *irp, void *context)
 {
+    IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
     ok(device == context, "Got device %p; expected %p.\n", device, context);
+
+    if (device == upper_device)
+    {
+        todo_wine_if (completion_lower_pending)
+            ok(irp->PendingReturned == completion_lower_pending, "Got PendingReturned %u, expected %u.\n",
+                    irp->PendingReturned, completion_lower_pending);
+
+        ok(irp->CurrentLocation == 2, "Got current location %u.\n", irp->CurrentLocation);
+        ok(stack->Control == (SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_SUCCESS),
+                "Got control flags %#x.\n", stack->Control);
+        stack = IoGetNextIrpStackLocation(irp);
+        todo_wine ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+        stack = irp->Tail.Overlay.CurrentStackLocation + 1; /* previous location */
+        ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+
+        if (irp->PendingReturned && completion_upper_pending)
+            IoMarkIrpPending(irp);
+    }
+    else
+    {
+        todo_wine_if (completion_upper_pending)
+            ok(irp->PendingReturned == completion_upper_pending, "Got PendingReturned %u, expected %u.\n",
+                    irp->PendingReturned, completion_upper_pending);
+
+        ok(irp->CurrentLocation == 3, "Got current location %u.\n", irp->CurrentLocation);
+        ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+        stack = IoGetNextIrpStackLocation(irp);
+        todo_wine ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+        stack = irp->Tail.Overlay.CurrentStackLocation - 2; /* lowest location */
+        todo_wine ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+    }
+
     ++got_completion;
     return STATUS_SUCCESS;
 }
@@ -1753,15 +1786,50 @@ static void test_completion(void)
     KEVENT event;
     IRP *irp;
 
+    completion_lower_pending = completion_upper_pending = FALSE;
+
     KeInitializeEvent(&event, NotificationEvent, FALSE);
 
     irp = IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION, upper_device,
             NULL, 0, NULL, 0, FALSE, &event, &io);
-
     IoSetCompletionRoutine(irp, completion_cb, NULL, TRUE, TRUE, TRUE);
     ret = IoCallDriver(upper_device, irp);
     ok(ret == STATUS_SUCCESS, "IoCallDriver returned %#x\n", ret);
     ok(got_completion == 2, "got %u calls to completion routine\n", got_completion);
+
+    completion_lower_pending = TRUE;
+    got_completion = 0;
+
+    irp = IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION, upper_device,
+            NULL, 0, NULL, 0, FALSE, &event, &io);
+    IoSetCompletionRoutine(irp, completion_cb, NULL, TRUE, TRUE, TRUE);
+    ret = IoCallDriver(upper_device, irp);
+    ok(ret == STATUS_PENDING, "IoCallDriver returned %#x\n", ret);
+    ok(!got_completion, "got %u calls to completion routine\n", got_completion);
+
+    ok(irp->CurrentLocation == 1, "Got current location %u.\n", irp->CurrentLocation);
+    ok(!irp->PendingReturned, "Got pending flag %u.\n", irp->PendingReturned);
+
+    irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+    ok(got_completion == 2, "got %u calls to completion routine\n", got_completion);
+
+    completion_upper_pending = TRUE;
+    got_completion = 0;
+
+    irp = IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION, upper_device,
+            NULL, 0, NULL, 0, FALSE, &event, &io);
+    IoSetCompletionRoutine(irp, completion_cb, NULL, TRUE, TRUE, TRUE);
+    ret = IoCallDriver(upper_device, irp);
+    ok(ret == STATUS_PENDING, "IoCallDriver returned %#x\n", ret);
+    ok(!got_completion, "got %u calls to completion routine\n", got_completion);
+
+    ok(irp->CurrentLocation == 1, "Got current location %u.\n", irp->CurrentLocation);
+    ok(!irp->PendingReturned, "Got pending flag %u.\n", irp->PendingReturned);
+
+    irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+    ok(got_completion == 2, "got %u calls to completion routine\n", got_completion);
 }
 
 static void test_IoAttachDeviceToDeviceStack(void)
@@ -2392,10 +2460,19 @@ static NTSTATUS test_mismatched_status_ioctl(IRP *irp, IO_STACK_LOCATION *stack,
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS test_completion_ioctl(DEVICE_OBJECT *device, IRP *irp)
+static NTSTATUS completion_ioctl(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack)
 {
     if (device == upper_device)
     {
+        ok(irp->CurrentLocation == 2, "Got current location %u.\n", irp->CurrentLocation);
+        ok(!irp->PendingReturned, "Got pending flag %u.\n", irp->PendingReturned);
+        ok(stack->Control == (SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_SUCCESS),
+                "Got control flags %#x.\n", stack->Control);
+        stack = IoGetNextIrpStackLocation(irp);
+        ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+        stack = irp->Tail.Overlay.CurrentStackLocation + 1; /* previous location */
+        ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+
         IoCopyCurrentIrpStackLocationToNext(irp);
         IoSetCompletionRoutine(irp, completion_cb, upper_device, TRUE, TRUE, TRUE);
         return IoCallDriver(lower_device, irp);
@@ -2403,9 +2480,27 @@ static NTSTATUS test_completion_ioctl(DEVICE_OBJECT *device, IRP *irp)
     else
     {
         ok(device == lower_device, "Got wrong device.\n");
-        irp->IoStatus.Status = STATUS_SUCCESS;
-        IoCompleteRequest(irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
+        ok(irp->CurrentLocation == 1, "Got current location %u.\n", irp->CurrentLocation);
+        ok(!irp->PendingReturned, "Got pending flag %u.\n", irp->PendingReturned);
+        ok(stack->Control == (SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_SUCCESS),
+                "Got control flags %#x.\n", stack->Control);
+        stack = irp->Tail.Overlay.CurrentStackLocation + 1; /* previous location */
+        ok(stack->Control == (SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_SUCCESS),
+                "Got control flags %#x.\n", stack->Control);
+        stack = irp->Tail.Overlay.CurrentStackLocation + 2; /* top location */
+        ok(!stack->Control, "Got control flags %#x.\n", stack->Control);
+
+        if (completion_lower_pending)
+        {
+            IoMarkIrpPending(irp);
+            return STATUS_PENDING;
+        }
+        else
+        {
+            irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
     }
 }
 
@@ -2481,7 +2576,7 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
         case IOCTL_WINETEST_MISMATCHED_STATUS:
             return test_mismatched_status_ioctl(irp, stack, &irp->IoStatus.Information);
         case IOCTL_WINETEST_COMPLETION:
-            return test_completion_ioctl(device, irp);
+            return completion_ioctl(device, irp, stack);
         default:
             break;
     }




More information about the wine-cvs mailing list