From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- loader/wine.inf.in | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 844f7c66d46..c3d3b770b5c 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -461,6 +461,8 @@ HKLM,System\CurrentControlSet\Control\Class{4d36e967-e325-11ce-bfc1-08002be1031 HKLM,System\CurrentControlSet\Control\Class{4d36e967-e325-11ce-bfc1-08002be10318},"Class",,"DiskDrive" HKLM,System\CurrentControlSet\Control\Class{4d36e978-e325-11ce-bfc1-08002be10318},,,"Ports (COM & LPT)" HKLM,System\CurrentControlSet\Control\Class{4d36e978-e325-11ce-bfc1-08002be10318},"Class",,"Ports" +HKLM,System\CurrentControlSet\Control\Class{4d36e97d-e325-11ce-bfc1-08002be10318},,,"System devices" +HKLM,System\CurrentControlSet\Control\Class{4d36e97d-e325-11ce-bfc1-08002be10318},"Class",,"System" HKLM,System\CurrentControlSet\Control\Class{6bdd1fc6-810f-11d0-bec7-08002be2092f},,,"Imaging devices" HKLM,System\CurrentControlSet\Control\Class{6bdd1fc6-810f-11d0-bec7-08002be2092f},"Class",,"Image" HKLM,System\CurrentControlSet\Control\Class{745a17a0-74d3-11d0-b6fe-00a0c90f57da},,,"Human Interface Devices"
From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 5 ++++ dlls/ntoskrnl.exe/ntoskrnl_private.h | 3 +++ dlls/ntoskrnl.exe/pnp.c | 36 ++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index a0812dc7c96..2fccadcacb3 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -854,6 +854,8 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) PsInitialSystemProcess = IoGetCurrentProcess(); request_thread = GetCurrentThreadId();
+ pnp_manager_start(); + handles[0] = stop_event; handles[1] = manager;
@@ -921,6 +923,9 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) }
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(); wine_rb_destroy( &wine_drivers, unload_driver, NULL ); return status; } diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h index 2823a1cd4f1..1c5952f7c10 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl_private.h +++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h @@ -76,6 +76,9 @@ extern POBJECT_TYPE SeTokenObjectType;
void ObReferenceObject( void *obj ) DECLSPEC_HIDDEN;
+void pnp_manager_start(void) DECLSPEC_HIDDEN; +void pnp_manager_stop(void) DECLSPEC_HIDDEN; + static const WCHAR servicesW[] = {'\','R','e','g','i','s','t','r','y', '\','M','a','c','h','i','n','e', '\','S','y','s','t','e','m', diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index b8bdf93e54b..fc99928a247 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -3,6 +3,7 @@ * * Copyright 2016 Sebastian Lackner * Copyright 2016 Aric Stewart for CodeWeavers + * Copyright 2019 Zebediah Figura * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -750,3 +751,38 @@ POWER_STATE WINAPI PoSetPowerState( DEVICE_OBJECT *device, POWER_STATE_TYPE type FIXME("device %p, type %u, state %u, stub!\n", device, type, state.DeviceState); return state; } + +static DRIVER_OBJECT *pnp_manager; + +static NTSTATUS WINAPI pnp_manager_device_pnp( DEVICE_OBJECT *device, IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + + TRACE("device %p, irp %p, minor function %#x.\n", device, irp, stack->MinorFunction); + + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return irp->IoStatus.u.Status; +} + +static NTSTATUS WINAPI pnp_manager_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *keypath ) +{ + pnp_manager = driver; + driver->MajorFunction[IRP_MJ_PNP] = pnp_manager_device_pnp; + return STATUS_SUCCESS; +} + +void pnp_manager_start(void) +{ + static const WCHAR driver_nameW[] = {'\','D','r','i','v','e','r','\','P','n','p','M','a','n','a','g','e','r',0}; + UNICODE_STRING driver_nameU; + NTSTATUS status; + + RtlInitUnicodeString( &driver_nameU, driver_nameW ); + if ((status = IoCreateDriver( &driver_nameU, pnp_manager_driver_entry ))) + ERR("Failed to create PnP manager driver, status %#x.\n", status); +} + +void pnp_manager_stop(void) +{ + IoDeleteDriver( pnp_manager ); +}
We want to load setupapi from services.exe. We do not want to initialize user32 there, as that results in creation of a window station. --- dlls/setupapi/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in index bf157cb7767..6bb9d59bf59 100644 --- a/dlls/setupapi/Makefile.in +++ b/dlls/setupapi/Makefile.in @@ -1,8 +1,8 @@ EXTRADEFS = -D_SETUPAPI_ MODULE = setupapi.dll IMPORTLIB = setupapi -IMPORTS = uuid user32 version advapi32 rpcrt4 -DELAYIMPORTS = shell32 wintrust ole32 winspool comdlg32 +IMPORTS = uuid version advapi32 rpcrt4 +DELAYIMPORTS = shell32 wintrust ole32 winspool comdlg32 user32
C_SRCS = \ devinst.c \
Signed-off-by: Zebediah Figura z.figura12@gmail.com
On 6/11/19 6:53 PM, Zebediah Figura wrote:
We want to load setupapi from services.exe. We do not want to initialize user32 there, as that results in creation of a window station.
dlls/setupapi/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in index bf157cb7767..6bb9d59bf59 100644 --- a/dlls/setupapi/Makefile.in +++ b/dlls/setupapi/Makefile.in @@ -1,8 +1,8 @@ EXTRADEFS = -D_SETUPAPI_ MODULE = setupapi.dll IMPORTLIB = setupapi -IMPORTS = uuid user32 version advapi32 rpcrt4 -DELAYIMPORTS = shell32 wintrust ole32 winspool comdlg32 +IMPORTS = uuid version advapi32 rpcrt4 +DELAYIMPORTS = shell32 wintrust ole32 winspool comdlg32 user32
C_SRCS = \ devinst.c \
--- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + dlls/ntoskrnl.exe/pnp.c | 111 +++++++++++++++++++++++++--- programs/services/Makefile.in | 2 +- programs/services/services.c | 29 +++++++- programs/winedevice/device.c | 4 +- 5 files changed, 135 insertions(+), 12 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 7c9370579dd..114b764fbe9 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1522,3 +1522,4 @@ # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
@ cdecl wine_ntoskrnl_main_loop(long) +@ cdecl wine_enumerate_root_pnp_devices(wstr) diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index fc99928a247..2c907d16314 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -376,6 +376,18 @@ static BOOL install_device_driver( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVIN return TRUE; }
+/* Load the function driver for a newly created PDO, if one is present, and + * send IRPs to start the device. */ +static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA *sp_device ) +{ + load_function_driver( device, set, sp_device ); + if (device->DriverObject) + { + send_pnp_irp( device, IRP_MN_START_DEVICE ); + send_power_irp( device, PowerDeviceD0 ); + } +} + static void handle_bus_relations( DEVICE_OBJECT *device ) { static const WCHAR infpathW[] = {'I','n','f','P','a','t','h',0}; @@ -421,19 +433,14 @@ static void handle_bus_relations( DEVICE_OBJECT *device ) return; }
- load_function_driver( device, set, &sp_device ); - if (device->DriverObject) - { - send_pnp_irp( device, IRP_MN_START_DEVICE ); - send_power_irp( device, PowerDeviceD0 ); - } + start_device( device, set, &sp_device );
SetupDiDestroyDeviceInfoList( set ); }
-static void handle_removal_relations( DEVICE_OBJECT *device ) +static void remove_device( DEVICE_OBJECT *device ) { - TRACE( "(%p)\n", device ); + TRACE("Removing device %p.\n", device);
send_power_irp( device, PowerDeviceD3 ); send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL ); @@ -453,7 +460,7 @@ void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RE handle_bus_relations( device_object ); break; case RemovalRelations: - handle_removal_relations( device_object ); + remove_device( device_object ); break; default: FIXME("Unhandled relation %#x.\n", type); @@ -754,6 +761,23 @@ POWER_STATE WINAPI PoSetPowerState( DEVICE_OBJECT *device, POWER_STATE_TYPE type
static DRIVER_OBJECT *pnp_manager;
+struct root_pnp_device +{ + WCHAR id[MAX_DEVICE_ID_LEN]; + struct wine_rb_entry entry; + DEVICE_OBJECT *device; +}; + +static int root_pnp_devices_rb_compare( const void *key, const struct wine_rb_entry *entry ) +{ + const struct root_pnp_device *device = WINE_RB_ENTRY_VALUE( entry, const struct root_pnp_device, entry ); + const WCHAR *k = key; + + return strcmpiW( k, device->id ); +} + +static struct wine_rb_tree root_pnp_devices = { root_pnp_devices_rb_compare }; + static NTSTATUS WINAPI pnp_manager_device_pnp( DEVICE_OBJECT *device, IRP *irp ) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); @@ -782,7 +806,76 @@ void pnp_manager_start(void) ERR("Failed to create PnP manager driver, status %#x.\n", status); }
+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 ); IoDeleteDriver( pnp_manager ); } + +/*********************************************************************** + * wine_enumerate_root_pnp_devices (Not a Windows API) + */ +NTSTATUS CDECL wine_enumerate_root_pnp_devices( const WCHAR *driver_name ) +{ + 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]; + SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; + struct root_pnp_device *pnp_device; + DEVICE_OBJECT *device; + NTSTATUS status; + unsigned int i; + HDEVINFO set; + + TRACE("Searching for new root-enumerated devices for driver %s.\n", debugstr_w(driver_name)); + + set = SetupDiGetClassDevsW( NULL, rootW, NULL, DIGCF_ALLCLASSES ); + if (set == INVALID_HANDLE_VALUE) + return GetLastError(); + + for (i = 0; SetupDiEnumDeviceInfo( set, i, &sp_device ); ++i) + { + if (!SetupDiGetDeviceRegistryPropertyW( set, &sp_device, SPDRP_SERVICE, + NULL, (BYTE *)buffer, sizeof(buffer), NULL ) + || lstrcmpiW( buffer, driver_name )) + { + continue; + } + + SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL ); + + if (wine_rb_get( &root_pnp_devices, id )) + continue; + + TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id)); + + if ((status = IoCreateDevice( pnp_manager, sizeof(struct root_pnp_device), NULL, + FILE_DEVICE_CONTROLLER, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &device ))) + { + ERR("Failed to create root-enumerated PnP device %s, status %#x.\n", debugstr_w(id), status); + continue; + } + + pnp_device = device->DeviceExtension; + strcpyW( 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; + } + + start_device( device, set, &sp_device ); + } + + SetupDiDestroyDeviceInfoList(set); + + return ERROR_SUCCESS; +} diff --git a/programs/services/Makefile.in b/programs/services/Makefile.in index e06514cbdd1..560e277a9bf 100644 --- a/programs/services/Makefile.in +++ b/programs/services/Makefile.in @@ -1,5 +1,5 @@ MODULE = services.exe -IMPORTS = rpcrt4 advapi32 userenv +IMPORTS = rpcrt4 advapi32 userenv setupapi
EXTRADLLFLAGS = -mconsole -mno-cygwin
diff --git a/programs/services/services.c b/programs/services/services.c index 7ca249c7a9d..3099b7805b1 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -27,6 +27,7 @@ #include <winsvc.h> #include <rpc.h> #include <userenv.h> +#include <setupapi.h>
#include "wine/debug.h" #include "svcctl.h" @@ -329,24 +330,49 @@ static int __cdecl compare_tags(const void *a, const void *b) return service_a->config.dwTagId - service_b->config.dwTagId; }
+static BOOL is_root_pnp_service(const struct service_entry *service, HDEVINFO set) +{ + SP_DEVINFO_DATA device = {sizeof(device)}; + WCHAR name[MAX_SERVICE_NAME]; + unsigned int i; + + for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i) + { + if (SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_SERVICE, NULL, + (BYTE *)name, sizeof(name), NULL) + && !wcsicmp(name, service->name)) + { + return TRUE; + } + } + + return FALSE; +} + static void scmdatabase_autostart_services(struct scmdatabase *db) { + static const WCHAR rootW[] = {'R','O','O','T',0}; struct service_entry **services_list; unsigned int i = 0; unsigned int size = 32; struct service_entry *service; + HDEVINFO set;
services_list = HeapAlloc(GetProcessHeap(), 0, size * sizeof(services_list[0])); if (!services_list) return;
+ if ((set = SetupDiGetClassDevsW( NULL, rootW, NULL, DIGCF_ALLCLASSES )) == INVALID_HANDLE_VALUE) + WINE_ERR("Failed to enumerate devices, error %#x.\n", GetLastError()); + scmdatabase_lock(db);
LIST_FOR_EACH_ENTRY(service, &db->services, struct service_entry, entry) { if (service->config.dwStartType == SERVICE_BOOT_START || service->config.dwStartType == SERVICE_SYSTEM_START || - service->config.dwStartType == SERVICE_AUTO_START) + service->config.dwStartType == SERVICE_AUTO_START || + (set != INVALID_HANDLE_VALUE && is_root_pnp_service(set, service))) { if (i+1 >= size) { @@ -379,6 +405,7 @@ static void scmdatabase_autostart_services(struct scmdatabase *db)
scmdatabase_unlock_startup(db); HeapFree(GetProcessHeap(), 0, services_list); + SetupDiDestroyDeviceInfoList(set); }
static void scmdatabase_wait_terminate(struct scmdatabase *db) diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index f4ebad2f2d0..9c90e4e2963 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -40,6 +40,7 @@ static const WCHAR servicesW[] = {'\','R','e','g','i','s','t','r','y', '\',0};
extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); +extern NTSTATUS CDECL wine_enumerate_root_pnp_devices( const WCHAR *driver_name );
static const WCHAR winedeviceW[] = {'w','i','n','e','d','e','v','i','c','e',0}; static SERVICE_STATUS_HANDLE service_handle; @@ -76,7 +77,8 @@ static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) switch (ctrl) { case SERVICE_CONTROL_START: - result = RtlNtStatusToDosError(ZwLoadDriver( &service_name )); + if (!(result = RtlNtStatusToDosError(ZwLoadDriver( &service_name )))) + result = RtlNtStatusToDosError(wine_enumerate_root_pnp_devices( driver_name )); break;
case SERVICE_CONTROL_STOP:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
On 6/11/19 6:53 PM, Zebediah Figura wrote:
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + dlls/ntoskrnl.exe/pnp.c | 111 +++++++++++++++++++++++++--- programs/services/Makefile.in | 2 +- programs/services/services.c | 29 +++++++- programs/winedevice/device.c | 4 +- 5 files changed, 135 insertions(+), 12 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 7c9370579dd..114b764fbe9 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1522,3 +1522,4 @@ # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
@ cdecl wine_ntoskrnl_main_loop(long) +@ cdecl wine_enumerate_root_pnp_devices(wstr) diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index fc99928a247..2c907d16314 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -376,6 +376,18 @@ static BOOL install_device_driver( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVIN return TRUE; }
+/* Load the function driver for a newly created PDO, if one is present, and
- send IRPs to start the device. */
+static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA *sp_device ) +{
- load_function_driver( device, set, sp_device );
- if (device->DriverObject)
- {
send_pnp_irp( device, IRP_MN_START_DEVICE );
send_power_irp( device, PowerDeviceD0 );
- }
+}
- static void handle_bus_relations( DEVICE_OBJECT *device ) { static const WCHAR infpathW[] = {'I','n','f','P','a','t','h',0};
@@ -421,19 +433,14 @@ static void handle_bus_relations( DEVICE_OBJECT *device ) return; }
- load_function_driver( device, set, &sp_device );
- if (device->DriverObject)
- {
send_pnp_irp( device, IRP_MN_START_DEVICE );
send_power_irp( device, PowerDeviceD0 );
- }
start_device( device, set, &sp_device );
SetupDiDestroyDeviceInfoList( set ); }
-static void handle_removal_relations( DEVICE_OBJECT *device ) +static void remove_device( DEVICE_OBJECT *device ) {
- TRACE( "(%p)\n", device );
TRACE("Removing device %p.\n", device);
send_power_irp( device, PowerDeviceD3 ); send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL );
@@ -453,7 +460,7 @@ void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RE handle_bus_relations( device_object ); break; case RemovalRelations:
handle_removal_relations( device_object );
remove_device( device_object ); break; default: FIXME("Unhandled relation %#x.\n", type);
@@ -754,6 +761,23 @@ POWER_STATE WINAPI PoSetPowerState( DEVICE_OBJECT *device, POWER_STATE_TYPE type
static DRIVER_OBJECT *pnp_manager;
+struct root_pnp_device +{
- WCHAR id[MAX_DEVICE_ID_LEN];
- struct wine_rb_entry entry;
- DEVICE_OBJECT *device;
+};
+static int root_pnp_devices_rb_compare( const void *key, const struct wine_rb_entry *entry ) +{
- const struct root_pnp_device *device = WINE_RB_ENTRY_VALUE( entry, const struct root_pnp_device, entry );
- const WCHAR *k = key;
- return strcmpiW( k, device->id );
+}
+static struct wine_rb_tree root_pnp_devices = { root_pnp_devices_rb_compare };
- static NTSTATUS WINAPI pnp_manager_device_pnp( DEVICE_OBJECT *device, IRP *irp ) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
@@ -782,7 +806,76 @@ void pnp_manager_start(void) ERR("Failed to create PnP manager driver, status %#x.\n", status); }
+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 ); IoDeleteDriver( pnp_manager ); }
+/***********************************************************************
wine_enumerate_root_pnp_devices (Not a Windows API)
- */
+NTSTATUS CDECL wine_enumerate_root_pnp_devices( const WCHAR *driver_name ) +{
- 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];
- SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
- struct root_pnp_device *pnp_device;
- DEVICE_OBJECT *device;
- NTSTATUS status;
- unsigned int i;
- HDEVINFO set;
- TRACE("Searching for new root-enumerated devices for driver %s.\n", debugstr_w(driver_name));
- set = SetupDiGetClassDevsW( NULL, rootW, NULL, DIGCF_ALLCLASSES );
- if (set == INVALID_HANDLE_VALUE)
return GetLastError();
- for (i = 0; SetupDiEnumDeviceInfo( set, i, &sp_device ); ++i)
- {
if (!SetupDiGetDeviceRegistryPropertyW( set, &sp_device, SPDRP_SERVICE,
NULL, (BYTE *)buffer, sizeof(buffer), NULL )
|| lstrcmpiW( buffer, driver_name ))
{
continue;
}
SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL );
if (wine_rb_get( &root_pnp_devices, id ))
continue;
TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id));
if ((status = IoCreateDevice( pnp_manager, sizeof(struct root_pnp_device), NULL,
FILE_DEVICE_CONTROLLER, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &device )))
{
ERR("Failed to create root-enumerated PnP device %s, status %#x.\n", debugstr_w(id), status);
continue;
}
pnp_device = device->DeviceExtension;
strcpyW( 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;
}
start_device( device, set, &sp_device );
- }
- SetupDiDestroyDeviceInfoList(set);
- return ERROR_SUCCESS;
+} diff --git a/programs/services/Makefile.in b/programs/services/Makefile.in index e06514cbdd1..560e277a9bf 100644 --- a/programs/services/Makefile.in +++ b/programs/services/Makefile.in @@ -1,5 +1,5 @@ MODULE = services.exe -IMPORTS = rpcrt4 advapi32 userenv +IMPORTS = rpcrt4 advapi32 userenv setupapi
EXTRADLLFLAGS = -mconsole -mno-cygwin
diff --git a/programs/services/services.c b/programs/services/services.c index 7ca249c7a9d..3099b7805b1 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -27,6 +27,7 @@ #include <winsvc.h> #include <rpc.h> #include <userenv.h> +#include <setupapi.h>
#include "wine/debug.h" #include "svcctl.h" @@ -329,24 +330,49 @@ static int __cdecl compare_tags(const void *a, const void *b) return service_a->config.dwTagId - service_b->config.dwTagId; }
+static BOOL is_root_pnp_service(const struct service_entry *service, HDEVINFO set) +{
- SP_DEVINFO_DATA device = {sizeof(device)};
- WCHAR name[MAX_SERVICE_NAME];
- unsigned int i;
- for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i)
- {
if (SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_SERVICE, NULL,
(BYTE *)name, sizeof(name), NULL)
&& !wcsicmp(name, service->name))
{
return TRUE;
}
- }
- return FALSE;
+}
static void scmdatabase_autostart_services(struct scmdatabase *db) {
static const WCHAR rootW[] = {'R','O','O','T',0}; struct service_entry **services_list; unsigned int i = 0; unsigned int size = 32; struct service_entry *service;
HDEVINFO set;
services_list = HeapAlloc(GetProcessHeap(), 0, size * sizeof(services_list[0])); if (!services_list) return;
if ((set = SetupDiGetClassDevsW( NULL, rootW, NULL, DIGCF_ALLCLASSES )) == INVALID_HANDLE_VALUE)
WINE_ERR("Failed to enumerate devices, error %#x.\n", GetLastError());
scmdatabase_lock(db); LIST_FOR_EACH_ENTRY(service, &db->services, struct service_entry, entry) { if (service->config.dwStartType == SERVICE_BOOT_START || service->config.dwStartType == SERVICE_SYSTEM_START ||
service->config.dwStartType == SERVICE_AUTO_START)
service->config.dwStartType == SERVICE_AUTO_START ||
(set != INVALID_HANDLE_VALUE && is_root_pnp_service(set, service))) { if (i+1 >= size) {
@@ -379,6 +405,7 @@ static void scmdatabase_autostart_services(struct scmdatabase *db)
scmdatabase_unlock_startup(db); HeapFree(GetProcessHeap(), 0, services_list);
SetupDiDestroyDeviceInfoList(set); }
static void scmdatabase_wait_terminate(struct scmdatabase *db)
diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index f4ebad2f2d0..9c90e4e2963 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -40,6 +40,7 @@ static const WCHAR servicesW[] = {'\','R','e','g','i','s','t','r','y', '\',0};
extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); +extern NTSTATUS CDECL wine_enumerate_root_pnp_devices( const WCHAR *driver_name );
static const WCHAR winedeviceW[] = {'w','i','n','e','d','e','v','i','c','e',0}; static SERVICE_STATUS_HANDLE service_handle; @@ -76,7 +77,8 @@ static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) switch (ctrl) { case SERVICE_CONTROL_START:
result = RtlNtStatusToDosError(ZwLoadDriver( &service_name ));
if (!(result = RtlNtStatusToDosError(ZwLoadDriver( &service_name ))))
result = RtlNtStatusToDosError(wine_enumerate_root_pnp_devices( driver_name )); break; case SERVICE_CONTROL_STOP:
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=53546
Your paranoid android.
=== debian9 (32 bit report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
=== debian9 (32 bit Chinese:China report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
=== debian9 (32 bit WoW report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
=== debian9 (64 bit WoW report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
On 6/11/19 9:15 PM, Marvin wrote:
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=53546
Your paranoid android.
=== debian9 (32 bit report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
=== debian9 (32 bit Chinese:China report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
=== debian9 (32 bit WoW report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
=== debian9 (64 bit WoW report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
This seems to be because the TestBot doesn't regenerate the corresponding Makefile when a single Makefile.in is updated; it works for me.
On Wed, 12 Jun 2019, Zebediah Figura wrote:
On 6/11/19 9:15 PM, Marvin wrote:
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=53546
Your paranoid android.
=== debian9 (32 bit report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
[...]
This seems to be because the TestBot doesn't regenerate the corresponding Makefile when a single Makefile.in is updated; it works for me.
If the makefile did not get regenerate that would be a dependency bug in Wine's build system. However running a simple make shows it does update the makefiles.
Also the result from the 53546 job seems to have changed.
Did you re-run it?
On 6/18/19 2:13 AM, Francois Gouget wrote:
On Wed, 12 Jun 2019, Zebediah Figura wrote:
On 6/11/19 9:15 PM, Marvin wrote:
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=53546
Your paranoid android.
=== debian9 (32 bit report) ===
services.exe: service.c:422: Test failed: service: Unexpected GetLastError: 0x6.
[...]
This seems to be because the TestBot doesn't regenerate the corresponding Makefile when a single Makefile.in is updated; it works for me.
If the makefile did not get regenerate that would be a dependency bug in Wine's build system. However running a simple make shows it does update the makefiles.
Looking at the build log from 53546, I don't see setupapi being re-linked.
Also the result from the 53546 job seems to have changed.
Did you re-run it?
I didn't manually re-run anything.