Commit df3cb063 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

setupapi: Create symbolic link value when interface is created.

parent d34ec8b8
...@@ -129,6 +129,18 @@ struct DeviceInfo ...@@ -129,6 +129,18 @@ struct DeviceInfo
struct InterfaceInstances *interfaces; struct InterfaceInstances *interfaces;
}; };
static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
{
static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
'%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
'0','2','X','}',0};
sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances) static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
{ {
DWORD i; DWORD i;
...@@ -205,6 +217,41 @@ static BOOL SETUPDI_FindInterfaceInstance( ...@@ -205,6 +217,41 @@ static BOOL SETUPDI_FindInterfaceInstance(
return found; return found;
} }
static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
{
static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
WCHAR guidStr[39];
DWORD len;
LPWSTR ret;
SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
/* omit length of format specifiers, but include NULL terminator: */
len = lstrlenW(fmt) - 4 + 1;
len += lstrlenW(instanceId) + lstrlenW(guidStr);
if (ReferenceString)
{
/* space for a hash between string and reference string: */
len += lstrlenW(ReferenceString) + 1;
}
ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (ret)
{
int printed = sprintfW(ret, fmt, instanceId, guidStr);
LPWSTR ptr;
/* replace '\\' with '#' after the "\\\\?\\" beginning */
for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
*ptr = '#';
if (ReferenceString)
{
ret[printed - 1] = '\\';
lstrcpyW(ret + printed, ReferenceString);
}
}
return ret;
}
/* Adds an interface with the given interface class and reference string to /* Adds an interface with the given interface class and reference string to
* the device, if it doesn't already exist in the device. If iface is not * the device, if it doesn't already exist in the device. If iface is not
* NULL, returns a pointer to the newly added (or already existing) interface. * NULL, returns a pointer to the newly added (or already existing) interface.
...@@ -285,7 +332,9 @@ static BOOL SETUPDI_AddInterfaceInstance(struct DeviceInfo *devInfo, ...@@ -285,7 +332,9 @@ static BOOL SETUPDI_AddInterfaceInstance(struct DeviceInfo *devInfo,
if (ifaceInfo) if (ifaceInfo)
{ {
ret = TRUE; ret = TRUE;
ifaceInfo->symbolicLink = NULL; ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
devInfo->instanceId, InterfaceClassGuid,
ReferenceString);
if (ReferenceString) if (ReferenceString)
{ {
ifaceInfo->referenceString = ifaceInfo->referenceString =
...@@ -425,18 +474,6 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo) ...@@ -425,18 +474,6 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
HeapFree(GetProcessHeap(), 0, devInfo); HeapFree(GetProcessHeap(), 0, devInfo);
} }
static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
{
static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
'%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
'0','2','X','}',0};
sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
/* Adds a device with GUID guid and identifer devInst to set. Allocates a /* Adds a device with GUID guid and identifer devInst to set. Allocates a
* struct DeviceInfo, and points the returned device info's Reserved member * struct DeviceInfo, and points the returned device info's Reserved member
* to it. "Phantom" devices are deleted from the registry when closed. * to it. "Phantom" devices are deleted from the registry when closed.
......
...@@ -482,7 +482,6 @@ static void testGetDeviceInterfaceDetail(void) ...@@ -482,7 +482,6 @@ static void testGetDeviceInterfaceDetail(void)
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
size, &size, NULL); size, &size, NULL);
todo_wine
ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
"Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
...@@ -490,7 +489,6 @@ static void testGetDeviceInterfaceDetail(void) ...@@ -490,7 +489,6 @@ static void testGetDeviceInterfaceDetail(void)
size, &size, NULL); size, &size, NULL);
ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n", ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
GetLastError()); GetLastError());
todo_wine
ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n", ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
detail->DevicePath); detail->DevicePath);
HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, buf);
......
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