I have a DEVINST, I need the Device Path

走远了吗. 提交于 2019-12-02 10:48:19

问题


I'm trying to open a WinUSB device that is part of a composite device. I have located the correct child device using cfgmgr32, and have its DEVINST number. In order to open it with WinUSB, I need to first call CreateFile, for which I need the Device Path.

The Device Path looks like:

\\\\?\\usb#vid_9999&pid_0102#3555303335351909000b0#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

How can I obtain the Device Path?


回答1:


This function returns a list of NULL-terminated Device Paths (that's what we get from CM_Get_Device_Interface_List)

You need to pass it the DEVINST, and the wanted interface GUID.

Since both the DEVINST and interface GUID are specified, it is highly likely that CM_Get_Device_Interface_List will return a single Device Path for that interface, but technically you should be prepared to get more than one result.

I used this function successfully in production code for getting the Device Interface of a USB HUB (GUID_CLASS_USBHUB): I used the resulting Device Path with CreateFile and opened it succesfully.

It is responsibility of the caller to delete[] the returned list if the function returns successfully (return code 0)

int GetDevInstInterfaces(DEVINST dev, LPGUID interfaceGUID, wchar_t**outIfaces, ULONG* outIfacesLen)
{
    CONFIGRET cres;
    if (!outIfaces)
        return -1;
    if (!outIfacesLen)
        return -2;

    // Get System Device ID
    WCHAR sysDeviceID[256];
    cres = CM_Get_Device_ID(dev, sysDeviceID, sizeof(sysDeviceID) / sizeof(sysDeviceID[0]), 0);
    if (cres != CR_SUCCESS)
        return -11;

    // 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];

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



回答2:


I recommend looking at the get_filename_from_devinst_and_guid function which is part of libusbp.

The basic outline is:

  1. Make sure you know the device interface GUID you are looking for. That is the thing in brackets at the end of the filename you provided. This usually comes from the INF file that sets up WinUSB, though it can also come from MS OS descriptors on the device. You can find it in the registry. You have to pack it into a Win32 API GUID struct.
  2. Call SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); to get a list of all the present (connected) devices supporting that device interface GUID.
  3. Use SetupDiEnumDeviceInfo to iterate through the list until you find the item that matches the DEVINST you already found.
  4. Use SetupDiEnumDeviceInterfaces to get the list of interfaces for that item. There should only be one entry because you already specified the device interface GUID you are interested in.
  5. Use SetupDiGetDeviceInterfaceDetail to get SP_DEVICE_INTERFACE_DETAIL_DATA_A data structure.
  6. The filename you are looking for is in the DevicePath member of that structure.


来源:https://stackoverflow.com/questions/50601220/i-have-a-devinst-i-need-the-device-path

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!