mirror of https://github.com/microsoft/WSL
103 lines
2.5 KiB
C++
103 lines
2.5 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Localization.cpp
|
|
|
|
Abstract:
|
|
|
|
This file contains the class to format localized strings.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "Localization.h"
|
|
|
|
extern bool g_runningInService;
|
|
|
|
namespace {
|
|
|
|
std::vector<std::wstring> GetUserLanguagesImpl()
|
|
{
|
|
DWORD count{};
|
|
DWORD bufferSize{};
|
|
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, nullptr, &bufferSize);
|
|
|
|
std::vector<wchar_t> buffer(bufferSize, '\0');
|
|
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, buffer.data(), &bufferSize))
|
|
{
|
|
LOG_LAST_ERROR_MSG("GetUserDefaultLocaleName failed");
|
|
return {L""};
|
|
}
|
|
|
|
std::vector<std::wstring> languages;
|
|
for (size_t i = 0; buffer[i] != '\0'; i += wcslen(&buffer[i]) + 1)
|
|
{
|
|
languages.emplace_back(&buffer[i]);
|
|
}
|
|
|
|
return languages;
|
|
}
|
|
|
|
std::vector<std::wstring> GetUserLanguages(bool impersonate)
|
|
{
|
|
if (g_runningInService)
|
|
{
|
|
// N.B. If we're in the service, the locale needs to be queried every time since different users
|
|
// can have different language configurations.
|
|
std::optional<wil::unique_coreverttoself_call> revert;
|
|
if (impersonate)
|
|
{
|
|
// If we're running in wslservice.exe, impersonation is needed to get the correct locale
|
|
try
|
|
{
|
|
revert = wil::CoImpersonateClient();
|
|
}
|
|
catch (...)
|
|
{
|
|
// Continue if this failed so we fall back to the machine's locale
|
|
LOG_CAUGHT_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
return GetUserLanguagesImpl();
|
|
}
|
|
else
|
|
{
|
|
static std::vector<std::wstring> languages;
|
|
static std::once_flag flag;
|
|
std::call_once(flag, [&]() { languages = GetUserLanguagesImpl(); });
|
|
|
|
return languages;
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
LPCWSTR wsl::shared::Localization::LookupString(const std::vector<std::pair<std::wstring, LPCWSTR>>& strings, Options options)
|
|
{
|
|
WI_ASSERT(!strings.empty());
|
|
|
|
try
|
|
{
|
|
for (const auto& language : GetUserLanguages(options != Options::DontImpersonate && g_runningInService))
|
|
{
|
|
for (const auto& e : strings)
|
|
{
|
|
if (e.first == language)
|
|
{
|
|
return e.second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
LOG_CAUGHT_EXCEPTION();
|
|
}
|
|
|
|
// Default to English is string is not found (English is always the first entry)
|
|
return strings[0].second;
|
|
}
|