setupapi: Avoid unnecessary buffer allocation in SetupDiCreateDeviceInfoW().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2018-11-27 19:55:37 -06:00 committed by Alexandre Julliard
parent 81d2b419b8
commit 462c74bcdb

View File

@ -1394,19 +1394,18 @@ static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
/*********************************************************************** /***********************************************************************
* SetupDiCreateDeviceInfoW (SETUPAPI.@) * SetupDiCreateDeviceInfoW (SETUPAPI.@)
*/ */
BOOL WINAPI SetupDiCreateDeviceInfoW(HDEVINFO devinfo, PCWSTR DeviceName, BOOL WINAPI SetupDiCreateDeviceInfoW(HDEVINFO devinfo, const WCHAR *name, const GUID *class,
const GUID *ClassGuid, PCWSTR DeviceDescription, HWND hwndParent, DWORD CreationFlags, const WCHAR *description, HWND parent, DWORD flags, SP_DEVINFO_DATA *device_data)
SP_DEVINFO_DATA *device_data)
{ {
WCHAR id[MAX_DEVICE_ID_LEN];
struct DeviceInfoSet *set; struct DeviceInfoSet *set;
BOOL ret = FALSE, allocatedInstanceId = FALSE; struct device *device;
LPCWSTR instanceId = NULL;
TRACE("devinfo %p, name %s, class %s, description %s, hwnd %p, flags %#x, device_data %p.\n", TRACE("devinfo %p, name %s, class %s, description %s, hwnd %p, flags %#x, device_data %p.\n",
devinfo, debugstr_w(DeviceName), debugstr_guid(ClassGuid), debugstr_w(DeviceDescription), devinfo, debugstr_w(name), debugstr_guid(class), debugstr_w(description),
hwndParent, CreationFlags, device_data); parent, flags, device_data);
if (!DeviceName || strlenW(DeviceName) >= MAX_DEVICE_ID_LEN) if (!name || strlenW(name) >= MAX_DEVICE_ID_LEN)
{ {
SetLastError(ERROR_INVALID_DEVINST_NAME); SetLastError(ERROR_INVALID_DEVINST_NAME);
return FALSE; return FALSE;
@ -1415,32 +1414,31 @@ BOOL WINAPI SetupDiCreateDeviceInfoW(HDEVINFO devinfo, PCWSTR DeviceName,
if (!(set = get_device_set(devinfo))) if (!(set = get_device_set(devinfo)))
return FALSE; return FALSE;
if (!ClassGuid) if (!class)
{ {
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) && if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) && !IsEqualGUID(class, &set->ClassGuid))
!IsEqualGUID(ClassGuid, &set->ClassGuid))
{ {
SetLastError(ERROR_CLASS_MISMATCH); SetLastError(ERROR_CLASS_MISMATCH);
return FALSE; return FALSE;
} }
if ((CreationFlags & DICD_GENERATE_ID)) if ((flags & DICD_GENERATE_ID))
{ {
if (strchrW(DeviceName, '\\')) static const WCHAR formatW[] = {'R','O','O','T','\\','%','s','\\','%','0','4','d',0};
SetLastError(ERROR_INVALID_DEVINST_NAME);
else
{
static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
'\\','%','0','4','d',0};
DWORD devId; DWORD devId;
if (strchrW(name, '\\'))
{
SetLastError(ERROR_INVALID_DEVINST_NAME);
return FALSE;
}
if (set->cDevices) if (set->cDevices)
{ {
DWORD highestDevID = 0; DWORD highestDevID = 0;
struct device *device;
LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry) LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry)
{ {
@ -1459,61 +1457,47 @@ BOOL WINAPI SetupDiCreateDeviceInfoW(HDEVINFO devinfo, PCWSTR DeviceName,
} }
else else
devId = 0; devId = 0;
/* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
instanceId = HeapAlloc(GetProcessHeap(), 0,
(17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
if (instanceId)
{
sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
devId);
allocatedInstanceId = TRUE;
ret = TRUE;
}
else
ret = FALSE;
}
}
else
{
struct device *device;
ret = TRUE; if (snprintfW(id, ARRAY_SIZE(id), formatW, name, devId) == -1)
instanceId = DeviceName; {
SetLastError(ERROR_INVALID_DEVINST_NAME);
return FALSE;
}
}
else
{
strcpyW(id, name);
LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry) LIST_FOR_EACH_ENTRY(device, &set->devices, struct device, entry)
{ {
if (!lstrcmpiW(DeviceName, device->instanceId)) if (!lstrcmpiW(name, device->instanceId))
{ {
SetLastError(ERROR_DEVINST_ALREADY_EXISTS); SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
ret = FALSE; return FALSE;
} }
} }
} }
if (ret)
{
struct device *device = NULL;
if ((device = SETUPDI_CreateDeviceInfo(set, ClassGuid, instanceId, TRUE))) if (!(device = SETUPDI_CreateDeviceInfo(set, class, id, TRUE)))
return FALSE;
if (description)
{ {
if (DeviceDescription)
SETUPDI_SetDeviceRegistryPropertyW(device, SPDRP_DEVICEDESC, SETUPDI_SetDeviceRegistryPropertyW(device, SPDRP_DEVICEDESC,
(const BYTE *)DeviceDescription, (const BYTE *)description, lstrlenW(description) * sizeof(WCHAR));
lstrlenW(DeviceDescription) * sizeof(WCHAR)); }
if (device_data) if (device_data)
{ {
if (device_data->cbSize != sizeof(SP_DEVINFO_DATA)) if (device_data->cbSize != sizeof(SP_DEVINFO_DATA))
{ {
SetLastError(ERROR_INVALID_USER_BUFFER); SetLastError(ERROR_INVALID_USER_BUFFER);
ret = FALSE; return FALSE;
} }
else else
copy_device_data(device_data, device); copy_device_data(device_data, device);
} }
}
}
if (allocatedInstanceId)
HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
return ret; return TRUE;
} }
/*********************************************************************** /***********************************************************************