[PATCH 2/9] setupapi: Use a handle table to allocate device nodes.

Zebediah Figura z.figura12 at gmail.com
Sun Jul 29 20:26:22 CDT 2018


The size of DEVINST is DWORD, so using the pointer directly won't work on
64-bit.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/setupapi/devinst.c          | 108 +++++++++++++++++++++++++--------------
 dlls/setupapi/setupapi_private.h |   5 ++
 dlls/setupapi/tests/devinst.c    |  22 ++++++++
 3 files changed, 96 insertions(+), 39 deletions(-)

diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c
index ea69dea..8c63298 100644
--- a/dlls/setupapi/devinst.c
+++ b/dlls/setupapi/devinst.c
@@ -33,6 +33,7 @@
 #include "winnls.h"
 #include "setupapi.h"
 #include "wine/debug.h"
+#include "wine/heap.h"
 #include "wine/list.h"
 #include "wine/unicode.h"
 #include "cfgmgr32.h"
@@ -140,6 +141,52 @@ struct DeviceInfo
     struct list           interfaces;
 };
 
+static struct DeviceInfo **devnode_table;
+static unsigned int devnode_table_size;
+
+static DEVINST alloc_devnode(struct DeviceInfo *device)
+{
+    unsigned int i;
+
+    for (i = 0; i < devnode_table_size; ++i)
+    {
+        if (!devnode_table[i])
+            break;
+    }
+
+    if (i == devnode_table_size)
+    {
+        if (devnode_table)
+        {
+            devnode_table_size *= 2;
+            devnode_table = heap_realloc_zero(devnode_table,
+                devnode_table_size * sizeof(*devnode_table));
+        }
+        else
+        {
+            devnode_table_size = 256;
+            devnode_table = heap_alloc_zero(devnode_table_size * sizeof(*devnode_table));
+        }
+    }
+
+    devnode_table[i] = device;
+    return i;
+}
+
+static void free_devnode(DEVINST devnode)
+{
+    devnode_table[devnode] = NULL;
+}
+
+static struct DeviceInfo *get_devnode_device(DEVINST devnode)
+{
+    if (devnode < devnode_table_size)
+        return devnode_table[devnode];
+
+    WARN("device node %u not found\n", devnode);
+    return NULL;
+}
+
 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
 {
     static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
@@ -460,15 +507,12 @@ static HKEY SETUPDI_CreateDrvKey(struct DeviceInfo *devInfo)
 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
         DWORD devId, LPCWSTR instanceId, BOOL phantom)
 {
-    struct DeviceInfo *devInfo = NULL;
-    HANDLE devInst = GlobalAlloc(GMEM_FIXED, sizeof(struct DeviceInfo));
-    if (devInst)
-        devInfo = GlobalLock(devInst);
+    struct DeviceInfo *devInfo = heap_alloc(sizeof(*devInfo));
 
     if (devInfo)
     {
         devInfo->set = set;
-        devInfo->devId = (DWORD)devInst;
+        devInfo->devId = alloc_devnode(devInfo);
 
         devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
                 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
@@ -486,12 +530,10 @@ static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
                             (LPBYTE)&phantom, sizeof(phantom));
             }
             list_init(&devInfo->interfaces);
-            GlobalUnlock(devInst);
         }
         else
         {
-            GlobalUnlock(devInst);
-            GlobalFree(devInst);
+            heap_free(devInfo);
             devInfo = NULL;
         }
     }
@@ -525,7 +567,8 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
         SETUPDI_FreeInterfaceInstances(iface);
         HeapFree(GetProcessHeap(), 0, iface);
     }
-    GlobalFree((HANDLE)devInfo->devId);
+    free_devnode(devInfo->devId);
+    heap_free(devInfo);
 }
 
 /* Adds a device with GUID guid and identifier devInst to set.  Allocates a
@@ -3979,63 +4022,50 @@ BOOL WINAPI SetupDiDeleteDevRegKey(
 /***********************************************************************
  *              CM_Get_Device_IDA  (SETUPAPI.@)
  */
-CONFIGRET WINAPI CM_Get_Device_IDA( DEVINST dnDevInst, PSTR Buffer,
-                                   ULONG  BufferLen, ULONG  ulFlags)
+CONFIGRET WINAPI CM_Get_Device_IDA(DEVINST devnode, char *buffer, ULONG len, ULONG flags)
 {
-    struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
+    struct DeviceInfo *device = get_devnode_device(devnode);
 
-    TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
+    TRACE("%u, %p, %u, %#x\n", devnode, buffer, len, flags);
 
-    if (!devInfo)
+    if (!device)
         return CR_NO_SUCH_DEVINST;
 
-    WideCharToMultiByte(CP_ACP, 0, devInfo->instanceId, -1, Buffer, BufferLen, 0, 0);
-    TRACE("Returning %s\n", debugstr_a(Buffer));
+    WideCharToMultiByte(CP_ACP, 0, device->instanceId, -1, buffer, len, 0, 0);
+    TRACE("Returning %s\n", debugstr_a(buffer));
     return CR_SUCCESS;
 }
 
 /***********************************************************************
  *              CM_Get_Device_IDW  (SETUPAPI.@)
  */
