[PATCH v2 1/3] ntoskrnl.exe/tests: Add basic tests for ZwLoadDriver()/ZwUnloadDriver().

Zebediah Figura z.figura12 at gmail.com
Fri Aug 24 23:08:52 CDT 2018


Signed-off-by: Zebediah Figura <z.figura12 at 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());
 }
-- 
2.7.4




More information about the wine-devel mailing list