{
switch (cr)
{
- case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
- case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
- case CR_SUCCESS: return ERROR_SUCCESS;
- default:
- /* FIXME */
- return ERROR_GEN_FAILURE;
+ case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
+ case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
+ case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
+ case CR_FAILURE: return ERROR_GEN_FAILURE;
+ case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
+ case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
+ case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
+ case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
+ case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
+ case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
+ case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
+ case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
+ case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
+ case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
+ case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
+ case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
+ case CR_SUCCESS: return ERROR_SUCCESS;
+ default: return ERROR_GEN_FAILURE;
}
/* Does not happen */
}
deviceInterface->DeviceInfo = deviceInfo;
strcpyW(deviceInterface->SymbolicLink, SymbolicLink);
- deviceInterface->Flags = 0; /* FIXME */
+ deviceInterface->Flags = 0; /* Flags will be updated later */
memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
*pDeviceInterface = deviceInterface;
}
}
+static BOOL DestroyDeviceInterface(struct DeviceInterface* deviceInterface)
+{
+ HeapFree(GetProcessHeap(), 0, deviceInterface);
+ return TRUE;
+}
+
static LONG SETUP_CreateInterfaceList(
struct DeviceInfoSet *list,
PCWSTR MachineName,
LPGUID InterfaceGuid,
- PCWSTR DeviceInstanceW /* OPTIONAL */)
+ PCWSTR DeviceInstanceW /* OPTIONAL */,
+ BOOL OnlyPresentInterfaces
+ )
{
HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
LONG rc;
WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
- PWSTR InstancePath;
+ PWSTR pSymbolicLink = NULL;
+ PWSTR InstancePath = NULL;
DWORD i, j;
DWORD dwLength, dwInstancePathLength;
DWORD dwRegType;
GUID ClassGuid;
struct DeviceInfoElement *deviceInfo;
+ hInterfaceKey = INVALID_HANDLE_VALUE;
+ hDeviceInstanceKey = INVALID_HANDLE_VALUE;
+
/* Open registry key related to this interface */
hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
if (hInterfaceKey == INVALID_HANDLE_VALUE)
- return GetLastError();
+ {
+ rc = GetLastError();
+ goto cleanup;
+ }
/* Enumerate sub keys of hInterfaceKey */
i = 0;
if (rc == ERROR_NO_MORE_ITEMS)
break;
if (rc != ERROR_SUCCESS)
- {
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
i++;
/* Open sub key */
+ if (hDeviceInstanceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hDeviceInstanceKey);
rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
if (rc != ERROR_SUCCESS)
- {
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
/* Read DeviceInstance */
rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
- if (rc != ERROR_SUCCESS )
- {
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ if (rc != ERROR_SUCCESS)
+ goto cleanup;
if (dwRegType != REG_SZ)
{
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return ERROR_GEN_FAILURE;
+ rc = ERROR_GEN_FAILURE;
+ goto cleanup;
}
+ if (InstancePath != NULL)
+ HeapFree(GetProcessHeap(), 0, InstancePath);
InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
if (!InstancePath)
{
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return ERROR_NOT_ENOUGH_MEMORY;
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
}
rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
if (rc != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
{
/* Check if device enumerator is not the right one */
if (strcmpW(DeviceInstanceW, InstancePath) != 0)
- {
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
continue;
- }
}
/* Find class GUID associated to the device instance */
0,
&hEnumKey);
if (rc != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
rc = RegOpenKeyExW(
hEnumKey,
InstancePath,
&hKey);
RegCloseKey(hEnumKey);
if (rc != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
RegCloseKey(hKey);
if (rc != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
{
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return ERROR_GEN_FAILURE;
+ rc = ERROR_GEN_FAILURE;
+ goto cleanup;
}
TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
/* If current device doesn't match the list GUID (if any), skip this entry */
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)
{
- LPWSTR pSymbolicLink;
struct DeviceInterface *interfaceInfo;
dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
if (rc == ERROR_NO_MORE_ITEMS)
break;
if (rc != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, InstancePath);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
j++;
if (KeyBuffer[0] != '#')
/* This entry doesn't represent an interesting entry */
continue;
/* Open sub key */
+ if (hReferenceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hReferenceKey);
rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
if (rc != ERROR_SUCCESS)
- {
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
/* Read SymbolicLink value */
rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
if (rc != ERROR_SUCCESS )
- {
- RegCloseKey(hReferenceKey);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
if (dwRegType != REG_SZ)
{
- RegCloseKey(hReferenceKey);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return ERROR_GEN_FAILURE;
+ rc = ERROR_GEN_FAILURE;
+ goto cleanup;
}
/* We have found a device */
/* Step 1. Create a device info element */
if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
{
- RegCloseKey(hReferenceKey);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return GetLastError();
+ rc = GetLastError();
+ goto cleanup;
}
TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
/* Step 2. Create an interface list for this element */
+ if (pSymbolicLink != NULL)
+ HeapFree(GetProcessHeap(), 0, pSymbolicLink);
pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1) * sizeof(WCHAR));
if (!pSymbolicLink)
{
- RegCloseKey(hReferenceKey);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return ERROR_NOT_ENOUGH_MEMORY;
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
}
rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
RegCloseKey(hReferenceKey);
if (rc != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, pSymbolicLink);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return rc;
- }
+ goto cleanup;
if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
{
- HeapFree(GetProcessHeap(), 0, pSymbolicLink);
- RegCloseKey(hDeviceInstanceKey);
- RegCloseKey(hInterfaceKey);
- return GetLastError();
+ rc = GetLastError();
+ goto cleanup;
}
/* Step 3. Update flags */
if (KeyBuffer[1] == '\0')
interfaceInfo->Flags |= SPINT_DEFAULT;
rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey);
- if (!rc)
- interfaceInfo->Flags |= SPINT_REMOVED;
+ if (rc != ERROR_SUCCESS)
+ {
+ if (OnlyPresentInterfaces)
+ {
+ DestroyDeviceInterface(interfaceInfo);
+ continue;
+ }
+ else
+ interfaceInfo->Flags |= SPINT_REMOVED;
+ }
else
{
dwLength = sizeof(DWORD);
}
TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
- HeapFree(GetProcessHeap(), 0, pSymbolicLink);
InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
}
- RegCloseKey(hDeviceInstanceKey);
}
- RegCloseKey(hInterfaceKey);
- return ERROR_SUCCESS;
+ rc = ERROR_SUCCESS;
+
+cleanup:
+ if (hReferenceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hReferenceKey);
+ if (hDeviceInstanceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hDeviceInstanceKey);
+ if (hInterfaceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hInterfaceKey);
+ if (InstancePath != NULL)
+ HeapFree(GetProcessHeap(), 0, InstancePath);
+ if (pSymbolicLink != NULL)
+ HeapFree(GetProcessHeap(), 0, pSymbolicLink);
+ return rc;
}
/***********************************************************************
else
pClassGuid = &list->ClassGuid;
- if (flags & DIGCF_PRESENT)
- FIXME(": flag DIGCF_PRESENT ignored\n");
if (flags & DIGCF_PROFILE)
FIXME(": flag DIGCF_PROFILE ignored\n");
return INVALID_HANDLE_VALUE;
}
- rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr);
+ rc = SETUP_CreateInterfaceList(list, machine, (LPGUID)class, enumstr, flags & DIGCF_PRESENT);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
list->MachineName = NULL;
}
- ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
+ ClassImageListData->Reserved = (ULONG_PTR)list;
ret = TRUE;
cleanup:
{
PLIST_ENTRY ListEntry;
struct DriverInfoElement *driverInfo;
+ struct DeviceInterface *deviceInterface;
while (!IsListEmpty(&deviceInfo->DriverListHead))
{
ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
- driverInfo = (struct DriverInfoElement *)ListEntry;
+ driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
if (!DestroyDriverInfoElement(driverInfo))
return FALSE;
}
while (!IsListEmpty(&deviceInfo->InterfaceListHead))
{
ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
- HeapFree(GetProcessHeap(), 0, ListEntry);
+ deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
+ if (!DestroyDeviceInterface(deviceInterface))
+ return FALSE;
}
DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
HeapFree(GetProcessHeap(), 0, deviceInfo);
return ret;
}
+static BOOL
+GetHardwareAndCompatibleIDsLists(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData,
+ OUT LPWSTR *pHardwareIDs OPTIONAL,
+ OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL,
+ OUT LPWSTR *pCompatibleIDs OPTIONAL,
+ OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL)
+{
+ LPWSTR HardwareIDs = NULL;
+ LPWSTR CompatibleIDs = NULL;
+ DWORD RequiredSize;
+ BOOL Result;
+
+ /* Get hardware IDs list */
+ Result = FALSE;
+ RequiredSize = 512; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ MyFree(HardwareIDs);
+ HardwareIDs = MyMalloc(RequiredSize);
+ if (!HardwareIDs)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ Result = SetupDiGetDeviceRegistryPropertyW(
+ DeviceInfoSet,
+ DeviceInfoData,
+ SPDRP_HARDWAREID,
+ NULL,
+ (PBYTE)HardwareIDs,
+ RequiredSize,
+ &RequiredSize);
+ }
+ if (!Result)
+ {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ /* No hardware ID for this device */
+ MyFree(HardwareIDs);
+ HardwareIDs = NULL;
+ RequiredSize = 0;
+ }
+ else
+ goto done;
+ }
+ if (pHardwareIDs)
+ *pHardwareIDs = HardwareIDs;
+ if (pHardwareIDsRequiredSize)
+ *pHardwareIDsRequiredSize = RequiredSize;
+
+ /* Get compatible IDs list */
+ Result = FALSE;
+ RequiredSize = 512; /* Initial buffer size */
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ MyFree(CompatibleIDs);
+ CompatibleIDs = MyMalloc(RequiredSize);
+ if (!CompatibleIDs)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ Result = SetupDiGetDeviceRegistryPropertyW(
+ DeviceInfoSet,
+ DeviceInfoData,
+ SPDRP_COMPATIBLEIDS,
+ NULL,
+ (PBYTE)CompatibleIDs,
+ RequiredSize,
+ &RequiredSize);
+ }
+ if (!Result)
+ {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ /* No compatible ID for this device */
+ MyFree(CompatibleIDs);
+ CompatibleIDs = NULL;
+ RequiredSize = 0;
+ }
+ else
+ goto done;
+ }
+ if (pCompatibleIDs)
+ *pCompatibleIDs = CompatibleIDs;
+ if (pCompatibleIDsRequiredSize)
+ *pCompatibleIDsRequiredSize = RequiredSize;
+
+ Result = TRUE;
+
+done:
+ if (!Result)
+ {
+ MyFree(HardwareIDs);
+ MyFree(CompatibleIDs);
+ }
+ return Result;
+}
+
/***********************************************************************
* SetupDiBuildDriverInfoList (SETUPAPI.@)
*/
if (DriverType == SPDIT_COMPATDRIVER)
{
- /* Get hardware IDs list */
- Result = FALSE;
- RequiredSize = 512; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- HeapFree(GetProcessHeap(), 0, HardwareIDs);
- HardwareIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
- if (!HardwareIDs)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
- }
- Result = SetupDiGetDeviceRegistryPropertyW(
- DeviceInfoSet,
- DeviceInfoData,
- SPDRP_HARDWAREID,
- NULL,
- (PBYTE)HardwareIDs,
- RequiredSize,
- &RequiredSize);
- }
+ /* Get hardware and compatible IDs lists */
+ Result = GetHardwareAndCompatibleIDsLists(
+ DeviceInfoSet,
+ DeviceInfoData,
+ &HardwareIDs,
+ NULL,
+ &CompatibleIDs,
+ NULL);
if (!Result)
goto done;
-
- /* Get compatible IDs list */
- Result = FALSE;
- RequiredSize = 512; /* Initial buffer size */
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ if (!HardwareIDs && !CompatibleIDs)
{
- HeapFree(GetProcessHeap(), 0, CompatibleIDs);
- CompatibleIDs = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
- if (!CompatibleIDs)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
- }
- Result = SetupDiGetDeviceRegistryPropertyW(
- DeviceInfoSet,
- DeviceInfoData,
- SPDRP_COMPATIBLEIDS,
- NULL,
- (PBYTE)CompatibleIDs,
- RequiredSize,
- &RequiredSize);
- if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
- {
- /* No compatible ID for this device */
- HeapFree(GetProcessHeap(), 0, CompatibleIDs);
- CompatibleIDs = NULL;
- Result = TRUE;
- }
- }
- if (!Result)
+ SetLastError(ERROR_FILE_NOT_FOUND);
goto done;
+ }
}
if (InstallParams.Flags & DI_ENUMSINGLEINF)
HeapFree(GetProcessHeap(), 0, ProviderName);
HeapFree(GetProcessHeap(), 0, ManufacturerName);
- HeapFree(GetProcessHeap(), 0, HardwareIDs);
- HeapFree(GetProcessHeap(), 0, CompatibleIDs);
+ MyFree(HardwareIDs);
+ MyFree(CompatibleIDs);
HeapFree(GetProcessHeap(), 0, FullInfFileName);
HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
if (currentInfFileDetails)
else
{
struct DriverInfoElement *driverInfoElement;
+ LPWSTR HardwareIDs = NULL;
+ LPWSTR CompatibleIDs = NULL;
+ LPWSTR pBuffer = NULL;
+ LPCWSTR DeviceID = NULL;
+ ULONG HardwareIDsSize, CompatibleIDsSize;
+ ULONG sizeNeeded, sizeLeft, size;
+ BOOL Result;
+
driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
+ /* Get hardware and compatible IDs lists */
+ Result = GetHardwareAndCompatibleIDsLists(
+ DeviceInfoSet,
+ DeviceInfoData,
+ &HardwareIDs, &HardwareIDsSize,
+ &CompatibleIDs, &CompatibleIDsSize);
+ if (!Result)
+ goto done;
+
+ sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)
+ + HardwareIDsSize + CompatibleIDsSize;
+ if (RequiredSize)
+ *RequiredSize = sizeNeeded;
+
+ if (!DriverInfoDetailData)
+ {
+ ret = TRUE;
+ goto done;
+ }
+
memcpy(
DriverInfoDetailData,
&driverInfoElement->Details,
driverInfoElement->Details.cbSize);
- /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
- * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
- */
- ret = TRUE;
+ DriverInfoDetailData->CompatIDsOffset = 0;
+ DriverInfoDetailData->CompatIDsLength = 0;
+
+ sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR);
+ pBuffer = DriverInfoDetailData->HardwareID;
+ /* Add as many as possible HardwareIDs in the list */
+ DeviceID = HardwareIDs;
+ while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
+ {
+ TRACE("Adding %S to list\n", DeviceID);
+ wcscpy(pBuffer, DeviceID);
+ DeviceID += size + 1;
+ pBuffer += size + 1;
+ sizeLeft -= size + 1;
+ DriverInfoDetailData->CompatIDsOffset += size + 1;
+ }
+ if (sizeLeft > 0)
+ {
+ *pBuffer = UNICODE_NULL;
+ sizeLeft--;
+ DriverInfoDetailData->CompatIDsOffset++;
+ }
+ /* Add as many as possible CompatibleIDs in the list */
+ DeviceID = CompatibleIDs;
+ while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
+ {
+ TRACE("Adding %S to list\n", DeviceID);
+ wcscpy(pBuffer, DeviceID);
+ DeviceID += size + 1;
+ pBuffer += size + 1;
+ sizeLeft -= size + 1;
+ DriverInfoDetailData->CompatIDsLength += size + 1;
+ }
+ if (sizeLeft > 0)
+ {
+ *pBuffer = UNICODE_NULL;
+ sizeLeft--;
+ DriverInfoDetailData->CompatIDsLength++;
+ }
+
+ if (sizeNeeded > DriverInfoDetailDataSize)
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ else
+ ret = TRUE;
+
+done:
+ MyFree(HardwareIDs);
+ MyFree(CompatibleIDs);
}
TRACE("Returning %d\n", ret);