[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