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

Can I use SetupDiEnumDeviceInterfaces to get a DevicePath from SetupDiGetDeviceInterfaceDetail when no InterfaceClassGUID is known?

概览...

我读过 How to get device interface GUID for a device? and How to open a handle to a device using its Device Instance ID?, but I'm still confused about how I am to (or whether I should even) use SetupDiEnumDeviceInterfaces paired with SetupDiGetDeviceInterfaceDetail to get a DevicePath that can be opened with CreateFile to access the device when no device interface class GUID is known. My question is based on the MSDN article here and here 依赖于这些功能。

更多详情...

我的问题的高级别是我有一个音频 USB 设备,我需要发送控制传输命令。为此,我想使用 WinUSB API, and to do that I need to get a handle to the device via CreateFile. Unfortunately, there is no .inf file associated with the device and so there is no known device interface class GUID. If one plugs the device in, Windows associates with it usbaudio.sys as the driver. To start talking over WinUSB, I use libwdi 将 WinUSB 安装为设备驱动程序,以便我可以通过 WinUSB API 与其通信。为了完成 WinUSB 的安装,libwdi 动态创建了一个自签名的 .cat 和 .inf 文件对,遗憾的是它没有定义设备接口 class。事实上,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,
   0,
   &usbInterface)

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

所以,一般来说,当没有接口 class 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, 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, NULL, interfaceGuid, instance, &devInterfaceData))
        goto cleanup;

    // Call this with an empty buffer to the required size of the structure.
    ULONG requiredSize;
    SetupDiGetDeviceInterfaceDetailW(hDevInfo, &devInterfaceData, NULL, 0, &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, &devInterfaceData, devInterfaceDetailData, requiredSize, &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)
       ;
}