Rémi Bernon : setupapi: Rank drivers according to their id match.

Alexandre Julliard julliard at winehq.org
Wed Aug 18 16:22:10 CDT 2021


Module: wine
Branch: master
Commit: cfddd2c1e24fc03ad570f771093fd08bbf8b9575
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=cfddd2c1e24fc03ad570f771093fd08bbf8b9575

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Wed Aug 18 09:40:12 2021 +0200

setupapi: Rank drivers according to their id match.

And as described on MSDN "Driver Rank Example".

In order to safely remove the hardcoded XBox gamepad ID list from
winebus.sys, and list their hardware IDs in the (future) xinput.sys
driver INF.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/setupapi/devinst.c       | 33 ++++++++++++++++++++++++---------
 dlls/setupapi/tests/devinst.c |  2 +-
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c
index 13e52f4534a..29cfbbeb87f 100644
--- a/dlls/setupapi/devinst.c
+++ b/dlls/setupapi/devinst.c
@@ -109,6 +109,7 @@ static const WCHAR emptyW[] = {0};
 
 struct driver
 {
+    DWORD rank;
     WCHAR inf_path[MAX_PATH];
     WCHAR manufacturer[LINE_LEN];
     WCHAR mfg_key[LINE_LEN];
@@ -4588,21 +4589,23 @@ BOOL WINAPI SetupDiRegisterCoDeviceInstallers(HDEVINFO devinfo, SP_DEVINFO_DATA
 
 /* Check whether the given hardware or compatible ID matches any of the device's
  * own hardware or compatible IDs. */
-static BOOL device_matches_id(const struct device *device, const WCHAR *id_type, const WCHAR *id)
+static BOOL device_matches_id(const struct device *device, const WCHAR *id_type, const WCHAR *id,
+                              DWORD *driver_rank)
 {
     WCHAR *device_ids;
     const WCHAR *p;
-    DWORD size;
+    DWORD i, size;
 
     if (!RegGetValueW(device->key, NULL, id_type, RRF_RT_REG_MULTI_SZ, NULL, NULL, &size))
     {
         device_ids = heap_alloc(size);
         if (!RegGetValueW(device->key, NULL, id_type, RRF_RT_REG_MULTI_SZ, NULL, device_ids, &size))
         {
-            for (p = device_ids; *p; p += lstrlenW(p) + 1)
+            for (p = device_ids, i = 0; *p; p += lstrlenW(p) + 1, i++)
             {
                 if (!wcsicmp(p, id))
                 {
+                    *driver_rank += min(i, 0xff);
                     heap_free(device_ids);
                     return TRUE;
                 }
@@ -4688,10 +4691,13 @@ static void enum_compat_drivers_from_file(struct device *device, const WCHAR *pa
 
         for (j = 0; SetupGetLineByIndexW(hinf, driver.mfg_key, j, &ctx); ++j)
         {
+            driver.rank = 0;
             for (k = 2, found = FALSE; SetupGetStringFieldW(&ctx, k, id, ARRAY_SIZE(id), NULL); ++k)
             {
-                if ((found = device_matches_id(device, HardwareId, id))) break;
-                if ((found = device_matches_id(device, CompatibleIDs, id))) break;
+                if ((found = device_matches_id(device, HardwareId, id, &driver.rank))) break;
+                driver.rank += 0x2000;
+                if ((found = device_matches_id(device, CompatibleIDs, id, &driver.rank))) break;
+                driver.rank = 0x1000 + min(0x0100 * (k - 2), 0xf00);
             }
 
             if (found)
@@ -4699,8 +4705,8 @@ static void enum_compat_drivers_from_file(struct device *device, const WCHAR *pa
                 SetupGetStringFieldW(&ctx, 0, driver.description, ARRAY_SIZE(driver.description), NULL);
                 SetupGetStringFieldW(&ctx, 1, driver.section, ARRAY_SIZE(driver.section), NULL);
 
-                TRACE("Found compatible driver: manufacturer %s, desc %s.\n",
-                        debugstr_w(driver.manufacturer), debugstr_w(driver.description));
+                TRACE("Found compatible driver: rank %#x manufacturer %s, desc %s.\n",
+                        driver.rank, debugstr_w(driver.manufacturer), debugstr_w(driver.description));
 
                 driver_count++;
                 drivers = heap_realloc(drivers, driver_count * sizeof(*drivers));
@@ -4867,6 +4873,8 @@ BOOL WINAPI SetupDiEnumDriverInfoA(HDEVINFO devinfo, SP_DEVINFO_DATA *device_dat
 BOOL WINAPI SetupDiSelectBestCompatDrv(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data)
 {
     struct device *device;
+    struct driver *best;
+    DWORD i;
 
     TRACE("devinfo %p, device_data %p.\n", devinfo, device_data);
 
@@ -4880,10 +4888,17 @@ BOOL WINAPI SetupDiSelectBestCompatDrv(HDEVINFO devinfo, SP_DEVINFO_DATA *device
         return FALSE;
     }
 
-    WARN("Semi-stub, selecting the first available driver.\n");
+    best = device->drivers;
+    for (i = 1; i < device->driver_count; ++i)
+    {
+        if (device->drivers[i].rank >= best->rank) continue;
+        best = device->drivers + i;
+    }
 
-    device->selected_driver = &device->drivers[0];
+    TRACE("selected driver: rank %#x manufacturer %s, desc %s.\n",
+            best->rank, debugstr_w(best->manufacturer), debugstr_w(best->description));
 
+    device->selected_driver = best;
     return TRUE;
 }
 
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
index 677d6bda02a..6f02acb9589 100644
--- a/dlls/setupapi/tests/devinst.c
+++ b/dlls/setupapi/tests/devinst.c
@@ -2575,7 +2575,7 @@ static void test_driver_list(void)
     ret = SetupDiGetSelectedDriverA(set, &device, &driver);
     ok(ret, "Failed to get selected driver, error %#x.\n", GetLastError());
     ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
-    todo_wine ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
+    ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
     ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
     ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
 




More information about the wine-cvs mailing list