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_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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue