3

我正在使用 和 API 枚举设备管理CM_Locate_DevNode()器树CM_Get_Child()CM_Get_DevNode_Registry_Property()我能够获得设备实例句柄。

使用该句柄,我试图获取设备句柄来查询设备的字符串描述符。

设备实例句柄和设备句柄是否相同,或者有什么方法可以从设备实例句柄中获取设备句柄?

4

1 回答 1

1

设备实例句柄和设备句柄是否相同,或者有什么方法可以从设备实例句柄中获取设备句柄?

不,它们不一样。一种称为Device Instance ID,另一种称为 Device Path。

您的问题与类似。

使用该句柄,我试图获取设备句柄来查询设备的字符串描述符。

为了从设备获取 USB 字符串描述符,给定其设备实例 ID,您需要:

  1. 使用CM_Get_Parent获取其父 USB 集线器
  2. GetInterfaces然后,使用我在下面提供的功能获取它的 USB 集线器设备接口
  3. 然后,您可以在 CreateFile 中使用 USB Device Interface 作为 Device Path,然后调用 DeviceIoControl 来获取您想要的 USB String Descriptor。

这个函数返回一个以 NULL 结尾的设备路径列表(这就是我们从中得到的CM_Get_Device_Interface_List

您需要将 Device Instance ID 和所需的 interface 传递给它GUID,对于 USB HUB,它是

const GUID* ptrGUID = &GUID_DEVINTERFACE_USB_HUB;

由于指定了设备实例 ID 和接口 GUID,因此很可能CM_Get_Device_Interface_List会为该接口返回单个设备路径,但从技术上讲,您应该准备好获得多个结果。

我在生产代码中成功地使用了这个函数的一个细微变化来获取 USB HUB 的设备接口(GUID_CLASS_USBHUB):我使用了生成的设备路径和 CreateFile 并成功打开它。

delete[]如果函数成功返回(返回代码 0),则由调用者对返回列表负责

int GetInterfaces(const WCHAR* sysDeviceID, const LPGUID interfaceGUID, wchar_t**outIfaces, ULONG* outIfacesLen)
{
    CONFIGRET cres;
    if (!outIfaces)
        return -1;
    if (!outIfacesLen)
        return -2;

    // Get list size
    ULONG ifaceListSize = 0;
    cres = CM_Get_Device_Interface_List_Size(&ifaceListSize, interfaceGUID, sysDeviceID, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
    if (cres != CR_SUCCESS)
        return -12;

    // Allocate memory for the list
    wchar_t* ifaceList = new wchar_t[ifaceListSize*2];    // Double the required size, in order minimize the chances of getting CR_BUFFER_SMALL errors

    // Populate the list
    cres = CM_Get_Device_Interface_List(interfaceGUID, sysDeviceID, ifaceList, ifaceListSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
    if (cres != CR_SUCCESS) {
        delete[] ifaceList;
        return -13;
    }

    // Return list
    *outIfaces = ifaceList;
    *outIfacesLen = ifaceListSize;

    return 0;
}
于 2019-07-08T11:34:22.217 回答