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