I am updating my question to better reflect what I was actually going after. To state a fact about my original confusion quickly, it is incorrect to say that there is a 1-to-1 relationship between "Device Interface Class GUID" and the Device Instance ID. A device can have many device interfaces. As Ben Voigt noted in the comments, see this for more information.
How can one open a handle to a child device after calling the CM_Get_Child (...)
function?
Take the following code snip as an example:
#pragma comment (lib, "Setupapi.lib")
#pragma comment (lib, "Cfgmgr32.lib")
#include <iostream>
#include <Windows.h>
#include <Setupapi.h>
#include <Cfgmgr32.h>
#define GUID_STRING_SIZE 40
int main ()
{
CONFIGRET CMResult = CR_SUCCESS;
WCHAR DeviceInstanceID[] = L"USB\\VID_2109&PID_0813\\8&216C1825&0&4\0"; // Parent Device Instance ID.
DEVNODE ParentDeviceNode = (DWORD) 0; // A device instance handle. This handle is bounded to the local machine.
CMResult = CM_Locate_DevNode ((PDEVINST) &ParentDeviceNode, DeviceInstanceID, CM_LOCATE_DEVNODE_NORMAL);
if (CMResult != CR_SUCCESS)
{
std::cout << "No parent device node found." << std::endl;
return -1;
}
else
{
DEVINST NextChildDeviceNode = (DWORD) 0;
CMResult = CM_Get_Child ((PDEVINST) &NextChildDeviceNode, ParentDeviceNode, 0x0); // Gets the first child of the parent node. If this returns "CR_NO_SUCH_DEVNODE," then there is no child attached.
if (CMResult != CR_SUCCESS)
{
std::cout << "No child device node found." << std::endl;
return -2;
}
else
{
ULONG ChildInstanceIDBuffLength = 0;
CMResult = CM_Get_Device_ID_Size (&ChildInstanceIDBuffLength, NextChildDeviceNode, 0x0);
if (CMResult != CR_SUCCESS)
{
std::cout << "Could not get the size of the device instance ID of child device." << std::endl;
return -3;
}
else
{
WCHAR * ChildInstanceIDBuff = (WCHAR *) malloc (ChildInstanceIDBuffLength);
CMResult = CM_Get_Device_IDW (NextChildDeviceNode, ChildInstanceIDBuff, ChildInstanceIDBuffLength, 0x0);
if (CMResult != CR_SUCCESS)
{
std::cout << "Could not actual device instance ID string of child device" << std::endl;
return -4;
}
else
{
std::cout << "Found child device instance ID: ";
std::wcout << ChildInstanceIDBuff << std::endl;
/*
* Open handle to the child device node now!
*/
}
free (ChildInstanceIDBuff);
}
}
}
return 0;
}
How can I use the newly obtained child Device Instance ID to open a handle to the device? CreateFile (...)
requires the complete device path, which includes the missing "Device Interface Class GUID."
More specifically, a device path has the following format:
\\?\usb#vid_2109&pid_0813#7&3981C8D6&0&2#{[DEVICE_INTERFACE_GUID]}
, where:
- [DEVICE_INTERFACE_GUID] - This the "Device Interface Class GUID." This is NOT the same as the "Device Setup Class GUID."
There does not appear to be an easy way to get this "Device Interface Class GUID" without some level of brute force (e.g. CM_Enumerate_Classes (...)
using the CM_ENUMERATE_CLASSES_INTERFACE flag). Is there a function I can call to get a handle to a device using only its "Device Instance ID," so that I can then call DeviceIoControl (...)
and query information about the device?