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:
Zebediah Figura 2018-08-24 23:08:52 -05:00 committed by Alexandre Julliard
parent 598b52ce38
commit 0a648b272c
6 changed files with 151 additions and 21 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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";

View File

@ -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;
}

View File

@ -0,0 +1 @@
# nothing here yet

View File

@ -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());
}