Jacek Caban : ntoskrnl.exe/tests: Add CancelIo tests.

Alexandre Julliard julliard at winehq.org
Thu May 2 16:45:09 CDT 2019


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu May  2 13:21:29 2019 +0200

ntoskrnl.exe/tests: Add CancelIo tests.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/tests/driver.c   | 36 +++++++++++++++++
 dlls/ntoskrnl.exe/tests/driver.h   |  3 ++
 dlls/ntoskrnl.exe/tests/ntoskrnl.c | 80 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 119 insertions(+)

diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index c2ef890..6d14a22 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -770,6 +770,15 @@ static void WINAPI cancel_irp(DEVICE_OBJECT *device, IRP *irp)
     cancel_cnt++;
 }
 
+static void WINAPI cancel_ioctl_irp(DEVICE_OBJECT *device, IRP *irp)
+{
+    IoReleaseCancelSpinLock(irp->CancelIrql);
+    irp->IoStatus.Status = STATUS_CANCELLED;
+    irp->IoStatus.Information = 0;
+    cancel_cnt++;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+}
+
 static NTSTATUS WINAPI cancel_test_completion(DEVICE_OBJECT *device, IRP *irp, void *context)
 {
     ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
@@ -1505,6 +1514,22 @@ static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS get_cancel_count(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
+{
+    ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
+    char *buffer = irp->AssociatedIrp.SystemBuffer;
+
+    if (!buffer)
+        return STATUS_ACCESS_VIOLATION;
+
+    if (length < sizeof(DWORD))
+        return STATUS_BUFFER_TOO_SMALL;
+
+    *(DWORD*)buffer = cancel_cnt;
+    *info = sizeof(DWORD);
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS test_load_driver_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
 {
     BOOL *load = irp->AssociatedIrp.SystemBuffer;
@@ -1549,6 +1574,17 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
         case IOCTL_WINETEST_LOAD_DRIVER:
             status = test_load_driver_ioctl(irp, stack, &irp->IoStatus.Information);
             break;
+        case IOCTL_WINETEST_RESET_CANCEL:
+            cancel_cnt = 0;
+            status = STATUS_SUCCESS;
+            break;
+        case IOCTL_WINETEST_TEST_CANCEL:
+            IoSetCancelRoutine(irp, cancel_ioctl_irp);
+            IoMarkIrpPending(irp);
+            return STATUS_PENDING;
+        case IOCTL_WINETEST_GET_CANCEL_COUNT:
+            status = get_cancel_count(irp, stack, &irp->IoStatus.Information);
+            break;
         default:
             break;
     }
diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h
index be4a9dc..1e75529 100644
--- a/dlls/ntoskrnl.exe/tests/driver.h
+++ b/dlls/ntoskrnl.exe/tests/driver.h
@@ -25,6 +25,9 @@
 #define IOCTL_WINETEST_BASIC_IOCTL      CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_WINETEST_MAIN_TEST        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_WINETEST_LOAD_DRIVER      CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_WINETEST_RESET_CANCEL     CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_WINETEST_TEST_CANCEL      CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_WINETEST_GET_CANCEL_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 static const char teststr[] = "Wine is not an emulator";
 
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index c17da7f..d9eb286 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -197,6 +197,85 @@ static void test_basic_ioctl(void)
     ok(!strcmp(buf, teststr), "got '%s'\n", buf);
 }
 
+static void test_cancel_io(void)
+{
+    OVERLAPPED overlapped, overlapped2;
+    DWORD cancel_cnt;
+    HANDLE file;
+    BOOL res;
+
+    overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+    overlapped2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+    file = CreateFileA("\\\\.\\WineTestDriver", 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError());
+
+    /* test cancelling all device requests */
+    res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
+    todo_wine
+    ok(res, "DeviceIoControl failed: %u\n", GetLastError());
+    if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
+
+    res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
+    ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError());
+
+    res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped2);
+    ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError());
+
+    cancel_cnt = 0xdeadbeef;
+    res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped);
+    todo_wine
+    ok(res, "DeviceIoControl failed: %u\n", GetLastError());
+    if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
+    ok(cancel_cnt == 0, "cancel_cnt = %u\n", cancel_cnt);
+
+    CancelIo(file);
+
+    cancel_cnt = 0xdeadbeef;
+    res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped);
+    todo_wine
+    ok(res, "DeviceIoControl failed: %u\n", GetLastError());
+    if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
+    todo_wine
+    ok(cancel_cnt == 2, "cancel_cnt = %u\n", cancel_cnt);
+
+    /* test cancelling selected overlapped event */
+    res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
+    todo_wine
+    ok(res, "DeviceIoControl failed: %u\n", GetLastError());
+    if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
+
+    res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped);
+    ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError());
+
+    res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped2);
+    ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %u\n", GetLastError());
+
+    CancelIoEx(file, &overlapped);
+
+    cancel_cnt = 0xdeadbeef;
+    res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped);
+    todo_wine
+    ok(res, "DeviceIoControl failed: %u\n", GetLastError());
+    if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
+    todo_wine
+    ok(cancel_cnt == 1, "cancel_cnt = %u\n", cancel_cnt);
+
+    CancelIoEx(file, &overlapped2);
+
+    cancel_cnt = 0xdeadbeef;
+    res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &overlapped);
+    todo_wine
+    ok(res, "DeviceIoControl failed: %u\n", GetLastError());
+    if (!res && GetLastError() == ERROR_IO_PENDING) WaitForSingleObject(overlapped.hEvent, INFINITE);
+    todo_wine
+    ok(cancel_cnt == 2, "cancel_cnt = %u\n", cancel_cnt);
+
+    CloseHandle(overlapped.hEvent);
+    CloseHandle(overlapped2.hEvent);
+    CloseHandle(file);
+}
+
 static void test_load_driver(SC_HANDLE service)
 {
     SERVICE_STATUS status;
@@ -268,6 +347,7 @@ START_TEST(ntoskrnl)
 
     test_basic_ioctl();
     main_test();
+    test_cancel_io();
     test_load_driver(service2);
 
     unload_driver(service2);




More information about the wine-cvs mailing list