Signed-off-by: Paul Gofman pgofman@codeweavers.com --- configure.ac | 1 + dlls/netio.sys/Makefile.in | 7 +++++ dlls/netio.sys/netio.c | 48 +++++++++++++++++++++++++++++++++++ dlls/netio.sys/netio.sys.spec | 1 + loader/wine.inf.in | 2 ++ 5 files changed, 59 insertions(+) create mode 100644 dlls/netio.sys/Makefile.in create mode 100644 dlls/netio.sys/netio.c create mode 100644 dlls/netio.sys/netio.sys.spec
diff --git a/configure.ac b/configure.ac index 83c451e0870..33a8a9a2888 100644 --- a/configure.ac +++ b/configure.ac @@ -3552,6 +3552,7 @@ WINE_CONFIG_MAKEFILE(dlls/netapi32) WINE_CONFIG_MAKEFILE(dlls/netapi32/tests) WINE_CONFIG_MAKEFILE(dlls/netcfgx) WINE_CONFIG_MAKEFILE(dlls/netcfgx/tests) +WINE_CONFIG_MAKEFILE(dlls/netio.sys) WINE_CONFIG_MAKEFILE(dlls/netprofm) WINE_CONFIG_MAKEFILE(dlls/netprofm/tests) WINE_CONFIG_MAKEFILE(dlls/newdev) diff --git a/dlls/netio.sys/Makefile.in b/dlls/netio.sys/Makefile.in new file mode 100644 index 00000000000..76e541021a6 --- /dev/null +++ b/dlls/netio.sys/Makefile.in @@ -0,0 +1,7 @@ +MODULE = netio.sys +IMPORTLIB = netio +IMPORTS = ntoskrnl +EXTRADLLFLAGS = -mno-cygwin -Wl,--subsystem,native + +C_SRCS = \ + netio.c diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c new file mode 100644 index 00000000000..16bf47ca0a2 --- /dev/null +++ b/dlls/netio.sys/netio.c @@ -0,0 +1,48 @@ +/* + * WSK (Winsock Kernel) driver library. + * + * Copyright 2020 Paul Gofman pgofman@codeweavers.com for Codeweavers + * + * 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> + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winioctl.h" +#include "winternl.h" +#include "ddk/wdm.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netio); + +static void WINAPI driver_unload(DRIVER_OBJECT *driver) +{ + TRACE("driver %p.\n", driver); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path) +{ + TRACE("driver %p, path %s.\n", driver, debugstr_w(path->Buffer)); + + driver->DriverUnload = driver_unload; + return STATUS_SUCCESS; +} + diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/dlls/netio.sys/netio.sys.spec @@ -0,0 +1 @@ +# diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 0a43cc779cb..de0dd4e4554 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -2617,6 +2617,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 12,,ksecdd.sys,- 12,,mountmgr.sys,- 12,,ndis.sys,- +12,,netio.sys,- 12,,scsiport.sys,- 12,,tdi.sys,- 12,,usbd.sys,- @@ -2673,6 +2674,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 12,,ksecdd.sys 12,,mountmgr.sys 12,,ndis.sys +12,,netio.sys 12,,scsiport.sys 12,,tdi.sys 12,,usbd.sys
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
Minor edits applied to original patch.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- include/Makefile.in | 1 + include/ddk/wsk.h | 116 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 include/ddk/wsk.h
diff --git a/include/Makefile.in b/include/Makefile.in index 9796dd8e5d9..01dc4dbe6cf 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -186,6 +186,7 @@ SOURCES = \ ddk/usbioctl.h \ ddk/usbiodef.h \ ddk/wdm.h \ + ddk/wsk.h \ ddk/winddiui.h \ ddk/winsplp.h \ ddraw.h \ diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h new file mode 100644 index 00000000000..c7100bb7997 --- /dev/null +++ b/include/ddk/wsk.h @@ -0,0 +1,116 @@ +/* + * Copyright 2020 Alistair Leslie-Hughes + * + * 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 + */ +#ifndef _INC_WSK +#define _INC_WSK + +#include <winsock2.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct _WSK_CLIENT; +typedef struct _WSK_CLIENT WSK_CLIENT, *PWSK_CLIENT; +typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH; + +typedef struct _WSK_BUF +{ + PMDL Mdl; + ULONG Offset; + SIZE_T Length; +} WSK_BUF, *PWSK_BUF; + +typedef struct _WSK_DATA_INDICATION +{ + struct _WSK_DATA_INDICATION *Next; + WSK_BUF Buffer; +} WSK_DATA_INDICATION, *PWSK_DATA_INDICATION; + +typedef NTSTATUS (WINAPI *PFN_WSK_CLIENT_EVENT)(void *context, ULONG event, void *info, SIZE_T length); +typedef NTSTATUS (WINAPI *PFN_WSK_DISCONNECT_EVENT)(void *context, ULONG flags); +typedef NTSTATUS (WINAPI *PFN_WSK_SEND_BACKLOG_EVENT)(void *socket_context, SIZE_T ideal_backlog_size); +typedef NTSTATUS (WINAPI *PFN_WSK_SOCKET)(WSK_CLIENT *client, ADDRESS_FAMILY family, + USHORT type, ULONG protocol, ULONG flags, void *context, const void *dispatch, + PEPROCESS process, PETHREAD thread, SECURITY_DESCRIPTOR *security, IRP *irp); +typedef NTSTATUS (WINAPI *PFN_WSK_SOCKET_CONNECT)(WSK_CLIENT *client, USHORT type, + ULONG protocol, SOCKADDR *local, SOCKADDR *remote, ULONG flags, void *context, + const WSK_CLIENT_CONNECTION_DISPATCH *dispatch, PEPROCESS process, PETHREAD owning, + SECURITY_DESCRIPTOR *descriptor, IRP *irp); +typedef NTSTATUS (WINAPI *PFN_WSK_CONTROL_CLIENT)(WSK_CLIENT *client, ULONG control, + SIZE_T input_size, void *input, SIZE_T output_size, void *output, SIZE_T *returned, + IRP *irp); +typedef NTSTATUS (WINAPI *PFN_WSK_GET_ADDRESS_INFO)(WSK_CLIENT *client, UNICODE_STRING *node_name, + UNICODE_STRING *service_name, ULONG name_space, GUID *provider, ADDRINFOEXW *hints, + ADDRINFOEXW **result, PEPROCESS process, PETHREAD thread, IRP *irp); +typedef void (WINAPI *PFN_WSK_FREE_ADDRESS_INFO)(WSK_CLIENT *client, ADDRINFOEXW *addrinfo); +typedef NTSTATUS (WINAPI *PFN_WSK_GET_NAME_INFO)(WSK_CLIENT *client, SOCKADDR *addr, + ULONG length, UNICODE_STRING *node_name, UNICODE_STRING *service_name, + ULONG flags, PEPROCESS process, PETHREAD thread, IRP *irp); +typedef NTSTATUS (WINAPI* PFN_WSK_RECEIVE_EVENT)(void *context, ULONG flags, + WSK_DATA_INDICATION *indication, SIZE_T size, SIZE_T *accepted); + +typedef struct _WSK_PROVIDER_DISPATCH +{ + USHORT Version; + USHORT Reserved; + PFN_WSK_SOCKET WskSocket; + PFN_WSK_SOCKET_CONNECT WskSocketConnect; + PFN_WSK_CONTROL_CLIENT WskControlClient; + PFN_WSK_GET_ADDRESS_INFO WskGetAddressInfo; + PFN_WSK_FREE_ADDRESS_INFO WskFreeAddressInfo; + PFN_WSK_GET_NAME_INFO WskGetNameInfo; +} WSK_PROVIDER_DISPATCH, *PWSK_PROVIDER_DISPATCH; + +typedef struct _WSK_CLIENT_CONNECTION_DISPATCH +{ + PFN_WSK_RECEIVE_EVENT WskReceiveEvent; + PFN_WSK_DISCONNECT_EVENT WskDisconnectEvent; + PFN_WSK_SEND_BACKLOG_EVENT WskSendBacklogEvent; +} WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH; + +typedef struct _WSK_CLIENT_DISPATCH +{ + USHORT Version; + USHORT Reserved; + PFN_WSK_CLIENT_EVENT WskClientEvent; +} WSK_CLIENT_DISPATCH, *PWSK_CLIENT_DISPATCH; + +typedef struct _WSK_CLIENT_NPI +{ + void *ClientContext; + const WSK_CLIENT_DISPATCH *Dispatch; +} WSK_CLIENT_NPI, *PWSK_CLIENT_NPI; + +typedef struct _WSK_REGISTRATION +{ + ULONGLONG ReservedRegistrationState; + void *ReservedRegistrationContext; + KSPIN_LOCK ReservedRegistrationLock; +} WSK_REGISTRATION, *PWSK_REGISTRATION; + +typedef struct _WSK_PROVIDER_NPI +{ + PWSK_CLIENT Client; + const WSK_PROVIDER_DISPATCH *Dispatch; +} WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI; + +#ifdef __cplusplus +} +#endif +#endif
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 8 ++++++++ dlls/netio.sys/netio.sys.spec | 2 +- include/ddk/wsk.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index 16bf47ca0a2..fdb32c1dd9a 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -29,10 +29,18 @@ #include "winioctl.h" #include "winternl.h" #include "ddk/wdm.h" +#include "ddk/wsk.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(netio);
+NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration) +{ + FIXME("wsk_client_npi %p, wsk_registration %p stub.\n", wsk_client_npi, wsk_registration); + + return STATUS_NOT_IMPLEMENTED; +} + static void WINAPI driver_unload(DRIVER_OBJECT *driver) { TRACE("driver %p.\n", driver); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index 792d6005489..90c3db4e7f7 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -1 +1 @@ -# +@ stdcall WskRegister(ptr ptr) diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index c7100bb7997..835adbba9dc 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -110,6 +110,8 @@ typedef struct _WSK_PROVIDER_NPI const WSK_PROVIDER_DISPATCH *Dispatch; } WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI;
+NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration); + #ifdef __cplusplus } #endif
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 5 +++++ dlls/netio.sys/netio.sys.spec | 1 + include/ddk/wsk.h | 1 + 3 files changed, 7 insertions(+)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index fdb32c1dd9a..d3448fced81 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -41,6 +41,11 @@ NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *ws return STATUS_NOT_IMPLEMENTED; }
+void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration) +{ + FIXME("wsk_registration %p stub.\n", wsk_registration); +} + static void WINAPI driver_unload(DRIVER_OBJECT *driver) { TRACE("driver %p.\n", driver); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index 90c3db4e7f7..235e827712e 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -1 +1,2 @@ +@ stdcall WskDeregister(ptr) @ stdcall WskRegister(ptr ptr) diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index 835adbba9dc..e990d054bd7 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -111,6 +111,7 @@ typedef struct _WSK_PROVIDER_NPI } WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI;
NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration); +void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration);
#ifdef __cplusplus }
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 9 +++++++++ dlls/netio.sys/netio.sys.spec | 1 + include/ddk/wsk.h | 2 ++ 3 files changed, 12 insertions(+)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index d3448fced81..16e09bd08fb 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -34,6 +34,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(netio);
+NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG wait_timeout, + WSK_PROVIDER_NPI *wsk_provider_npi) +{ + FIXME("wsk_registration %p, wait_timeout %u, wsk_provider_npi %p stub.\n", + wsk_registration, wait_timeout, wsk_provider_npi); + + return STATUS_NOT_IMPLEMENTED; +} + NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration) { FIXME("wsk_client_npi %p, wsk_registration %p stub.\n", wsk_client_npi, wsk_registration); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index 235e827712e..2ec967d04bb 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -1,2 +1,3 @@ +@ stdcall WskCaptureProviderNPI(ptr long ptr) @ stdcall WskDeregister(ptr) @ stdcall WskRegister(ptr ptr) diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index e990d054bd7..ead8f830a22 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -112,6 +112,8 @@ typedef struct _WSK_PROVIDER_NPI
NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration); void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration); +NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG wait_timeout, + WSK_PROVIDER_NPI *wsk_provider_npi);
#ifdef __cplusplus }
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 5 +++++ dlls/netio.sys/netio.sys.spec | 1 + include/ddk/wsk.h | 1 + 3 files changed, 7 insertions(+)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index 16e09bd08fb..ac34b765a8b 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -43,6 +43,11 @@ NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG return STATUS_NOT_IMPLEMENTED; }
+void WINAPI WskReleaseProviderNPI(WSK_REGISTRATION *wsk_registration) +{ + FIXME("wsk_registration %p stub.\n", wsk_registration); +} + NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration) { FIXME("wsk_client_npi %p, wsk_registration %p stub.\n", wsk_client_npi, wsk_registration); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index 2ec967d04bb..f6de07bba73 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -1,3 +1,4 @@ @ stdcall WskCaptureProviderNPI(ptr long ptr) @ stdcall WskDeregister(ptr) @ stdcall WskRegister(ptr ptr) +@ stdcall WskReleaseProviderNPI(ptr) diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index ead8f830a22..d19da999be8 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -114,6 +114,7 @@ NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *ws void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration); NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG wait_timeout, WSK_PROVIDER_NPI *wsk_provider_npi); +void WINAPI WskReleaseProviderNPI(WSK_REGISTRATION *wsk_registration);
#ifdef __cplusplus }
ndis.sys links to netio.sys on newer Windows. Adding the dependency now is needed to get libnetio.cross.a built to be usable in ntoskrnl.exe test drivers.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ndis.sys/Makefile.in | 1 + dlls/ntoskrnl.exe/tests/driver4.c | 0 dlls/ntoskrnl.exe/tests/driver4.spec | 1 + 3 files changed, 2 insertions(+) create mode 100644 dlls/ntoskrnl.exe/tests/driver4.c create mode 100644 dlls/ntoskrnl.exe/tests/driver4.spec
diff --git a/dlls/ndis.sys/Makefile.in b/dlls/ndis.sys/Makefile.in index cc522606258..70e6bb2afdf 100644 --- a/dlls/ndis.sys/Makefile.in +++ b/dlls/ndis.sys/Makefile.in @@ -1,4 +1,5 @@ MODULE = ndis.sys +IMPORTS = ntoskrnl netio EXTRADLLFLAGS = -Wl,--subsystem,native
EXTRADLLFLAGS = -mno-cygwin diff --git a/dlls/ntoskrnl.exe/tests/driver4.c b/dlls/ntoskrnl.exe/tests/driver4.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dlls/ntoskrnl.exe/tests/driver4.spec b/dlls/ntoskrnl.exe/tests/driver4.spec new file mode 100644 index 00000000000..ad33444716a --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver4.spec @@ -0,0 +1 @@ +# nothing here yet
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver.c | 140 +-------------------------- dlls/ntoskrnl.exe/tests/utils.h | 161 +++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 138 deletions(-) create mode 100644 dlls/ntoskrnl.exe/tests/utils.h
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index f51064986b5..b3865fea0d9 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -35,6 +35,8 @@
#include "driver.h"
+#include "utils.h" + static const WCHAR device_name[] = {'\','D','e','v','i','c','e', '\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0}; static const WCHAR upper_name[] = {'\','D','e','v','i','c','e', @@ -45,17 +47,6 @@ static const WCHAR driver_link[] = {'\','D','o','s','D','e','v','i','c','e','s' static DRIVER_OBJECT *driver_obj; static DEVICE_OBJECT *lower_device, *upper_device;
-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 winetest_report_success; - static POBJECT_TYPE *pExEventObjectType, *pIoFileObjectType, *pPsThreadType, *pIoDriverObjectType; static PEPROCESS *pPsInitialSystemProcess; static void *create_caller_thread; @@ -64,133 +55,6 @@ static PETHREAD create_irp_thread;
NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
-static void kvprintf(const char *format, __ms_va_list ap) -{ - static char buffer[512]; - IO_STATUS_BLOCK io; - int len = vsnprintf(buffer, sizeof(buffer), format, ap); - ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL); -} - -static void WINAPIV kprintf(const char *format, ...) -{ - __ms_va_list valist; - - __ms_va_start(valist, format); - kvprintf(format, valist); - __ms_va_end(valist); -} - -static void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args) -{ - const char *current_file; - - if (!(current_file = drv_strrchr(file, '/')) && - !(current_file = drv_strrchr(file, '\'))) - current_file = file; - else - current_file++; - - 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 (winetest_report_success) - kprintf("%s:%d: Test succeeded\n", current_file, line); - InterlockedIncrement(&successes); - } - } -} - -static void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...) -{ - __ms_va_list args; - __ms_va_start(args, msg); - vok_(file, line, condition, msg, args); - __ms_va_end(args); -} - -static void vskip_(const char *file, int line, const char *msg, __ms_va_list args) -{ - const char *current_file; - - if (!(current_file = drv_strrchr(file, '/')) && - !(current_file = drv_strrchr(file, '\'))) - current_file = file; - else - current_file++; - - kprintf("%s:%d: Tests skipped: ", current_file, line); - kvprintf(msg, args); - skipped++; -} - -static void WINAPIV win_skip_(const char *file, int line, const char *msg, ...) -{ - __ms_va_list args; - __ms_va_start(args, msg); - if (running_under_wine) - vok_(file, line, 0, msg, args); - else - vskip_(file, line, msg, args); - __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; -} - -static int broken(int condition) -{ - return !running_under_wine && condition; -} - -#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) -#define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__) - static void *get_proc_address(const char *name) { UNICODE_STRING name_u; diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h new file mode 100644 index 00000000000..8b09bff1d39 --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -0,0 +1,161 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2015 Sebastian Lackner + * Copyright 2015 Michael Müller + * Copyright 2015 Christian Costa + * Copyright 2020 Paul Gofman for Codeweavers + * + * 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 + */ + +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 winetest_report_success; + +static inline void kvprintf(const char *format, __ms_va_list ap) +{ + static char buffer[512]; + IO_STATUS_BLOCK io; + int len = vsnprintf(buffer, sizeof(buffer), format, ap); + ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL); +} + +static inline void WINAPIV kprintf(const char *format, ...) +{ + __ms_va_list valist; + + __ms_va_start(valist, format); + kvprintf(format, valist); + __ms_va_end(valist); +} + +static inline void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args) +{ + const char *current_file; + + if (!(current_file = drv_strrchr(file, '/')) && + !(current_file = drv_strrchr(file, '\'))) + current_file = file; + else + current_file++; + + 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 (winetest_report_success) + kprintf("%s:%d: Test succeeded\n", current_file, line); + InterlockedIncrement(&successes); + } + } +} + +static inline void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...) +{ + __ms_va_list args; + __ms_va_start(args, msg); + vok_(file, line, condition, msg, args); + __ms_va_end(args); +} + +static inline void vskip_(const char *file, int line, const char *msg, __ms_va_list args) +{ + const char *current_file; + + if (!(current_file = drv_strrchr(file, '/')) && + !(current_file = drv_strrchr(file, '\'))) + current_file = file; + else + current_file++; + + kprintf("%s:%d: Tests skipped: ", current_file, line); + kvprintf(msg, args); + skipped++; +} + +static inline void WINAPIV win_skip_(const char *file, int line, const char *msg, ...) +{ + __ms_va_list args; + __ms_va_start(args, msg); + if (running_under_wine) + vok_(file, line, 0, msg, args); + else + vskip_(file, line, msg, args); + __ms_va_end(args); +} + +static inline void winetest_start_todo( int is_todo ) +{ + todo_level = (todo_level << 1) | (is_todo != 0); + todo_do_loop=1; +} + +static inline int winetest_loop_todo(void) +{ + int do_loop=todo_do_loop; + todo_do_loop=0; + return do_loop; +} + +static inline void winetest_end_todo(void) +{ + todo_level >>= 1; +} + +static inline int broken(int condition) +{ + return !running_under_wine && condition; +} + +#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) +#define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__) +
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- include/ddk/wsk.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index d19da999be8..18a7de3b2c5 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -27,6 +27,8 @@ extern "C"
struct _WSK_CLIENT; typedef struct _WSK_CLIENT WSK_CLIENT, *PWSK_CLIENT; +#define MAKE_WSK_VERSION(major, minor) ((USHORT)((major) << 8) | (USHORT)((minor) & 0xff)) + typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH;
typedef struct _WSK_BUF
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- include/ddk/wsk.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index 18a7de3b2c5..a46eeadcc4b 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -28,6 +28,8 @@ extern "C" struct _WSK_CLIENT; typedef struct _WSK_CLIENT WSK_CLIENT, *PWSK_CLIENT; #define MAKE_WSK_VERSION(major, minor) ((USHORT)((major) << 8) | (USHORT)((minor) & 0xff)) +#define WSK_NO_WAIT 0 +#define WSK_INFINITE_WAIT 0xffffffff
typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH;
Test driver should import netio.sys which is available since Vista, so a new test driver is needed to preserve XP compatibility for the existing tests.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/tests/Makefile.in | 4 + dlls/ntoskrnl.exe/tests/driver4.c | 249 ++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 59 ++++++- 3 files changed, 304 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in index 7946b8de220..06c06671ca1 100644 --- a/dlls/ntoskrnl.exe/tests/Makefile.in +++ b/dlls/ntoskrnl.exe/tests/Makefile.in @@ -7,6 +7,8 @@ driver2_IMPORTS = winecrt0 ntoskrnl driver2_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native driver3_IMPORTS = winecrt0 ntoskrnl driver3_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native +driver4_IMPORTS = winecrt0 ntoskrnl netio +driver4_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
SOURCES = \ driver.c \ @@ -15,4 +17,6 @@ SOURCES = \ driver2.spec \ driver3.c \ driver3.spec \ + driver4.c \ + driver4.spec \ ntoskrnl.c diff --git a/dlls/ntoskrnl.exe/tests/driver4.c b/dlls/ntoskrnl.exe/tests/driver4.c index e69de29bb2d..10e583993e3 100644 --- a/dlls/ntoskrnl.exe/tests/driver4.c +++ b/dlls/ntoskrnl.exe/tests/driver4.c @@ -0,0 +1,249 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2020 Paul Gofman for Codeweavers + * + * 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 <stdio.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "winioctl.h" +#include "ddk/ntddk.h" +#include "ddk/ntifs.h" +#include "ddk/wdm.h" +#include "ddk/wsk.h" + +#include "driver.h" + +#include "utils.h" + +static DRIVER_OBJECT *driver_obj; +static DEVICE_OBJECT *lower_device, *upper_device; + +static unsigned int create_count, close_count; + +static const WCHAR driver_link[] = L"\DosDevices\WineTestDriver4"; +static const WCHAR device_name[] = L"\Device\WineTestDriver4"; +static const WCHAR upper_name[] = L"\Device\WineTestUpper4"; + +static FILE_OBJECT *last_created_file; +static void *create_caller_thread; +static PETHREAD create_irp_thread; + +static POBJECT_TYPE *pIoDriverObjectType; + +static WSK_CLIENT_NPI client_npi; +static WSK_REGISTRATION registration; +static WSK_PROVIDER_NPI provider_npi; + +static void netio_init(void) +{ + const WSK_CLIENT_DISPATCH client_dispatch = + { + MAKE_WSK_VERSION(1, 0), 0, NULL + }; + + NTSTATUS status; + + client_npi.Dispatch = &client_dispatch; + status = WskRegister(&client_npi, ®istration); + todo_wine ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status); + + status = WskCaptureProviderNPI(®istration, WSK_INFINITE_WAIT, &provider_npi); + todo_wine ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status); +} + +static void netio_uninit(void) +{ + WskReleaseProviderNPI(®istration); + WskDeregister(®istration); +} + +static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) +{ + ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; + void *buffer = irp->AssociatedIrp.SystemBuffer; + struct test_input *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; + winetest_report_success = test_input->winetest_report_success; + attr.ObjectName = &pathU; + attr.Attributes = OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */ + ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT); + + netio_init(); + + if (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; + irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.Information = sizeof(failures); + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_PENDING; +} + +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_MAIN_TEST: + status = main_test(device, irp, stack); + break; + case IOCTL_WINETEST_DETACH: + IoDetachDevice(lower_device); + status = STATUS_SUCCESS; + break; + default: + break; + } + + if (status != STATUS_PENDING) + { + irp->IoStatus.Status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + } + else IoMarkIrpPending(irp); + return status; +} + +static NTSTATUS WINAPI driver_create(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + DWORD *context = ExAllocatePool(PagedPool, sizeof(*context)); + + last_created_file = irpsp->FileObject; + ++create_count; + if (context) + *context = create_count; + irpsp->FileObject->FsContext = context; + create_caller_thread = KeGetCurrentThread(); + create_irp_thread = irp->Tail.Overlay.Thread; + + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +static NTSTATUS WINAPI driver_close(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + + netio_uninit(); + + ++close_count; + if (stack->FileObject->FsContext) + ExFreePool(stack->FileObject->FsContext); + 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(upper_device); + IoDeleteDevice(lower_device); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) +{ + static const WCHAR IoDriverObjectTypeW[] = L"IoDriverObjectType"; + static const WCHAR driver_nameW[] = L"\Driver\WineTestDriver4"; + UNICODE_STRING nameW, linkW; + NTSTATUS status; + void *obj; + + DbgPrint("Loading driver.\n"); + + driver_obj = driver; + + driver->DriverUnload = driver_unload; + driver->MajorFunction[IRP_MJ_CREATE] = driver_create; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_iocontrol; + driver->MajorFunction[IRP_MJ_CLOSE] = driver_close; + + RtlInitUnicodeString(&nameW, IoDriverObjectTypeW); + pIoDriverObjectType = MmGetSystemRoutineAddress(&nameW); + + RtlInitUnicodeString(&nameW, driver_nameW); + if ((status = ObReferenceObjectByName(&nameW, 0, NULL, 0, *pIoDriverObjectType, KernelMode, NULL, &obj))) + return status; + if (obj != driver) + { + ObDereferenceObject(obj); + return STATUS_UNSUCCESSFUL; + } + ObDereferenceObject(obj); + + RtlInitUnicodeString(&nameW, device_name); + RtlInitUnicodeString(&linkW, driver_link); + + if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device))) + { + status = IoCreateSymbolicLink(&linkW, &nameW); + lower_device->Flags &= ~DO_DEVICE_INITIALIZING; + } + + if (!status) + { + RtlInitUnicodeString(&nameW, upper_name); + + status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device); + } + + if (!status) + { + IoAttachDeviceToDeviceStack(upper_device, lower_device); + upper_device->Flags &= ~DO_DEVICE_INITIALIZING; + } + + return status; +} diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 8d2da92455a..c2afee3dfe9 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -109,17 +109,25 @@ static SC_HANDLE load_driver(char *filename, const char *resname, const char *dr return service; }
-static BOOL start_driver(HANDLE service) +static BOOL start_driver(HANDLE service, BOOL vista_plus) { SERVICE_STATUS status; BOOL ret;
SetLastError(0xdeadbeef); ret = StartServiceA(service, 0, NULL); - if (!ret && (GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH)) + if (!ret && (GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH + || (vista_plus && GetLastError() == ERROR_FILE_NOT_FOUND))) { - /* 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"); + if (vista_plus && GetLastError() == ERROR_FILE_NOT_FOUND) + { + skip("Windows Vista or newer is required to run this service.\n"); + } + else + { + /* 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); return FALSE; @@ -143,13 +151,14 @@ static BOOL start_driver(HANDLE service) return TRUE; }
+static ULONG64 modified_value; + 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; DWORD len, written, read; - ULONG64 modified_value; UNICODE_STRING pathU; LONG new_failures; char buffer[512]; @@ -178,8 +187,6 @@ static void main_test(void) ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(written == sizeof(new_failures), "got size %x\n", written);
- todo_wine ok(modified_value == 0xdeadbeeffeedcafe, "Got unexpected value %#I64x.\n", modified_value); - 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());
@@ -506,6 +513,37 @@ static void test_driver3(void) DeleteFileA(filename); }
+void test_driver4(void) +{ + char filename[MAX_PATH]; + SC_HANDLE service; + DWORD written; + BOOL ret; + + if (!(service = load_driver(filename, "driver4.dll", "WineTestDriver4"))) + return; + + if (!start_driver(service, TRUE)) + { + DeleteFileA(filename); + return; + } + + device = CreateFileA("\\.\WineTestDriver4", 0, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(device != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); + + main_test(); + + ret = DeviceIoControl(device, IOCTL_WINETEST_DETACH, NULL, 0, NULL, 0, &written, NULL); + ok(ret, "DeviceIoControl failed: %u\n", GetLastError()); + + CloseHandle(device); + + unload_driver(service); + ret = DeleteFileA(filename); + ok(ret, "DeleteFile failed: %u\n", GetLastError()); +} + START_TEST(ntoskrnl) { char filename[MAX_PATH], filename2[MAX_PATH]; @@ -523,7 +561,7 @@ START_TEST(ntoskrnl) subtest("driver"); if (!(service = load_driver(filename, "driver.dll", "WineTestDriver"))) return; - if (!start_driver(service)) + if (!start_driver(service, FALSE)) { DeleteFileA(filename); return; @@ -535,7 +573,10 @@ START_TEST(ntoskrnl)
test_basic_ioctl(); test_mismatched_status_ioctl(); + main_test(); + todo_wine ok(modified_value == 0xdeadbeeffeedcafe, "Got unexpected value %#I64x.\n", modified_value); + test_overlapped(); test_load_driver(service2); test_file_handles(); @@ -556,4 +597,6 @@ START_TEST(ntoskrnl) ok(ret, "DeleteFile failed: %u\n", GetLastError());
test_driver3(); + subtest("driver4"); + test_driver4(); }
Paul Gofman pgofman@codeweavers.com writes:
diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/dlls/netio.sys/netio.sys.spec @@ -0,0 +1 @@ +#
It would be better to add the full list of exports, declared as stubs, so we can see that there's a lot more to implement.
On 6/2/20 23:04, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/dlls/netio.sys/netio.sys.spec @@ -0,0 +1 @@ +#
It would be better to add the full list of exports, declared as stubs, so we can see that there's a lot more to implement.
I guess there are just 1 or 2 of documented exports besides those 4 exported in the next patches. The real interface is passed through dynamic tables from registration functions. Should I still dig for any potentially remaining and add the stubs?
Paul Gofman pgofman@codeweavers.com writes:
On 6/2/20 23:04, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec new file mode 100644 index 00000000000..792d6005489 --- /dev/null +++ b/dlls/netio.sys/netio.sys.spec @@ -0,0 +1 @@ +#
It would be better to add the full list of exports, declared as stubs, so we can see that there's a lot more to implement.
I guess there are just 1 or 2 of documented exports besides those 4 exported in the next patches. The real interface is passed through dynamic tables from registration functions. Should I still dig for any potentially remaining and add the stubs?
There should be a lot more than that. My version of netio.sys (from win10) has more than 500 exports.
On 6/2/20 23:21, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
I guess there are just 1 or 2 of documented exports besides those 4 exported in the next patches. The real interface is passed through dynamic tables from registration functions. Should I still dig for any potentially remaining and add the stubs?
There should be a lot more than that. My version of netio.sys (from win10) has more than 500 exports.
Yes, I driver exports some lot of internal functions, but here is the complete list of documented ones:
- WskCaptureProviderNPI
- WskDeregister
- WskQueryProviderCharacteristics
- WskRegister
- WskReleaseProviderNPI.
The WSK interface is well documented and all the driver functions which are supposed to used by application are provided through dispatch tables from WskCaptureProviderNPI() (some of which return objects with their own dispatch tables). The examples I could find and Denuvo driver I tested all work this way.
Do you think I should grab the export symbols from Windows driver binary and add all of those as stubs?
Paul Gofman pgofman@codeweavers.com writes:
On 6/2/20 23:21, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
I guess there are just 1 or 2 of documented exports besides those 4 exported in the next patches. The real interface is passed through dynamic tables from registration functions. Should I still dig for any potentially remaining and add the stubs?
There should be a lot more than that. My version of netio.sys (from win10) has more than 500 exports.
Yes, I driver exports some lot of internal functions, but here is the complete list of documented ones:
WskCaptureProviderNPI
WskDeregister
WskQueryProviderCharacteristics
WskRegister
WskReleaseProviderNPI.
The WSK interface is well documented and all the driver functions which are supposed to used by application are provided through dispatch tables from WskCaptureProviderNPI() (some of which return objects with their own dispatch tables). The examples I could find and Denuvo driver I tested all work this way.
Do you think I should grab the export symbols from Windows driver binary and add all of those as stubs?
Yes, it doesn't matter whether they are documented or not, if they are exported they are available to other apps/drivers. Of course, chances are that nobody calls them, but we can still have them as documentation.