potisanのプログラミングメモ

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

C++20&Win API&WIL コンポーネントカテゴリマネージャーを使う

CLSID_StdComponentCategoriesMgrICatInformationインターフェイスを使ってコンポーネントカテゴリの情報を取得するコードです。カテゴリの概要や所属するクラスを列挙できます。

カテゴリの概要を列挙する

#include <string>

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

// WIL
#include <wil/com.h>

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    auto coinit{ wil::CoInitializeEx(COINIT_APARTMENTTHREADED) };

    auto catInfo{wil::CoCreateInstance<ICatInformation>(CLSID_StdComponentCategoriesMgr)};
    wil::com_ptr<IEnumCATEGORYINFO> enumCatInfo;
    catInfo->EnumCategories(0, enumCatInfo.put());

    CATEGORYINFO info;
    ULONG fetched;
    std::wstring output;
    while (enumCatInfo->Next(1, &info, &fetched) == S_OK)
    {
        output += info.szDescription;
        output += L"\r\n";
    }

    ::MessageBoxW(nullptr, output.c_str(), L"", MB_OK);

    return 0;
}

DeskBandカテゴリのクラスのCLSID・概要を列挙する

#include <bit>
#include <format>
#include <string>

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

// WIL
#include <wil/com.h>
#include <wil/resource.h>

std::wstring CLSIDToWString(const CLSID& clsid)
{
    std::wstring s(38, '\0');
    if (FAILED(::StringFromGUID2(clsid, s.data(), 39)))
        return {};
    return std::move(s);
}

std::wstring RegQueryStringValue(
    HKEY hkey,
    std::wstring_view valueName)
{
    DWORD type;
    DWORD size;
    if (::RegQueryValueEx(hkey, valueName.data(), nullptr, &type,
        nullptr, &size) != ERROR_SUCCESS)
    {
        return {};
    }
    if (type != REG_SZ && type != REG_EXPAND_SZ)
    {
        return {};
    }

    std::wstring buffer(size / sizeof(wchar_t) - 1, L'\0');
    if (::RegQueryValueEx(hkey, valueName.data(), nullptr, &type,
        std::bit_cast<LPBYTE>(buffer.data()), &size) != NOERROR)
    {
        return {};
    }
    return std::move(buffer);
}

std::wstring RegQueryStringValue(
    HKEY hkey,
    std::wstring_view subKey,
    DWORD samDesired,
    std::wstring_view valueName)
{
    wil::unique_hkey hkeySub;
    if (::RegOpenKeyExW(hkey, subKey.data(), 0, samDesired, hkeySub.put()) != ERROR_SUCCESS)
        return {};
    return RegQueryStringValue(hkeySub.get(), valueName);
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    auto coinit{ wil::CoInitializeEx(COINIT_APARTMENTTHREADED) };

    auto catInfo{ wil::CoCreateInstance<ICatInformation>(CLSID_StdComponentCategoriesMgr) };
    wil::com_ptr<IEnumCLSID> enumClsid;
    THROW_IF_FAILED(catInfo->EnumClassesOfCategories(1, &CATID_DeskBand, 0, nullptr, &enumClsid));

    CLSID clsid;
    ULONG fetched;
    std::wstring output;
    while (enumClsid->Next(1, &clsid, &fetched) == S_OK)
    {
        wil::unique_hkey clsidKey;
        auto clsidStr{ CLSIDToWString(clsid) };
        auto subKeyName{ std::format(L"CLSID\\{}", clsidStr) };
        output += std::format(L"{} {}\r\n",
            clsidStr,
            RegQueryStringValue(HKEY_CLASSES_ROOT, subKeyName, KEY_READ | KEY_WOW64_64KEY, L""));
    }

    ::MessageBoxW(nullptr, output.c_str(), L"", MB_OK);

    return 0;
}