枚举所有设备路径

Enumerate all device paths

我正在尝试获取所有具有设备接口的设备的路径,但是当我调用 SetupDiEnumDeviceInterfaces 时,我得到 ERROR_NO_MORE_ITEMS.


#include <windows.h>
#include <setupapi.h>

#include <iostream>
#include <string>
#include <vector>

int main(int argc, const char **argv)
{

    HDEVINFO hdevinfo = SetupDiGetClassDevs(0, 0, 0, DIGCF_ALLCLASSES |
            DIGCF_PRESENT |
            DIGCF_DEVICEINTERFACE);
    if (hdevinfo == INVALID_HANDLE_VALUE)
    {
        std::cerr << "Failed to get device information set" << std::endl;
        return -1;
    }

    SP_DEVINFO_DATA devinfoData{sizeof(SP_DEVINFO_DATA)};
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData{sizeof(SP_DEVICE_INTERFACE_DATA)};

    std::vector<std::string> devicePaths{};
    devicePaths.reserve(512);

    DWORD index = 0;

    while (SetupDiEnumDeviceInfo(hdevinfo, index, &devinfoData))
    {
        if (!SetupDiEnumDeviceInterfaces(hdevinfo, &devinfoData, &devinfoData.ClassGuid, index, &deviceInterfaceData))
        {
            DWORD error = GetLastError();
            std::cout << "Error: " << error << std::endl; // always get 259
            ++index;
            continue;
        }

        DWORD reqSize = 0;
        SetupDiGetDeviceInterfaceDetail(hdevinfo, &deviceInterfaceData, 0, 0, &reqSize, 0);
        PSP_INTERFACE_DEVICE_DETAIL_DATA pDetailData = PSP_INTERFACE_DEVICE_DETAIL_DATA(new char[reqSize]);
        pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &deviceInterfaceData, pDetailData, reqSize, 0, 0));
            devicePaths.push_back(pDetailData->DevicePath);

        delete [] pDetailData;

        ++index;
    }

    SetupDiDestroyDeviceInfoList(hdevinfo);

    return 0;
}

我已经研究过 this answer,但它对我不起作用,因为它使用 GUID 用于 USB 设备。在我的例子中,所需的设备不仅可以通过 USB 连接,还可以通过 PCI 和 PCI express 连接。

我需要在 CreateFile 中使用这些路径。 我采取了不适当的方法吗?有其他选择吗?

我们可以检索设备列表 instance IDs for the local computer's device instances with CM_Get_Device_ID_ListW 函数

然后通过CM_Locate_DevNodeW

为每个 ID 获取设备的设备实例句柄

然后使用 CM_Get_DevNode_PropertyW. for example DEVPKEY_NAME and DEVPKEY_Device_PDOName - name of the physical device object (PDO). this name we can use inside NtOpenFile

检索设备实例 属性
volatile UCHAR guz = 0;

void ProcessList(PZZWSTR pDeviceID)
{
    ULONG cb = 0, rcb = 0x80;
    CONFIGRET cr;
    PVOID stack = alloca(guz);

    union {
        PVOID buf;
        PBYTE PropertyBuffer;
    };

    HANDLE hFile;
    IO_STATUS_BLOCK iosb;
    UNICODE_STRING ObjectName;
    OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };

    do
    {
        DEVINST dnDevInst;

        if (CM_Locate_DevNodeW(&dnDevInst, pDeviceID, CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS)
        {
            DbgPrint("\n%S:\t", pDeviceID);

            DEVPROPTYPE PropertyType;

            static const DEVPROPKEY PropertyKeys[] = { DEVPKEY_Device_PDOName, DEVPKEY_NAME };
            static const PCSTR Names[] = { "PDOName", "FriendlyName" };

            ULONG i = _countof(PropertyKeys);

            do 
            {
                const DEVPROPKEY* PropertyKey = &PropertyKeys[--i];
                PCSTR Name = Names[i];

                do 
                {
                    if (cb < rcb)
                    {
                        cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
                    }

                    cr = CM_Get_DevNode_PropertyW(dnDevInst, PropertyKey, 
                        &PropertyType, PropertyBuffer, &(rcb = cb), 0);

                    if (cr == CR_SUCCESS && PropertyType == DEVPROP_TYPE_STRING)
                    {
                        DbgPrint("[%s=%S]\t", Name, PropertyBuffer);

                        if (!i)
                        {
                            RtlInitUnicodeString(&ObjectName, (PWSTR)PropertyBuffer);
                            NTSTATUS status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0);
                            if (0 <= status)
                            {
                                NtClose(hFile);
                            }
                            DbgPrint("=%x", status);
                        }
                    }

                } while (cr == CR_BUFFER_SMALL);

            } while (i);
        }

    } while (*(pDeviceID += wcslen(pDeviceID) + 1));
}

void cccm()
{
    CONFIGRET cr;
    PZZWSTR pDeviceID;
    ULONG ulLen;

    do 
    {
        if (CM_Get_Device_ID_List_SizeW(&ulLen, 0, CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS || ulLen <= 1)
        {
            break;
        }

        if (pDeviceID = new WCHAR[ulLen])
        {
            if ((cr = CM_Get_Device_ID_ListW(0, pDeviceID, ulLen, CM_GETIDLIST_FILTER_PRESENT)) == CR_SUCCESS)
            {
                if (*pDeviceID) ProcessList(pDeviceID);
            }
            delete [] pDeviceID;
        }
        else
        {
            break;
        }

    } while (cr == CR_BUFFER_SMALL);

}