-CONFIGRET WINAPI CM_Get_Device_IDW( DEVINST dnDevInst, LPWSTR Buffer,
-                                   ULONG  BufferLen, ULONG  ulFlags)
+CONFIGRET WINAPI CM_Get_Device_IDW(DEVINST devnode, WCHAR *buffer, ULONG len, ULONG flags)
 {
-    struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
+    struct DeviceInfo *device = get_devnode_device(devnode);
 
-    TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
+    TRACE("%u, %p, %u, %#x\n", devnode, buffer, len, flags);
 
-    if (!devInfo)
-    {
-        WARN("dev instance %d not found!\n", dnDevInst);
+    if (!device)
         return CR_NO_SUCH_DEVINST;
-    }
 
-    lstrcpynW(Buffer, devInfo->instanceId, BufferLen);
-    TRACE("Returning %s\n", debugstr_w(Buffer));
-    GlobalUnlock((HANDLE)dnDevInst);
+    lstrcpynW(buffer, device->instanceId, len);
+    TRACE("Returning %s\n", debugstr_w(buffer));
     return CR_SUCCESS;
 }
 
-
-
 /***********************************************************************
  *              CM_Get_Device_ID_Size  (SETUPAPI.@)
  */
-CONFIGRET WINAPI CM_Get_Device_ID_Size( PULONG  pulLen, DEVINST dnDevInst,
-                                        ULONG  ulFlags)
+CONFIGRET WINAPI CM_Get_Device_ID_Size(ULONG *len, DEVINST devnode, ULONG flags)
 {
-    struct DeviceInfo *ppdevInfo = GlobalLock((HANDLE)dnDevInst);
+    struct DeviceInfo *device = get_devnode_device(devnode);
 
-    TRACE("%x->%p, %p, %u\n", dnDevInst, ppdevInfo, pulLen, ulFlags);
+    TRACE("%p, %u, %#x\n", len, devnode, flags);
 
-    if (!ppdevInfo)
-    {
-        WARN("dev instance %d not found!\n", dnDevInst);
+    if (!device)
         return CR_NO_SUCH_DEVINST;
-    }
 
-    *pulLen = lstrlenW(ppdevInfo->instanceId);
-    GlobalUnlock((HANDLE)dnDevInst);
+    *len = lstrlenW(device->instanceId);
     return CR_SUCCESS;
 }
 
diff --git a/dlls/setupapi/setupapi_private.h b/dlls/setupapi/setupapi_private.h
index 5cdedb6..1df96b1 100644
--- a/dlls/setupapi/setupapi_private.h
+++ b/dlls/setupapi/setupapi_private.h
@@ -45,6 +45,11 @@
 
 extern HINSTANCE SETUPAPI_hInstance DECLSPEC_HIDDEN;
 
+static inline void * __WINE_ALLOC_SIZE(2) heap_realloc_zero(void *mem, size_t len)
+{
+    return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len);
+}
+
 static inline WCHAR *strdupW( const WCHAR *str )
 {
     WCHAR *ret = NULL;
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
index 420c65a..2bb8027 100644
--- a/dlls/setupapi/tests/devinst.c
+++ b/dlls/setupapi/tests/devinst.c
@@ -28,6 +28,7 @@
 #include "winreg.h"
 #include "guiddef.h"
 #include "setupapi.h"
+#include "cfgmgr32.h"
 
 #include "wine/test.h"
 
@@ -1355,6 +1356,26 @@ static void testSetupDiGetINFClassA(void)
     }
 }
 
+static void test_devnode(void)
+{
+    HDEVINFO set;
+    SP_DEVINFO_DATA device = { sizeof(SP_DEVINFO_DATA) };
+    char buffer[50];
+    DWORD ret;
+
+    set = SetupDiGetClassDevsA(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);
+    ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed: %#x\n", GetLastError());
+    ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL,
+        NULL, 0, &device);
+    ok(ret, "SetupDiCreateDeviceInfo failed: %#x\n", GetLastError());
+
+    ret = CM_Get_Device_IDA(device.DevInst, buffer, sizeof(buffer), 0);
+    ok(!ret, "got %#x\n", ret);
+    ok(!strcmp(buffer, "ROOT\\LEGACY_BOGUS\\0000"), "got %s\n", buffer);
+
+    SetupDiDestroyDeviceInfoList(set);
+}
+
 START_TEST(devinst)
 {
     HKEY hkey;
@@ -1392,4 +1413,5 @@ START_TEST(devinst)
     testDeviceRegistryPropertyA();
     testDeviceRegistryPropertyW();
     testSetupDiGetINFClassA();
+    test_devnode();
 }
-- 
2.7.4




More information about the wine-devel mailing list