potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

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

バイス情報要素のGUID、不透明ハンドル(Opaque Handle)、概要を列挙するサンプルコードです。C++&Win32 API デバイス情報要素のGUIDと不透明ハンドルを列挙するの拡張です。

#include <array>
#include <memory>
#include <string>
#include <numeric>
#include <iostream>
#include <tuple>
#include <list>

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

using namespace std;

using unique_devinfo_handle = unique_ptr<remove_pointer_t<HDEVINFO>,
    decltype(&::SetupDiDestroyDeviceInfoList)>;

unique_devinfo_handle make_unique_devinfo_handle(HDEVINFO handle) noexcept;
unique_devinfo_handle unique_SetupDiGetClassDevsW(
    const GUID* ClassGuid,
    LPCWSTR Enumerator,
    HWND hWndParent,
    DWORD Flags) noexcept;
wstring guid_to_wstring(const GUID& guid);
list<tuple<GUID, DWORD>> SetupDiEnumDeviceInfo_list(HDEVINFO DeviceInfoSet) noexcept;

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

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

    wcout << L"ClassGuid, DevInst, Class Description" << endl;
    array<wchar_t, LINE_LEN> class_des;
    for (const auto& [ClassGuid, DevInst] : devinfos)
    {
        ::SetupDiGetClassDescriptionExW(&ClassGuid,
            class_des.data(), class_des.size(), nullptr, nullptr, nullptr);
        wcout << guid_to_wstring(ClassGuid) << L", " << DevInst << L", " << class_des.data() << endl;
    }
}

unique_devinfo_handle make_unique_devinfo_handle(HDEVINFO handle) noexcept
{
    return unique_devinfo_handle(handle, &::SetupDiDestroyDeviceInfoList);
}

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

wstring guid_to_wstring(const GUID& guid)
{
    LPWSTR s;
    if (FAILED(StringFromCLSID(guid, &s)))
        return {};
    wstring str = s;
    CoTaskMemFree(s);
    return move(str);
}

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