获取USB设备C++的父信息

Get parent information of a USB device C++

我正在开发一个 MFC 工具来检查连接的 USB 设备的一些驱动程序信息,例如位置信息、父级、硬件 ID 等。我已经获得了我想要的所有其他信息,但我一直无法获取设备家长信息。

我在我的代码中使用了Setupapi.dll来获取设备信息。 使用 SetupDiGetClassDevs 函数获取 USB 设备信息句柄。 使用 SetupDiEnumDeviceInfo 函数获取特定设备信息数据。 使用 SetupDiGetDeviceRegistryProperty 函数获取设备描述和硬件 ID。

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

获取USB设备的父信息对我很有用。请帮忙提供一些线索。

please look into image

CM_Locate_DevNode 打开给定设备 ID 的设备句柄;

CM_Get_Parent找到父设备;

CM_Get_Device_ID_SizeCM_Get_Device_ID 获取设备句柄和 return 设备 ID。

样本:

#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;
}

调试结果: