Search code examples
c++windowswinapidevice-instance-id

Get parent information of a USB device C++


I'm working on an MFC tool that check some driver information's of connected USB device such as location info, parent, hardware id, etc. I have got all other information i want but i'm stuck in getting device parent information.

I have used Setupapi.dll to get device information in my code. Got USB device information handle using SetupDiGetClassDevs function. Got specific device info data using SetupDiEnumDeviceInfo function. Got device description and hardware id using SetupDiGetDeviceRegistryProperty function.

// List all connected USB devices
hDevInfo = SetupDiGetClassDevs(pClassGuid, pszEnumerator, 
    NULL, pClassGuid != NULL ? DIGCF_PRESENT : DIGCF_ALLCLASSES | 
    DIGCF_PRESENT);

// Get device info data
SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);

// Get device instance id
CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 
    0);

// Get device description
SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, 
    SPDRP_DEVICEDESC,
    &dwPropertyRegDataType, (BYTE*)szDesc, sizeof(szDesc), &dwSize);

#define DEFINE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, 
    b8, pid) EXTERN_C const DEVPROPKEY DECLSPEC_SELECTANY 
    name = { { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6, b7,  b8 } }, pid 
}

// DEVPROP_TYPE_STRING 
DEFINE_DEVPROPKEY(DEVPKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 
    0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13);        
// DEVPROP_TYPE_GUID
DEFINE_DEVPROPKEY(DEVPKEY_Device_ContainerId, 0x8c7ed206, 0x3f8a, 0x4827, 
    0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c, 2);     

typedef BOOL(WINAPI *FN_SetupDiGetDevicePropertyW)(
    __in       HDEVINFO DeviceInfoSet,
    __in       PSP_DEVINFO_DATA DeviceInfoData,
    __in       const DEVPROPKEY *PropertyKey,
    __out      DEVPROPTYPE *PropertyType,
    __out_opt  PBYTE PropertyBuffer,
    __in       DWORD PropertyBufferSize,
    __out_opt  PDWORD RequiredSize,
    __in       DWORD Flags
);

FN_SetupDiGetDevicePropertyW fn_SetupDiGetDevicePropertyW = 
    (FN_SetupDiGetDevicePropertyW) 
    GetProcAddress(GetModuleHandle(TEXT("Setupapi.dll")), 
    "SetupDiGetDevicePropertyW");

if (fn_SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, 
    &DEVPKEY_Device_Manufacturer, &ulPropertyType, (BYTE*)szBuffer, 
    sizeof(szBuffer), &dwSize, 0)) 
{
    _tprintf(TEXT("    Device Manufacturer: \"%ls\"\n"), szBuffer);
}

if (fn_SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, 
    &DEVPKEY_Device_ContainerId, &ulPropertyType, (BYTE*)szDesc, 
    sizeof(szDesc), &dwSize, 0)) 
{
    StringFromGUID2((REFGUID)szDesc, szBuffer, ARRAY_SIZE(szBuffer));
    _tprintf(TEXT("    ContainerId: \"%ls\"\n"), szBuffer);
}

It is very useful for me to get the parent information of USB device. Please help with some clues.

please look into image


Solution

  • CM_Locate_DevNode opens a device handle given a device ID;

    CM_Get_Parent finds the parent device;

    CM_Get_Device_ID_Size and CM_Get_Device_ID take the device handle and return the device ID.

    Sample:

    #include <Windows.h>
    #include <setupapi.h>
    #include <cfgmgr32.h>
    #include <tchar.h>
    #include <stdio.h>
    #define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))
    
    #pragma comment (lib, "setupapi.lib")
    
    int main()
    {
        HDEVINFO hDevInfo;
        GUID guid;
        BYTE buffer[1024];
        DWORD dwRequiredSize;
        DEVINST devInstParent;
        SP_DEVICE_INTERFACE_DATA devInterfaceData;
        SP_DEVINFO_DATA devInfoData;
        PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
        CONFIGRET status;
        TCHAR szDeviceInstanceID[MAX_DEVICE_ID_LEN];
        BOOL bSuccess;
    
        guid = GUID_DEVINTERFACE_VOLUME;
        hDevInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
        if (hDevInfo == INVALID_HANDLE_VALUE) {
            return 1;
        }
    
        for (DWORD dwIndex = 0;; dwIndex++)
        {
            ZeroMemory(&devInterfaceData, sizeof(devInterfaceData));
            devInterfaceData.cbSize = sizeof(devInterfaceData);
    
            if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guid, dwIndex, &devInterfaceData)) {
                DWORD dwErrorCode = GetLastError();
                if (dwErrorCode == ERROR_NO_MORE_ITEMS)
                    break;
                else
                    return 1;  
            }
    
            ZeroMemory(&devInfoData, sizeof(devInfoData));
            devInfoData.cbSize = sizeof(devInfoData);
            pDevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer;
            pDevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    
            // Get device interface detail data to get Device Instance from
            // SP_DEVINFO_DATA and Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
            bSuccess = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData,
                pDevDetail,// SP_DEVICE_INTERFACE_DETAIL_DATA
                sizeof(buffer), &dwRequiredSize, &devInfoData); // SP_DEVINFO_DATA
    
            status = CM_Get_Parent(&devInstParent, devInfoData.DevInst, 0);
            if (status == CR_SUCCESS) 
            {
                status = CM_Get_Device_ID(devInstParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
                if (status == CR_SUCCESS)
                    _tprintf(TEXT("    %s\n"), szDeviceInstanceID);
            }
            else 
            {
                continue;
            }
        }
    
        return 0;
    }
    

    Debug result:

    1

    2