当不知道 InterfaceClassGUID 时,我可以使用 SetupDiEnumDeviceInterfaces 从 SetupDiGetDeviceInterfaceDetail 获取 DevicePath 吗?

问题描述

概述...

我已经阅读了 How to get device interface GUID for a device?How to open a handle to a device using its Device Instance ID?,但我仍然对如何(或者我是否应该)使用 SetupDiEnumDeviceInterfacesSetupDiGetDeviceInterfaceDetail 配对感到困惑获取一个 DevicePath,当不知道 device interface class GUID 时,可以使用 CreateFile 打开它以访问设备。我的问题基于依赖这些函数的 MSDN 文章 herehere

更多详情...

我的问题最严重的是我有一个音频 USB 设备,我需要发送控制传输命令。为此,我想使用 WinUSB 的 API,并且要做到这一点,我需要通过 CreateFile 获取设备句柄。不幸的是,没有与设备关联的 .inf 文件,因此没有已知的设备接口类 GUID。如果插入设备,Windows 会将其关联为 usbaudio.sys 作为驱动程序。为了开始讨论 WinUSB,我使用 libwdi 安装 WinUSB 作为设备驱动程序,以便我可以通过 WinUSB API 与它通信。为了完成 WinUSB 的安装,libwdi 动态创建了一个自签名的 .cat 和 .inf 文件对,遗憾的是没有定义设备接口类。其实INF文件里面有以下内容

[NoDeviceInterfaceGUID]
; Avoids adding a DeviceInterfaceGUID for generic driver

因此,尽管我现在已将 usbaudio.sys 换成 winusb.sys,但我无法与设备通信。

起初我想也许我应该尝试使用 GUID_DEVINTERFACE_USB_DEVICE,理由是这是 WinUSB,因此被视为通用 USB 设备。但是,如果我调用

SetupDiEnumDeviceInterfaces(_deviceList,&devInfo,&GUID_DEVINTERFACE_USB_DEVICE,&usbInterface)

失败并且 GetLastError 立即返回 259 或 ERROR_NO_MORE_ITEMS。我假设这意味着它没有实现接口?

那么,一般来说,当不知道接口类 guid 时,我是否能够以任何形式使用上述函数获取完整的设备路径? 提前感谢您抽出宝贵时间。

解决方法

是的,首先您需要为通过 SetupDiGetClassDevs 实现接口的设备获取一个设备信息集,然后选择其中一个设备并读取其设备接口数据,并使用它获取包含设备路径的设备接口详细信息。

示例:

#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include <usbioctl.h>
#include <stdio.h>

BOOL DevicePath(_In_ LPCGUID interfaceGuid,DWORD instance)
{
    BOOL result = FALSE;
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W devInterfaceDetailData = NULL;

    HDEVINFO hDevInfo = SetupDiGetClassDevsW(interfaceGuid,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if(hDevInfo == INVALID_HANDLE_VALUE)
        goto cleanup;

    SP_DEVICE_INTERFACE_DATA devInterfaceData;
    devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    if(!SetupDiEnumDeviceInterfaces(hDevInfo,interfaceGuid,instance,&devInterfaceData))
        goto cleanup;

    // Call this with an empty buffer to the required size of the structure.
    ULONG requiredSize;
    SetupDiGetDeviceInterfaceDetailW(hDevInfo,&devInterfaceData,&requiredSize,NULL);
    if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        goto cleanup;

    devInterfaceDetailData = malloc(requiredSize);
    if(!devInterfaceDetailData)
        goto cleanup;

    devInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    if(!SetupDiGetDeviceInterfaceDetailW(hDevInfo,devInterfaceDetailData,requiredSize,NULL))
        goto cleanup;

    wprintf(L"%s\n",devInterfaceDetailData->DevicePath);
    result = TRUE;

cleanup:
    if(hDevInfo != INVALID_HANDLE_VALUE)
        SetupDiDestroyDeviceInfoList(hDevInfo);
    free(devInterfaceDetailData);
    return result;
}

int main()
{
    for(DWORD i = 0; DevicePath(&GUID_DEVINTERFACE_USB_DEVICE,i); ++i)
       ;
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...