Obtain Device Information Set for Monitors: Returned Handle is always INVALID_HANDLE_VALUE

Started by
1 comment, last by gretty 11 years, 3 months ago

Hello

I am attempting to list the device information for all the monitors currently connected to the computer. I have a function that can do this and its 90% done except when I go to call the function SetupDiGetClassDevs() with the 2nd parameter set(not NULL) then the function always fails(returns INVALID_HANDLE_VALUE).

When I call GetLastError() I get the error 13(decimal), ie, "The data is invalid" which I am not sure what that means?

What is going wrong? Can you provide any advice on whats happening and how I can fix it?

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
);


My function that attempts to get a Device Information Set for Monitors only and output each monitors details(the error line is commented):


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);
    }
Advertisement
The documentation is very clear. DIGCF_DEVICEINTERFACE is used only if you are providing a device instance ID, which you are not - you are providing an enumerator GUID.

Remove the flag.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Thanks, removing that flag and using "PCI" as the enumerator works now. But I am not sure PCI is the correct enumator value I should be using?

If I want to obtain Device Information for all Monitors, what enumerator should I use? MSDN doesn't list all possible enumerator values.

So far I have tried "Monitor" and "{4d36e96e-e325-11ce-bfc1-08002be10318}" but that causes the same error "data is invalid"

This topic is closed to new replies.

Advertisement