potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。

C++20&Win API デバイス情報要素のGUID、不透明ハンドル、概要を列挙する

バイス情報要素のGUID、不透明ハンドル(Opaque Handle)、概要を列挙するサンプルコードです。

#include <memory>
#include <string>
#include <format>
#include <numeric>
#include <iostream>
#include <list>

#pragma comment(lib, "SetupAPI.lib")
#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <SetupAPI.h>

struct HDEVINFO_deleter {
    void operator() (HDEVINFO handle) const noexcept {
        ::SetupDiDestroyDeviceInfoList(handle);
    }
};
using unique_HDEVINFO = std::unique_ptr<std::remove_pointer_t<HDEVINFO>, HDEVINFO_deleter>;

unique_HDEVINFO unique_SetupDiGetClassDevsW(
    const GUID* ClassGuid,
    LPCWSTR Enumerator,
    HWND hWndParent,
    DWORD Flags) noexcept
{
    return unique_HDEVINFO(::SetupDiGetClassDevsW(ClassGuid, Enumerator, hWndParent, Flags));
}

std::wstring GUIDToWString(const GUID& guid)
{
    std::wstring s(38, L'\0');
    if (FAILED(::StringFromGUID2(guid, s.data(), 38)))
        return {};
    return std::move(s);
}

std::list<SP_DEVINFO_DATA> SetupDiEnumDeviceInfo_list(HDEVINFO DeviceInfoSet) noexcept
{
    std::list<SP_DEVINFO_DATA> list;
    for (DWORD i = 0; i < std::numeric_limits<DWORD>::max(); i++)
    {
        SP_DEVINFO_DATA data{ sizeof(data) };
        if (!::SetupDiEnumDeviceInfo(DeviceInfoSet, i, &data))
            break;
        list.emplace_back(data);
    }
    return std::move(list);
}

int main()
{
    std::wcout.imbue(std::locale("", std::locale::ctype));

    auto devinfo_handle{ unique_SetupDiGetClassDevsW(
        nullptr,
        nullptr,
        nullptr,
        DIGCF_ALLCLASSES) };
    auto devinfos{ SetupDiEnumDeviceInfo_list(devinfo_handle.get()) };

    std::wcout << L"ClassGuid, DevInst, Class Description" << std::endl;
    std::wstring class_des(LINE_LEN - 1, L'\0');
    for (const auto& devinfo : devinfos)
    {
        ::SetupDiGetClassDescriptionExW(&devinfo.ClassGuid,
            class_des.data(), class_des.size(), nullptr, nullptr, nullptr);
        std::wcout
            << std::format(L"{}, {}, {}",
                GUIDToWString(devinfo.ClassGuid), devinfo.DevInst, class_des.data())
            << std::endl;
    }
}