Перечислить все пути к устройствам - PullRequest
1 голос
/ 19 июня 2020

Я пытаюсь получить пути ко всем устройствам с интерфейсами устройств, но когда я звоню 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;
}

Я просмотрел этот ответ , но у меня это не работает, так как использует GUID для устройств usb. В моем случае нужные устройства могут быть подключены не только через USB, но также через PCI и PCI express.

Мне нужны эти пути для использования в CreateFile. Я применил неподходящий подход? Есть ли альтернативы?

1 Ответ

1 голос
/ 21 июня 2020

мы можем получить список устройств идентификаторов экземпляров для экземпляров устройств на локальном компьютере с помощью CM_Get_Device_ID_ListW функции

затем для каждого ID получает дескриптор экземпляра устройства с помощью CM_Locate_DevNodeW

, а затем получает свойство экземпляра устройства с помощью CM_Get_DevNode_PropertyW. например DEVPKEY_NAME и DEVPKEY_Device_PDOName - имя объекта физического устройства (PDO). это имя мы можем использовать внутри 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);

}
...