获取监视器的设备信息集:返回的句柄始终为INVALID_HANDLE_VALUE

时间:2013-01-12 00:02:29

标签: c++ winapi device guid

我正在尝试列出当前连接到计算机的所有显示器的设备信息。我有一个可以做到这一点并且90%完成的函数,除非我用第二个参数集(非NULL)调用函数SetupDiGetClassDevs(),然后函数总是失败(返回INVALID_HANDLE_VALUE)。

当我拨打GetLastError()时,我收到错误13(十进制),即"The data is invalid",我不确定这是什么意思?

出了什么问题?您能否提供有关最新情况以及如何解决问题的建议?

Function Information:

HDEVINFO SetupDiGetClassDevs(
  _In_opt_  const GUID *ClassGuid,
  _In_opt_  PCTSTR Enumerator,     // According to MSDN this param MUST be set if I want Device Information for a specific class(Monitors)
  _In_opt_  HWND hwndParent,
  _In_      DWORD Flags
);

我的功能是尝试仅为监视器获取设备信息集并输出每个监视器详细信息(错误行已注释):

void printDeviceData(GUID guID)
{
    // Device Classes:        http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426
    // System Device Classes: http://msdn.microsoft.com/en-us/library/windows/hardware/ff553428
    // Monitor Class GUI:     {4d36e96e-e325-11ce-bfc1-08002be10318}

    DWORD dataT                    = 0;
    PCTSTR monitorGuID             = _T("");
    SP_DEVINFO_DATA deviceInfoData = {0};
    deviceInfoData.cbSize          = sizeof(SP_DEVINFO_DATA);
    deviceInfoData.ClassGuid       = guID;

    // Step 1: Get Device Information Set for Monitors only
    // ERROR OCCURS HERE: SetupDiGetClassDevs() always fails
    // Also tried these values for param 2: "Monitor" "PCI" but all cause the function to return INVALID_HANDLE_VALUE
    HDEVINFO hDevInfo = SetupDiGetClassDevs(&guID, _T("{4d36e96e-e325-11ce-bfc1-08002be10318}"), NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hDevInfo == INVALID_HANDLE_VALUE) {
        //outputLastError(_T("Fail 1"));
        printf("hDevInfo == INVALID_HANDLE_VALUE\n");
        return;
    }
    else printf("SUCCESS 1\n");

    if (SetupDiGetSelectedDevice(hDevInfo, &deviceInfoData) == FALSE) {
        //outputLastError(_T("SetupDiGetSelectedDevice(hDevInfo, &deviceInfoData) == FALSE"));
        printf("SetupDiGetSelectedDevice(hDevInfo, &deviceInfoData) == FALSE, %d, %x\n", GetLastError(), GetLastError());
        return;
    }
    else printf("SUCCESS 2\n");

    // Step 2: For each Monitor: Output Device information
    const unsigned int FLAG_NUM = 30;
    DWORD flags[] = {SPDRP_FRIENDLYNAME, SPDRP_ENUMERATOR_NAME, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, SPDRP_DEVICEDESC,
                        SPDRP_ADDRESS, SPDRP_BUSNUMBER, SPDRP_BUSTYPEGUID, SPDRP_CHARACTERISTICS, SPDRP_CLASS, SPDRP_CLASSGUID,
                        SPDRP_COMPATIBLEIDS, SPDRP_CONFIGFLAGS, SPDRP_DEVICE_POWER_DATA, SPDRP_DEVTYPE, SPDRP_DRIVER,
                        SPDRP_ENUMERATOR_NAME, SPDRP_EXCLUSIVE, SPDRP_HARDWAREID, SPDRP_INSTALL_STATE, SPDRP_LEGACYBUSTYPE,
                        SPDRP_LOCATION_INFORMATION, SPDRP_LOCATION_PATHS, SPDRP_LOWERFILTERS, SPDRP_MFG, 
                        SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, SPDRP_UI_NUMBER, SPDRP_UI_NUMBER_DESC_FORMAT, SPDRP_UPPERFILTERS, 
                        SPDRP_SECURITY_SDS, SPDRP_SECURITY, SPDRP_SERVICE };

    for (int i=0; i<=FLAG_NUM; i++) {
        DWORD buffersize = 0;
        LPTSTR buffer    = NULL;

        while (!SetupDiGetDeviceRegistryProperty(hDevInfo,  &deviceInfoData, flags[i], &dataT,
                                                    (PBYTE)buffer, buffersize, &buffersize))
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                // Change the buffer size.
                if (buffer) 
                    LocalFree(buffer);
                buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);
            }
            else {
                // Insert error handling here.
                break;
            }
        }

        printf("Data: %d: %s\n", i, buffer);
        if (buffer) 
            LocalFree(buffer);
    }

    SetupDiDestroyDeviceInfoList(hDevInfo);
}

1 个答案:

答案 0 :(得分:0)

根据文档,必须将Enumerator设置为有效的设备实例ID,根据http://msdn.microsoft.com/en-us/library/windows/hardware/ff541327必须像这样指定

“PCI \ VEN_1000&安培; DEV_0001&安培; SUBSYS_00000000&安培; REV_02 \ 1安培; 08”

我还没有测试过,但我认为这是无效数据的来源。