Does SetupDiGetClassDevs work with device instance IDs as documented?
Asked Answered
J

2

11

According to MSDN documentation, SetupDiGetClassDevs can be passed a device instance ID to obtain a device information set for a specific device:

To return only a specific device, set the DIFCF_DEVICEINTERFACE flag and use the Enumerator parameter to supply the device instance ID of the device.

I get the device instance ID by parsing the symbolic name from the WM_DEVICECHANGE message DBT_DEVICEARRIVAL event, and I have verified the resulting ID by comparing it to that returned from SetupDiGetDeviceInstanceId. Even passing the OS supplied device instance ID does not work (i.e. the SetupDiGetClassDevs call fails with ERROR_INVALID_PARAMETER).

My current workaround to fetch a SP_DEVINFO_DATA structure for the newly arrived device is to enumerate all devices in the same class and compare the result of SetupDiGetDeviceInstanceId to the symbolic name. However, I don't see why this should be necessary according to the documentation...

Has anyone gotten SetupDiGetClassDevs to work in this way? Is there a better method for getting further information for a device using data in the DBT_DEVICEARRIVAL event?

Jimerson answered 5/6, 2009 at 15:55 Comment(0)
P
13

It seems you have to either specify the DIGCF_ALLCLASSES flag to find all classes that match the given device instance id, or else specify the ClassGuid and use the DIGCF_DEFAULT flag.

This worked for me:

void error(DWORD err)
{
    WCHAR buf[0x200];
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, 0x200, NULL);
    wprintf(L"%x: %s\n", err,  buf);
}


int _tmain(int argc, _TCHAR* argv[])
{
    PCWSTR devinst = L"HID\\VID_413C&PID_2105\\6&22CE0F66&0&0000";
    HDEVINFO hinfo = SetupDiGetClassDevs(NULL, devinst, NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);
    if (hinfo == INVALID_HANDLE_VALUE)
    {
        error(GetLastError());
        return 1;
    }

    SP_DEVINFO_DATA dinfo;
    dinfo.cbSize = sizeof(dinfo);
    int ix = 0;
    while (SetupDiEnumDeviceInfo(hinfo, ix++, &dinfo))
    {
        wprintf(L"Match\n");
    }

    error(GetLastError());

    SetupDiDestroyDeviceInfoList(hinfo);
    return 0;
}

With output:

Match
103: No more data is available.
Pillowcase answered 8/6, 2009 at 17:22 Comment(1)
The DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES was the missing part for me. From MSDN documentation I understood that only DIGCF_DEVICEINTERFACE was necessary, but that gave error 87 (bad arguments).Torbart
I
4

It seems that you're misunderstanding DBT_DEVICEARRIVAL.

There are a few different types of DBT_DEVICEARRIVAL messages-- for a volume, for a handle, for a device interface. I'm guessing you're talking about the DBT_DEVTYP_DEVICEINTERFACE variety. In this case, the dbcc_name field of the DEV_BROADCAST_DEVICEINTERFACE structure will contain the "device interface path".

The "device interface path" is NOT the same as a "device instance ID".

If you want to know more information about this device, you should enumerate all device interfaces by this device interface GUID (through SetupDiGetClassDevs with DIGCF_DEVICEINTERFACE), and compare the dbcc_name to the strings retrieved by SetupDiEnumDeviceInterfaces.

Impellent answered 29/12, 2010 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.