Commit f840bcc6 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

setupapi: Use a handle table to allocate device nodes.

The size of DEVINST is DWORD, so using the pointer directly won't work on 64-bit. Signed-off-by: 's avatarZebediah Figura <z.figura12@gmail.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent a3cedc1f
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "winnls.h" #include "winnls.h"
#include "setupapi.h" #include "setupapi.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/heap.h"
#include "wine/list.h" #include "wine/list.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "cfgmgr32.h" #include "cfgmgr32.h"
...@@ -140,6 +141,52 @@ struct DeviceInfo ...@@ -140,6 +141,52 @@ struct DeviceInfo
struct list interfaces; 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 void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
{ {
static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-', static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
...@@ -460,15 +507,12 @@ static HKEY SETUPDI_CreateDrvKey(struct DeviceInfo *devInfo) ...@@ -460,15 +507,12 @@ static HKEY SETUPDI_CreateDrvKey(struct DeviceInfo *devInfo)
static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set, static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
DWORD devId, LPCWSTR instanceId, BOOL phantom) DWORD devId, LPCWSTR instanceId, BOOL phantom)
{ {
struct DeviceInfo *devInfo = NULL; struct DeviceInfo *devInfo = heap_alloc(sizeof(*devInfo));
HANDLE devInst = GlobalAlloc(GMEM_FIXED, sizeof(struct DeviceInfo));
if (devInst)
devInfo = GlobalLock(devInst);
if (devInfo) if (devInfo)
{ {
devInfo->set = set; devInfo->set = set;
devInfo->devId = (DWORD)devInst; devInfo->devId = alloc_devnode(devInfo);
devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0, devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
(lstrlenW(instanceId) + 1) * sizeof(WCHAR)); (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
...@@ -486,12 +530,10 @@ static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set, ...@@ -486,12 +530,10 @@ static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
(LPBYTE)&phantom, sizeof(phantom)); (LPBYTE)&phantom, sizeof(phantom));
} }
list_init(&devInfo->interfaces); list_init(&devInfo->interfaces);
GlobalUnlock(devInst);
} }
else else
{ {
GlobalUnlock(devInst); heap_free(devInfo);
GlobalFree(devInst);
devInfo = NULL; devInfo = NULL;
} }
} }
...@@ -525,7 +567,8 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo) ...@@ -525,7 +567,8 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
SETUPDI_FreeInterfaceInstances(iface); SETUPDI_FreeInterfaceInstances(iface);
HeapFree(GetProcessHeap(), 0, 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 /* Adds a device with GUID guid and identifier devInst to set. Allocates a
...@@ -3979,63 +4022,50 @@ BOOL WINAPI SetupDiDeleteDevRegKey( ...@@ -3979,63 +4022,50 @@ BOOL WINAPI SetupDiDeleteDevRegKey(
/*********************************************************************** /***********************************************************************
* CM_Get_Device_IDA (SETUPAPI.@) * CM_Get_Device_IDA (SETUPAPI.@)
*/ */
CONFIGRET WINAPI CM_Get_Device_IDA( DEVINST dnDevInst, PSTR Buffer, CONFIGRET WINAPI CM_Get_Device_IDA(DEVINST devnode, char *buffer, ULONG len, ULONG flags)
ULONG BufferLen, ULONG ulFlags)
{ {
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; return CR_NO_SUCH_DEVINST;
WideCharToMultiByte(CP_ACP, 0, devInfo->instanceId, -1, Buffer, BufferLen, 0, 0); WideCharToMultiByte(CP_ACP, 0, device->instanceId, -1, buffer, len, 0, 0);
TRACE("Returning %s\n", debugstr_a(Buffer)); TRACE("Returning %s\n", debugstr_a(buffer));
return CR_SUCCESS; return CR_SUCCESS;
} }
/*********************************************************************** /***********************************************************************
* CM_Get_Device_IDW (SETUPAPI.@) * CM_Get_Device_IDW (SETUPAPI.@)
*/ */
CONFIGRET WINAPI CM_Get_Device_IDW( DEVINST dnDevInst, LPWSTR Buffer, CONFIGRET WINAPI CM_Get_Device_IDW(DEVINST devnode, WCHAR *buffer, ULONG len, ULONG flags)
ULONG BufferLen, ULONG ulFlags)
{ {
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)
{
WARN("dev instance %d not found!\n", dnDevInst);
return CR_NO_SUCH_DEVINST; return CR_NO_SUCH_DEVINST;
}
lstrcpynW(Buffer, devInfo->instanceId, BufferLen); lstrcpynW(buffer, device->instanceId, len);
TRACE("Returning %s\n", debugstr_w(Buffer)); TRACE("Returning %s\n", debugstr_w(buffer));
GlobalUnlock((HANDLE)dnDevInst);
return CR_SUCCESS; return CR_SUCCESS;
} }
/*********************************************************************** /***********************************************************************
* CM_Get_Device_ID_Size (SETUPAPI.@) * CM_Get_Device_ID_Size (SETUPAPI.@)
*/ */
CONFIGRET WINAPI CM_Get_Device_ID_Size( PULONG pulLen, DEVINST dnDevInst, CONFIGRET WINAPI CM_Get_Device_ID_Size(ULONG *len, DEVINST devnode, ULONG flags)
ULONG ulFlags)
{ {
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) if (!device)
{
WARN("dev instance %d not found!\n", dnDevInst);
return CR_NO_SUCH_DEVINST; return CR_NO_SUCH_DEVINST;
}
*pulLen = lstrlenW(ppdevInfo->instanceId); *len = lstrlenW(device->instanceId);
GlobalUnlock((HANDLE)dnDevInst);
return CR_SUCCESS; return CR_SUCCESS;
} }
......
...@@ -45,6 +45,11 @@ ...@@ -45,6 +45,11 @@
extern HINSTANCE SETUPAPI_hInstance DECLSPEC_HIDDEN; 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 ) static inline WCHAR *strdupW( const WCHAR *str )
{ {
WCHAR *ret = NULL; WCHAR *ret = NULL;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "winreg.h" #include "winreg.h"
#include "guiddef.h" #include "guiddef.h"
#include "setupapi.h" #include "setupapi.h"
#include "cfgmgr32.h"
#include "wine/test.h" #include "wine/test.h"
...@@ -1355,6 +1356,26 @@ static void testSetupDiGetINFClassA(void) ...@@ -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) START_TEST(devinst)
{ {
HKEY hkey; HKEY hkey;
...@@ -1392,4 +1413,5 @@ START_TEST(devinst) ...@@ -1392,4 +1413,5 @@ START_TEST(devinst)
testDeviceRegistryPropertyA(); testDeviceRegistryPropertyA();
testDeviceRegistryPropertyW(); testDeviceRegistryPropertyW();
testSetupDiGetINFClassA(); testSetupDiGetINFClassA();
test_devnode();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment