ntoskrnl.exe/tests: Add basic tests for ZwLoadDriver()/ZwUnloadDriver().
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
598b52ce38
commit
0a648b272c
|
@ -3,8 +3,12 @@ IMPORTS = advapi32
|
||||||
|
|
||||||
driver_IMPORTS = winecrt0 ntoskrnl
|
driver_IMPORTS = winecrt0 ntoskrnl
|
||||||
driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
|
driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
|
||||||
|
driver2_IMPORTS = winecrt0 ntoskrnl
|
||||||
|
driver2_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
driver.c \
|
driver.c \
|
||||||
driver.spec \
|
driver.spec \
|
||||||
|
driver2.c \
|
||||||
|
driver2.spec \
|
||||||
ntoskrnl.c
|
ntoskrnl.c
|
||||||
|
|
|
@ -187,6 +187,29 @@ static void test_init_funcs(void)
|
||||||
ok(timer2.Header.SignalState == 0, "got: %u\n", timer2.Header.SignalState);
|
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)
|
static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
|
||||||
{
|
{
|
||||||
ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
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_currentprocess();
|
||||||
test_mdl_map();
|
test_mdl_map();
|
||||||
test_init_funcs();
|
test_init_funcs();
|
||||||
|
test_load_driver();
|
||||||
|
|
||||||
/* print process report */
|
/* print process report */
|
||||||
if (test_input->winetest_debug)
|
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;
|
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)
|
static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
@ -265,6 +306,9 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
case IOCTL_WINETEST_MAIN_TEST:
|
case IOCTL_WINETEST_MAIN_TEST:
|
||||||
status = main_test(irp, stack, &irp->IoStatus.Information);
|
status = main_test(irp, stack, &irp->IoStatus.Information);
|
||||||
break;
|
break;
|
||||||
|
case IOCTL_WINETEST_LOAD_DRIVER:
|
||||||
|
status = test_load_driver_ioctl(irp, stack, &irp->IoStatus.Information);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
/* All custom IOCTLs need to have a function value >= 0x800. */
|
/* 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_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_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";
|
static const char teststr[] = "Wine is not an emulator";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Second driver loaded by driver.c
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "winioctl.h"
|
||||||
|
#include "ddk/wdm.h"
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
static void WINAPI driver_Unload(DRIVER_OBJECT *driver)
|
||||||
|
{
|
||||||
|
DbgPrint("unloading driver2\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry)
|
||||||
|
{
|
||||||
|
DbgPrint("loading driver2\n");
|
||||||
|
|
||||||
|
driver->DriverUnload = driver_Unload;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
# nothing here yet
|
|
@ -30,9 +30,6 @@
|
||||||
|
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
static const char driver_name[] = "WineTestDriver";
|
|
||||||
static const char device_path[] = "\\\\.\\WineTestDriver";
|
|
||||||
|
|
||||||
static HANDLE device;
|
static HANDLE device;
|
||||||
|
|
||||||
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
|
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
|
||||||
|
@ -80,11 +77,9 @@ static void unload_driver(SC_HANDLE service)
|
||||||
CloseServiceHandle(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;
|
SC_HANDLE manager, service;
|
||||||
SERVICE_STATUS status;
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||||
if (!manager && GetLastError() == ERROR_ACCESS_DENIED)
|
if (!manager && GetLastError() == ERROR_ACCESS_DENIED)
|
||||||
|
@ -94,12 +89,11 @@ static SC_HANDLE load_driver(char *filename)
|
||||||
}
|
}
|
||||||
ok(!!manager, "OpenSCManager failed\n");
|
ok(!!manager, "OpenSCManager failed\n");
|
||||||
|
|
||||||
/* before we start with the actual tests, make sure to terminate
|
/* stop any old drivers running under this name */
|
||||||
* any old wine test drivers. */
|
|
||||||
service = OpenServiceA(manager, driver_name, SERVICE_ALL_ACCESS);
|
service = OpenServiceA(manager, driver_name, SERVICE_ALL_ACCESS);
|
||||||
if (service) unload_driver(service);
|
if (service) unload_driver(service);
|
||||||
|
|
||||||
load_resource("driver.dll", filename);
|
load_resource(resname, filename);
|
||||||
trace("Trying to load driver %s\n", filename);
|
trace("Trying to load driver %s\n", filename);
|
||||||
|
|
||||||
service = CreateServiceA(manager, driver_name, driver_name,
|
service = CreateServiceA(manager, driver_name, driver_name,
|
||||||
|
@ -107,7 +101,15 @@ static SC_HANDLE load_driver(char *filename)
|
||||||
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
|
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
|
||||||
filename, NULL, NULL, NULL, NULL, NULL);
|
filename, NULL, NULL, NULL, NULL, NULL);
|
||||||
ok(!!service, "CreateService failed: %u\n", GetLastError());
|
ok(!!service, "CreateService failed: %u\n", GetLastError());
|
||||||
|
|
||||||
CloseServiceHandle(manager);
|
CloseServiceHandle(manager);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL start_driver(HANDLE service)
|
||||||
|
{
|
||||||
|
SERVICE_STATUS status;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = StartServiceA(service, 0, NULL);
|
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");
|
skip("Failed to start service; probably your machine doesn't accept unsigned drivers.\n");
|
||||||
DeleteService(service);
|
DeleteService(service);
|
||||||
CloseServiceHandle(service);
|
CloseServiceHandle(service);
|
||||||
DeleteFileA(filename);
|
return FALSE;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
ok(ret, "StartService failed: %u\n", GetLastError());
|
ok(ret, "StartService failed: %u\n", GetLastError());
|
||||||
|
|
||||||
|
@ -134,10 +135,7 @@ static SC_HANDLE load_driver(char *filename)
|
||||||
ok(status.dwCurrentState == SERVICE_RUNNING,
|
ok(status.dwCurrentState == SERVICE_RUNNING,
|
||||||
"expected SERVICE_RUNNING, got %d\n", status.dwCurrentState);
|
"expected SERVICE_RUNNING, got %d\n", status.dwCurrentState);
|
||||||
|
|
||||||
device = CreateFileA(device_path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
|
return TRUE;
|
||||||
ok(device != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError());
|
|
||||||
|
|
||||||
return service;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void main_test(void)
|
static void main_test(void)
|
||||||
|
@ -194,22 +192,59 @@ static void test_basic_ioctl(void)
|
||||||
ok(!strcmp(buf, teststr), "got '%s'\n", buf);
|
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)
|
START_TEST(ntoskrnl)
|
||||||
{
|
{
|
||||||
char filename[MAX_PATH];
|
char filename[MAX_PATH], filename2[MAX_PATH];
|
||||||
SC_HANDLE service;
|
SC_HANDLE service, service2;
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||||
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
|
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
|
||||||
|
|
||||||
if (!(service = load_driver(filename)))
|
if (!(service = load_driver(filename, "driver.dll", "WineTestDriver")))
|
||||||
return;
|
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();
|
test_basic_ioctl();
|
||||||
main_test();
|
main_test();
|
||||||
|
test_load_driver(service2);
|
||||||
|
|
||||||
|
unload_driver(service2);
|
||||||
unload_driver(service);
|
unload_driver(service);
|
||||||
ret = DeleteFileA(filename);
|
ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError());
|
||||||
ok(ret, "DeleteFile failed: %u\n", GetLastError());
|
ok(DeleteFileA(filename2), "DeleteFile failed: %u\n", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue