potisanのプログラミングメモ

プログラミング素人です。昔の自分を育ててくれたネット情報に少しでも貢献できるよう、情報を貯めていこうと思っています。Windows環境のC++やC#がメインです。

C++20&WinAPI&WIL ZIPファイルに関連付けられたCLSIDを取得する

ZIPファイルに関連付けられたCLSIDとそのProgIDを取得するコードです。

#include <array>
#include <bit>
#include <format>
#include <string>
#include <optional>

#define STRICT
#include <windows.h>

#include "wil/resource.h"

std::optional<GUID> GetSystemFileAssociationCLSID(PCWSTR name) noexcept
{
    const auto path = std::format(L"SystemFileAssociations\\{}\\CLSID", name);
    wil::unique_hkey hkey;
    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, path.data(), 0, KEY_READ, hkey.put()) != ERROR_SUCCESS)
    {
        return std::nullopt;
    }

    DWORD keyType = 0;
    DWORD dataLen = 0;
    RegQueryValueExW(hkey.get(), L"", nullptr, &keyType, nullptr, &dataLen);
    if (keyType != REG_SZ || dataLen != 39 * sizeof(wchar_t))
    {
        return std::nullopt;
    }

    std::array<wchar_t, 39> data;
    if (RegQueryValueExW(hkey.get(), L"", nullptr, &keyType,
        std::bit_cast<PBYTE>(data.data()), &dataLen) != ERROR_SUCCESS || keyType != REG_SZ)
    {
        return std::nullopt;
    }

    GUID guid;
    if (CLSIDFromString(data.data(), &guid) != S_OK)
    {
        return std::nullopt;
    }

    return guid;
}

wil::unique_cotaskmem_string ProgIDFromCLSID(REFCLSID clsid)
{
    wil::unique_cotaskmem_string progId;
    THROW_IF_FAILED(ProgIDFromCLSID(clsid, progId.put()));
    return progId;
}

int main()
{
    auto clsid = GetSystemFileAssociationCLSID(L".zip");
    if (!clsid) return 0;

    auto progId = ProgIDFromCLSID(*clsid);

    return 0;
}

参考