From: Matteo Bruni mbruni@codeweavers.com
--- dlls/ntoskrnl.exe/tests/driver.c | 39 +++++ dlls/ntoskrnl.exe/tests/driver.h | 21 +-- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 238 ++++++++++++++++++++++++++++- 3 files changed, 287 insertions(+), 11 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index dda8806ba74..220e4fbd190 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -58,6 +58,9 @@ static int kmemcmp( const void *ptr1, const void *ptr2, size_t n ) static DRIVER_OBJECT *driver_obj; static DEVICE_OBJECT *lower_device, *upper_device;
+static KDEVICE_QUEUE device_queue; +static IRP *current_irp; + static POBJECT_TYPE *pExEventObjectType, *pIoFileObjectType, *pPsThreadType, *pIoDriverObjectType; static PEPROCESS *pPsInitialSystemProcess; static void *create_caller_thread; @@ -2682,10 +2685,18 @@ static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) return STATUS_SUCCESS; }
+static void cancel_complete(IRP *irp) +{ + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); +} + static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); NTSTATUS status = STATUS_NOT_SUPPORTED; + KDEVICE_QUEUE_ENTRY *entry; + BOOLEAN ret;
switch (stack->Parameters.DeviceIoControl.IoControlCode) { @@ -2706,6 +2717,34 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) IoSetCancelRoutine(irp, cancel_ioctl_irp); IoMarkIrpPending(irp); return STATUS_PENDING; + case IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT: + KeInitializeDeviceQueue(&device_queue); + ok(IsListEmpty(&device_queue.DeviceListHead), "expected empty queue list\n"); + status = STATUS_SUCCESS; + break; + case IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE: + /* put the IRP into the queue */ + ret = KeInsertDeviceQueue(&device_queue, &irp->Tail.Overlay.DeviceQueueEntry); + /* or store it elsewhere if it's the one we're supposing to be + * working on "currently" */ + if (!ret) + current_irp = irp; + ok(device_queue.Busy, "expected Busy state\n"); + IoMarkIrpPending(irp); + return STATUS_PENDING; + case IOCTL_WINETEST_TEST_CANCEL_COMPLETE: + /* complete the pending IRPs gathered from + * IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE */ + cancel_complete(current_irp); + current_irp = NULL; + while ((entry = KeRemoveDeviceQueue(&device_queue))) + { + current_irp = CONTAINING_RECORD( entry, IRP, Tail.Overlay.DeviceQueueEntry.DeviceListEntry ); + cancel_complete(current_irp); + current_irp = NULL; + } + status = STATUS_SUCCESS; + break; case IOCTL_WINETEST_GET_CANCEL_COUNT: status = get_dword(irp, stack, &irp->IoStatus.Information, cancel_cnt); break; diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index e22d756e69e..4ee97c8d7ce 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -27,15 +27,18 @@ #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) -#define IOCTL_WINETEST_DETACH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_GET_CREATE_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_GET_CLOSE_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_GET_FSCONTEXT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_RETURN_STATUS_BUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80a, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_RETURN_STATUS_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80a, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_RETURN_STATUS_NEITHER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80a, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_WINETEST_COMPLETION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80c, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_TEST_CANCEL_COMPLETE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_CANCEL_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_DETACH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_CREATE_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80a, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_CLOSE_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80b, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_FSCONTEXT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80c, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_RETURN_STATUS_BUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80d, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_RETURN_STATUS_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80d, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_RETURN_STATUS_NEITHER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80d, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_COMPLETION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80e, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_WINETEST_BUS_MAIN CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_BUS_REGISTER_IFACE CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index bd2d490cba6..1c80bcd3898 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -438,16 +438,65 @@ static void test_basic_ioctl(void) ok(!strcmp(buf, "Wine is no"), "got '%s'\n", buf); }
+static BOOL returned; + +struct cancel_thread_ctx +{ + HANDLE file; + BOOL ex; +}; + +static DWORD WINAPI test_cancel_complete_thread(void *parameter) +{ + struct cancel_thread_ctx *ctx = parameter; + OVERLAPPED overlapped; + BOOL res; + + Sleep(200); + ok(!returned == !ctx->ex, "%s() %sreturned\n", + ctx->ex ? "CancelIoEx" : "CancelIo", returned ? "" : "not "); + res = DeviceIoControl(ctx->file, IOCTL_WINETEST_TEST_CANCEL_COMPLETE, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + return res; +} + +static DWORD WINAPI test_cancel_ex_thread(void *parameter) +{ + struct cancel_thread_ctx *ctx = parameter; + BOOL res; + + Sleep(100); + res = CancelIoEx(ctx->file, NULL); + ok(res, "CancelIoEx failed: %lu\n", GetLastError()); + return res; +} + +static DWORD WINAPI test_cancel_sync_thread(void *parameter) +{ + HANDLE tid = parameter; + BOOL res; + + Sleep(100); + ok(!returned, "Synchronous DeviceIoControl() already returned\n"); + res = CancelSynchronousIo(tid); + ok(res, "CancelSynchronousIo failed: %lu\n", GetLastError()); + Sleep(0); + todo_wine ok(returned, "Synchronous DeviceIoControl() hasn't returned yet\n"); + return res; +} + static void test_overlapped(void) { - OVERLAPPED overlapped, overlapped2, *o; + HANDLE file, port, thread, thread2, thread_current; + OVERLAPPED overlapped, overlapped2, o3, *o; + struct cancel_thread_ctx ctx; DWORD cancel_cnt, size; - HANDLE file, port; ULONG_PTR key; BOOL res;
overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); overlapped2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + o3.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
file = CreateFileA("\\.\WineTestDriver", FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); @@ -502,6 +551,189 @@ static void test_overlapped(void) ok(cancel_cnt == 2, "cancel_cnt = %lu\n", cancel_cnt); }
+ /* test cancelling uncancellable requests - CancelIo */ + res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped2); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + returned = FALSE; + ctx.file = file; + ctx.ex = FALSE; + thread = CreateThread(NULL, 0, test_cancel_complete_thread, &ctx, 0, NULL); + res = CancelIo(file); + ok(res, "CancelIo failed: %lu\n", GetLastError()); + returned = TRUE; + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + + res = CancelIo(file); + ok(res, "CancelIo failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + /* test cancelling uncancellable requests - CancelIoEx */ + res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped2); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + returned = FALSE; + ctx.file = file; + ctx.ex = TRUE; + thread = CreateThread(NULL, 0, test_cancel_complete_thread, &ctx, 0, NULL); + res = CancelIoEx(file, NULL); + ok(res, "CancelIoEx failed: %lu\n", GetLastError()); + res = CancelIoEx(file, NULL); + ok(res, "CancelIoEx failed: %lu\n", GetLastError()); + returned = TRUE; + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + + res = CancelIoEx(file, NULL); + ok(!res && GetLastError() == ERROR_NOT_FOUND, "CancelIoEx failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + /* test cancelling uncancellable requests - CancelIoEx + CancelIo */ + res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped2); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + returned = FALSE; + ctx.file = file; + ctx.ex = FALSE; + thread = CreateThread(NULL, 0, test_cancel_complete_thread, &ctx, 0, NULL); + res = CancelIoEx(file, NULL); + ok(res, "CancelIoEx failed: %lu\n", GetLastError()); + res = CancelIo(file); + ok(res, "CancelIo failed: %lu\n", GetLastError()); + returned = TRUE; + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + /* test cancelling uncancellable requests - CancelIo + CancelIoEx */ + res = DeviceIoControl(file, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT, NULL, 0, NULL, 0, NULL, &overlapped); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(file, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, NULL, &overlapped2); + ok(!res && GetLastError() == ERROR_IO_PENDING, "DeviceIoControl failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + returned = FALSE; + ctx.file = file; + ctx.ex = FALSE; + thread = CreateThread(NULL, 0, test_cancel_complete_thread, &ctx, 0, NULL); + thread2 = CreateThread(NULL, 0, test_cancel_ex_thread, &ctx, 0, NULL); + res = CancelIo(file); + ok(res, "CancelIo failed: %lu\n", GetLastError()); + returned = TRUE; + WaitForSingleObject(thread, INFINITE); + WaitForSingleObject(thread2, INFINITE); + CloseHandle(thread); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(file, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), NULL, &o3); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + /* test cancelling uncancellable requests - CancelSynchronousIo */ + res = DeviceIoControl(device, IOCTL_WINETEST_RESET_CANCEL, NULL, 0, NULL, 0, &size, NULL); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + res = DeviceIoControl(device, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE_INIT, NULL, 0, NULL, 0, &size, NULL); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(device, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), &size, NULL); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 0, "cancel_cnt = %lu\n", cancel_cnt); + + returned = FALSE; + res = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &thread_current, 0, FALSE, DUPLICATE_SAME_ACCESS); + ok(res, "DuplicateHandle failed: %lu\n", GetLastError()); + thread2 = CreateThread(NULL, 0, test_cancel_sync_thread, thread_current, 0, NULL); + /* This hangs */ + if (0) + { + ctx.file = device; + thread = CreateThread(NULL, 0, test_cancel_complete_thread, &ctx, 0, NULL); + res = DeviceIoControl(device, IOCTL_WINETEST_TEST_CANCEL_UNCANCELLABLE, NULL, 0, NULL, 0, &size, NULL); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + } + /* This hangs if the cancel routine doesn't call IoCompleteRequest() + * (regardless of Status / Information values) */ + res = DeviceIoControl(device, IOCTL_WINETEST_TEST_CANCEL, NULL, 0, NULL, 0, &size, NULL); + ok(!res && GetLastError() == ERROR_OPERATION_ABORTED, "DeviceIoControl failed: %lu\n", GetLastError()); + returned = TRUE; + WaitForSingleObject(thread2, INFINITE); + CloseHandle(thread2); + CloseHandle(thread_current); + + cancel_cnt = 0xdeadbeef; + res = DeviceIoControl(device, IOCTL_WINETEST_GET_CANCEL_COUNT, NULL, 0, &cancel_cnt, sizeof(cancel_cnt), &size, NULL); + ok(res, "DeviceIoControl failed: %lu\n", GetLastError()); + ok(cancel_cnt == 1, "cancel_cnt = %lu\n", cancel_cnt); + + /* test completion port */ port = CreateIoCompletionPort(file, NULL, 0xdeadbeef, 0); ok(port != NULL, "CreateIoCompletionPort failed, error %lu\n", GetLastError()); res = GetQueuedCompletionStatus(port, &size, &key, &o, 0); @@ -527,6 +759,7 @@ static void test_overlapped(void) CloseHandle(port); CloseHandle(overlapped.hEvent); CloseHandle(overlapped2.hEvent); + CloseHandle(o3.hEvent); CloseHandle(file); }
@@ -1261,6 +1494,7 @@ static void test_driver_netio(struct testsign_context *ctx) hthread = CreateThread(NULL, 0, wsk_test_thread, NULL, 0, NULL); main_test(); WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread);
CloseHandle(device);