Signed-off-by: Zebediah Figura z.figura12@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)
Signed-off-by: Zebediah Figura z.figura12@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[] )
Zebediah Figura z.figura12@gmail.com writes:
Signed-off-by: Zebediah Figura z.figura12@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.
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@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 ); }
Signed-off-by: Zebediah Figura z.figura12@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
Signed-off-by: Zebediah Figura z.figura12@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); }
If the service is already running, starting it has no effect.
Signed-off-by: Zebediah Figura z.figura12@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
Allow them to be unloaded.
Signed-off-by: Zebediah Figura z.figura12@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; }
Signed-off-by: Zebediah Figura z.figura12@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); }
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.