static void
frida_foreach_usb_device (const GUID * guid, FridaEnumerateDeviceFunc func, gpointer user_data)
{
  HANDLE info_set;
  gboolean carry_on = TRUE;
  guint member_index;

  info_set = SetupDiGetClassDevs (guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  if (info_set == INVALID_HANDLE_VALUE)
    goto beach;

  for (member_index = 0; carry_on; member_index++)
  {
    SP_DEVICE_INTERFACE_DATA iface_data = { 0, };
    SP_DEVINFO_DATA info_data = { 0, };
    DWORD detail_size;
    SP_DEVICE_INTERFACE_DETAIL_DATA_W * detail_data = NULL;
    BOOL success;
    FridaDeviceInfo device_info = { 0, };
    DWORD instance_id_size;

    iface_data.cbSize = sizeof (iface_data);
    if (!SetupDiEnumDeviceInterfaces (info_set, NULL, guid, member_index, &iface_data))
      break;

    info_data.cbSize = sizeof (info_data);
    success = SetupDiGetDeviceInterfaceDetailW (info_set, &iface_data, NULL, 0, &detail_size, &info_data);
    if (!success && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
      goto skip_device;

    detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *) g_malloc (detail_size);
    detail_data->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA_W);
    success = SetupDiGetDeviceInterfaceDetailW (info_set, &iface_data, detail_data, detail_size, NULL, &info_data);
    if (!success)
      goto skip_device;

    device_info.device_path = detail_data->DevicePath;

    success = SetupDiGetDeviceInstanceIdW (info_set, &info_data, NULL, 0, &instance_id_size);
    if (!success && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
      goto skip_device;

    device_info.instance_id = (WCHAR *) g_malloc (instance_id_size * sizeof (WCHAR));
    success = SetupDiGetDeviceInstanceIdW (info_set, &info_data, device_info.instance_id, instance_id_size, NULL);
    if (!success)
      goto skip_device;

    device_info.friendly_name = frida_read_device_registry_string_property (info_set, &info_data, SPDRP_FRIENDLYNAME);

    device_info.location = frida_read_device_registry_string_property (info_set, &info_data, SPDRP_LOCATION_INFORMATION);

    device_info.device_info_set = info_set;
    device_info.device_info_data = &info_data;

    carry_on = func (&device_info, user_data);

skip_device:
    g_free (device_info.location);
    g_free (device_info.friendly_name);
    g_free (device_info.instance_id);

    g_free (detail_data);
  }

beach:
  if (info_set != INVALID_HANDLE_VALUE)
    SetupDiDestroyDeviceInfoList (info_set);
}
Exemple #2
0
static DWORD
InstallNetDevice(
	IN HDEVINFO DeviceInfoSet,
	IN PSP_DEVINFO_DATA DeviceInfoData,
	LPCWSTR UuidString,
	DWORD Characteristics,
	LPCWSTR BusType)
{
	LPWSTR InstanceId = NULL;
	LPWSTR DeviceName = NULL;
	LPWSTR ExportName = NULL;
	LONG rc;
	HKEY hKey = NULL;
	HKEY hNetworkKey = NULL;
	HKEY hLinkageKey = NULL;
	HKEY hConnectionKey = NULL;
	DWORD dwShowIcon, dwLength, dwValue;
	WCHAR szBuffer[300];

	/* Get Instance ID */
	if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, NULL, 0, &dwLength))
	{
		DPRINT("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
		rc = ERROR_GEN_FAILURE;
		goto cleanup;
	}
	InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
	if (!InstanceId)
	{
		DPRINT("HeapAlloc() failed\n");
		rc = ERROR_NOT_ENOUGH_MEMORY;
		goto cleanup;
	}
	if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, InstanceId, dwLength, NULL))
	{
		rc = GetLastError();
		DPRINT("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}

	/* Create device name */
	DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
	if (!DeviceName)
	{
		DPRINT("HeapAlloc() failed\n");
		rc = ERROR_NOT_ENOUGH_MEMORY;
		goto cleanup;
	}
	wcscpy(DeviceName, L"\\Device\\");
	wcscat(DeviceName, UuidString);

	/* Create export name */
	ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
	if (!ExportName)
	{
		DPRINT("HeapAlloc() failed\n");
		rc = ERROR_NOT_ENOUGH_MEMORY;
		goto cleanup;
	}
	wcscpy(ExportName, L"\\Device\\Tcpip_");
	wcscat(ExportName, UuidString);

	/* Write Tcpip parameters in new service Key */
	rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hNetworkKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	RegCloseKey(hKey);
	hKey = NULL;
	rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	RegCloseKey(hNetworkKey);
	hNetworkKey = NULL;
	rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hKey, L"SubnetMask", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
        dwValue = 1;
	rc = RegSetValueExW(hKey, L"EnableDHCP", 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(DWORD));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	RegCloseKey(hKey);
	hKey = NULL;

	/* Write 'Linkage' key in hardware key */
#if _WIN32_WINNT >= 0x502
	hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
#else
	hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
#endif
	if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
		hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
	if (hKey == INVALID_HANDLE_VALUE)
	{
		hKey = NULL;
		rc = GetLastError();
		DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	if (BusType)
		rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 1) * sizeof(WCHAR));
		if (rc != ERROR_SUCCESS)
		{
			DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
			goto cleanup;
		}
	rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	RegCloseKey(hKey);
	hKey = NULL;

	/* Write connection information in network subkey */
	rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hNetworkKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
	RegCloseKey(hKey);
	hKey = NULL;
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	if (!LoadStringW(netcfgx_hInstance, IDS_NET_CONNECT, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
	{
		wcscpy(szBuffer,L"Network connection");
	}
	rc = RegSetValueExW(hConnectionKey, L"Name", 0, REG_SZ, (const BYTE*)szBuffer, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = RegSetValueExW(hConnectionKey, L"PnpInstanceId", 0, REG_SZ, (const BYTE*)InstanceId, (wcslen(InstanceId) + 1) * sizeof(WCHAR));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	dwShowIcon = 1;
	rc = RegSetValueExW(hConnectionKey, L"ShowIcon", 0, REG_DWORD, (const BYTE*)&dwShowIcon, sizeof(dwShowIcon));
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}

	/* Write linkage information in Tcpip service */
	rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hKey, NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
		goto cleanup;
	}
	rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
		goto cleanup;
	}

	/* Install additionnal services */
	rc = InstallAdditionalServices(NULL);
	if (rc != ERROR_SUCCESS)
	{
		DPRINT("InstallAdditionalServices() failed with error 0x%lx\n", rc);
		goto cleanup;
	}

	rc = ERROR_SUCCESS;

cleanup:
	HeapFree(GetProcessHeap(), 0, InstanceId);
	HeapFree(GetProcessHeap(), 0, DeviceName);
	HeapFree(GetProcessHeap(), 0, ExportName);
	if (hKey != NULL)
		RegCloseKey(hKey);
	if (hNetworkKey != NULL)
		RegCloseKey(hNetworkKey);
	if (hLinkageKey != NULL)
		RegCloseKey(hLinkageKey);
	if (hConnectionKey != NULL)
		RegCloseKey(hConnectionKey);
	return rc;
}
Exemple #3
0
/*
* @implemented
*/
BOOL WINAPI
UpdateDriverForPlugAndPlayDevicesW(
    IN HWND hwndParent,
    IN LPCWSTR HardwareId,
    IN LPCWSTR FullInfPath,
    IN DWORD InstallFlags,
    OUT PBOOL bRebootRequired OPTIONAL)
{
    DEVINSTDATA DevInstData;
    DWORD i;
    LPWSTR Buffer = NULL;
    DWORD BufferSize;
    LPCWSTR CurrentHardwareId; /* Pointer into Buffer */
    BOOL FoundHardwareId, FoundAtLeastOneDevice = FALSE;
    BOOL ret = FALSE;

    DevInstData.hDevInfo = INVALID_HANDLE_VALUE;

    TRACE("UpdateDriverForPlugAndPlayDevicesW(%p %s %s 0x%x %p)\n",
        hwndParent, debugstr_w(HardwareId), debugstr_w(FullInfPath), InstallFlags, bRebootRequired);

    /* FIXME: InstallFlags bRebootRequired ignored! */

    /* Check flags */
    if (InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE))
    {
        TRACE("Unknown flags: 0x%08lx\n", InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE));
        SetLastError(ERROR_INVALID_FLAGS);
        goto cleanup;
    }

    /* Enumerate all devices of the system */
    DevInstData.hDevInfo = SetupDiGetClassDevsW(NULL, NULL, hwndParent, DIGCF_ALLCLASSES | DIGCF_PRESENT);
    if (DevInstData.hDevInfo == INVALID_HANDLE_VALUE)
        goto cleanup;
    DevInstData.devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    for (i = 0; ; i++)
    {
        if (!SetupDiEnumDeviceInfo(DevInstData.hDevInfo, i, &DevInstData.devInfoData))
        {
            if (GetLastError() != ERROR_NO_MORE_ITEMS)
            {
                TRACE("SetupDiEnumDeviceInfo() failed with error 0x%x\n", GetLastError());
                goto cleanup;
            }
            /* This error was expected */
            break;
        }

        /* Get Hardware ID */
        HeapFree(GetProcessHeap(), 0, Buffer);
        Buffer = NULL;
        BufferSize = 0;
        while (!SetupDiGetDeviceRegistryPropertyW(
            DevInstData.hDevInfo,
            &DevInstData.devInfoData,
            SPDRP_HARDWAREID,
            NULL,
            (PBYTE)Buffer,
            BufferSize,
            &BufferSize))
        {
            if (GetLastError() == ERROR_FILE_NOT_FOUND)
            {
                Buffer = NULL;
                break;
            }
            else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            {
                TRACE("SetupDiGetDeviceRegistryPropertyW() failed with error 0x%x\n", GetLastError());
                goto cleanup;
            }
            /* This error was expected */
            HeapFree(GetProcessHeap(), 0, Buffer);
            Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize);
            if (!Buffer)
            {
                TRACE("HeapAlloc() failed\n", GetLastError());
                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                goto cleanup;
            }
        }
        if (Buffer == NULL)
            continue;

        /* Check if we match the given hardware ID */
        FoundHardwareId = FALSE;
        for (CurrentHardwareId = Buffer; *CurrentHardwareId != UNICODE_NULL; CurrentHardwareId += wcslen(CurrentHardwareId) + 1)
        {
            if (wcscmp(CurrentHardwareId, HardwareId) == 0)
            {
                FoundHardwareId = TRUE;
                break;
            }
        }
        if (!FoundHardwareId)
            continue;

        /* We need to try to update the driver of this device */

        /* Get Instance ID */
        HeapFree(GetProcessHeap(), 0, Buffer);
        Buffer = NULL;
        if (SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, NULL, 0, &BufferSize))
        {
            /* Error, as the output buffer should be too small */
            SetLastError(ERROR_GEN_FAILURE);
            goto cleanup;
        }
        else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        {
            TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError());
            goto cleanup;
        }
        else if ((Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize * sizeof(WCHAR))) == NULL)
        {
            TRACE("HeapAlloc() failed\n", GetLastError());
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            goto cleanup;
        }
        else if (!SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, Buffer, BufferSize, NULL))
        {
            TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError());
            goto cleanup;
        }
        TRACE("Trying to update the driver of %s\n", debugstr_w(Buffer));

        /* Search driver in the specified .inf file */
        if (!SearchDriver(&DevInstData, NULL, FullInfPath))
        {
            TRACE("SearchDriver() failed with error 0x%x\n", GetLastError());
            continue;
        }

        /* FIXME: HACK! We shouldn't check of ERROR_PRIVILEGE_NOT_HELD */
        //if (!InstallCurrentDriver(&DevInstData))
        if (!InstallCurrentDriver(&DevInstData) && GetLastError() != ERROR_PRIVILEGE_NOT_HELD)
        {
            TRACE("InstallCurrentDriver() failed with error 0x%x\n", GetLastError());
            continue;
        }

        FoundAtLeastOneDevice = TRUE;
    }

    if (FoundAtLeastOneDevice)
    {
        SetLastError(NO_ERROR);
        ret = TRUE;
    }
    else
    {
        TRACE("No device found with HardwareID %s\n", debugstr_w(HardwareId));
        SetLastError(ERROR_NO_SUCH_DEVINST);
    }

