[PATCH v4 5/5] services: Load root PnP drivers on startup.

Zebediah Figura z.figura12 at gmail.com
Sat Jun 22 10:12:34 CDT 2019


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
Windows starts up all root PnP drivers on startup. Native root PnP drivers are
generally marked as SERVICE_DEMAND_START, so they will not be started up
otherwise.

If using setupapi from services.exe is unpalatable or architecturally wrong, I
can send a patch to duplicate the logic, so that we check the registry
directly. I would appreciate an explanation of why this is the case,
however. If loading root PnP drivers on startup itself from services.exe is
unpalatable or architecturally wrong, we will have to warn users that any root
PnP drivers they install will have to have their startup type changed from
SERVICE_DEMAND_START.

 programs/services/Makefile.in |  2 +-
 programs/services/services.c  | 29 ++++++++++++++++++++++++++++-
 2 files changed, 29 insertions(+), 2 deletions(-)

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 2dff8115595..96a18bcd18e 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 "wine/heap.h"
@@ -423,25 +424,50 @@ static BOOL schedule_delayed_autostart(struct service_entry **services, unsigned
     return TRUE;
 }
 
+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;
     unsigned int delayed_cnt = 0;
     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)
             {
@@ -482,6 +508,7 @@ static void scmdatabase_autostart_services(struct scmdatabase *db)
 
     if (!delayed_cnt || !schedule_delayed_autostart(services_list, delayed_cnt))
         heap_free(services_list);
+    SetupDiDestroyDeviceInfoList(set);
 }
 
 static void scmdatabase_wait_terminate(struct scmdatabase *db)
-- 
2.21.0




More information about the wine-devel mailing list