This is necessary for services.exe to correctly start the driver, and seems desirable given the function's other uses.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/module.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 3410d2e..e1255c5 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -610,6 +610,8 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType ) break; } case BINARY_PE: + case BINARY_UNIX_EXE: + case BINARY_UNIX_LIB: *lpBinaryType = (binary_info.flags & BINARY_FLAG_64BIT) ? SCS_64BIT_BINARY : SCS_32BIT_BINARY; ret = TRUE; break; @@ -625,10 +627,6 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType ) *lpBinaryType = SCS_DOS_BINARY; ret = TRUE; break; - case BINARY_UNIX_EXE: - case BINARY_UNIX_LIB: - ret = FALSE; - break; }
CloseHandle( hfile );
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- tools/makedep.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/tools/makedep.c b/tools/makedep.c index c9ab24d..e1a3647 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -2858,6 +2858,8 @@ static void output_source_spec( struct makefile *make, struct incl_file *source,
if (crosstarget) { + struct strarray crossdllflags = get_expanded_file_local_var( make, obj, "CROSSDLLFLAGS" ); + dep_libs = empty_strarray; all_libs = add_import_libs( make, &dep_libs, imports, 1 ); add_import_libs( make, &dep_libs, get_default_imports( make ), 1 ); /* dependencies only */ @@ -2880,6 +2882,7 @@ static void output_source_spec( struct makefile *make, struct incl_file *source, output_filename( strmake( "-B%s", tools_dir_path( make, "winebuild" ))); if (tools_dir) output_filename( strmake( "--sysroot=%s", top_obj_dir_path( make, "" ))); output_filename( "--lib-suffix=.cross.a" ); + output_filenames( crossdllflags ); output_filename( "-shared" ); output_filename( source->filename ); output_filename( strmake( "%s.cross.o", obj_dir_path( make, obj )));
From: Sebastian Lackner sebastian@fds-team.de
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- configure | 1 + configure.ac | 1 + dlls/ntoskrnl.exe/tests/Makefile.in | 11 +++ dlls/ntoskrnl.exe/tests/driver.c | 126 ++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/driver.h | 27 ++++++ dlls/ntoskrnl.exe/tests/driver.spec | 0 dlls/ntoskrnl.exe/tests/ntoskrnl.c | 159 ++++++++++++++++++++++++++++++++++++ 7 files changed, 325 insertions(+) create mode 100644 dlls/ntoskrnl.exe/tests/Makefile.in create mode 100644 dlls/ntoskrnl.exe/tests/driver.c create mode 100644 dlls/ntoskrnl.exe/tests/driver.h create mode 100644 dlls/ntoskrnl.exe/tests/driver.spec create mode 100644 dlls/ntoskrnl.exe/tests/ntoskrnl.c
diff --git a/configure b/configure index 2f650b9..c81d3d9 100755 --- a/configure +++ b/configure @@ -18891,6 +18891,7 @@ wine_fn_config_makefile dlls/ntdll/tests enable_tests wine_fn_config_makefile dlls/ntdsapi enable_ntdsapi wine_fn_config_makefile dlls/ntdsapi/tests enable_tests wine_fn_config_makefile dlls/ntoskrnl.exe enable_ntoskrnl_exe +wine_fn_config_makefile dlls/ntoskrnl.exe/tests enable_tests wine_fn_config_makefile dlls/ntprint enable_ntprint wine_fn_config_makefile dlls/ntprint/tests enable_tests wine_fn_config_makefile dlls/objsel enable_objsel diff --git a/configure.ac b/configure.ac index ba98c12..841ac3c 100644 --- a/configure.ac +++ b/configure.ac @@ -3508,6 +3508,7 @@ WINE_CONFIG_MAKEFILE(dlls/ntdll/tests) WINE_CONFIG_MAKEFILE(dlls/ntdsapi) WINE_CONFIG_MAKEFILE(dlls/ntdsapi/tests) WINE_CONFIG_MAKEFILE(dlls/ntoskrnl.exe) +WINE_CONFIG_MAKEFILE(dlls/ntoskrnl.exe/tests) WINE_CONFIG_MAKEFILE(dlls/ntprint) WINE_CONFIG_MAKEFILE(dlls/ntprint/tests) WINE_CONFIG_MAKEFILE(dlls/objsel) diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in new file mode 100644 index 0000000..4e856a3 --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/Makefile.in @@ -0,0 +1,11 @@ +TESTDLL = ntoskrnl.exe +IMPORTS = advapi32 + +driver_IMPORTS = ntoskrnl +EXTRADLLFLAGS = -Wb,--subsystem,native +driver_CROSSDLLFLAGS = -nostdlib -Wl,--subsystem,native -Wl,-entry,_DriverEntry@8 + +SOURCES = \ + driver.c \ + driver.spec \ + ntoskrnl.c diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c new file mode 100644 index 0000000..a6f4971 --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -0,0 +1,126 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2015 Sebastian Lackner + * Copyright 2015 Michael Müller + * Copyright 2015 Christian Costa + * + * 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" + +const WCHAR driver_device[] = {'\','D','e','v','i','c','e', + '\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0}; +const WCHAR driver_link[] = {'\','D','o','s','D','e','v','i','c','e','s', + '\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0}; + +static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) +{ + ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; + char *buffer = irp->AssociatedIrp.SystemBuffer; + + if (!buffer) + return STATUS_ACCESS_VIOLATION; + + if (length < sizeof(teststr)) + return STATUS_BUFFER_TOO_SMALL; + + strcpy(buffer, teststr); + *info = sizeof(teststr); + + return STATUS_SUCCESS; +} + +static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) +{ + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + NTSTATUS status = STATUS_NOT_SUPPORTED; + + switch (stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_WINETEST_BASIC_IOCTL: + status = test_basic_ioctl(irp, stack, &irp->IoStatus.Information); + break; + default: + break; + } + + irp->IoStatus.Status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return status; +} + +static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp) +{ + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver) +{ + UNICODE_STRING linkW; + + DbgPrint("unloading driver\n"); + + RtlInitUnicodeString(&linkW, driver_link); + IoDeleteSymbolicLink(&linkW); + + IoDeleteDevice(driver->DeviceObject); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) +{ + UNICODE_STRING nameW, linkW; + DEVICE_OBJECT *device; + NTSTATUS status; + + DbgPrint("loading driver\n"); + + /* Allow unloading of the driver */ + driver->DriverUnload = driver_Unload; + + /* Set driver functions */ + driver->MajorFunction[IRP_MJ_CREATE] = driver_Create; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl; + driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close; + + RtlInitUnicodeString(&nameW, driver_device); + RtlInitUnicodeString(&linkW, driver_link); + + if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, FALSE, &device))) + status = IoCreateSymbolicLink(&linkW, &nameW); + + return status; +} diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h new file mode 100644 index 0000000..8c32bf2 --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -0,0 +1,27 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2015 Sebastian Lackner + * Copyright 2015 Michael Müller + * Copyright 2015 Christian Costa + * + * 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 + */ + + +/* 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) + +static const char teststr[] = "Wine is not an emulator"; diff --git a/dlls/ntoskrnl.exe/tests/driver.spec b/dlls/ntoskrnl.exe/tests/driver.spec new file mode 100644 index 0000000..e69de29 diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c new file mode 100644 index 0000000..623e10d --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -0,0 +1,159 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2015 Sebastian Lackner + * Copyright 2015 Michael Müller + * Copyright 2015 Christian Costa + * + * 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 "windows.h" +#include "winsvc.h" +#include "winioctl.h" +#include "wine/test.h" + +#include "driver.h" + +static const char driver_name[] = "WineTestDriver"; +static const char device_path[] = "\\.\WineTestDriver"; + +static HANDLE device; + +static void load_resource(const char *name, char *filename) +{ + static char path[MAX_PATH]; + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + GetTempPathA(sizeof(path), path); + GetTempFileNameA(path, name, 0, filename); + + file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", filename, GetLastError()); + + res = FindResourceA(NULL, name, "TESTDLL"); + ok( res != 0, "couldn't find resource\n" ); + ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res )); + WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL ); + ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" ); + CloseHandle( file ); +} + +static void unload_driver(SC_HANDLE service) +{ + SERVICE_STATUS status; + + CloseHandle(device); + + ControlService(service, SERVICE_CONTROL_STOP, &status); + while (status.dwCurrentState == SERVICE_STOP_PENDING) + { + Sleep(100); + ok(QueryServiceStatus(service, &status), "QueryServiceStatus failed: %u\n", GetLastError()); + } + ok(status.dwCurrentState == SERVICE_STOPPED, + "expected SERVICE_STOPPED, got %d\n", status.dwCurrentState); + + DeleteService(service); + CloseServiceHandle(service); +} + +static SC_HANDLE load_driver(char *filename) +{ + SC_HANDLE manager, service; + SERVICE_STATUS status; + BOOL ret; + + manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (!manager && GetLastError() == ERROR_ACCESS_DENIED) + { + skip("Failed to open SC manager, not enough permissions\n"); + return FALSE; + } + ok(!!manager, "OpenSCManager failed\n"); + + /* before we start with the actual tests, make sure to terminate + * any old wine test drivers. */ + service = OpenServiceA(manager, driver_name, SERVICE_ALL_ACCESS); + if (service) unload_driver(service); + + load_resource("driver.dll", filename); + trace("Trying to load driver %s\n", filename); + + service = CreateServiceA(manager, driver_name, driver_name, + SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + filename, NULL, NULL, NULL, NULL, NULL); + ok(!!service, "CreateService failed: %u\n", GetLastError()); + CloseServiceHandle(manager); + + SetLastError(0xdeadbeef); + ret = StartServiceA(service, 0, NULL); + if (!ret && GetLastError() == ERROR_DRIVER_BLOCKED) + { + /* If Secure Boot is enabled or the machine is 64-bit, it will reject an unsigned driver. */ + skip("Failed to start service; probably your machine doesn't accept unsigned drivers.\n"); + DeleteService(service); + CloseServiceHandle(service); + DeleteFileA(filename); + return NULL; + } + ok(ret, "StartService failed: %u\n", GetLastError()); + + /* wait for the service to start up properly */ + ok(QueryServiceStatus(service, &status), "QueryServiceStatus failed: %u\n", GetLastError()); + while (status.dwCurrentState == SERVICE_START_PENDING) + { + Sleep(100); + ok(QueryServiceStatus(service, &status), "QueryServiceStatus failed: %u\n", GetLastError()); + } + 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; +} + +static void test_basic_ioctl(void) +{ + DWORD written; + char buf[32]; + BOOL res; + + res = DeviceIoControl(device, IOCTL_WINETEST_BASIC_IOCTL, NULL, 0, buf, + sizeof(buf), &written, NULL); + ok(res, "DeviceIoControl failed: %u\n", GetLastError()); + ok(written == sizeof(teststr), "got size %d\n", written); + ok(!strcmp(buf, teststr), "got '%s'\n", buf); +} + +START_TEST(ntoskrnl) +{ + char filename[MAX_PATH]; + SC_HANDLE service; + + if (!(service = load_driver(filename))) + return; + + test_basic_ioctl(); + + unload_driver(service); + ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError()); +}
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37583
Your paranoid android.
=== build (build) === Unable to regenerate dlls/ntoskrnl/Makefile Recreation of tests/Makefile failed
On 10/04/18 10:50, Marvin wrote:
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37583
Your paranoid android.
=== build (build) === Unable to regenerate dlls/ntoskrnl/Makefile Recreation of tests/Makefile failed
A successful run of ntoskrnl.exe_crosstest.exe can be found here:
For https://bugs.winehq.org/show_bug.cgi?id=29460
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 8 +- dlls/ntoskrnl.exe/tests/driver.c | 157 ++++++++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/driver.h | 9 +++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 50 ++++++++++++ include/wine/test.h | 5 +- 5 files changed, 224 insertions(+), 5 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 1b03233..982da8d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1299,7 +1299,7 @@ @ stdcall -private ZwCancelIoFile(long ptr) NtCancelIoFile @ stdcall -private ZwCancelTimer(long ptr) NtCancelTimer @ stdcall -private ZwClearEvent(long) NtClearEvent -@ stdcall -private ZwClose(long) NtClose +@ stdcall ZwClose(long) NtClose @ stub ZwCloseObjectAuditAlarm @ stdcall -private ZwConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr) NtConnectPort @ stdcall -private ZwCreateDirectoryObject(ptr long ptr) NtCreateDirectoryObject @@ -1335,7 +1335,7 @@ @ stdcall -private ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey @ stdcall -private ZwOpenDirectoryObject(ptr long ptr) NtOpenDirectoryObject @ stdcall -private ZwOpenEvent(ptr long ptr) NtOpenEvent -@ stdcall -private ZwOpenFile(ptr long ptr ptr long long) NtOpenFile +@ stdcall ZwOpenFile(ptr long ptr ptr long long) NtOpenFile @ stdcall -private ZwOpenJobObject(ptr long ptr) NtOpenJobObject @ stdcall -private ZwOpenKey(ptr long ptr) NtOpenKey @ stdcall -private ZwOpenProcess(ptr long ptr ptr) NtOpenProcess @@ -1403,7 +1403,7 @@ @ stdcall -private ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection @ stdcall -private ZwWaitForMultipleObjects(long ptr long long ptr) NtWaitForMultipleObjects @ stdcall -private ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject -@ stdcall -private ZwWriteFile(long long ptr ptr ptr ptr long ptr ptr) NtWriteFile +@ stdcall ZwWriteFile(long long ptr ptr ptr ptr long ptr ptr) NtWriteFile @ stdcall -private ZwYieldExecution() NtYieldExecution @ stdcall -private -arch=arm,x86_64 -norelay __chkstk() @ cdecl -private -arch=i386 _CIcos() msvcrt._CIcos @@ -1439,7 +1439,7 @@ @ cdecl -private _strrev(str) msvcrt._strrev @ cdecl -private _strset(str long) msvcrt._strset @ cdecl -private _strupr(str) msvcrt._strupr -@ cdecl -private _vsnprintf(ptr long str ptr) msvcrt._vsnprintf +@ cdecl _vsnprintf(ptr long str ptr) msvcrt._vsnprintf @ cdecl -private _vsnwprintf(ptr long wstr ptr) msvcrt._vsnwprintf @ cdecl -private _wcsicmp(wstr wstr) msvcrt._wcsicmp @ cdecl -private _wcslwr(wstr) msvcrt._wcslwr diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index a6f4971..e2eaf79 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -37,6 +37,160 @@ const WCHAR driver_device[] = {'\','D','e','v','i','c','e', const WCHAR driver_link[] = {'\','D','o','s','D','e','v','i','c','e','s', '\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
+static HANDLE okfile; +static LONG successes; +static LONG failures; +static LONG skipped; +static LONG todo_successes; +static LONG todo_failures; +static int todo_level, todo_do_loop; +static int running_under_wine; +static int winetest_debug; +static int report_success; + +extern int CDECL _vsnprintf(char *str, size_t len, const char *format, __ms_va_list argptr); + +static void kvprintf(const char *format, __ms_va_list ap) +{ + static char buffer[512]; + LARGE_INTEGER offset; + IO_STATUS_BLOCK io; + + _vsnprintf(buffer, sizeof(buffer), format, ap); + offset.QuadPart = -1; + ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, strlen(buffer), &offset, NULL); +} + +static void kprintf(const char *format, ...) +{ + __ms_va_list valist; + + __ms_va_start(valist, format); + kvprintf(format, valist); + __ms_va_end(valist); +} + +static void ok_(const char *file, int line, int condition, const char *msg, ...) +{ + const char *current_file; + __ms_va_list args; + + if (!(current_file = strrchr(file, '/')) && + !(current_file = strrchr(file, '\'))) + current_file = file; + else + current_file++; + + __ms_va_start(args, msg); + if (todo_level) + { + if (condition) + { + kprintf("%s:%d: Test succeeded inside todo block: ", current_file, line); + kvprintf(msg, args); + InterlockedIncrement(&todo_failures); + } + else + { + if (winetest_debug > 0) + { + kprintf("%s:%d: Test marked todo: ", current_file, line); + kvprintf(msg, args); + } + InterlockedIncrement(&todo_successes); + } + } + else + { + if (!condition) + { + kprintf("%s:%d: Test failed: ", current_file, line); + kvprintf(msg, args); + InterlockedIncrement(&failures); + } + else + { + if (report_success) + kprintf("%s:%d: Test succeeded\n", current_file, line); + InterlockedIncrement(&successes); + } + } + __ms_va_end(args); +} + +static void winetest_start_todo( int is_todo ) +{ + todo_level = (todo_level << 1) | (is_todo != 0); + todo_do_loop=1; +} + +static int winetest_loop_todo(void) +{ + int do_loop=todo_do_loop; + todo_do_loop=0; + return do_loop; +} + +static void winetest_end_todo(void) +{ + todo_level >>= 1; +} + +#define ok(condition, ...) ok_(__FILE__, __LINE__, condition, __VA_ARGS__) +#define todo_if(is_todo) for (winetest_start_todo(is_todo); \ + winetest_loop_todo(); \ + winetest_end_todo()) +#define todo_wine todo_if(running_under_wine) +#define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine) + +static void test_currentprocess(void) +{ + PEPROCESS current; + + current = IoGetCurrentProcess(); +todo_wine + ok(current != NULL, "Expected current process to be non-NULL\n"); +} + +static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) +{ + ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; + void *buffer = irp->AssociatedIrp.SystemBuffer; + struct test_input *test_input = (struct test_input *)buffer; + OBJECT_ATTRIBUTES attr = {0}; + UNICODE_STRING pathU; + IO_STATUS_BLOCK io; + + if (!buffer) + return STATUS_ACCESS_VIOLATION; + + if (length < sizeof(failures)) + return STATUS_BUFFER_TOO_SMALL; + + attr.Length = sizeof(attr); + RtlInitUnicodeString(&pathU, test_input->path); + running_under_wine = test_input->running_under_wine; + winetest_debug = test_input->winetest_debug; + report_success = test_input->report_success; + attr.ObjectName = &pathU; + ZwOpenFile(&okfile, FILE_APPEND_DATA, &attr, &io, 0, 0); + + test_currentprocess(); + + /* print process report */ + if (test_input->winetest_debug) + { + kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", + PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures, + todo_successes, failures + todo_failures, + (failures + todo_failures != 1) ? "failures" : "failure", skipped ); + } + ZwClose(okfile); + *((LONG *)buffer) = failures; + *info = sizeof(failures); + return STATUS_SUCCESS; +} + static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -71,6 +225,9 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) case IOCTL_WINETEST_BASIC_IOCTL: status = test_basic_ioctl(irp, stack, &irp->IoStatus.Information); break; + case IOCTL_WINETEST_MAIN_TEST: + status = main_test(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 8c32bf2..da6d129 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -23,5 +23,14 @@
/* 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)
static const char teststr[] = "Wine is not an emulator"; + +struct test_input +{ + int running_under_wine; + int report_success; + int winetest_debug; + WCHAR path[1]; +}; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 623e10d..1b61278 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -20,10 +20,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdio.h> #include "windows.h" #include "winsvc.h" #include "winioctl.h" +#include "winternl.h" #include "wine/test.h" +#include "wine/heap.h"
#include "driver.h"
@@ -32,6 +35,8 @@ static const char device_path[] = "\\.\WineTestDriver";
static HANDLE device;
+static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* ); + static void load_resource(const char *name, char *filename) { static char path[MAX_PATH]; @@ -131,6 +136,47 @@ static SC_HANDLE load_driver(char *filename) return service; }
+static void main_test(void) +{ + static const WCHAR dokW[] = {'d','o','k',0}; + WCHAR temppathW[MAX_PATH], pathW[MAX_PATH]; + struct test_input *test_input; + UNICODE_STRING pathU; + DWORD written, read; + LONG new_failures; + char buffer[512]; + HANDLE okfile; + BOOL res; + + /* Create a temporary file that the driver will write ok/trace output to. */ + GetTempPathW(MAX_PATH, temppathW); + GetTempFileNameW(temppathW, dokW, 0, pathW); + pRtlDosPathNameToNtPathName_U( pathW, &pathU, NULL, NULL ); + + test_input = heap_alloc(sizeof(*test_input) + pathU.Length); + test_input->running_under_wine = !strcmp(winetest_platform, "wine"); + test_input->report_success = report_success; + test_input->winetest_debug = winetest_debug; + lstrcpynW(test_input->path, pathU.Buffer, pathU.Length); + res = DeviceIoControl(device, IOCTL_WINETEST_MAIN_TEST, test_input, sizeof(*test_input) + pathU.Length, + &new_failures, sizeof(new_failures), &written, NULL); + ok(res, "DeviceIoControl failed: %u\n", GetLastError()); + ok(written == sizeof(new_failures), "got size %x\n", written); + + okfile = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(okfile != INVALID_HANDLE_VALUE, "failed to create %s: %u\n", wine_dbgstr_w(pathW), GetLastError()); + + /* Print the ok/trace output and then add to our failure count. */ + do { + ReadFile(okfile, buffer, sizeof(buffer), &read, NULL); + printf("%.*s", read, buffer); + } while (read == sizeof(buffer)); + winetest_add_failures(new_failures); + + CloseHandle(okfile); + DeleteFileW(pathW); +} + static void test_basic_ioctl(void) { DWORD written; @@ -149,10 +195,14 @@ START_TEST(ntoskrnl) char filename[MAX_PATH]; SC_HANDLE service;
+ HMODULE hntdll = GetModuleHandleA("ntdll.dll"); + pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); + if (!(service = load_driver(filename))) return;
test_basic_ioctl(); + main_test();
unload_driver(service); ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError()); diff --git a/include/wine/test.h b/include/wine/test.h index 4ec66d5..5dd0861 100644 --- a/include/wine/test.h +++ b/include/wine/test.h @@ -52,6 +52,9 @@ extern int winetest_debug; /* running in interactive mode? */ extern int winetest_interactive;
+/* report successful tests (BOOL) */ +extern int report_success; + /* current platform */ extern const char *winetest_platform;
@@ -204,7 +207,7 @@ int winetest_interactive = 0; const char *winetest_platform = "windows";
/* report successful tests (BOOL) */ -static int report_success = 0; +int report_success = 0;
/* passing arguments around */ static int winetest_argc;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37584
Your paranoid android.
=== build (build) === Unable to regenerate dlls/ntoskrnl/Makefile Recreation of tests/Makefile failed
For https://bugs.winehq.org/show_bug.cgi?id=37355.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/driver.c | 21 +++++++++++++++++++++ include/ddk/wdm.h | 1 + 2 files changed, 22 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index e2eaf79..9cfdec5 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -152,6 +152,26 @@ todo_wine ok(current != NULL, "Expected current process to be non-NULL\n"); }
+static void test_mdl_map(void) +{ + char buffer[20] = "test buffer"; + void *addr; + MDL *mdl; + + mdl = IoAllocateMdl(buffer, sizeof(buffer), FALSE, FALSE, NULL); + ok(mdl != NULL, "IoAllocateMdl failed\n"); + + MmProbeAndLockPages(mdl, KernelMode, IoReadAccess); + + addr = MmMapLockedPagesSpecifyCache(mdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority); +todo_wine + ok(addr != NULL, "MmMapLockedPagesSpecifyCache failed\n"); + + /* MmUnmapLockedPages(addr, mdl); */ + + IoFreeMdl(mdl); +} + static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -176,6 +196,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) ZwOpenFile(&okfile, FILE_APPEND_DATA, &attr, &io, 0, 0);
test_currentprocess(); + test_mdl_map();
/* print process report */ if (test_input->winetest_debug) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 5b7c9e6..77370b9 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1421,6 +1421,7 @@ PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS,PHYSICAL_ADDRESS,PHYSICA void WINAPI MmFreeNonCachedMemory(PVOID,SIZE_T); PVOID WINAPI MmMapLockedPagesSpecifyCache(PMDL,KPROCESSOR_MODE,MEMORY_CACHING_TYPE,PVOID,ULONG,ULONG); MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void); +void WINAPI MmProbeAndLockPages(PMDLX, KPROCESSOR_MODE, LOCK_OPERATION);
static inline void *MmGetSystemAddressForMdlSafe(MDL *mdl, ULONG priority) {
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37585
Your paranoid android.
=== build (build) === Unable to regenerate dlls/ntoskrnl/Makefile Recreation of tests/Makefile failed
Zebediah Figura z.figura12@gmail.com writes:
This is necessary for services.exe to correctly start the driver, and seems desirable given the function's other uses.
I don't think it's a good idea to claim that non-PE files are Windows binaries. It's going to break many assumptions in app code, and even in Wine itself (cf. SHGetFileInfo).
On 11/04/18 10:41, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
This is necessary for services.exe to correctly start the driver, and seems desirable given the function's other uses.
I don't think it's a good idea to claim that non-PE files are Windows binaries. It's going to break many assumptions in app code, and even in Wine itself (cf. SHGetFileInfo).
Thanks for the review; sorry it took so long to get back to this.
services.exe uses GetBinaryType to determine which architecture of winedevice.exe to start, and in the case of the given test DLL it'll be passed a builtin .so when running under Linux. What should be done instead in this case? Reimplement MODULE_GetBinaryType in services.exe? Somehow pass a fake DLL from the test?
Zebediah Figura z.figura12@gmail.com writes:
On 11/04/18 10:41, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
This is necessary for services.exe to correctly start the driver, and seems desirable given the function's other uses.
I don't think it's a good idea to claim that non-PE files are Windows binaries. It's going to break many assumptions in app code, and even in Wine itself (cf. SHGetFileInfo).
Thanks for the review; sorry it took so long to get back to this.
services.exe uses GetBinaryType to determine which architecture of winedevice.exe to start, and in the case of the given test DLL it'll be passed a builtin .so when running under Linux. What should be done instead in this case? Reimplement MODULE_GetBinaryType in services.exe? Somehow pass a fake DLL from the test?
services.exe should never be passed a .so file directly. It should be passed the path to a PE binary, and rely on the loader to find the corresponding builtin. If the PE file doesn't exist, it should still try to load the builtin; in that case it would be OK to default to the current platform.
On 30/04/18 12:44, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
On 11/04/18 10:41, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
This is necessary for services.exe to correctly start the driver, and seems desirable given the function's other uses.
I don't think it's a good idea to claim that non-PE files are Windows binaries. It's going to break many assumptions in app code, and even in Wine itself (cf. SHGetFileInfo).
Thanks for the review; sorry it took so long to get back to this.
services.exe uses GetBinaryType to determine which architecture of winedevice.exe to start, and in the case of the given test DLL it'll be passed a builtin .so when running under Linux. What should be done instead in this case? Reimplement MODULE_GetBinaryType in services.exe? Somehow pass a fake DLL from the test?
services.exe should never be passed a .so file directly. It should be passed the path to a PE binary, and rely on the loader to find the corresponding builtin. If the PE file doesn't exist, it should still try to load the builtin; in that case it would be OK to default to the current platform.
Thanks, I agree this seems sensible. I'll send a revised patch series.