cleanup:
    if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE)
        SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo);
    HeapFree(GetProcessHeap(), 0, Buffer);
    return ret;
}
Exemple #4
0
//+---------------------------------------------------------------------------
//
// Function:  HrShowNetAdapters
//
// Purpose:   Display all installed net class devices using Setup API
//
// Arguments: None
//
// Returns:   S_OK on success, otherwise an error code
//
// Notes:
//
HRESULT HrShowNetAdapters()
{
#define MAX_COMP_INSTID 4096
#define MAX_COMP_DESC   4096

    HRESULT hr=S_OK;
    HDEVINFO hdi;
    DWORD dwIndex=0;
    SP_DEVINFO_DATA deid;
    BOOL fSuccess=FALSE;
//    DWORD   cchRequiredSize;
    WCHAR szCompInstanceId[MAX_COMP_INSTID];
    WCHAR szCompDescription[MAX_COMP_DESC];
    DWORD dwRegType;
    BOOL fFound=FALSE;

    // get a list of all devices of class 'GUID_DEVCLASS_NET'
    hdi = SetupDiGetClassDevs((struct _GUID *)&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT);

    if (INVALID_HANDLE_VALUE != hdi)
    {
        // enumerate over each device
        while (deid.cbSize = sizeof(SP_DEVINFO_DATA),
               SetupDiEnumDeviceInfo(hdi, dwIndex, &deid))
        {
            dwIndex++;

            // the right thing to do here would be to call this function
            // to get the size required to hold the instance ID and then
            // to call it second time with a buffer large enough for that size.
            // However, that would tend to obscure the control flow in
            // the sample code. Lets keep things simple by keeping the
            // buffer large enough.

            // get the device instance ID
            fSuccess = SetupDiGetDeviceInstanceIdW(hdi, &deid,
                                                  szCompInstanceId,
                                                  MAX_COMP_INSTID, NULL);
            if (fSuccess)
            {
                // get the description for this instance
                fSuccess =
                    SetupDiGetDeviceRegistryProperty(hdi, &deid,
                                                     SPDRP_DEVICEDESC,
                                                     &dwRegType,
                                                     (BYTE*) szCompDescription,
                                                     MAX_COMP_DESC,
                                                     NULL);
                if (fSuccess)
                {
                    if (!fFound)
                    {
                        fFound = TRUE;
                    }
                }
            }
        }

        // release the device info list
        SetupDiDestroyDeviceInfoList(hdi);
    }

    if (!fSuccess)
    {
        DWORD dwError = GetLastError();
        hr = HRESULT_FROM_WIN32(dwError);
    }

    return hr;
}