potisanのプログラミングメモ

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

C++20&Win API&WIL バッテリーデバイスの名前を列挙する

C++20・Win API・WILでバッテリーデバイスの名前を列挙するサンプルコードです。

#include <functional>
#include <string>
#include <vector>

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

#include "wil/resource.h"

struct hdevinfo_invalid_resource_policy : wil::details::resource_policy<
    HDEVINFO,
    decltype(&::SetupDiDestroyDeviceInfoList),
    &::SetupDiDestroyDeviceInfoList,
    wil::details::pointer_access_all,
    HDEVINFO,
    INT_PTR,
    -1,
    HDEVINFO>
{
    __forceinline static bool is_valid(HANDLE ptr) WI_NOEXCEPT { return ((ptr != INVALID_HANDLE_VALUE) && (ptr != nullptr)); }
};

using unique_hdevinfo = wil::unique_any_t<wil::details::unique_storage<hdevinfo_invalid_resource_policy>>;

std::wstring SetupDiGetDevicePropertyWString(
    HDEVINFO DeviceInfoSet,
    PSP_DEVINFO_DATA DeviceInfoData,
    CONST DEVPROPKEY& PropertyKey,
    DWORD Flags)
{
    DWORD propType = 0;
    DWORD propSize = 0;
    ::SetupDiGetDevicePropertyW(DeviceInfoSet, DeviceInfoData,
        &PropertyKey, &propType, nullptr, 0, &propSize, Flags);
    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && propType == DEVPROP_TYPE_STRING)
    {
        std::wstring buffer(propSize / sizeof(wchar_t) - 1, L'\0');
        if (::SetupDiGetDevicePropertyW(DeviceInfoSet, DeviceInfoData,
            &PropertyKey, &propType, reinterpret_cast<PBYTE>(buffer.data()),
            propSize, &propSize, Flags))
        {
            return buffer;
        }
    }
    return {};
}

void EnumerateSetupDiDeviceInfos(
    HDEVINFO DeviceInfoSet,
    std::function<void(HDEVINFO DeviceInfoSet, SP_DEVINFO_DATA& Data, DWORD MemberIndex)> fn)
{
    SP_DEVINFO_DATA data{ sizeof(SP_DEVINFO_DATA) };
    for (DWORD i = 0; ::SetupDiEnumDeviceInfo(DeviceInfoSet, i, &data); i++)
        fn(DeviceInfoSet, data, i);
}

#include <iostream>

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

    unique_hdevinfo hdevinfo(::SetupDiGetClassDevsW(
        &GUID_DEVCLASS_BATTERY, nullptr, nullptr, DIGCF_PRESENT));
    EnumerateSetupDiDeviceInfos(hdevinfo.get(),
        [](HDEVINFO DeviceInfoSet, SP_DEVINFO_DATA& Data, DWORD MemberIndex)
        {
            auto description = SetupDiGetDevicePropertyWString(
                DeviceInfoSet, &Data, DEVPKEY_Device_DeviceDesc, 0);
            std::wcout << description << std::endl;
        });

    return 0;
}