mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Implement SetupDiGetDeviceInterfaceDetailA/W
svn path=/trunk/; revision=16622
This commit is contained in:
parent
ad59c91e1b
commit
6d83f83840
3 changed files with 235 additions and 111 deletions
|
@ -20,6 +20,7 @@
|
||||||
#define _INC_SETUPAPI
|
#define _INC_SETUPAPI
|
||||||
|
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
#include <pshpack1.h>
|
||||||
|
|
||||||
/* setupapi doesn't use the normal convention, it adds an underscore before A/W */
|
/* setupapi doesn't use the normal convention, it adds an underscore before A/W */
|
||||||
#ifdef __WINESRC__
|
#ifdef __WINESRC__
|
||||||
|
@ -859,4 +860,5 @@ BOOL WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID);
|
||||||
|
|
||||||
#undef DECL_WINELIB_SETUPAPI_TYPE_AW
|
#undef DECL_WINELIB_SETUPAPI_TYPE_AW
|
||||||
|
|
||||||
|
#include <poppack.h>
|
||||||
#endif /* _INC_SETUPAPI */
|
#endif /* _INC_SETUPAPI */
|
||||||
|
|
|
@ -56,6 +56,7 @@ static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l',
|
||||||
static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
|
static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
|
||||||
static const WCHAR NtExtension[] = {'.','N','T',0};
|
static const WCHAR NtExtension[] = {'.','N','T',0};
|
||||||
static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
|
static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0};
|
||||||
|
static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
|
||||||
static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
|
static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
|
||||||
static const WCHAR WinExtension[] = {'.','W','i','n',0};
|
static const WCHAR WinExtension[] = {'.','W','i','n',0};
|
||||||
|
|
||||||
|
@ -89,12 +90,16 @@ typedef struct _DeviceInfo
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
GUID InterfaceGuid;
|
GUID InterfaceGuid;
|
||||||
#ifdef __WINE__
|
|
||||||
WCHAR InterfaceName[0]; /* "COMx" */
|
|
||||||
#else
|
|
||||||
GUID ClassGuid;
|
GUID ClassGuid;
|
||||||
WCHAR DeviceInstance[0]; /* "ACPI\PNP0501\4&2658d0a0&0"..., NULL on Wine */
|
#ifndef __WINE__
|
||||||
|
/* Pointer into Data field. Contains something like */
|
||||||
|
/* "ACPI\PNP0501\4&2658d0a0&0" */
|
||||||
|
PWSTR pInstancePath;
|
||||||
#endif
|
#endif
|
||||||
|
/* Pointer into Data field. Contains something like
|
||||||
|
* "\\?\ACPI#PNP0501#4&2658d0a0&0#{GUID}", or "COMx" for WINE */
|
||||||
|
PWSTR pSymbolicLink;
|
||||||
|
WCHAR Data[0];
|
||||||
} Interface;
|
} Interface;
|
||||||
};
|
};
|
||||||
} DeviceInfo;
|
} DeviceInfo;
|
||||||
|
@ -1152,7 +1157,7 @@ static LONG SETUP_CreateSerialDeviceList(
|
||||||
|
|
||||||
if (MachineName)
|
if (MachineName)
|
||||||
WARN("'MachineName' is ignored on Wine!\n");
|
WARN("'MachineName' is ignored on Wine!\n");
|
||||||
if (DeviceInstanceW){
|
if (DeviceInstanceW)
|
||||||
WARN("'DeviceInstanceW' can't be set on Wine!\n");
|
WARN("'DeviceInstanceW' can't be set on Wine!\n");
|
||||||
|
|
||||||
devices = buf;
|
devices = buf;
|
||||||
|
@ -1187,7 +1192,7 @@ static LONG SETUP_CreateSerialDeviceList(
|
||||||
/* We have found a device */
|
/* We have found a device */
|
||||||
TRACE("Adding %s to list\n", debugstr_w(ptr));
|
TRACE("Adding %s to list\n", debugstr_w(ptr));
|
||||||
deviceInfo = HeapAlloc(GetProcessHeap(), 0,
|
deviceInfo = HeapAlloc(GetProcessHeap(), 0,
|
||||||
FIELD_OFFSET(DeviceInfo, Interface.InterfaceName) + strlenW(ptr) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
|
FIELD_OFFSET(DeviceInfo, Interface.Data) + strlenW(ptr) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
|
||||||
if (!deviceInfo)
|
if (!deviceInfo)
|
||||||
{
|
{
|
||||||
if (devices != buf)
|
if (devices != buf)
|
||||||
|
@ -1195,8 +1200,9 @@ static LONG SETUP_CreateSerialDeviceList(
|
||||||
return ERROR_NO_SYSTEM_RESOURCES;
|
return ERROR_NO_SYSTEM_RESOURCES;
|
||||||
}
|
}
|
||||||
deviceInfo->IsDevice = FALSE;
|
deviceInfo->IsDevice = FALSE;
|
||||||
|
deviceInfo->Interface.pSymbolicLink = &deviceInfo->Interface.Data[0];
|
||||||
memcpy(&deviceInfo->Interface.InterfaceGuid, InterfaceGuid, sizeof(GUID));
|
memcpy(&deviceInfo->Interface.InterfaceGuid, InterfaceGuid, sizeof(GUID));
|
||||||
wcscpy(&deviceInfo->Interface.InterfaceName[0], ptr);
|
wcscpy(deviceInfo->Interface.pSymbolicLink, ptr);
|
||||||
InsertTailList(&list->ListHead, &deviceInfo->ItemEntry);
|
InsertTailList(&list->ListHead, &deviceInfo->ItemEntry);
|
||||||
list->numberOfEntries++;
|
list->numberOfEntries++;
|
||||||
}
|
}
|
||||||
|
@ -1214,11 +1220,18 @@ static LONG SETUP_CreateInterfaceList(
|
||||||
LPGUID InterfaceGuid,
|
LPGUID InterfaceGuid,
|
||||||
PCWSTR DeviceInstanceW /* OPTIONAL */)
|
PCWSTR DeviceInstanceW /* OPTIONAL */)
|
||||||
{
|
{
|
||||||
HKEY hInterfaceKey, hEnumKey, hKey;
|
HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
|
||||||
|
HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
|
||||||
|
HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
|
||||||
|
HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
|
||||||
|
HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
|
||||||
LONG rc;
|
LONG rc;
|
||||||
WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
|
WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
|
||||||
DWORD i;
|
PWSTR InstancePath;
|
||||||
DWORD dwLength, dwRegType;
|
DWORD i, j;
|
||||||
|
DWORD dwLength, dwInstancePathLength;
|
||||||
|
DWORD dwRegType;
|
||||||
|
GUID ClassGuid;
|
||||||
DeviceInfo *deviceInfo;
|
DeviceInfo *deviceInfo;
|
||||||
|
|
||||||
/* Open registry key related to this interface */
|
/* Open registry key related to this interface */
|
||||||
|
@ -1226,7 +1239,7 @@ static LONG SETUP_CreateInterfaceList(
|
||||||
if (hInterfaceKey == INVALID_HANDLE_VALUE)
|
if (hInterfaceKey == INVALID_HANDLE_VALUE)
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
|
|
||||||
/* Enumerate sub keys */
|
/* Enumerate sub keys of hInterfaceKey */
|
||||||
i = 0;
|
i = 0;
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
@ -1242,54 +1255,52 @@ static LONG SETUP_CreateInterfaceList(
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
/* Open sub key */
|
/* Open sub key */
|
||||||
rc = RegOpenKeyEx(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hKey);
|
rc = RegOpenKeyEx(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read DeviceInstance value */
|
/* Read DeviceInstance */
|
||||||
rc = RegQueryValueExW(hKey, DeviceInstance, NULL, &dwRegType, NULL, &dwLength);
|
rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
|
||||||
if (rc != ERROR_SUCCESS )
|
if (rc != ERROR_SUCCESS )
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (dwRegType != REG_SZ)
|
if (dwRegType != REG_SZ)
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return ERROR_GEN_FAILURE;
|
return ERROR_GEN_FAILURE;
|
||||||
}
|
}
|
||||||
|
InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(UNICODE_NULL));
|
||||||
/* Allocate memory for list entry and read DeviceInstance */
|
if (!InstancePath)
|
||||||
deviceInfo = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DeviceInfo, Interface.DeviceInstance) + dwLength + sizeof(UNICODE_NULL));
|
|
||||||
if (!deviceInfo)
|
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return ERROR_NO_SYSTEM_RESOURCES;
|
return ERROR_NO_SYSTEM_RESOURCES;
|
||||||
}
|
}
|
||||||
rc = RegQueryValueExW(hKey, DeviceInstance, NULL, NULL, (LPBYTE)&deviceInfo->Interface.DeviceInstance[0], &dwLength);
|
rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
deviceInfo->Interface.DeviceInstance[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
|
InstancePath[dwInstancePathLength / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
TRACE("DeviceInstance %s\n", debugstr_w(deviceInfo->Interface.DeviceInstance));
|
TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
|
||||||
RegCloseKey(hKey);
|
|
||||||
|
|
||||||
if (DeviceInstanceW)
|
if (DeviceInstanceW)
|
||||||
{
|
{
|
||||||
/* Check if device enumerator is not the right one */
|
/* Check if device enumerator is not the right one */
|
||||||
if (wcscmp(DeviceInstanceW, deviceInfo->Interface.DeviceInstance) != 0)
|
if (wcscmp(DeviceInstanceW, InstancePath) != 0)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);;
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1303,58 +1314,133 @@ static LONG SETUP_CreateInterfaceList(
|
||||||
&hEnumKey);
|
&hEnumKey);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
rc = RegOpenKeyEx(
|
rc = RegOpenKeyEx(
|
||||||
hEnumKey,
|
hEnumKey,
|
||||||
deviceInfo->Interface.DeviceInstance,
|
InstancePath,
|
||||||
0, /* Options */
|
0, /* Options */
|
||||||
KEY_QUERY_VALUE,
|
KEY_QUERY_VALUE,
|
||||||
&hKey);
|
&hKey);
|
||||||
RegCloseKey(hEnumKey);
|
RegCloseKey(hEnumKey);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
dwLength = sizeof(KeyBuffer) - sizeof(UNICODE_NULL);
|
dwLength = sizeof(KeyBuffer) - sizeof(UNICODE_NULL);
|
||||||
rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
|
rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
|
||||||
|
RegCloseKey(hKey);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
KeyBuffer[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
|
KeyBuffer[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
RegCloseKey(hKey);
|
|
||||||
KeyBuffer[37] = UNICODE_NULL; /* Replace the } by a NULL character */
|
KeyBuffer[37] = UNICODE_NULL; /* Replace the } by a NULL character */
|
||||||
if (UuidFromStringW(&KeyBuffer[1], &deviceInfo->Interface.ClassGuid) != RPC_S_OK)
|
if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
return ERROR_GEN_FAILURE;
|
return ERROR_GEN_FAILURE;
|
||||||
}
|
}
|
||||||
TRACE("ClassGUID %s\n", debugstr_guid(&deviceInfo->Interface.ClassGuid));
|
TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
|
||||||
|
|
||||||
/* If current device matches the list GUID (if any), append the entry to the list */
|
/* If current device doesn't match the list GUID (if any), skip this entry */
|
||||||
if (IsEqualIID(&list->ClassGuid, &GUID_NULL) || IsEqualIID(&list->ClassGuid, &deviceInfo->Interface.ClassGuid))
|
if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
|
||||||
{
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
|
||||||
|
j = 0;
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
|
||||||
|
rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
|
||||||
|
if (rc == ERROR_NO_MORE_ITEMS)
|
||||||
|
break;
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, InstancePath);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
if (KeyBuffer[0] != '#')
|
||||||
|
/* This entry doesn't represent an interesting entry */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Open sub key */
|
||||||
|
rc = RegOpenKeyEx(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read SymbolicLink value */
|
||||||
|
rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
|
||||||
|
if (rc != ERROR_SUCCESS )
|
||||||
|
{
|
||||||
|
RegCloseKey(hReferenceKey);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (dwRegType != REG_SZ)
|
||||||
|
{
|
||||||
|
RegCloseKey(hReferenceKey);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
|
return ERROR_GEN_FAILURE;
|
||||||
|
}
|
||||||
|
deviceInfo = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(DeviceInfo, Interface.Data) + dwInstancePathLength + sizeof(UNICODE_NULL) + dwLength + sizeof(UNICODE_NULL));
|
||||||
|
if (!deviceInfo)
|
||||||
|
{
|
||||||
|
RegCloseKey(hReferenceKey);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
|
return ERROR_NO_SYSTEM_RESOURCES;
|
||||||
|
}
|
||||||
|
deviceInfo->Interface.pInstancePath = &deviceInfo->Interface.Data[0];
|
||||||
|
deviceInfo->Interface.pSymbolicLink = &deviceInfo->Interface.Data[dwInstancePathLength + 1];
|
||||||
|
rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)deviceInfo->Interface.pSymbolicLink, &dwLength);
|
||||||
|
RegCloseKey(hReferenceKey);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
||||||
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
|
RegCloseKey(hInterfaceKey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
deviceInfo->Interface.pSymbolicLink[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
TRACE("Symbolic link %s\n", debugstr_w(deviceInfo->Interface.pSymbolicLink));
|
||||||
|
|
||||||
|
/* Add this entry to the list */
|
||||||
TRACE("Entry found\n");
|
TRACE("Entry found\n");
|
||||||
deviceInfo->IsDevice = FALSE;
|
deviceInfo->IsDevice = FALSE;
|
||||||
memcpy(
|
memcpy(
|
||||||
&deviceInfo->Interface.InterfaceGuid,
|
&deviceInfo->Interface.InterfaceGuid,
|
||||||
InterfaceGuid,
|
InterfaceGuid,
|
||||||
sizeof(deviceInfo->Interface.InterfaceGuid));
|
sizeof(deviceInfo->Interface.InterfaceGuid));
|
||||||
|
wcscpy(deviceInfo->Interface.pInstancePath, InstancePath);
|
||||||
InsertTailList(&list->ListHead, &deviceInfo->ItemEntry);
|
InsertTailList(&list->ListHead, &deviceInfo->ItemEntry);
|
||||||
list->numberOfEntries++;
|
list->numberOfEntries++;
|
||||||
}
|
}
|
||||||
else
|
RegCloseKey(hDeviceInstanceKey);
|
||||||
{
|
|
||||||
HeapFree(GetProcessHeap(), 0, deviceInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RegCloseKey(hInterfaceKey);
|
RegCloseKey(hInterfaceKey);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
@ -1555,11 +1641,7 @@ BOOL WINAPI SetupDiEnumDeviceInterfaces(
|
||||||
* expected lifetime of the device data is the same as the
|
* expected lifetime of the device data is the same as the
|
||||||
* HDEVINFO; once that is closed, the data are no longer valid.
|
* HDEVINFO; once that is closed, the data are no longer valid.
|
||||||
*/
|
*/
|
||||||
#ifdef __WINE__
|
|
||||||
DeviceInterfaceData->Reserved = (ULONG_PTR)DevInfo->Interface.InterfaceName;
|
|
||||||
#else
|
|
||||||
DeviceInterfaceData->Reserved = (ULONG_PTR)DevInfo;
|
DeviceInterfaceData->Reserved = (ULONG_PTR)DevInfo;
|
||||||
#endif
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1619,70 +1701,61 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
|
||||||
PDWORD RequiredSize,
|
PDWORD RequiredSize,
|
||||||
PSP_DEVINFO_DATA DeviceInfoData)
|
PSP_DEVINFO_DATA DeviceInfoData)
|
||||||
{
|
{
|
||||||
|
PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
|
||||||
|
DWORD sizeW = 0, sizeA;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
|
TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
|
||||||
DeviceInterfaceData, DeviceInterfaceDetailData,
|
DeviceInterfaceData, DeviceInterfaceDetailData,
|
||||||
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
|
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
|
||||||
if (!DeviceInterfaceData)
|
|
||||||
|
if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
|
||||||
|
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||||
|
else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) ||
|
else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
|
||||||
(DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize))
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
DeviceInfoList *list = (DeviceInfoList *)DeviceInfoSet;
|
|
||||||
|
|
||||||
if (list->magic == SETUP_DEV_INFO_LIST_MAGIC)
|
|
||||||
{
|
|
||||||
#ifdef __WINE__
|
|
||||||
/* FIXME: this assumes the only possible enumeration is of serial
|
|
||||||
* ports.
|
|
||||||
*/
|
|
||||||
LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved;
|
|
||||||
DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) +
|
|
||||||
lstrlenW(devName);
|
|
||||||
|
|
||||||
if (sizeRequired > DeviceInterfaceDetailDataSize)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
||||||
if (RequiredSize)
|
|
||||||
*RequiredSize = sizeRequired;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LPSTR dst = DeviceInterfaceDetailData->DevicePath;
|
|
||||||
LPCWSTR src = devName;
|
|
||||||
|
|
||||||
/* MSDN claims cbSize must be set by the caller, but it lies */
|
|
||||||
DeviceInterfaceDetailData->cbSize =
|
|
||||||
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
|
||||||
for ( ; *src; src++, dst++)
|
|
||||||
*dst = *src;
|
|
||||||
*dst = '\0';
|
|
||||||
TRACE("DevicePath is %s\n",
|
|
||||||
debugstr_a(DeviceInterfaceDetailData->DevicePath));
|
|
||||||
if (DeviceInfoData)
|
|
||||||
{
|
|
||||||
DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
|
|
||||||
memcpy(&DeviceInfoData->ClassGuid,
|
|
||||||
&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
|
|
||||||
sizeof(DeviceInfoData->ClassGuid));
|
|
||||||
DeviceInfoData->DevInst = 0;
|
|
||||||
DeviceInfoData->Reserved = (ULONG_PTR)devName;
|
|
||||||
}
|
|
||||||
ret = TRUE;
|
|
||||||
}
|
|
||||||
#else /* __WINE__ */
|
|
||||||
FIXME("unimplemented\n");
|
|
||||||
ret = FALSE;
|
|
||||||
#endif /* __WINE__ */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
{
|
||||||
|
if (DeviceInterfaceDetailData != NULL)
|
||||||
|
{
|
||||||
|
sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
|
||||||
|
+ (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
|
||||||
|
DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
|
||||||
|
if (!DeviceInterfaceDetailDataW)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
|
||||||
|
{
|
||||||
|
DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
|
||||||
|
ret = SetupDiGetDeviceInterfaceDetailW(
|
||||||
|
DeviceInfoSet,
|
||||||
|
DeviceInterfaceData,
|
||||||
|
DeviceInterfaceDetailDataW,
|
||||||
|
sizeW,
|
||||||
|
&sizeW,
|
||||||
|
DeviceInfoData);
|
||||||
|
sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
|
||||||
|
+ FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
|
||||||
|
if (RequiredSize)
|
||||||
|
*RequiredSize = sizeA;
|
||||||
|
if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
|
||||||
|
{
|
||||||
|
if (!WideCharToMultiByte(
|
||||||
|
CP_ACP, 0,
|
||||||
|
DeviceInterfaceDetailDataW->DevicePath, -1,
|
||||||
|
DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
|
||||||
|
NULL, NULL))
|
||||||
|
{
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("Returning %d\n", ret);
|
TRACE("Returning %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1698,10 +1771,59 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
|
||||||
PDWORD RequiredSize,
|
PDWORD RequiredSize,
|
||||||
PSP_DEVINFO_DATA DeviceInfoData)
|
PSP_DEVINFO_DATA DeviceInfoData)
|
||||||
{
|
{
|
||||||
FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
|
BOOL ret = FALSE;
|
||||||
DeviceInterfaceData, DeviceInterfaceDetailData,
|
|
||||||
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
|
TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
|
||||||
return FALSE;
|
DeviceInterfaceData, DeviceInterfaceDetailData,
|
||||||
|
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
|
||||||
|
|
||||||
|
if (!DeviceInfoSet || !DeviceInterfaceData)
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
|
||||||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
else if (((DeviceInfoList*)DeviceInfoSet)->magic != SETUP_DEV_INFO_LIST_MAGIC)
|
||||||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
|
||||||
|
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||||
|
else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
|
||||||
|
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||||
|
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
|
||||||
|
SetLastError(ERROR_INVALID_USER_BUFFER);
|
||||||
|
else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(UNICODE_NULL))
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeviceInfo *deviceInfo = (DeviceInfo *)DeviceInterfaceData->Reserved;
|
||||||
|
LPCWSTR devName = deviceInfo->Interface.pSymbolicLink;
|
||||||
|
DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
|
||||||
|
lstrlenW(devName);
|
||||||
|
|
||||||
|
if (sizeRequired > DeviceInterfaceDetailDataSize)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
if (RequiredSize)
|
||||||
|
*RequiredSize = sizeRequired;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wcscpy(DeviceInterfaceDetailData->DevicePath, devName);
|
||||||
|
TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
|
||||||
|
if (DeviceInfoData)
|
||||||
|
{
|
||||||
|
memcpy(&DeviceInfoData->ClassGuid,
|
||||||
|
&deviceInfo->Interface.ClassGuid,
|
||||||
|
sizeof(GUID));
|
||||||
|
DeviceInfoData->DevInst = 0; /* FIXME */
|
||||||
|
DeviceInfoData->Reserved = (ULONG_PTR)0;
|
||||||
|
}
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -327,7 +327,7 @@
|
||||||
@ stub SetupDiGetDeviceInstanceIdA
|
@ stub SetupDiGetDeviceInstanceIdA
|
||||||
@ stub SetupDiGetDeviceInstanceIdW
|
@ stub SetupDiGetDeviceInstanceIdW
|
||||||
@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr)
|
@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr)
|
||||||
@ stub SetupDiGetDeviceRegistryPropertyW
|
@ stdcall SetupDiGetDeviceRegistryPropertyW(long ptr long ptr ptr long ptr)
|
||||||
@ stub SetupDiGetDriverInfoDetailA
|
@ stub SetupDiGetDriverInfoDetailA
|
||||||
@ stub SetupDiGetDriverInfoDetailW
|
@ stub SetupDiGetDriverInfoDetailW
|
||||||
@ stub SetupDiGetDriverInstallParamsA
|
@ stub SetupDiGetDriverInstallParamsA
|
||||||
|
|
Loading…
Reference in a new issue