Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: fix test failures on w8adm
dlls/ntoskrnl.exe/tests/Makefile.in | 4 ++ dlls/ntoskrnl.exe/tests/driver.c | 44 ++++++++++++++ dlls/ntoskrnl.exe/tests/driver.h | 1 + dlls/ntoskrnl.exe/tests/{driver.h => driver2.c} | 37 +++++++----- dlls/ntoskrnl.exe/tests/driver2.spec | 1 + dlls/ntoskrnl.exe/tests/ntoskrnl.c | 77 ++++++++++++++++++------- 6 files changed, 129 insertions(+), 35 deletions(-) copy dlls/ntoskrnl.exe/tests/{driver.h => driver2.c} (55%) create mode 100644 dlls/ntoskrnl.exe/tests/driver2.spec
diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in index 6a427ca..fae11bb 100644 --- a/dlls/ntoskrnl.exe/tests/Makefile.in +++ b/dlls/ntoskrnl.exe/tests/Makefile.in @@ -3,8 +3,12 @@ IMPORTS = advapi32
driver_IMPORTS = winecrt0 ntoskrnl driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native +driver2_IMPORTS = winecrt0 ntoskrnl +driver2_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
SOURCES = \ driver.c \ driver.spec \ + driver2.c \ + driver2.spec \ ntoskrnl.c diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index cde78e5..d424396 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -187,6 +187,29 @@ static void test_init_funcs(void) ok(timer2.Header.SignalState == 0, "got: %u\n", timer2.Header.SignalState); }
+static const WCHAR driver2_path[] = { + '\','R','e','g','i','s','t','r','y', + '\','M','a','c','h','i','n','e', + '\','S','y','s','t','e','m', + '\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', + '\','S','e','r','v','i','c','e','s', + '\','W','i','n','e','T','e','s','t','D','r','i','v','e','r','2',0 +}; + +static void test_load_driver(void) +{ + UNICODE_STRING name; + NTSTATUS ret; + + RtlInitUnicodeString(&name, driver2_path); + + ret = ZwLoadDriver(&name); + ok(!ret, "got %#x\n", ret); + + ret = ZwUnloadDriver(&name); + ok(!ret, "got %#x\n", ret); +} + static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -213,6 +236,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) test_currentprocess(); test_mdl_map(); test_init_funcs(); + test_load_driver();
/* print process report */ if (test_input->winetest_debug) @@ -245,6 +269,23 @@ static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR * return STATUS_SUCCESS; }
+static NTSTATUS test_load_driver_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) +{ + BOOL *load = irp->AssociatedIrp.SystemBuffer; + UNICODE_STRING name; + + if (!load) + return STATUS_ACCESS_VIOLATION; + + *info = 0; + + RtlInitUnicodeString(&name, driver2_path); + if (*load) + return ZwLoadDriver(&name); + else + return ZwUnloadDriver(&name); +} + static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) { irp->IoStatus.Status = STATUS_SUCCESS; @@ -265,6 +306,9 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) case IOCTL_WINETEST_MAIN_TEST: status = main_test(irp, stack, &irp->IoStatus.Information); break; + case IOCTL_WINETEST_LOAD_DRIVER: + status = test_load_driver_ioctl(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 b254d44..6a4179e 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -24,6 +24,7 @@ /* All custom IOCTLs need to have a function value >= 0x800. */ #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)
static const char teststr[] = "Wine is not an emulator";
diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver2.c similarity index 55% copy from dlls/ntoskrnl.exe/tests/driver.h copy to dlls/ntoskrnl.exe/tests/driver2.c index b254d44..c648ec6 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver2.c @@ -1,9 +1,7 @@ /* - * ntoskrnl.exe testing framework + * Second driver loaded by driver.c * - * Copyright 2015 Sebastian Lackner - * Copyright 2015 Michael Müller - * Copyright 2015 Christian Costa + * Copyright 2018 Zebediah Figura * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,17 +18,28 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdarg.h>
-/* All custom IOCTLs need to have a function value >= 0x800. */ -#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) +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "winioctl.h" +#include "ddk/wdm.h"
-static const char teststr[] = "Wine is not an emulator"; +#include "driver.h"
-struct test_input +static void WINAPI driver_Unload(DRIVER_OBJECT *driver) { - int running_under_wine; - int winetest_report_success; - int winetest_debug; - WCHAR path[1]; -}; + DbgPrint("unloading driver2\n"); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) +{ + DbgPrint("loading driver2\n"); + + driver->DriverUnload = driver_Unload; + + return STATUS_SUCCESS; +} diff --git a/dlls/ntoskrnl.exe/tests/driver2.spec b/dlls/ntoskrnl.exe/tests/driver2.spec new file mode 100644 index 0000000..ad33444 --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver2.spec @@ -0,0 +1 @@ +# nothing here yet diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 40de760..73f0e85 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -30,9 +30,6 @@
#include "driver.h"
-static const char driver_name[] = "WineTestDriver"; -static const char device_path[] = "\\.\WineTestDriver"; - static HANDLE device;
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* ); @@ -80,11 +77,9 @@ static void unload_driver(SC_HANDLE service) CloseServiceHandle(service); }
-static SC_HANDLE load_driver(char *filename) +static SC_HANDLE load_driver(char *filename, const char *resname, const char *driver_name) { SC_HANDLE manager, service; - SERVICE_STATUS status; - BOOL ret;
manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!manager && GetLastError() == ERROR_ACCESS_DENIED) @@ -94,12 +89,11 @@ static SC_HANDLE load_driver(char *filename) } ok(!!manager, "OpenSCManager failed\n");
- /* before we start with the actual tests, make sure to terminate - * any old wine test drivers. */ + /* stop any old drivers running under this name */ service = OpenServiceA(manager, driver_name, SERVICE_ALL_ACCESS); if (service) unload_driver(service);
- load_resource("driver.dll", filename); + load_resource(resname, filename); trace("Trying to load driver %s\n", filename);
service = CreateServiceA(manager, driver_name, driver_name, @@ -107,7 +101,15 @@ static SC_HANDLE load_driver(char *filename) SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, filename, NULL, NULL, NULL, NULL, NULL); ok(!!service, "CreateService failed: %u\n", GetLastError()); + CloseServiceHandle(manager); + return service; +} + +static BOOL start_driver(HANDLE service) +{ + SERVICE_STATUS status; + BOOL ret;
SetLastError(0xdeadbeef); ret = StartServiceA(service, 0, NULL); @@ -117,8 +119,7 @@ static SC_HANDLE load_driver(char *filename) skip("Failed to start service; probably your machine doesn't accept unsigned drivers.\n"); DeleteService(service); CloseServiceHandle(service); - DeleteFileA(filename); - return NULL; + return FALSE; } ok(ret, "StartService failed: %u\n", GetLastError());
@@ -134,10 +135,7 @@ static SC_HANDLE load_driver(char *filename) ok(status.dwCurrentState == SERVICE_RUNNING, "expected SERVICE_RUNNING, got %d\n", status.dwCurrentState);
- device = CreateFileA(device_path, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - ok(device != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); - - return service; + return TRUE; }
static void main_test(void) @@ -194,22 +192,59 @@ static void test_basic_ioctl(void) ok(!strcmp(buf, teststr), "got '%s'\n", buf); }
+static void test_load_driver(SC_HANDLE service) +{ + SERVICE_STATUS status; + BOOL load, res; + DWORD sz; + + res = QueryServiceStatus(service, &status); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status.dwCurrentState == SERVICE_STOPPED, "got state %#x\n", status.dwCurrentState); + + load = TRUE; + res = DeviceIoControl(device, IOCTL_WINETEST_LOAD_DRIVER, &load, sizeof(load), NULL, 0, &sz, NULL); + ok(res, "DeviceIoControl failed: %u\n", GetLastError()); + + res = QueryServiceStatus(service, &status); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status.dwCurrentState == SERVICE_RUNNING, "got state %#x\n", status.dwCurrentState); + + load = FALSE; + res = DeviceIoControl(device, IOCTL_WINETEST_LOAD_DRIVER, &load, sizeof(load), NULL, 0, &sz, NULL); + ok(res, "DeviceIoControl failed: %u\n", GetLastError()); + + res = QueryServiceStatus(service, &status); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status.dwCurrentState == SERVICE_STOPPED, "got state %#x\n", status.dwCurrentState); +} + START_TEST(ntoskrnl) { - char filename[MAX_PATH]; - SC_HANDLE service; - BOOL ret; + char filename[MAX_PATH], filename2[MAX_PATH]; + SC_HANDLE service, service2;
HMODULE hntdll = GetModuleHandleA("ntdll.dll"); pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
- if (!(service = load_driver(filename))) + if (!(service = load_driver(filename, "driver.dll", "WineTestDriver"))) return; + if (!start_driver(service)) + { + DeleteFileA(filename); + return; + } + service2 = load_driver(filename2, "driver2.dll", "WineTestDriver2"); + + device = CreateFileA("\\.\WineTestDriver", 0, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(device != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError());
test_basic_ioctl(); main_test(); + test_load_driver(service2);
+ unload_driver(service2); unload_driver(service); - ret = DeleteFileA(filename); - ok(ret, "DeleteFile failed: %u\n", GetLastError()); + ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError()); + ok(DeleteFileA(filename2), "DeleteFile failed: %u\n", GetLastError()); }