ntoskrnl.exe/tests: Add CancelIo tests.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-05-02 13:21:29 +02:00 committed by Alexandre Julliard
parent 5f10c86d5b
commit 60ddf0f09e
3 changed files with 119 additions and 0 deletions

View File

@ -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;
}

View File

@ -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";

View File

@ -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);