[PATCH 1/8] ntoskrnl/tests: Fix a test failure on LUA Windows.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 50abb9f9d1f..c3ebe5b8ee1 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -173,6 +173,17 @@ static BOOL testsign_create_cert(struct testsign_context *ctx) ok(ret, "Failed to set provider info, error %#x\n", GetLastError()); ctx->root_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_A, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "root"); + if (!ctx->root_store && GetLastError() == ERROR_ACCESS_DENIED) + { + skip("Failed to open root store.\n"); + + ret = CertFreeCertificateContext(ctx->cert); + ok(ret, "Failed to free certificate, error %u\n", GetLastError()); + ret = CryptReleaseContext(ctx->provider, 0); + ok(ret, "failed to release context, error %u\n", GetLastError()); + + return FALSE; + } ok(!!ctx->root_store, "Failed to open store, error %u\n", GetLastError()); ret = CertAddCertificateContextToStore(ctx->root_store, ctx->cert, CERT_STORE_ADD_ALWAYS, &ctx->root_cert); if (!ret && GetLastError() == ERROR_ACCESS_DENIED) -- 2.30.2
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 89 ++++++++++++++++++++++- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- programs/winedevice/device.c | 106 ++-------------------------- 3 files changed, 93 insertions(+), 104 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 685f7d4345b..b50886da137 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -894,16 +894,98 @@ static void unload_driver( struct wine_rb_entry *entry, void *context ) PEPROCESS PsInitialSystemProcess = NULL; +static HANDLE stop_event; +static SERVICE_STATUS_HANDLE group_handle; + +static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) +{ + UNICODE_STRING service_name; + DWORD result = NO_ERROR; + WCHAR *str; + + if (!(str = heap_alloc( sizeof(servicesW) + wcslen(driver_name) * sizeof(WCHAR) ))) + return STATUS_NO_MEMORY; + + wcscpy( str, servicesW ); + wcscat( str, driver_name ); + RtlInitUnicodeString( &service_name, str ); + + switch (ctrl) + { + case SERVICE_CONTROL_START: + result = RtlNtStatusToDosError( ZwLoadDriver( &service_name ) ); + break; + + case SERVICE_CONTROL_STOP: + result = RtlNtStatusToDosError( ZwUnloadDriver( &service_name ) ); + break; + + default: + FIXME( "got driver ctrl %#x for %s\n", ctrl, debugstr_w(driver_name) ); + break; + } + + RtlFreeUnicodeString( &service_name ); + return result; +} + +static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, void *event_data, void *context ) +{ + if (ctrl & SERVICE_CONTROL_FORWARD_FLAG) + { + if (!event_data) return ERROR_INVALID_PARAMETER; + return device_handler( ctrl & ~SERVICE_CONTROL_FORWARD_FLAG, (const WCHAR *)event_data ); + } + + switch (ctrl) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + TRACE( "shutting down\n" ); + set_service_status( group_handle, SERVICE_STOP_PENDING, 0 ); + SetEvent( stop_event ); + return NO_ERROR; + default: + FIXME( "got service ctrl %#x\n", ctrl ); + set_service_status( group_handle, SERVICE_RUNNING, + SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); + return NO_ERROR; + } +} + /*********************************************************************** * wine_ntoskrnl_main_loop (Not a Windows API) */ -NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) +NTSTATUS CDECL wine_ntoskrnl_main_loop(void) { HANDLE manager = get_device_manager(); struct dispatch_context context; NTSTATUS status = STATUS_SUCCESS; + WCHAR driver_dir[MAX_PATH]; + SC_HANDLE manager_handle; HANDLE handles[2]; + if ((status = NtCreateEvent( &stop_event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ))) + return status; + + if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT ))) + { + ERR( "Failed to open service manager, error %u.\n", GetLastError() ); + return STATUS_UNSUCCESSFUL; + } + if (!(group_handle = RegisterServiceCtrlHandlerExW( L"winedevice", service_handler, NULL ))) + { + ERR( "Failed to register service control handler, error %u.\n", GetLastError() ); + CloseServiceHandle( manager_handle ); + return STATUS_UNSUCCESSFUL; + } + + GetSystemDirectoryW( driver_dir, MAX_PATH ); + wcscat( driver_dir, L"\\drivers" ); + AddDllDirectory( driver_dir ); + + set_service_status( group_handle, SERVICE_RUNNING, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); + context.handle = NULL; context.irp = NULL; context.in_size = 4096; @@ -986,6 +1068,11 @@ done: * their unload routine is called, so we must stop the PnP manager first. */ pnp_manager_stop(); wine_rb_destroy( &wine_drivers, unload_driver, NULL ); + + set_service_status( group_handle, SERVICE_STOPPED, 0 ); + CloseServiceHandle( manager_handle ); + CloseHandle( stop_event ); + return status; } diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0f5ab76a195..aa97dc60fec 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1685,4 +1685,4 @@ # All functions must be prefixed with '__wine_' (for internal functions) # or 'wine_' (for user-visible functions) to avoid namespace conflicts. -@ cdecl wine_ntoskrnl_main_loop(long) +@ cdecl wine_ntoskrnl_main_loop() diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index 3acc5e8a799..f1a30d3b447 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -25,120 +25,22 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" -#include "ddk/wdm.h" -#include "wine/svcctl.h" +#include "winsvc.h" #include "wine/debug.h" -#include "wine/heap.h" -WINE_DEFAULT_DEBUG_CHANNEL(winedevice); +WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl); -static const WCHAR servicesW[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; - -extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); +extern NTSTATUS CDECL wine_ntoskrnl_main_loop(void); static WCHAR winedeviceW[] = L"winedevice"; -static SERVICE_STATUS_HANDLE service_handle; -static SC_HANDLE manager_handle; -static HANDLE stop_event; - -/* helper function to update service status */ -static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD accepted ) -{ - SERVICE_STATUS status; - status.dwServiceType = SERVICE_WIN32; - status.dwCurrentState = state; - status.dwControlsAccepted = accepted; - status.dwWin32ExitCode = 0; - status.dwServiceSpecificExitCode = 0; - status.dwCheckPoint = 0; - status.dwWaitHint = (state == SERVICE_START_PENDING) ? 10000 : 0; - SetServiceStatus( handle, &status ); -} - -static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) -{ - UNICODE_STRING service_name; - DWORD result = NO_ERROR; - WCHAR *str; - - if (!(str = heap_alloc( sizeof(servicesW) + lstrlenW(driver_name)*sizeof(WCHAR) ))) - return STATUS_NO_MEMORY; - - lstrcpyW( str, servicesW ); - lstrcatW( str, driver_name ); - RtlInitUnicodeString( &service_name, str ); - - switch (ctrl) - { - case SERVICE_CONTROL_START: - result = RtlNtStatusToDosError(ZwLoadDriver( &service_name )); - break; - - case SERVICE_CONTROL_STOP: - result = RtlNtStatusToDosError(ZwUnloadDriver( &service_name )); - break; - - default: - FIXME( "got driver ctrl %x for %s\n", ctrl, wine_dbgstr_w(driver_name) ); - break; - } - - RtlFreeUnicodeString( &service_name ); - return result; -} - -static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context ) -{ - const WCHAR *service_group = context; - - if (ctrl & SERVICE_CONTROL_FORWARD_FLAG) - { - if (!event_data) return ERROR_INVALID_PARAMETER; - return device_handler( ctrl & ~SERVICE_CONTROL_FORWARD_FLAG, (const WCHAR *)event_data ); - } - - switch (ctrl) - { - case SERVICE_CONTROL_STOP: - case SERVICE_CONTROL_SHUTDOWN: - TRACE( "shutting down %s\n", wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_STOP_PENDING, 0 ); - SetEvent( stop_event ); - return NO_ERROR; - default: - FIXME( "got service ctrl %x for %s\n", ctrl, wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_RUNNING, - SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); - return NO_ERROR; - } -} static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) { - WCHAR driver_dir[MAX_PATH]; const WCHAR *service_group = (argc >= 2) ? argv[1] : argv[0]; - if (!(stop_event = CreateEventW( NULL, TRUE, FALSE, NULL ))) - return; - if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT ))) - return; - if (!(service_handle = RegisterServiceCtrlHandlerExW( winedeviceW, service_handler, (void *)service_group ))) - return; - - GetSystemDirectoryW( driver_dir, MAX_PATH ); - wcscat( driver_dir, L"\\drivers" ); - AddDllDirectory( driver_dir ); - TRACE( "starting service group %s\n", wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_RUNNING, - SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); - - wine_ntoskrnl_main_loop( stop_event ); - + wine_ntoskrnl_main_loop(); TRACE( "service group %s stopped\n", wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_STOPPED, 0 ); - CloseServiceHandle( manager_handle ); - CloseHandle( stop_event ); } int __cdecl wmain( int argc, WCHAR *argv[] ) -- 2.30.2
Zebediah Figura <z.figura12(a)gmail.com> writes:
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 89 ++++++++++++++++++++++- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- programs/winedevice/device.c | 106 ++-------------------------- 3 files changed, 93 insertions(+), 104 deletions(-)
This looks like it's going to break the Android driver. -- Alexandre Julliard julliard(a)winehq.org
It is quite rare to have more than one or two of these, and lists are slightly easier to work with. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/pnp.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 6652be73c47..913a63e8f0d 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -42,6 +42,7 @@ #include "wine/exception.h" #include "wine/heap.h" #include "wine/rbtree.h" +#include "wine/list.h" #include "ntoskrnl_private.h" #include "plugplay.h" @@ -923,19 +924,24 @@ static DRIVER_OBJECT *pnp_manager; struct root_pnp_device { WCHAR id[MAX_DEVICE_ID_LEN]; - struct wine_rb_entry entry; + struct list entry; DEVICE_OBJECT *device; }; -static int root_pnp_devices_rb_compare( const void *key, const struct wine_rb_entry *entry ) +static struct list root_pnp_devices = LIST_INIT(root_pnp_devices); + +static struct root_pnp_device *find_root_pnp_device( const WCHAR *id ) { - const struct root_pnp_device *device = WINE_RB_ENTRY_VALUE( entry, const struct root_pnp_device, entry ); - const WCHAR *k = key; + struct root_pnp_device *device; - return wcsicmp( k, device->id ); -} + LIST_FOR_EACH_ENTRY( device, &root_pnp_devices, struct root_pnp_device, entry ) + { + if (!wcsicmp( id, device->id )) + return device; + } -static struct wine_rb_tree root_pnp_devices = { root_pnp_devices_rb_compare }; + return NULL; +} static NTSTATUS WINAPI pnp_manager_device_pnp( DEVICE_OBJECT *device, IRP *irp ) { @@ -1043,15 +1049,12 @@ void pnp_manager_start(void) ERR("RpcBindingFromStringBinding() failed, error %#x\n", err); } -static void destroy_root_pnp_device( struct wine_rb_entry *entry, void *context ) -{ - struct root_pnp_device *device = WINE_RB_ENTRY_VALUE(entry, struct root_pnp_device, entry); - remove_device( device->device ); -} - void pnp_manager_stop(void) { - wine_rb_destroy( &root_pnp_devices, destroy_root_pnp_device, NULL ); + struct root_pnp_device *device, *next; + + LIST_FOR_EACH_ENTRY_SAFE( device, next, &root_pnp_devices, struct root_pnp_device, entry ) + remove_device( device->device ); IoDeleteDriver( pnp_manager ); RpcBindingFree( &plugplay_binding_handle ); } @@ -1088,7 +1091,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL ); - if (wine_rb_get( &root_pnp_devices, id )) + if (find_root_pnp_device( id )) continue; TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id)); @@ -1103,12 +1106,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) pnp_device = device->DeviceExtension; wcscpy( pnp_device->id, id ); pnp_device->device = device; - if (wine_rb_put( &root_pnp_devices, id, &pnp_device->entry )) - { - ERR("Failed to insert device %s into tree.\n", debugstr_w(id)); - IoDeleteDevice( device ); - continue; - } + list_add_tail( &root_pnp_devices, &pnp_device->entry ); start_device( device, set, &sp_device ); } -- 2.30.2
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 36 ++++++++------------------- dlls/ntoskrnl.exe/ntoskrnl_private.h | 26 ++++++++++++++++++- dlls/ntoskrnl.exe/pnp.c | 37 ++++++++++------------------ dlls/ntoskrnl.exe/sync.c | 13 +--------- 4 files changed, 49 insertions(+), 63 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index b50886da137..f51055fd6c0 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -21,34 +21,20 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include <stdarg.h> #include <assert.h> #define NONAMELESSUNION #define NONAMELESSSTRUCT -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winsvc.h" -#include "winternl.h" +#include "ntoskrnl_private.h" #include "excpt.h" -#include "winioctl.h" -#include "winbase.h" #include "winreg.h" #include "ntsecapi.h" #include "ddk/csq.h" -#include "ddk/ntddk.h" -#include "ddk/ntifs.h" -#include "ddk/wdm.h" #include "wine/server.h" -#include "wine/debug.h" #include "wine/heap.h" -#include "wine/rbtree.h" #include "wine/svcctl.h" -#include "ntoskrnl_private.h" - WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl); WINE_DECLARE_DEBUG_CHANNEL(relay); @@ -90,14 +76,6 @@ static void *ldr_notify_cookie; static PLOAD_IMAGE_NOTIFY_ROUTINE load_image_notify_routines[8]; static unsigned int load_image_notify_routine_count; -struct wine_driver -{ - DRIVER_OBJECT driver_obj; - DRIVER_EXTENSION driver_extension; - SERVICE_STATUS_HANDLE service_handle; - struct wine_rb_entry entry; -}; - static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry ) { const struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, const struct wine_driver, entry ); @@ -962,6 +940,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop(void) struct dispatch_context context; NTSTATUS status = STATUS_SUCCESS; WCHAR driver_dir[MAX_PATH]; + struct wine_driver *driver; SC_HANDLE manager_handle; HANDLE handles[2]; @@ -1065,9 +1044,13 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop(void) done: /* Native PnP drivers expect that all of their devices will be removed when - * their unload routine is called, so we must stop the PnP manager first. */ - pnp_manager_stop(); + * their unload routine is called. Moreover, we cannot unload a module + * until we have removed devices for all lower drivers, so we have to stop + * all devices first, and then unload all drivers. */ + WINE_RB_FOR_EACH_ENTRY( driver, &wine_drivers, struct wine_driver, entry ) + pnp_manager_stop_driver( driver ); wine_rb_destroy( &wine_drivers, unload_driver, NULL ); + pnp_manager_stop(); set_service_status( group_handle, SERVICE_STOPPED, 0 ); CloseServiceHandle( manager_handle ); @@ -1573,6 +1556,7 @@ NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init ) build_driver_keypath( driver->driver_obj.DriverName.Buffer, &driver->driver_extension.ServiceKeyName ); for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) driver->driver_obj.MajorFunction[i] = unhandled_irp; + list_init( &driver->root_pnp_devices ); EnterCriticalSection( &drivers_cs ); if (wine_rb_put( &wine_drivers, &driver->driver_obj.DriverName, &driver->entry )) @@ -3909,7 +3893,7 @@ NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *service_name ) driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry ); driver->service_handle = service_handle; - pnp_manager_enumerate_root_devices( service_name->Buffer + wcslen( servicesW ) ); + pnp_manager_enumerate_root_devices( driver ); set_service_status( service_handle, SERVICE_RUNNING, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h index a1e1b892e8c..3a6b2144004 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl_private.h +++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h @@ -21,7 +21,21 @@ #ifndef __WINE_NTOSKRNL_PRIVATE_H #define __WINE_NTOSKRNL_PRIVATE_H +#include <stdarg.h> +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winioctl.h" +#include "winbase.h" +#include "winsvc.h" +#include "winternl.h" +#include "ddk/ntifs.h" +#include "ddk/wdm.h" + #include "wine/asm.h" +#include "wine/debug.h" +#include "wine/list.h" +#include "wine/rbtree.h" static inline LPCSTR debugstr_us( const UNICODE_STRING *us ) { @@ -76,10 +90,20 @@ extern POBJECT_TYPE SeTokenObjectType; 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \ static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }; +struct wine_driver +{ + DRIVER_OBJECT driver_obj; + DRIVER_EXTENSION driver_extension; + SERVICE_STATUS_HANDLE service_handle; + struct wine_rb_entry entry; + struct list root_pnp_devices; +}; + void ObReferenceObject( void *obj ) DECLSPEC_HIDDEN; -void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) DECLSPEC_HIDDEN; +void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) DECLSPEC_HIDDEN; void pnp_manager_start(void) DECLSPEC_HIDDEN; +void pnp_manager_stop_driver( struct wine_driver *driver ) DECLSPEC_HIDDEN; void pnp_manager_stop(void) DECLSPEC_HIDDEN; static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y', diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 913a63e8f0d..1c1f241591b 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -20,31 +20,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include <stdarg.h> - #define NONAMELESSUNION -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "winioctl.h" +#include "ntoskrnl_private.h" #include "winreg.h" #include "winuser.h" -#include "winsvc.h" -#include "winternl.h" #include "setupapi.h" #include "cfgmgr32.h" #include "dbt.h" -#include "ddk/wdm.h" -#include "ddk/ntifs.h" -#include "wine/debug.h" #include "wine/exception.h" #include "wine/heap.h" -#include "wine/rbtree.h" -#include "wine/list.h" -#include "ntoskrnl_private.h" #include "plugplay.h" #include "initguid.h" @@ -928,13 +914,11 @@ struct root_pnp_device DEVICE_OBJECT *device; }; -static struct list root_pnp_devices = LIST_INIT(root_pnp_devices); - -static struct root_pnp_device *find_root_pnp_device( const WCHAR *id ) +static struct root_pnp_device *find_root_pnp_device( struct wine_driver *driver, const WCHAR *id ) { struct root_pnp_device *device; - LIST_FOR_EACH_ENTRY( device, &root_pnp_devices, struct root_pnp_device, entry ) + LIST_FOR_EACH_ENTRY( device, &driver->root_pnp_devices, struct root_pnp_device, entry ) { if (!wcsicmp( id, device->id )) return device; @@ -1049,18 +1033,23 @@ void pnp_manager_start(void) ERR("RpcBindingFromStringBinding() failed, error %#x\n", err); } -void pnp_manager_stop(void) +void pnp_manager_stop_driver( struct wine_driver *driver ) { struct root_pnp_device *device, *next; - LIST_FOR_EACH_ENTRY_SAFE( device, next, &root_pnp_devices, struct root_pnp_device, entry ) + LIST_FOR_EACH_ENTRY_SAFE( device, next, &driver->root_pnp_devices, struct root_pnp_device, entry ) remove_device( device->device ); +} + +void pnp_manager_stop(void) +{ IoDeleteDriver( pnp_manager ); RpcBindingFree( &plugplay_binding_handle ); } -void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) +void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) { + const WCHAR *driver_name = wcsrchr( driver->driver_obj.DriverName.Buffer, '\\' ) + 1; static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0}; static const WCHAR rootW[] = {'R','O','O','T',0}; WCHAR buffer[MAX_SERVICE_NAME + ARRAY_SIZE(driverW)], id[MAX_DEVICE_ID_LEN]; @@ -1091,7 +1080,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL ); - if (find_root_pnp_device( id )) + if (find_root_pnp_device( driver, id )) continue; TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id)); @@ -1106,7 +1095,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) pnp_device = device->DeviceExtension; wcscpy( pnp_device->id, id ); pnp_device->device = device; - list_add_tail( &root_pnp_devices, &pnp_device->entry ); + list_add_tail( &driver->root_pnp_devices, &pnp_device->entry ); start_device( device, set, &sp_device ); } diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 2aa60a0f2a0..445c8d890ab 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -19,24 +19,13 @@ */ #include <limits.h> -#include <stdarg.h> -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "winternl.h" +#include "ntoskrnl_private.h" #include "ddk/ntddk.h" -#include "ddk/wdm.h" -#include "ddk/ntifs.h" -#include "wine/asm.h" -#include "wine/debug.h" #include "wine/heap.h" #include "wine/server.h" -#include "ntoskrnl_private.h" - WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl); enum object_type -- 2.30.2
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 48 +++++++++++++++++++++++++----------- dlls/ntoskrnl.exe/pnp.c | 21 +++++++++++++--- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index f51055fd6c0..d4536c39578 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -88,6 +88,21 @@ static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare }; DECLARE_CRITICAL_SECTION(drivers_cs); +static BOOLEAN get_drv_name( UNICODE_STRING *drv_name, const UNICODE_STRING *service_name ) +{ + static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0}; + WCHAR *str; + + if (!(str = heap_alloc( sizeof(driverW) + service_name->Length - lstrlenW(servicesW)*sizeof(WCHAR) ))) + return FALSE; + + lstrcpyW( str, driverW ); + lstrcpynW( str + lstrlenW(driverW), service_name->Buffer + lstrlenW(servicesW), + service_name->Length/sizeof(WCHAR) - lstrlenW(servicesW) + 1 ); + RtlInitUnicodeString( drv_name, str ); + return TRUE; +} + static HANDLE get_device_manager(void) { static HANDLE device_manager; @@ -875,6 +890,8 @@ PEPROCESS PsInitialSystemProcess = NULL; static HANDLE stop_event; static SERVICE_STATUS_HANDLE group_handle; +#define SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES 128 + static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) { UNICODE_STRING service_name; @@ -898,6 +915,22 @@ static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) result = RtlNtStatusToDosError( ZwUnloadDriver( &service_name ) ); break; + case SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES: + { + struct wine_rb_entry *entry; + UNICODE_STRING drv_name; + + if (!get_drv_name( &drv_name, &service_name )) + return STATUS_NO_MEMORY; + + entry = wine_rb_get( &wine_drivers, &drv_name ); + RtlFreeUnicodeString( &drv_name ); + + TRACE( "reenumerating PnP devices for %s\n", debugstr_w(service_name.Buffer) ); + pnp_manager_enumerate_root_devices( WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry ) ); + return NO_ERROR; + } + default: FIXME( "got driver ctrl %#x for %s\n", ctrl, debugstr_w(driver_name) ); break; @@ -3834,21 +3867,6 @@ static NTSTATUS WINAPI init_driver( DRIVER_OBJECT *driver_object, UNICODE_STRING return status; } -static BOOLEAN get_drv_name( UNICODE_STRING *drv_name, const UNICODE_STRING *service_name ) -{ - static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0}; - WCHAR *str; - - if (!(str = heap_alloc( sizeof(driverW) + service_name->Length - lstrlenW(servicesW)*sizeof(WCHAR) ))) - return FALSE; - - lstrcpyW( str, driverW ); - lstrcpynW( str + lstrlenW(driverW), service_name->Buffer + lstrlenW(servicesW), - service_name->Length/sizeof(WCHAR) - lstrlenW(servicesW) + 1 ); - RtlInitUnicodeString( drv_name, str ); - return TRUE; -} - /*********************************************************************** * ZwLoadDriver (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 1c1f241591b..9c86450406d 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -1054,7 +1054,8 @@ void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) static const WCHAR rootW[] = {'R','O','O','T',0}; WCHAR buffer[MAX_SERVICE_NAME + ARRAY_SIZE(driverW)], id[MAX_DEVICE_ID_LEN]; SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; - struct root_pnp_device *pnp_device; + struct list new_list = LIST_INIT(new_list); + struct root_pnp_device *pnp_device, *next; DEVICE_OBJECT *device; NTSTATUS status; unsigned int i; @@ -1080,8 +1081,13 @@ void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL ); - if (find_root_pnp_device( driver, id )) + if ((pnp_device = find_root_pnp_device( driver, id ))) + { + TRACE("Found device %s already enumerated.\n", debugstr_w(id)); + list_remove( &pnp_device->entry ); + list_add_tail( &new_list, &pnp_device->entry ); continue; + } TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id)); @@ -1095,10 +1101,19 @@ void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) pnp_device = device->DeviceExtension; wcscpy( pnp_device->id, id ); pnp_device->device = device; - list_add_tail( &driver->root_pnp_devices, &pnp_device->entry ); + list_add_tail( &new_list, &pnp_device->entry ); start_device( device, set, &sp_device ); } + LIST_FOR_EACH_ENTRY_SAFE( pnp_device, next, &driver->root_pnp_devices, struct root_pnp_device, entry ) + { + TRACE("Removing device %s.\n", debugstr_w(pnp_device->id)); + + remove_device( pnp_device->device ); + } + + list_move_head( &driver->root_pnp_devices, &new_list ); + SetupDiDestroyDeviceInfoList(set); } -- 2.30.2
If the service is already running, starting it has no effect. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/setupapi/devinst.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index de0413e74f5..0a396cc8464 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -104,6 +104,8 @@ static const WCHAR AddInterface[] = {'A','d','d','I','n','t','e','r','f','a','c' static const WCHAR backslashW[] = {'\\',0}; static const WCHAR emptyW[] = {0}; +#define SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES 128 + struct driver { WCHAR inf_path[MAX_PATH]; @@ -5123,13 +5125,20 @@ BOOL WINAPI SetupDiInstallDevice(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data) if (!wcsnicmp(device->instanceId, rootW, lstrlenW(rootW)) && svc_name[0] && (manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT))) { - if ((service = OpenServiceW(manager, svc_name, SERVICE_START))) + if ((service = OpenServiceW(manager, svc_name, SERVICE_START | SERVICE_USER_DEFINED_CONTROL))) { + SERVICE_STATUS status; + if (!StartServiceW(service, 0, NULL) && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING) { ERR("Failed to start service %s for device %s, error %u.\n", debugstr_w(svc_name), debugstr_w(device->instanceId), GetLastError()); } + if (!ControlService(service, SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES, &status)) + { + ERR("Failed to control service %s for device %s, error %u.\n", + debugstr_w(svc_name), debugstr_w(device->instanceId), GetLastError()); + } CloseServiceHandle(service); } else -- 2.30.2
Allow them to be unloaded. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/setupapi/devinst.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 0a396cc8464..8f826c30250 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -19,6 +19,7 @@ */ #include <stdarg.h> +#include <stdlib.h> #include "windef.h" #include "winbase.h" @@ -1692,15 +1693,38 @@ BOOL WINAPI SetupDiRegisterDeviceInfo(HDEVINFO devinfo, SP_DEVINFO_DATA *device_ */ BOOL WINAPI SetupDiRemoveDevice(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data) { + SC_HANDLE manager = NULL, service = NULL; struct device *device; + WCHAR *service_name; + DWORD size; TRACE("devinfo %p, device_data %p.\n", devinfo, device_data); if (!(device = get_device(devinfo, device_data))) return FALSE; + if (!(manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT))) + return FALSE; + + if (!RegGetValueW(device->key, NULL, L"Service", RRF_RT_REG_SZ, NULL, NULL, &size)) + { + service_name = malloc(size); + if (!RegGetValueW(device->key, NULL, L"Service", RRF_RT_REG_SZ, NULL, service_name, &size)) + service = OpenServiceW(manager, service_name, SERVICE_USER_DEFINED_CONTROL); + free(service_name); + } + remove_device(device); + if (service) + { + SERVICE_STATUS status; + if (!ControlService(service, SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES, &status)) + ERR("Failed to control service %s, error %u.\n", debugstr_w(service_name), GetLastError()); + CloseServiceHandle(service); + } + CloseServiceHandle(manager); + return TRUE; } -- 2.30.2
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/ntoskrnl.exe/tests/Makefile.in | 6 +- dlls/ntoskrnl.exe/tests/driver_pnp.c | 143 ++++++++++++++++ dlls/ntoskrnl.exe/tests/driver_pnp.spec | 1 + dlls/ntoskrnl.exe/tests/ntoskrnl.c | 209 ++++++++++++++++++++++++ 4 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 dlls/ntoskrnl.exe/tests/driver_pnp.c create mode 100644 dlls/ntoskrnl.exe/tests/driver_pnp.spec diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in index 4b2052d43f4..c799dfcaf77 100644 --- a/dlls/ntoskrnl.exe/tests/Makefile.in +++ b/dlls/ntoskrnl.exe/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = ntoskrnl.exe -IMPORTS = advapi32 crypt32 wintrust ws2_32 +IMPORTS = advapi32 crypt32 newdev setupapi wintrust ws2_32 driver_IMPORTS = winecrt0 ntoskrnl driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native @@ -9,6 +9,8 @@ driver3_IMPORTS = winecrt0 ntoskrnl driver3_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native driver4_IMPORTS = winecrt0 ntoskrnl netio driver4_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native +driver_pnp_IMPORTS = winecrt0 ntoskrnl +driver_pnp_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native SOURCES = \ driver.c \ @@ -19,4 +21,6 @@ SOURCES = \ driver3.spec \ driver4.c \ driver4.spec \ + driver_pnp.c \ + driver_pnp.spec \ ntoskrnl.c diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c new file mode 100644 index 00000000000..53403d2fa7b --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -0,0 +1,143 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2020 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 const GUID control_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc0}}; +static UNICODE_STRING control_symlink; + +static DEVICE_OBJECT *bus_fdo, *bus_pdo; + +static NTSTATUS fdo_pnp(IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + NTSTATUS ret; + + switch (stack->MinorFunction) + { + case IRP_MN_START_DEVICE: + irp->IoStatus.Status = IoSetDeviceInterfaceState(&control_symlink, TRUE); + break; + + case IRP_MN_SURPRISE_REMOVAL: + irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IRP_MN_REMOVE_DEVICE: + IoSetDeviceInterfaceState(&control_symlink, FALSE); + irp->IoStatus.Status = STATUS_SUCCESS; + IoSkipCurrentIrpStackLocation(irp); + ret = IoCallDriver(bus_pdo, irp); + IoDetachDevice(bus_pdo); + IoDeleteDevice(bus_fdo); + RtlFreeUnicodeString(&control_symlink); + return ret; + } + + IoSkipCurrentIrpStackLocation(irp); + return IoCallDriver(bus_pdo, irp); +} + +static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + NTSTATUS ret = irp->IoStatus.Status; + + switch (stack->MinorFunction) + { + case IRP_MN_START_DEVICE: + ret = STATUS_SUCCESS; + break; + + case IRP_MN_QUERY_CAPABILITIES: + case IRP_MN_SURPRISE_REMOVAL: + ret = STATUS_SUCCESS; + break; + } + + irp->IoStatus.Status = ret; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return ret; +} + +static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) +{ + if (device == bus_fdo) + return fdo_pnp(irp); + return pdo_pnp(device, irp); +} + +static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo) +{ + NTSTATUS ret; + + if ((ret = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &bus_fdo))) + return ret; + + if ((ret = IoRegisterDeviceInterface(pdo, &control_class, NULL, &control_symlink))) + { + IoDeleteDevice(bus_fdo); + return ret; + } + + IoAttachDeviceToDeviceStack(bus_fdo, pdo); + bus_pdo = pdo; + bus_fdo->Flags &= ~DO_DEVICE_INITIALIZING; + 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_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) +{ +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) +{ + driver->DriverExtension->AddDevice = driver_add_device; + driver->DriverUnload = driver_unload; + driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; + driver->MajorFunction[IRP_MJ_CREATE] = driver_create; + driver->MajorFunction[IRP_MJ_CLOSE] = driver_close; + + return STATUS_SUCCESS; +} diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.spec b/dlls/ntoskrnl.exe/tests/driver_pnp.spec new file mode 100644 index 00000000000..ad33444716a --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.spec @@ -0,0 +1 @@ +# nothing here yet diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index c3ebe5b8ee1..70398e90627 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -32,12 +32,16 @@ #include "ntsecapi.h" #include "mscat.h" #include "mssip.h" +#include "setupapi.h" +#include "newdev.h" #include "wine/test.h" #include "wine/heap.h" #include "wine/mssign.h" #include "driver.h" +static const GUID GUID_NULL; + static HANDLE device; static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR *, UNICODE_STRING *, WCHAR **, CURDIR *); @@ -934,6 +938,209 @@ static void test_driver4(struct testsign_context *ctx) ok(ret, "DeleteFile failed: %u\n", GetLastError()); } +static void add_file_to_catalog(HANDLE catalog, const WCHAR *file) +{ + SIP_SUBJECTINFO subject_info = {sizeof(SIP_SUBJECTINFO)}; + SIP_INDIRECT_DATA *indirect_data; + const WCHAR *filepart = file; + CRYPTCATMEMBER *member; + WCHAR hash_buffer[100]; + GUID subject_guid; + unsigned int i; + DWORD size; + BOOL ret; + + ret = CryptSIPRetrieveSubjectGuidForCatalogFile(file, NULL, &subject_guid); + todo_wine ok(ret, "Failed to get subject guid, error %u\n", GetLastError()); + + size = 0; + subject_info.pgSubjectType = &subject_guid; + subject_info.pwsFileName = file; + subject_info.DigestAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1; + subject_info.dwFlags = SPC_INC_PE_RESOURCES_FLAG | SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG | SPC_EXC_PE_PAGE_HASHES_FLAG | 0x10000; + ret = CryptSIPCreateIndirectData(&subject_info, &size, NULL); + todo_wine ok(ret, "Failed to get indirect data size, error %u\n", GetLastError()); + + indirect_data = malloc(size); + ret = CryptSIPCreateIndirectData(&subject_info, &size, indirect_data); + todo_wine ok(ret, "Failed to get indirect data, error %u\n", GetLastError()); + if (ret) + { + memset(hash_buffer, 0, sizeof(hash_buffer)); + for (i = 0; i < indirect_data->Digest.cbData; ++i) + swprintf(&hash_buffer[i * 2], 2, L"%02X", indirect_data->Digest.pbData[i]); + + member = CryptCATPutMemberInfo(catalog, (WCHAR *)file, + hash_buffer, &subject_guid, 0, size, (BYTE *)indirect_data); + ok(!!member, "Failed to write member, error %u\n", GetLastError()); + + if (wcsrchr(file, '\\')) + filepart = wcsrchr(file, '\\') + 1; + + ret = !!CryptCATPutAttrInfo(catalog, member, (WCHAR *)L"File", + CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED, + (wcslen(filepart) + 1) * 2, (BYTE *)filepart); + ok(ret, "Failed to write attr, error %u\n", GetLastError()); + + ret = !!CryptCATPutAttrInfo(catalog, member, (WCHAR *)L"OSAttr", + CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED, + sizeof(L"2:6.0"), (BYTE *)L"2:6.0"); + ok(ret, "Failed to write attr, error %u\n", GetLastError()); + } +} + +static void test_pnp_driver(struct testsign_context *ctx) +{ + static const char hardware_id[] = "test_hardware_id\0"; + char path[MAX_PATH], dest[MAX_PATH], *filepart; + SP_DEVINFO_DATA device = {sizeof(device)}; + char cwd[MAX_PATH], tempdir[MAX_PATH]; + WCHAR driver_filename[MAX_PATH]; + SC_HANDLE manager, service; + HANDLE catalog, file; + HDEVINFO set; + BOOL ret; + FILE *f; + + static const char inf_text[] = + "[Version]\n" + "Signature=$Chicago$\n" + "ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}\n" + "CatalogFile=winetest.cat\n" + "DriverVer=09/21/2006,6.0.5736.1\n" + + "[Manufacturer]\n" + "Wine=mfg_section,NTamd64\n" + + "[mfg_section.NTamd64]\n" + "Wine test root driver=device_section,test_hardware_id\n" + + "[device_section.NTamd64]\n" + "CopyFiles=file_section\n" + + "[device_section.NTamd64.Services]\n" + "AddService=winetest,0x2,svc_section\n" + + "[file_section]\n" + "winetest.sys\n" + + "[SourceDisksFiles]\n" + "winetest.sys=1\n" + + "[SourceDisksNames]\n" + "1=,winetest.sys\n" + + "[DestinationDirs]\n" + "DefaultDestDir=12\n" + + "[svc_section]\n" + "ServiceBinary=%12%\\winetest.sys\n" + "ServiceType=1\n" + "StartType=3\n" + "ErrorControl=1\n" + "LoadOrderGroup=Extended Base\n" + "DisplayName=\"winetest bus driver\"\n" + "; they don't sleep anymore, on the beach\n"; + + GetCurrentDirectoryA(ARRAY_SIZE(cwd), cwd); + GetTempPathA(ARRAY_SIZE(tempdir), tempdir); + SetCurrentDirectoryA(tempdir); + + load_resource(L"driver_pnp.dll", driver_filename); + ret = MoveFileW(driver_filename, L"winetest.sys"); + ok(ret, "failed to move file, error %u\n", GetLastError()); + + f = fopen("winetest.inf", "w"); + ok(!!f, "failed to open winetest.inf: %s\n", strerror(errno)); + fputs(inf_text, f); + fclose(f); + + /* Create the catalog file. */ + + catalog = CryptCATOpen((WCHAR *)L"winetest.cat", CRYPTCAT_OPEN_CREATENEW, 0, CRYPTCAT_VERSION_1, 0); + ok(catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %#x\n", GetLastError()); + + ret = !!CryptCATPutCatAttrInfo(catalog, (WCHAR *)L"HWID1", + CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED, + sizeof(L"test_hardware_id"), (BYTE *)L"test_hardware_id"); + todo_wine ok(ret, "failed to add attribute, error %#x\n", GetLastError()); + + ret = !!CryptCATPutCatAttrInfo(catalog, (WCHAR *)L"OS", + CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED, + sizeof(L"VistaX64"), (BYTE *)L"VistaX64"); + todo_wine ok(ret, "failed to add attribute, error %#x\n", GetLastError()); + + add_file_to_catalog(catalog, L"winetest.sys"); + add_file_to_catalog(catalog, L"winetest.inf"); + + ret = CryptCATPersistStore(catalog); + todo_wine ok(ret, "Failed to write catalog, error %u\n", GetLastError()); + + ret = CryptCATClose(catalog); + ok(ret, "Failed to close catalog, error %u\n", GetLastError()); + + testsign_sign(ctx, L"winetest.cat"); + + /* Install the driver. */ + + set = SetupDiCreateDeviceInfoList(NULL, NULL); + ok(set != INVALID_HANDLE_VALUE, "failed to create device list, error %#x\n", GetLastError()); + + ret = SetupDiCreateDeviceInfoA(set, "root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device); + ok(ret, "failed to create device, error %#x\n", GetLastError()); + + ret = SetupDiSetDeviceRegistryPropertyA( set, &device, SPDRP_HARDWAREID, + (const BYTE *)hardware_id, sizeof(hardware_id) ); + ok(ret, "failed to create set hardware ID, error %#x\n", GetLastError()); + + ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device); + ok(ret, "failed to register device, error %#x\n", GetLastError()); + + GetFullPathNameA("winetest.inf", sizeof(path), path, NULL); + ret = UpdateDriverForPlugAndPlayDevicesA(NULL, hardware_id, path, INSTALLFLAG_FORCE, NULL); + ok(ret, "failed to install device, error %#x\n", GetLastError()); + + /* Tests. */ + + file = CreateFileA("\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError()); + CloseHandle(file); + + /* Clean up. */ + + ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device); + ok(ret, "failed to remove device, error %#x\n", GetLastError()); + + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "failed to destroy set, error %#x\n", GetLastError()); + + /* Windows stops the service but does not delete it. */ + manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); + ok(!!manager, "failed to open service manager, error %u\n", GetLastError()); + service = OpenServiceA(manager, "winetest", SERVICE_STOP | DELETE); + ok(!!service, "failed to open service, error %u\n", GetLastError()); + unload_driver(service); + CloseServiceHandle(manager); + + GetFullPathNameA("winetest.inf", sizeof(path), path, NULL); + ret = SetupCopyOEMInfA(path, NULL, 0, 0, dest, sizeof(dest), NULL, &filepart); + ok(ret, "Failed to copy INF, error %#x\n", GetLastError()); + ret = SetupUninstallOEMInfA(filepart, 0, NULL); + ok(ret, "Failed to uninstall INF, error %u\n", GetLastError()); + + ret = DeleteFileA("winetest.cat"); + ok(ret, "Failed to delete file, error %u\n", GetLastError()); + ret = DeleteFileA("winetest.inf"); + ok(ret, "Failed to delete file, error %u\n", GetLastError()); + ret = DeleteFileA("winetest.sys"); + ok(ret, "Failed to delete file, error %u\n", GetLastError()); + /* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */ + ret = DeleteFileA("C:/windows/system32/drivers/winetest.sys"); + ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %u\n", GetLastError()); + + SetCurrentDirectoryA(cwd); +} + START_TEST(ntoskrnl) { WCHAR filename[MAX_PATH], filename2[MAX_PATH]; @@ -1000,5 +1207,7 @@ START_TEST(ntoskrnl) subtest("driver4"); test_driver4(&ctx); + test_pnp_driver(&ctx); + testsign_cleanup(&ctx); } -- 2.30.2
Hi, While running your changed tests, 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=88026 Your paranoid android. === w7u_2qxl (32 bit report) === ntoskrnl.exe: ntoskrnl.c:1101: Test failed: failed to install device, error 0x103 ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 1121 === w7u_el (32 bit report) === ntoskrnl.exe: ntoskrnl.c:1101: Test failed: failed to install device, error 0x103 ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 1121 === w8 (32 bit report) === ntoskrnl.exe: ntoskrnl.c:1101: Test failed: failed to install device, error 0x103 ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 1121 === debiant2 (32 bit report) === ntoskrnl.exe: ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 6681336 === debiant2 (32 bit French report) === ntoskrnl.exe: ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 6681336 === debiant2 (32 bit Japanese:Japan report) === ntoskrnl.exe: ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 6681336 === debiant2 (32 bit Chinese:China report) === ntoskrnl.exe: ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 6681336 === debiant2 (32 bit WoW report) === ntoskrnl.exe: ntoskrnl.c:1106: Test failed: got error 2 ntoskrnl.c:1121: Test failed: failed to open service, error 1060 ntoskrnl.c:283: Test failed: expected SERVICE_STOPPED, got 6681336 ntoskrnl.c:1139: Test failed: Failed to delete file, error 3
Hi, While running your changed tests, 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=88019 Your paranoid android. === w8 (32 bit report) === ntoskrnl.exe: driver.c:272: Test failed: Got unexpected test_load_image_notify_count 0.
participants (3)
-
Alexandre Julliard -
Marvin -
Zebediah Figura