potisanのプログラミングメモ

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

C++20&WIL プロパティ記述子を列挙する

C++20とWILでプロパティ記述子(IPropertyDescriptor)を列挙するサンプルコードです。実行するとプロパティの正規名と表示名を出力します。

#include <functional>
#include <format>
#include <iostream>

#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <propsys.h>

// Microsoft WIL 1.0.220201.1
#include "wil/com.h"

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

void ForEachPropertyDescriptions(
    IPropertySystem* ppropSys,
    PROPDESC_ENUMFILTER enumFilter,
    std::function<void(IPropertyDescription*)> fn)
{
    wil::com_ptr<IPropertyDescriptionList> propDescs;
    THROW_IF_FAILED(ppropSys->EnumeratePropertyDescriptions(
        enumFilter, IID_PPV_ARGS(propDescs.put())));

    UINT count;
    THROW_IF_FAILED(propDescs->GetCount(&count));
    for (UINT i = 0; i < count; i++)
    {
        wil::com_ptr<IPropertyDescription> propDesc;
        THROW_IF_FAILED(propDescs->GetAt(i, IID_PPV_ARGS(propDesc.put())));
        fn(propDesc.get());
    }
}

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

    auto coinit{ wil::CoInitializeEx(COINIT_APARTMENTTHREADED) };

    auto propSys{ wil::CoCreateInstance<PropertySystem, IPropertySystem>() };
    ForEachPropertyDescriptions(
        propSys.get(),
        PROPDESC_ENUMFILTER::PDEF_SYSTEM,
        [](IPropertyDescription* ppropDesc)
        {
            // TODO:ここでIPropertyDescriptionを処理します。
            wil::unique_cotaskmem_string pcanonicalName;
            wil::unique_cotaskmem_string pdisplayName;
            PROPERTYKEY propKey{};
            ppropDesc->GetCanonicalName(pcanonicalName.put());
            ppropDesc->GetDisplayName(pdisplayName.put());
            ppropDesc->GetPropertyKey(&propKey);

            std::wcout
                << std::format(L"{}, {}, ({}, {})",
                    wil::string_get_not_null(pcanonicalName),
                    wil::string_get_not_null(pdisplayName),
                    GUIDToWString(propKey.fmtid),
                    propKey.pid)
                << std::endl;
        });

    return 0;
}