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 @@
#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;
}
......
......@@ -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;
......
......@@ -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();
}
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