potisanのプログラミングメモ

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

17 C++&Win32 API ファイルの多言語対応リソースの言語とファイルパスを取得する

C++とWin32 APIでファイルの多言語対応リソース(Microsoft Docsでは「language-specific resource files」)の言語名とMUIファイルパスを取得するサンプルコードです。

// 動作確認環境:C++ 17
#include <io.h>
#include <fcntl.h>

#include <array>
#include <filesystem>
#include <iostream>
#include <string>

#define STRICT
#include <Windows.h>

using namespace std;

filesystem::path get_system_directory() noexcept;

int main()
{
    const auto path = get_system_directory() / L"comctl32.dll";

    // ユニコードモードの設定
    _setmode(_fileno(stdout), _O_U16TEXT);

    // 言語名とMUIファイルパスの最大長の取得
    ULONG maxLangLen;
    ULONG maxFileMuiPath;
    ULONGLONG enumId = 0;
    if (!GetFileMUIPath(MUI_USE_SEARCH_ALL_LANGUAGES, path.c_str(),
        nullptr, &maxLangLen, nullptr, &maxFileMuiPath, &enumId))
    {
        return 0;
    }

    // バッファーの確保
    wstring lang(maxLangLen, L'\0');
    wstring fileMuiPath(maxFileMuiPath, L'\0');

    // 言語の名前とMUIファイルパスの取得
    for (;;)
    {
        ULONG langLen = maxLangLen;
        ULONG fileMuiPathLen = maxFileMuiPath;
        if (!GetFileMUIPath(MUI_USE_SEARCH_ALL_LANGUAGES, path.c_str(),
            lang.data(), &langLen, fileMuiPath.data(), &fileMuiPathLen, &enumId))
        {
            break;
        }
        wcout << lang << L"," << fileMuiPath << endl;
    }

    return 0;
}

filesystem::path get_system_directory() noexcept
{
    array<WCHAR, MAX_PATH> buffer;
    if (!GetSystemDirectoryW(buffer.data(), static_cast<DWORD>(buffer.size()))) {
        return {};
    }
    return buffer.data();
}

参考