Signed-off-by: Zebediah Figura z.figura12@gmail.com --- The idea of this series is twofold: first, to make it possible to use ok() almost everywhere (including in the driver initialization and unload routines), and secondly, to reduce the programming overhead of communicating test results, which is especially useful as we add more and more test drivers.
dlls/ntoskrnl.exe/tests/driver.c | 23 +++++------------------ dlls/ntoskrnl.exe/tests/driver_netio.c | 22 +++++----------------- dlls/ntoskrnl.exe/tests/utils.h | 25 +++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 179d2d5e02d..1d78f576ecf 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1782,15 +1782,7 @@ static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) test_stack_limits(); test_completion();
- /* print process report */ - if (winetest_debug) - { - kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", - PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures, - todo_successes, failures + todo_failures, - (failures + todo_failures != 1) ? "failures" : "failure", skipped ); - } - ZwClose(okfile); + winetest_cleanup();
*((LONG *)buffer) = failures; irp->IoStatus.Status = STATUS_SUCCESS; @@ -2116,24 +2108,19 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; void *buffer = irp->AssociatedIrp.SystemBuffer; struct test_input *test_input = (struct test_input *)buffer; - OBJECT_ATTRIBUTES attr = {0}; - UNICODE_STRING pathU; - IO_STATUS_BLOCK io; + NTSTATUS status;
if (!buffer) return STATUS_ACCESS_VIOLATION; if (length < sizeof(failures)) return STATUS_BUFFER_TOO_SMALL;
- attr.Length = sizeof(attr); - RtlInitUnicodeString(&pathU, L"\??\C:\windows\winetest_ntoskrnl_okfile"); running_under_wine = test_input->running_under_wine; winetest_debug = test_input->winetest_debug; winetest_report_success = test_input->winetest_report_success; - attr.ObjectName = &pathU; - attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */ - ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, - FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); + + if ((status = winetest_init())) + return status;
pExEventObjectType = get_proc_address("ExEventObjectType"); ok(!!pExEventObjectType, "ExEventObjectType not found\n"); diff --git a/dlls/ntoskrnl.exe/tests/driver_netio.c b/dlls/ntoskrnl.exe/tests/driver_netio.c index 3d783dbef0d..98392c9c7fd 100644 --- a/dlls/ntoskrnl.exe/tests/driver_netio.c +++ b/dlls/ntoskrnl.exe/tests/driver_netio.c @@ -468,38 +468,26 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; void *buffer = irp->AssociatedIrp.SystemBuffer; struct test_input *test_input = buffer; - OBJECT_ATTRIBUTES attr = {0}; - UNICODE_STRING pathU; - IO_STATUS_BLOCK io; + NTSTATUS status;
if (!buffer) return STATUS_ACCESS_VIOLATION; if (length < sizeof(failures)) return STATUS_BUFFER_TOO_SMALL;
- attr.Length = sizeof(attr); - RtlInitUnicodeString(&pathU, L"\??\C:\winetest_ntoskrnl_okfile"); running_under_wine = test_input->running_under_wine; winetest_debug = test_input->winetest_debug; winetest_report_success = test_input->winetest_report_success; - attr.ObjectName = &pathU; - attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */ - ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, - FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); + + if ((status = winetest_init())) + return status;
netio_init(); test_wsk_get_address_info(); test_wsk_listen_socket(); test_wsk_connect_socket();
- if (winetest_debug) - { - kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", - PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures, - todo_successes, failures + todo_failures, - (failures + todo_failures != 1) ? "failures" : "failure", skipped ); - } - ZwClose(okfile); + winetest_cleanup();
*((LONG *)buffer) = failures; irp->IoStatus.Information = sizeof(failures); diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h index be0f58f837c..508346ef9bf 100644 --- a/dlls/ntoskrnl.exe/tests/utils.h +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -49,6 +49,31 @@ static inline void WINAPIV kprintf(const char *format, ...) __ms_va_end(valist); }
+static inline NTSTATUS winetest_init(void) +{ + OBJECT_ATTRIBUTES attr; + UNICODE_STRING string; + IO_STATUS_BLOCK io; + + RtlInitUnicodeString(&string, L"\??\C:\windows\winetest_ntoskrnl_okfile"); + /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */ + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL); + return ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); +} + +static inline void winetest_cleanup(void) +{ + if (winetest_debug) + { + kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", + PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures, + todo_successes, failures + todo_failures, + (failures + todo_failures != 1) ? "failures" : "failure", skipped ); + } + ZwClose(okfile); +} + static inline void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args) { const char *current_file;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 6 +++--- dlls/ntoskrnl.exe/tests/driver.c | 10 +++------- dlls/ntoskrnl.exe/tests/driver.h | 6 +++++- dlls/ntoskrnl.exe/tests/driver_netio.c | 5 ----- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 27 ++++++++++++++++---------- dlls/ntoskrnl.exe/tests/utils.h | 26 ++++++++++++++++++++++++- 6 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index b6808c2fa38..bdb3687cfe2 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1430,7 +1430,7 @@ @ stdcall -private ZwLockFile(long long ptr ptr ptr ptr ptr ptr long long) NtLockFile @ stdcall -private ZwLockVirtualMemory(long ptr ptr long) NtLockVirtualMemory @ stdcall ZwMakeTemporaryObject(long) NtMakeTemporaryObject -@ stdcall -private ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection +@ stdcall ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection @ stdcall -private ZwNotifyChangeDirectoryFile(long long ptr ptr ptr ptr long long long) NtNotifyChangeDirectoryFile @ stdcall -private ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey @ stdcall ZwOpenDirectoryObject(ptr long ptr) NtOpenDirectoryObject @@ -1444,7 +1444,7 @@ @ stdcall -private ZwOpenProcess(ptr long ptr ptr) NtOpenProcess @ stdcall -private ZwOpenProcessToken(long long ptr) NtOpenProcessToken @ stdcall -private ZwOpenProcessTokenEx(long long long ptr) NtOpenProcessTokenEx -@ stdcall -private ZwOpenSection(ptr long ptr) NtOpenSection +@ stdcall ZwOpenSection(ptr long ptr) NtOpenSection @ stdcall -private ZwOpenSymbolicLinkObject(ptr long ptr) NtOpenSymbolicLinkObject @ stdcall -private ZwOpenThread(ptr long ptr ptr) NtOpenThread @ stdcall -private ZwOpenThreadToken(long long long ptr) NtOpenThreadToken @@ -1520,7 +1520,7 @@ @ stdcall -private ZwUnloadKey(ptr) NtUnloadKey @ stdcall -private ZwUnlockFile(long ptr ptr ptr ptr) NtUnlockFile @ stdcall -private ZwUnlockVirtualMemory(long ptr ptr long) NtUnlockVirtualMemory -@ stdcall -private ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection +@ stdcall ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection @ stdcall -private ZwWaitForMultipleObjects(long ptr long long ptr) NtWaitForMultipleObjects @ stdcall ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject @ stdcall ZwWriteFile(long long ptr ptr ptr ptr long ptr ptr) NtWriteFile diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 1d78f576ecf..c5e0bdf754f 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1990,7 +1990,7 @@ static void test_dpc(void) KeRevertToUserAffinityThread(); }
-static void test_process_memory(const struct test_input *test_input) +static void test_process_memory(const struct main_test_input *test_input) { NTSTATUS (WINAPI *pMmCopyVirtualMemory)(PEPROCESS fromprocess, void *fromaddress, PEPROCESS toprocess, void *toaddress, SIZE_T bufsize, KPROCESSOR_MODE mode, SIZE_T *copied); @@ -2044,7 +2044,7 @@ static void test_process_memory(const struct test_input *test_input) win_skip("MmCopyVirtualMemory is not available.\n"); }
- if (!test_input->running_under_wine) + if (!running_under_wine) { KeStackAttachProcess((PKPROCESS)process, &state); todo_wine ok(!strcmp(teststr, (char *)(base + test_input->teststr_offset)), @@ -2107,7 +2107,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; void *buffer = irp->AssociatedIrp.SystemBuffer; - struct test_input *test_input = (struct test_input *)buffer; + struct main_test_input *test_input = (struct main_test_input *)buffer; NTSTATUS status;
if (!buffer) @@ -2115,10 +2115,6 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st if (length < sizeof(failures)) return STATUS_BUFFER_TOO_SMALL;
- running_under_wine = test_input->running_under_wine; - winetest_debug = test_input->winetest_debug; - winetest_report_success = test_input->winetest_report_success; - if ((status = winetest_init())) return status;
diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index d55dd95cf20..cdf706b9830 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -38,11 +38,15 @@
static const char teststr[] = "Wine is not an emulator";
-struct test_input +struct test_data { int running_under_wine; int winetest_report_success; int winetest_debug; +}; + +struct main_test_input +{ DWORD process_id; SIZE_T teststr_offset; ULONG64 *modified_value; diff --git a/dlls/ntoskrnl.exe/tests/driver_netio.c b/dlls/ntoskrnl.exe/tests/driver_netio.c index 98392c9c7fd..55b5688ff53 100644 --- a/dlls/ntoskrnl.exe/tests/driver_netio.c +++ b/dlls/ntoskrnl.exe/tests/driver_netio.c @@ -467,7 +467,6 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; void *buffer = irp->AssociatedIrp.SystemBuffer; - struct test_input *test_input = buffer; NTSTATUS status;
if (!buffer) @@ -475,10 +474,6 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st if (length < sizeof(failures)) return STATUS_BUFFER_TOO_SMALL;
- running_under_wine = test_input->running_under_wine; - winetest_debug = test_input->winetest_debug; - winetest_report_success = test_input->winetest_report_success; - if ((status = winetest_init())) return status;
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 4667915f621..92cbfa6a329 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -4,6 +4,7 @@ * Copyright 2015 Sebastian Lackner * Copyright 2015 Michael Müller * Copyright 2015 Christian Costa + * Copyright 2020-2021 Zebediah Figura for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -367,7 +368,7 @@ static ULONG64 modified_value;
static void main_test(void) { - struct test_input *test_input; + struct main_test_input *test_input; DWORD written, read; LONG new_failures; char buffer[512]; @@ -381,9 +382,6 @@ static void main_test(void) ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
test_input = heap_alloc( sizeof(*test_input) ); - test_input->running_under_wine = !strcmp(winetest_platform, "wine"); - test_input->winetest_report_success = winetest_report_success; - test_input->winetest_debug = winetest_debug; test_input->process_id = GetCurrentProcessId(); test_input->teststr_offset = (SIZE_T)((BYTE *)&teststr - (BYTE *)NtCurrentTeb()->Peb->ImageBaseAddress); test_input->modified_value = &modified_value; @@ -1195,7 +1193,9 @@ START_TEST(ntoskrnl) WCHAR filename[MAX_PATH], filename2[MAX_PATH]; struct testsign_context ctx; SC_HANDLE service, service2; + struct test_data *data; BOOL ret, is_wow64; + HANDLE mapping; DWORD written;
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(GetModuleHandleA("ntdll"), "RtlDosPathNameToNtPathName_U"); @@ -1215,18 +1215,22 @@ START_TEST(ntoskrnl) if (!testsign_create_cert(&ctx)) return;
+ mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + 0, sizeof(*data), "Global\winetest_ntoskrnl_section"); + ok(!!mapping, "got error %u\n", GetLastError()); + data = MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024); + data->running_under_wine = !strcmp(winetest_platform, "wine"); + data->winetest_report_success = winetest_report_success; + data->winetest_debug = winetest_debug; + subtest("driver"); if (!(service = load_driver(&ctx, filename, L"driver.dll", L"WineTestDriver"))) - { - testsign_cleanup(&ctx); - return; - } + goto out;
if (!start_driver(service, FALSE)) { DeleteFileW(filename); - testsign_cleanup(&ctx); - return; + goto out; } service2 = load_driver(&ctx, filename2, L"driver2.dll", L"WineTestDriver2");
@@ -1265,5 +1269,8 @@ START_TEST(ntoskrnl)
test_pnp_driver(&ctx);
+out: testsign_cleanup(&ctx); + UnmapViewOfFile(data); + CloseHandle(mapping); } diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h index 508346ef9bf..f743e88097a 100644 --- a/dlls/ntoskrnl.exe/tests/utils.h +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -5,6 +5,7 @@ * Copyright 2015 Michael Müller * Copyright 2015 Christian Costa * Copyright 2020 Paul Gofman for CodeWeavers + * Copyright 2020-2021 Zebediah Figura for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,13 +52,36 @@ static inline void WINAPIV kprintf(const char *format, ...)
static inline NTSTATUS winetest_init(void) { + const struct test_data *data; + SIZE_T size = sizeof(*data); OBJECT_ATTRIBUTES attr; UNICODE_STRING string; IO_STATUS_BLOCK io; + void *addr = NULL; + HANDLE section; + NTSTATUS ret;
- RtlInitUnicodeString(&string, L"\??\C:\windows\winetest_ntoskrnl_okfile"); + RtlInitUnicodeString(&string, L"\BaseNamedObjects\winetest_ntoskrnl_section"); /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */ InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL); + if ((ret = ZwOpenSection(§ion, SECTION_MAP_READ, &attr))) + return ret; + + if ((ret = ZwMapViewOfSection(section, NtCurrentProcess(), &addr, + 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READONLY))) + { + ZwClose(section); + return ret; + } + data = addr; + running_under_wine = data->running_under_wine; + winetest_debug = data->winetest_debug; + winetest_report_success = data->winetest_report_success; + + ZwUnmapViewOfSection(NtCurrentProcess(), addr); + ZwClose(section); + + RtlInitUnicodeString(&string, L"\??\C:\windows\winetest_ntoskrnl_okfile"); return ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- In theory, we could just keep the section mapped for the driver's entire lifetime, and store the "failures" variable directly in the section. In practice, Windows panics when I try this. I suspect the reason is that memory mapped in one process (i.e. the system process) can't be safely accessed in another process (i.e. a user context), even if the section handle is created with OBJ_KERNEL_HANDLE.
dlls/ntoskrnl.exe/tests/driver.c | 7 +----- dlls/ntoskrnl.exe/tests/driver.h | 1 + dlls/ntoskrnl.exe/tests/driver_netio.c | 6 +---- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 33 +++++++++++++------------- dlls/ntoskrnl.exe/tests/utils.h | 30 +++++++++++++++++++++++ 5 files changed, 49 insertions(+), 28 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index c5e0bdf754f..6d46314216b 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1770,7 +1770,6 @@ static PIO_WORKITEM main_test_work_item; static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) { IRP *irp = context; - void *buffer = irp->AssociatedIrp.SystemBuffer;
IoFreeWorkItem(main_test_work_item); main_test_work_item = NULL; @@ -1784,9 +1783,8 @@ static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context)
winetest_cleanup();
- *((LONG *)buffer) = failures; irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information = sizeof(failures); + irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); }
@@ -2105,15 +2103,12 @@ static void test_permanence(void)
static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { - ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; void *buffer = irp->AssociatedIrp.SystemBuffer; struct main_test_input *test_input = (struct main_test_input *)buffer; NTSTATUS status;
if (!buffer) return STATUS_ACCESS_VIOLATION; - if (length < sizeof(failures)) - return STATUS_BUFFER_TOO_SMALL;
if ((status = winetest_init())) return status; diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index cdf706b9830..397dd528e84 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -43,6 +43,7 @@ struct test_data int running_under_wine; int winetest_report_success; int winetest_debug; + int successes, failures, skipped, todo_successes, todo_failures; };
struct main_test_input diff --git a/dlls/ntoskrnl.exe/tests/driver_netio.c b/dlls/ntoskrnl.exe/tests/driver_netio.c index 55b5688ff53..ec8161d2424 100644 --- a/dlls/ntoskrnl.exe/tests/driver_netio.c +++ b/dlls/ntoskrnl.exe/tests/driver_netio.c @@ -465,14 +465,11 @@ static void test_wsk_connect_socket(void)
static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { - ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; void *buffer = irp->AssociatedIrp.SystemBuffer; NTSTATUS status;
if (!buffer) return STATUS_ACCESS_VIOLATION; - if (length < sizeof(failures)) - return STATUS_BUFFER_TOO_SMALL;
if ((status = winetest_init())) return status; @@ -484,8 +481,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st
winetest_cleanup();
- *((LONG *)buffer) = failures; - irp->IoStatus.Information = sizeof(failures); + irp->IoStatus.Information = 0; return STATUS_SUCCESS; }
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 92cbfa6a329..d0320fbb2b4 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -47,6 +47,8 @@ static const GUID GUID_NULL;
static HANDLE device;
+static struct test_data *test_data; + static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR *, UNICODE_STRING *, WCHAR **, CURDIR *); static BOOL (WINAPI *pRtlFreeUnicodeString)(UNICODE_STRING *); static BOOL (WINAPI *pCancelIoEx)(HANDLE, OVERLAPPED *); @@ -369,10 +371,9 @@ static ULONG64 modified_value; static void main_test(void) { struct main_test_input *test_input; - DWORD written, read; - LONG new_failures; char buffer[512]; HANDLE okfile; + DWORD size; BOOL res;
/* Create a temporary file that the driver will write ok/trace output to. */ @@ -387,17 +388,16 @@ static void main_test(void) test_input->modified_value = &modified_value; modified_value = 0;
- res = DeviceIoControl(device, IOCTL_WINETEST_MAIN_TEST, test_input, sizeof(*test_input), - &new_failures, sizeof(new_failures), &written, NULL); + res = DeviceIoControl(device, IOCTL_WINETEST_MAIN_TEST, test_input, sizeof(*test_input), NULL, 0, &size, NULL); ok(res, "DeviceIoControl failed: %u\n", GetLastError()); - ok(written == sizeof(new_failures), "got size %x\n", written); + ok(!size, "got size %u\n", size);
- /* Print the ok/trace output and then add to our failure count. */ do { - ReadFile(okfile, buffer, sizeof(buffer), &read, NULL); - printf("%.*s", read, buffer); - } while (read == sizeof(buffer)); - winetest_add_failures(new_failures); + ReadFile(okfile, buffer, sizeof(buffer), &size, NULL); + printf("%.*s", size, buffer); + } while (size == sizeof(buffer)); + + winetest_add_failures(InterlockedExchange(&test_data->failures, 0));
heap_free(test_input); CloseHandle(okfile); @@ -1193,7 +1193,6 @@ START_TEST(ntoskrnl) WCHAR filename[MAX_PATH], filename2[MAX_PATH]; struct testsign_context ctx; SC_HANDLE service, service2; - struct test_data *data; BOOL ret, is_wow64; HANDLE mapping; DWORD written; @@ -1216,12 +1215,12 @@ START_TEST(ntoskrnl) return;
mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, sizeof(*data), "Global\winetest_ntoskrnl_section"); + 0, sizeof(*test_data), "Global\winetest_ntoskrnl_section"); ok(!!mapping, "got error %u\n", GetLastError()); - data = MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024); - data->running_under_wine = !strcmp(winetest_platform, "wine"); - data->winetest_report_success = winetest_report_success; - data->winetest_debug = winetest_debug; + test_data = MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024); + test_data->running_under_wine = !strcmp(winetest_platform, "wine"); + test_data->winetest_report_success = winetest_report_success; + test_data->winetest_debug = winetest_debug;
subtest("driver"); if (!(service = load_driver(&ctx, filename, L"driver.dll", L"WineTestDriver"))) @@ -1271,6 +1270,6 @@ START_TEST(ntoskrnl)
out: testsign_cleanup(&ctx); - UnmapViewOfFile(data); + UnmapViewOfFile(test_data); CloseHandle(mapping); } diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h index f743e88097a..60a5e4d1255 100644 --- a/dlls/ntoskrnl.exe/tests/utils.h +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -88,6 +88,13 @@ static inline NTSTATUS winetest_init(void)
static inline void winetest_cleanup(void) { + struct test_data *data; + SIZE_T size = sizeof(*data); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING string; + void *addr = NULL; + HANDLE section; + if (winetest_debug) { kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", @@ -95,6 +102,29 @@ static inline void winetest_cleanup(void) todo_successes, failures + todo_failures, (failures + todo_failures != 1) ? "failures" : "failure", skipped ); } + + RtlInitUnicodeString(&string, L"\BaseNamedObjects\winetest_ntoskrnl_section"); + /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */ + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL); + + if (!ZwOpenSection(§ion, SECTION_MAP_READ | SECTION_MAP_WRITE, &attr)) + { + if (!ZwMapViewOfSection(section, NtCurrentProcess(), &addr, + 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READWRITE)) + { + data = addr; + + InterlockedExchangeAdd(&data->successes, successes); + InterlockedExchangeAdd(&data->failures, failures); + InterlockedExchangeAdd(&data->skipped, skipped); + InterlockedExchangeAdd(&data->todo_successes, todo_successes); + InterlockedExchangeAdd(&data->todo_failures, todo_failures); + + ZwUnmapViewOfSection(NtCurrentProcess(), addr); + } + ZwClose(section); + } + ZwClose(okfile); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index d0320fbb2b4..22fddfd3192 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -366,19 +366,37 @@ static BOOL start_driver(HANDLE service, BOOL vista_plus) return TRUE; }
+static void cat_okfile(HANDLE okfile) +{ + char buffer[512]; + DWORD size; + + SetFilePointer(okfile, 0, NULL, FILE_BEGIN); + + do + { + ReadFile(okfile, buffer, sizeof(buffer), &size, NULL); + printf("%.*s", size, buffer); + } while (size == sizeof(buffer)); + + SetFilePointer(okfile, 0, NULL, FILE_BEGIN); + SetEndOfFile(okfile); + + winetest_add_failures(InterlockedExchange(&test_data->failures, 0)); +} + static ULONG64 modified_value;
static void main_test(void) { struct main_test_input *test_input; - char buffer[512]; HANDLE okfile; DWORD size; BOOL res;
/* Create a temporary file that the driver will write ok/trace output to. */
- okfile = CreateFileA("C:\windows\winetest_ntoskrnl_okfile", GENERIC_READ, + okfile = CreateFileA("C:\windows\winetest_ntoskrnl_okfile", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
@@ -392,12 +410,7 @@ static void main_test(void) ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(!size, "got size %u\n", size);
- do { - ReadFile(okfile, buffer, sizeof(buffer), &size, NULL); - printf("%.*s", size, buffer); - } while (size == sizeof(buffer)); - - winetest_add_failures(InterlockedExchange(&test_data->failures, 0)); + cat_okfile(okfile);
heap_free(test_input); CloseHandle(okfile);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 22fddfd3192..4f7afed171c 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -366,7 +366,9 @@ static BOOL start_driver(HANDLE service, BOOL vista_plus) return TRUE; }
-static void cat_okfile(HANDLE okfile) +static HANDLE okfile; + +static void cat_okfile(void) { char buffer[512]; DWORD size; @@ -390,16 +392,9 @@ static ULONG64 modified_value; static void main_test(void) { struct main_test_input *test_input; - HANDLE okfile; DWORD size; BOOL res;
- /* Create a temporary file that the driver will write ok/trace output to. */ - - okfile = CreateFileA("C:\windows\winetest_ntoskrnl_okfile", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); - ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError()); - test_input = heap_alloc( sizeof(*test_input) ); test_input->process_id = GetCurrentProcessId(); test_input->teststr_offset = (SIZE_T)((BYTE *)&teststr - (BYTE *)NtCurrentTeb()->Peb->ImageBaseAddress); @@ -410,11 +405,9 @@ static void main_test(void) ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(!size, "got size %u\n", size);
- cat_okfile(okfile); + cat_okfile();
heap_free(test_input); - CloseHandle(okfile); - DeleteFileA("C:\windows\winetest_ntoskrnl_okfile"); }
static void test_basic_ioctl(void) @@ -1235,6 +1228,10 @@ START_TEST(ntoskrnl) test_data->winetest_report_success = winetest_report_success; test_data->winetest_debug = winetest_debug;
+ okfile = CreateFileA("C:\windows\winetest_ntoskrnl_okfile", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError()); + subtest("driver"); if (!(service = load_driver(&ctx, filename, L"driver.dll", L"WineTestDriver"))) goto out; @@ -1285,4 +1282,6 @@ out: testsign_cleanup(&ctx); UnmapViewOfFile(test_data); CloseHandle(mapping); + CloseHandle(okfile); + DeleteFileA("C:\windows\winetest_ntoskrnl_okfile"); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/driver.c | 53 ++++++++++---------------- dlls/ntoskrnl.exe/tests/driver_netio.c | 24 ++++++------ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 6 ++- 3 files changed, 35 insertions(+), 48 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 6d46314216b..0d991cd98d6 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1781,8 +1781,6 @@ static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) test_stack_limits(); test_completion();
- winetest_cleanup(); - irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); @@ -2104,15 +2102,11 @@ static void test_permanence(void) static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { void *buffer = irp->AssociatedIrp.SystemBuffer; - struct main_test_input *test_input = (struct main_test_input *)buffer; - NTSTATUS status; + struct main_test_input *test_input = buffer;
if (!buffer) return STATUS_ACCESS_VIOLATION;
- if ((status = winetest_init())) - return status; - pExEventObjectType = get_proc_address("ExEventObjectType"); ok(!!pExEventObjectType, "ExEventObjectType not found\n");
@@ -2520,6 +2514,8 @@ static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver)
IoDeleteDevice(upper_device); IoDeleteDevice(lower_device); + + winetest_cleanup(); }
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) @@ -2528,6 +2524,9 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) NTSTATUS status; void *obj;
+ if ((status = winetest_init())) + return status; + DbgPrint("loading driver\n");
driver_obj = driver; @@ -2547,38 +2546,26 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) pIoDriverObjectType = MmGetSystemRoutineAddress(&nameW);
RtlInitUnicodeString(&nameW, L"\Driver\WineTestDriver"); - if ((status = ObReferenceObjectByName(&nameW, 0, NULL, 0, *pIoDriverObjectType, KernelMode, NULL, &obj))) - return status; - if (obj != driver) - { - ObDereferenceObject(obj); - return STATUS_UNSUCCESSFUL; - } + status = ObReferenceObjectByName(&nameW, 0, NULL, 0, *pIoDriverObjectType, KernelMode, NULL, &obj); + ok(!status, "got %#x\n", status); + ok(obj == driver, "expected %p, got %p\n", driver, obj); ObDereferenceObject(obj);
RtlInitUnicodeString(&nameW, L"\Device\WineTestDriver"); RtlInitUnicodeString(&linkW, L"\DosDevices\WineTestDriver");
- if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, - FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device))) - { - status = IoCreateSymbolicLink(&linkW, &nameW); - lower_device->Flags &= ~DO_DEVICE_INITIALIZING; - } + status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device); + ok(!status, "failed to create device, status %#x\n", status); + status = IoCreateSymbolicLink(&linkW, &nameW); + ok(!status, "failed to create link, status %#x\n", status); + lower_device->Flags &= ~DO_DEVICE_INITIALIZING;
- if (!status) - { - RtlInitUnicodeString(&nameW, L"\Device\WineTestUpper"); + RtlInitUnicodeString(&nameW, L"\Device\WineTestUpper"); + status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device); + ok(!status, "failed to create device, status %#x\n", status);
- status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, - FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device); - } + IoAttachDeviceToDeviceStack(upper_device, lower_device); + upper_device->Flags &= ~DO_DEVICE_INITIALIZING;
- if (!status) - { - IoAttachDeviceToDeviceStack(upper_device, lower_device); - upper_device->Flags &= ~DO_DEVICE_INITIALIZING; - } - - return status; + return STATUS_SUCCESS; } diff --git a/dlls/ntoskrnl.exe/tests/driver_netio.c b/dlls/ntoskrnl.exe/tests/driver_netio.c index ec8161d2424..ea9cfd1a4c5 100644 --- a/dlls/ntoskrnl.exe/tests/driver_netio.c +++ b/dlls/ntoskrnl.exe/tests/driver_netio.c @@ -466,21 +466,15 @@ static void test_wsk_connect_socket(void) static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { void *buffer = irp->AssociatedIrp.SystemBuffer; - NTSTATUS status;
if (!buffer) return STATUS_ACCESS_VIOLATION;
- if ((status = winetest_init())) - return status; - netio_init(); test_wsk_get_address_info(); test_wsk_listen_socket(); test_wsk_connect_socket();
- winetest_cleanup(); - irp->IoStatus.Information = 0; return STATUS_SUCCESS; } @@ -533,6 +527,8 @@ static VOID WINAPI driver_unload(DRIVER_OBJECT *driver) IoDeleteSymbolicLink(&linkW);
IoDeleteDevice(device_obj); + + winetest_cleanup(); }
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) @@ -540,6 +536,9 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) UNICODE_STRING nameW, linkW; NTSTATUS status;
+ if ((status = winetest_init())) + return status; + DbgPrint("Loading driver.\n");
driver_obj = driver; @@ -552,12 +551,11 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) RtlInitUnicodeString(&nameW, device_name); RtlInitUnicodeString(&linkW, driver_link);
- if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, - FILE_DEVICE_SECURE_OPEN, FALSE, &device_obj))) - { - status = IoCreateSymbolicLink(&linkW, &nameW); - device_obj->Flags &= ~DO_DEVICE_INITIALIZING; - } + status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &device_obj); + ok(!status, "failed to create device, status %#x\n", status); + status = IoCreateSymbolicLink(&linkW, &nameW); + ok(!status, "failed to create link, status %#x\n", status); + device_obj->Flags &= ~DO_DEVICE_INITIALIZING;
- return status; + return STATUS_SUCCESS; } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 4f7afed171c..4981709034c 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -405,8 +405,6 @@ static void main_test(void) ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(!size, "got size %u\n", size);
- cat_okfile(); - heap_free(test_input); }
@@ -931,6 +929,8 @@ static void test_driver_netio(struct testsign_context *ctx) unload_driver(service); ret = DeleteFileW(filename); ok(ret, "DeleteFile failed: %u\n", GetLastError()); + + cat_okfile(); }
static void add_file_to_catalog(HANDLE catalog, const WCHAR *file) @@ -1272,6 +1272,8 @@ START_TEST(ntoskrnl) ret = DeleteFileW(filename2); ok(ret, "DeleteFile failed: %u\n", GetLastError());
+ cat_okfile(); + test_driver3(&ctx); subtest("driver_netio"); test_driver_netio(&ctx);