[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