-
-
Notifications
You must be signed in to change notification settings - Fork 548
/
dll_resources.cpp
126 lines (103 loc) · 4.38 KB
/
dll_resources.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
* Copyright (C) 2014 Patrick Mours
* SPDX-License-Identifier: BSD-3-Clause OR MIT
*/
#include "dll_resources.hpp"
#include <cassert>
#include <algorithm> // std::find
#include <utf8/unchecked.h>
#include <Windows.h>
extern HMODULE g_module_handle;
reshade::resources::data_resource reshade::resources::load_data_resource(unsigned short id)
{
const HRSRC info = FindResource(g_module_handle, MAKEINTRESOURCE(id), RT_RCDATA);
assert(info != nullptr);
const HGLOBAL handle = LoadResource(g_module_handle, info);
data_resource result;
result.data = LockResource(handle);
result.data_size = SizeofResource(g_module_handle, info);
return result;
}
std::string reshade::resources::load_string(unsigned short id)
{
LPCWSTR s = nullptr;
const int length = LoadStringW(g_module_handle, id, reinterpret_cast<LPWSTR>(&s), 0);
assert(length > 0);
std::string utf8_string;
utf8_string.reserve(length);
utf8::unchecked::utf16to8(s, s + length, std::back_inserter(utf8_string));
return utf8_string;
}
#if RESHADE_LOCALIZATION
std::string reshade::resources::get_current_language()
{
ULONG num = 0, size = 0;
if (!GetThreadPreferredUILanguages(MUI_LANGUAGE_NAME | MUI_UI_FALLBACK, &num, nullptr, &size))
return std::string();
std::vector<WCHAR> languages(size);
if (!GetThreadPreferredUILanguages(MUI_LANGUAGE_NAME | MUI_UI_FALLBACK, &num, languages.data(), &size) || num == 0)
return std::string();
std::string language;
// Extract first language from the double null-terminated multi-string buffer
utf8::unchecked::utf16to8(languages.begin(), std::find(languages.begin(), languages.end(), L'\0'), std::back_inserter(language));
return language;
}
std::string reshade::resources::set_current_language(const std::string &language)
{
ULONG num = 0, size = 0;
if (!GetThreadPreferredUILanguages(MUI_LANGUAGE_NAME | MUI_THREAD_LANGUAGES, &num, nullptr, &size))
return language;
std::vector<WCHAR> languages(size);
if (!GetThreadPreferredUILanguages(MUI_LANGUAGE_NAME | MUI_THREAD_LANGUAGES, &num, languages.data(), &size))
return language;
std::string prev_language;
if (num != 0)
// Extract first language from the double null-terminated multi-string buffer
utf8::unchecked::utf16to8(languages.begin(), std::find(languages.begin(), languages.end(), L'\0'), std::back_inserter(prev_language));
if (language == prev_language)
return language;
constexpr WCHAR english_language[] = L"en-US";
// Create new double null-terminated buffer with the new language
languages.clear();
languages.reserve(language.size() + std::size(english_language) + 2);
utf8::unchecked::utf8to16(language.begin(), language.end(), std::back_inserter(languages));
languages.push_back(L'\0');
if (!language.empty())
// Fall back to English by default if a resource does not exist in the specified language
languages.insert(languages.end(), english_language, english_language + std::size(english_language));
languages.push_back(L'\0');
SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, languages.data(), &num);
return prev_language;
}
std::vector<std::string> reshade::resources::get_languages()
{
const DWORD error = GetLastError();
// Find a valid string table resource to use as reference to query languages for
LPCWSTR first_string_table_block = nullptr;
EnumResourceNamesW(g_module_handle, RT_STRING,
[](HMODULE, LPCWSTR, LPWSTR lpName, LONG_PTR lParam) -> BOOL {
*reinterpret_cast<LPCWSTR *>(lParam) = lpName;
return FALSE;
}, reinterpret_cast<LONG_PTR>(&first_string_table_block));
if (first_string_table_block == nullptr)
return {};
std::vector<std::string> languages;
EnumResourceLanguages(g_module_handle, RT_STRING, first_string_table_block,
[](HMODULE, LPCTSTR, LPCTSTR, LANGID wLanguage, LONG_PTR lParam) -> BOOL {
WCHAR locale_name[16];
const int length = LCIDToLocaleName(MAKELCID(wLanguage, SORT_DEFAULT), locale_name, ARRAYSIZE(locale_name), 0);
if (length != 0)
{
std::string utf8_locale_name;
utf8_locale_name.reserve(length);
// Length includes null-terminator
utf8::unchecked::utf16to8(locale_name, locale_name + length - 1, std::back_inserter(utf8_locale_name));
reinterpret_cast<std::vector<std::string> *>(lParam)->push_back(std::move(utf8_locale_name));
}
return TRUE;
}, reinterpret_cast<LONG_PTR>(&languages));
// Prevent 'ERROR_RESOURCE_ENUM_USER_STOP' generated by 'EnumResourceNamesW' above from leaking through
SetLastError(error);
return languages;
}
#endif