Write Dalamud.Boot log to TEMP, then CWD (#886)

This commit is contained in:
kizer 2022-06-19 18:42:41 +09:00 committed by GitHub
parent cd41fda202
commit ce49874935
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 22375 additions and 98 deletions

View file

@ -121,6 +121,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="DalamudStartInfo.cpp" />
<ClCompile Include="hooks.cpp" /> <ClCompile Include="hooks.cpp" />
<ClCompile Include="logging.cpp"> <ClCompile Include="logging.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
@ -161,7 +162,7 @@
<ClInclude Include="..\lib\TsudaKageyu-minhook\src\HDE\table32.h" /> <ClInclude Include="..\lib\TsudaKageyu-minhook\src\HDE\table32.h" />
<ClInclude Include="..\lib\TsudaKageyu-minhook\src\HDE\table64.h" /> <ClInclude Include="..\lib\TsudaKageyu-minhook\src\HDE\table64.h" />
<ClInclude Include="..\lib\TsudaKageyu-minhook\src\trampoline.h" /> <ClInclude Include="..\lib\TsudaKageyu-minhook\src\trampoline.h" />
<ClInclude Include="bootconfig.h" /> <ClInclude Include="DalamudStartInfo.h" />
<ClInclude Include="hooks.h" /> <ClInclude Include="hooks.h" />
<ClInclude Include="logging.h" /> <ClInclude Include="logging.h" />
<ClInclude Include="unicode.h" /> <ClInclude Include="unicode.h" />

View file

@ -70,6 +70,9 @@
<ClCompile Include="hooks.cpp"> <ClCompile Include="hooks.cpp">
<Filter>Dalamud.Boot DLL</Filter> <Filter>Dalamud.Boot DLL</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="DalamudStartInfo.cpp">
<Filter>Dalamud.Boot DLL</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\lib\CoreCLR\CoreCLR.h"> <ClInclude Include="..\lib\CoreCLR\CoreCLR.h">
@ -99,7 +102,7 @@
<ClInclude Include="hooks.h"> <ClInclude Include="hooks.h">
<Filter>Dalamud.Boot DLL</Filter> <Filter>Dalamud.Boot DLL</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="bootconfig.h"> <ClInclude Include="DalamudStartInfo.h">
<Filter>Dalamud.Boot DLL</Filter> <Filter>Dalamud.Boot DLL</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="xivfixes.h"> <ClInclude Include="xivfixes.h">

View file

@ -0,0 +1,113 @@
#include "pch.h"
#include "DalamudStartInfo.h"
#include "utils.h"
DalamudStartInfo g_startInfo;
void from_json(const nlohmann::json& json, DalamudStartInfo::WaitMessageboxFlags& value) {
if (json.is_number_integer()) {
value = static_cast<DalamudStartInfo::WaitMessageboxFlags>(json.get<int>());
} else if (json.is_array()) {
value = DalamudStartInfo::WaitMessageboxFlags::None;
for (const auto& item : json) {
if (item.is_number_integer()) {
value = static_cast<DalamudStartInfo::WaitMessageboxFlags>(static_cast<int>(value) | item.get<int>());
} else if (item.is_string()) {
const auto iteml = unicode::convert<std::string>(item.get<std::string>(), &unicode::lower);
if (item == "beforeinitialize")
value = static_cast<DalamudStartInfo::WaitMessageboxFlags>(static_cast<int>(value) | static_cast<int>(DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize));
else if (item == "beforedalamudentrypoint")
value = static_cast<DalamudStartInfo::WaitMessageboxFlags>(static_cast<int>(value) | static_cast<int>(DalamudStartInfo::WaitMessageboxFlags::BeforeDalamudEntrypoint));
}
}
} else if (json.is_string()) {
value = DalamudStartInfo::WaitMessageboxFlags::None;
for (const auto& item : utils::split(json.get<std::string>(), ",")) {
const auto iteml = unicode::convert<std::string>(item, &unicode::lower);
if (iteml == "beforeinitialize")
value = static_cast<DalamudStartInfo::WaitMessageboxFlags>(static_cast<int>(value) | static_cast<int>(DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize));
else if (iteml == "beforedalamudentrypoint")
value = static_cast<DalamudStartInfo::WaitMessageboxFlags>(static_cast<int>(value) | static_cast<int>(DalamudStartInfo::WaitMessageboxFlags::BeforeDalamudEntrypoint));
}
}
}
void from_json(const nlohmann::json& json, DalamudStartInfo::DotNetOpenProcessHookMode& value) {
if (json.is_number_integer()) {
value = static_cast<DalamudStartInfo::DotNetOpenProcessHookMode>(json.get<int>());
} else if (json.is_string()) {
const auto langstr = unicode::convert<std::string>(json.get<std::string>(), &unicode::lower);
if (langstr == "importhooks")
value = DalamudStartInfo::DotNetOpenProcessHookMode::ImportHooks;
else if (langstr == "directhook")
value = DalamudStartInfo::DotNetOpenProcessHookMode::DirectHook;
}
}
void from_json(const nlohmann::json& json, DalamudStartInfo::ClientLanguage& value) {
if (json.is_number_integer()) {
value = static_cast<DalamudStartInfo::ClientLanguage>(json.get<int>());
} else if (json.is_string()) {
const auto langstr = unicode::convert<std::string>(json.get<std::string>(), &unicode::lower);
if (langstr == "japanese")
value = DalamudStartInfo::ClientLanguage::Japanese;
else if (langstr == "english")
value = DalamudStartInfo::ClientLanguage::English;
else if (langstr == "german")
value = DalamudStartInfo::ClientLanguage::German;
else if (langstr == "french")
value = DalamudStartInfo::ClientLanguage::French;
}
}
void from_json(const nlohmann::json& json, DalamudStartInfo& config) {
if (!json.is_object())
return;
config.WorkingDirectory = json.value("WorkingDirectory", config.WorkingDirectory);
config.ConfigurationPath = json.value("ConfigurationPath", config.ConfigurationPath);
config.PluginDirectory = json.value("PluginDirectory", config.PluginDirectory);
config.DefaultPluginDirectory = json.value("DefaultPluginDirectory", config.DefaultPluginDirectory);
config.AssetDirectory = json.value("AssetDirectory", config.AssetDirectory);
config.Language = json.value("Language", config.Language);
config.GameVersion = json.value("GameVersion", config.GameVersion);
config.DelayInitializeMs = json.value("DelayInitializeMs", config.DelayInitializeMs);
config.BootShowConsole = json.value("BootShowConsole", config.BootShowConsole);
config.BootDisableFallbackConsole = json.value("BootDisableFallbackConsole", config.BootDisableFallbackConsole);
config.BootWaitMessageBox = json.value("BootWaitMessageBox", config.BootWaitMessageBox);
config.BootWaitDebugger = json.value("BootWaitDebugger", config.BootWaitDebugger);
config.BootVehEnabled = json.value("BootVehEnabled", config.BootVehEnabled);
config.BootVehFull = json.value("BootVehFull", config.BootVehFull);
config.BootDotnetOpenProcessHookMode = json.value("BootDotnetOpenProcessHookMode", config.BootDotnetOpenProcessHookMode);
if (const auto it = json.find("EnabledGameFixes"); it != json.end() && it->is_array()) {
config.BootEnabledGameFixes.clear();
for (const auto& val : *it)
config.BootEnabledGameFixes.insert(unicode::convert<std::string>(val.get<std::string>(), &unicode::lower));
}
if (const auto it = json.find("BootUnhookDlls"); it != json.end() && it->is_array()) {
config.BootUnhookDlls.clear();
for (const auto& val : *it)
config.BootUnhookDlls.insert(unicode::convert<std::string>(val.get<std::string>(), &unicode::lower));
}
}
void DalamudStartInfo::from_envvars() {
BootShowConsole = utils::get_env<bool>(L"DALAMUD_SHOW_CONSOLE");
BootDisableFallbackConsole = utils::get_env<bool>(L"DALAMUD_DISABLE_FALLBACK_CONSOLE");
BootWaitMessageBox = static_cast<WaitMessageboxFlags>(utils::get_env<int>(L"DALAMUD_WAIT_MESSAGEBOX"));
BootWaitDebugger = utils::get_env<bool>(L"DALAMUD_WAIT_DEBUGGER");
BootVehEnabled = utils::get_env<bool>(L"DALAMUD_IS_VEH");
BootVehFull = utils::get_env<bool>(L"DALAMUD_IS_VEH_FULL");
BootDotnetOpenProcessHookMode = static_cast<DotNetOpenProcessHookMode>(utils::get_env<int>(L"DALAMUD_DOTNET_OPENPROCESS_HOOKMODE"));
for (const auto& item : utils::get_env_list<std::string>(L"DALAMUD_GAMEFIX_LIST"))
BootEnabledGameFixes.insert(unicode::convert<std::string>(item, &unicode::lower));
for (const auto& item : utils::get_env_list<std::string>(L"DALAMUD_UNHOOK_DLLS"))
BootUnhookDlls.insert(unicode::convert<std::string>(item, &unicode::lower));
}

View file

@ -0,0 +1,48 @@
#pragma once
struct DalamudStartInfo {
enum class WaitMessageboxFlags : int {
None = 0,
BeforeInitialize = 1 << 0,
BeforeDalamudEntrypoint = 1 << 1,
};
friend void from_json(const nlohmann::json&, WaitMessageboxFlags&);
enum class DotNetOpenProcessHookMode : int {
ImportHooks = 0,
DirectHook = 1,
};
friend void from_json(const nlohmann::json&, DotNetOpenProcessHookMode&);
enum class ClientLanguage : int {
Japanese,
English,
German,
French,
};
friend void from_json(const nlohmann::json&, ClientLanguage&);
std::string WorkingDirectory;
std::string ConfigurationPath;
std::string PluginDirectory;
std::string DefaultPluginDirectory;
std::string AssetDirectory;
ClientLanguage Language = ClientLanguage::English;
std::string GameVersion;
int DelayInitializeMs = 0;
bool BootShowConsole = false;
bool BootDisableFallbackConsole = false;
WaitMessageboxFlags BootWaitMessageBox = WaitMessageboxFlags::None;
bool BootWaitDebugger = false;
bool BootVehEnabled = false;
bool BootVehFull = false;
DotNetOpenProcessHookMode BootDotnetOpenProcessHookMode = DotNetOpenProcessHookMode::ImportHooks;
std::set<std::string> BootEnabledGameFixes{};
std::set<std::string> BootUnhookDlls{};
friend void from_json(const nlohmann::json&, DalamudStartInfo&);
void from_envvars();
};
extern DalamudStartInfo g_startInfo;

View file

@ -1,56 +0,0 @@
#pragma once
#include "utils.h"
namespace bootconfig {
enum WaitMessageboxFlags : int {
None = 0,
BeforeInitialize = 1 << 0,
BeforeDalamudEntrypoint = 1 << 1,
};
inline WaitMessageboxFlags wait_messagebox() {
return static_cast<WaitMessageboxFlags>(utils::get_env<int>(L"DALAMUD_WAIT_MESSAGEBOX"));
}
enum DotNetOpenProcessHookMode : int {
ImportHooks = 0,
DirectHook = 1,
};
inline DotNetOpenProcessHookMode dotnet_openprocess_hook_mode() {
return static_cast<DotNetOpenProcessHookMode>(utils::get_env<int>(L"DALAMUD_DOTNET_OPENPROCESS_HOOKMODE"));
}
inline bool is_show_console() {
return utils::get_env<bool>(L"DALAMUD_SHOW_CONSOLE");
}
inline bool is_disable_fallback_console() {
return utils::get_env<bool>(L"DALAMUD_DISABLE_FALLBACK_CONSOLE");
}
inline bool is_wait_debugger() {
return utils::get_env<bool>(L"DALAMUD_WAIT_DEBUGGER");
}
inline bool is_veh_enabled() {
return utils::get_env<bool>(L"DALAMUD_IS_VEH");
}
inline bool is_veh_full() {
return utils::get_env<bool>(L"DALAMUD_IS_VEH_FULL");
}
inline bool gamefix_is_enabled(const wchar_t* name) {
static const auto list = utils::get_env_list<std::wstring>(L"DALAMUD_GAMEFIX_LIST");
for (const auto& item : list)
if (item == name)
return true;
return false;
}
inline std::vector<std::wstring> gamefix_unhookdll_list() {
return utils::get_env_list<std::wstring>(L"DALAMUD_UNHOOK_DLLS");
}
}

View file

@ -1,7 +1,8 @@
#include "pch.h" #include "pch.h"
#include "bootconfig.h" #include "DalamudStartInfo.h"
#include "logging.h" #include "logging.h"
#include "utils.h"
#include "veh.h" #include "veh.h"
#include "xivfixes.h" #include "xivfixes.h"
@ -9,30 +10,69 @@ HMODULE g_hModule;
HINSTANCE g_hGameInstance = GetModuleHandleW(nullptr); HINSTANCE g_hGameInstance = GetModuleHandleW(nullptr);
DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) { DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
if (bootconfig::is_show_console()) MessageBoxW(nullptr, L"", L"", MB_OK);
g_startInfo.from_envvars();
std::string jsonParseError;
try {
from_json(nlohmann::json::parse(std::string_view(static_cast<char*>(lpParam))), g_startInfo);
} catch (const std::exception& e) {
jsonParseError = e.what();
}
if (g_startInfo.BootShowConsole)
ConsoleSetup(L"Dalamud Boot"); ConsoleSetup(L"Dalamud Boot");
logging::update_dll_load_status(true); logging::update_dll_load_status(true);
auto attemptFallbackLog = false;
if (const auto logFilePath = utils::get_env<std::wstring>("DALAMUD_BOOT_LOGFILE"); logFilePath.empty()) { if (const auto logFilePath = utils::get_env<std::wstring>("DALAMUD_BOOT_LOGFILE"); logFilePath.empty()) {
if (!bootconfig::is_show_console() && !bootconfig::is_disable_fallback_console()) attemptFallbackLog = true;
ConsoleSetup(L"Dalamud Boot - Fallback Console");
logging::I("No log file path given; not logging to file."); logging::I("No log file path given; not logging to file.");
} else { } else {
try { try {
logging::start_file_logging(logFilePath, !bootconfig::is_show_console()); logging::start_file_logging(logFilePath, !g_startInfo.BootShowConsole);
logging::I("Logging to file: {}", logFilePath); logging::I("Logging to file: {}", logFilePath);
} catch (const std::exception& e) { } catch (const std::exception& e) {
if (!bootconfig::is_show_console() && !bootconfig::is_disable_fallback_console()) attemptFallbackLog = true;
ConsoleSetup(L"Dalamud Boot - Fallback Console");
logging::E("Couldn't open log file: {}", logFilePath); logging::E("Couldn't open log file: {}", logFilePath);
logging::E("Error: {} / {}", errno, e.what()); logging::E("Error: {} / {}", errno, e.what());
} }
} }
if (!jsonParseError.empty())
logging::E("Couldn't parse input JSON: {}", jsonParseError);
if (attemptFallbackLog) {
std::wstring logFilePath(PATHCCH_MAX_CCH + 1, L'\0');
logFilePath.resize(GetTempPathW(static_cast<DWORD>(logFilePath.size()), &logFilePath[0]));
if (logFilePath.empty()) {
logFilePath.resize(PATHCCH_MAX_CCH + 1);
logFilePath.resize(GetCurrentDirectoryW(static_cast<DWORD>(logFilePath.size()), &logFilePath[0]));
}
if (!logFilePath.empty() && logFilePath.back() != '/' && logFilePath.back() != '\\')
logFilePath += L"\\";
SYSTEMTIME st;
GetLocalTime(&st);
logFilePath += std::format(L"Dalamud.Boot.{:04}{:02}{:02}.{:02}{:02}{:02}.{:03}.{}.log", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, GetCurrentProcessId());
try {
logging::start_file_logging(logFilePath, !g_startInfo.BootShowConsole);
logging::I("Logging to fallback log file: {}", logFilePath);
} catch (const std::exception& e) {
if (!g_startInfo.BootShowConsole && !g_startInfo.BootDisableFallbackConsole)
ConsoleSetup(L"Dalamud Boot - Fallback Console");
logging::E("Couldn't open fallback log file: {}", logFilePath);
logging::E("Error: {} / {}", errno, e.what());
}
}
auto minHookLoaded = false; auto minHookLoaded = false;
if (const auto mhStatus = MH_Initialize(); mhStatus == MH_OK) { if (const auto mhStatus = MH_Initialize(); mhStatus == MH_OK) {
logging::I("MinHook initialized."); logging::I("MinHook initialized.");
@ -47,7 +87,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
logging::I("Dalamud.Boot Injectable, (c) 2021 XIVLauncher Contributors"); logging::I("Dalamud.Boot Injectable, (c) 2021 XIVLauncher Contributors");
logging::I("Built at: " __DATE__ "@" __TIME__); logging::I("Built at: " __DATE__ "@" __TIME__);
if (bootconfig::wait_messagebox() & bootconfig::WaitMessageboxFlags::BeforeInitialize) if (static_cast<int>(g_startInfo.BootWaitMessageBox) & static_cast<int>(DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize))
MessageBoxW(nullptr, L"Press OK to continue", L"Dalamud Boot", MB_OK); MessageBoxW(nullptr, L"Press OK to continue", L"Dalamud Boot", MB_OK);
if (minHookLoaded) { if (minHookLoaded) {
@ -58,7 +98,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
logging::W("Skipping fixes, as MinHook has failed to load."); logging::W("Skipping fixes, as MinHook has failed to load.");
} }
if (bootconfig::is_wait_debugger()) { if (g_startInfo.BootWaitDebugger) {
logging::I("Waiting for debugger to attach..."); logging::I("Waiting for debugger to attach...");
while (!IsDebuggerPresent()) while (!IsDebuggerPresent())
Sleep(100); Sleep(100);
@ -94,8 +134,8 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
logging::I("Initializing VEH..."); logging::I("Initializing VEH...");
if (utils::is_running_on_linux()) { if (utils::is_running_on_linux()) {
logging::I("=> VEH was disabled, running on linux"); logging::I("=> VEH was disabled, running on linux");
} else if (bootconfig::is_veh_enabled()) { } else if (g_startInfo.BootVehEnabled) {
if (veh::add_handler(bootconfig::is_veh_full())) if (veh::add_handler(g_startInfo.BootVehFull))
logging::I("=> Done!"); logging::I("=> Done!");
else else
logging::I("=> Failed!"); logging::I("=> Failed!");
@ -105,7 +145,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
// ============================== Dalamud ==================================== // // ============================== Dalamud ==================================== //
if (bootconfig::wait_messagebox() & bootconfig::WaitMessageboxFlags::BeforeDalamudEntrypoint) if (static_cast<int>(g_startInfo.BootWaitMessageBox) & static_cast<int>(DalamudStartInfo::WaitMessageboxFlags::BeforeDalamudEntrypoint))
MessageBoxW(nullptr, L"Press OK to continue", L"Dalamud Boot", MB_OK); MessageBoxW(nullptr, L"Press OK to continue", L"Dalamud Boot", MB_OK);
if (hMainThreadContinue) { if (hMainThreadContinue) {

View file

@ -53,6 +53,9 @@
#include "../lib/CoreCLR/CoreCLR.h" #include "../lib/CoreCLR/CoreCLR.h"
#include "../lib/CoreCLR/boot.h" #include "../lib/CoreCLR/boot.h"
// https://github.com/nlohmann/json
#include "../lib/nlohmann-json/json.hpp"
#include "unicode.h" #include "unicode.h"
// Commonly used macros // Commonly used macros

View file

@ -231,3 +231,15 @@ size_t unicode::encode(EncodingTag<char>, char* ptr, char32_t c, bool strict) {
size_t unicode::encode(EncodingTag<wchar_t>, wchar_t* ptr, char32_t c, bool strict) { size_t unicode::encode(EncodingTag<wchar_t>, wchar_t* ptr, char32_t c, bool strict) {
return encode(EncodingTag<char16_t>(), reinterpret_cast<char16_t*>(ptr), c, strict); return encode(EncodingTag<char16_t>(), reinterpret_cast<char16_t*>(ptr), c, strict);
} }
char32_t unicode::lower(char32_t in) {
if ('A' <= in && in <= 'Z')
return in - 'A' + 'a';
return in;
}
char32_t unicode::upper(char32_t in) {
if ('a' <= in && in <= 'z')
return in - 'a' + 'A';
return in;
}

View file

@ -41,52 +41,68 @@ namespace unicode {
return encode(EncodingTag<T>(), ptr, c, strict); return encode(EncodingTag<T>(), ptr, c, strict);
} }
char32_t lower(char32_t in);
char32_t upper(char32_t in);
template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>> template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>>
inline TTo& convert(TTo& out, const std::basic_string_view<TFromElem, TFromTraits>& in, bool strict = true) { TTo& convert(TTo& out, const std::basic_string_view<TFromElem, TFromTraits>& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) {
out.reserve(out.size() + in.size() * 4 / sizeof(in[0]) / sizeof(out[0])); out.reserve(out.size() + in.size() * 4 / sizeof(in[0]) / sizeof(out[0]));
char32_t c{}; char32_t c{};
for (size_t decLen = 0, decIdx = 0; decIdx < in.size() && (decLen = unicode::decode(c, &in[decIdx], in.size() - decIdx, strict)); decIdx += decLen) { for (size_t decLen = 0, decIdx = 0; decIdx < in.size() && ((decLen = decode(c, &in[decIdx], in.size() - decIdx, strict))); decIdx += decLen) {
if (pfnCharMap)
c = pfnCharMap(c);
const auto encIdx = out.size(); const auto encIdx = out.size();
const auto encLen = unicode::encode<typename TTo::value_type>(nullptr, c, strict); const auto encLen = encode<typename TTo::value_type>(nullptr, c, strict);
out.resize(encIdx + encLen); out.resize(encIdx + encLen);
unicode::encode(&out[encIdx], c, strict); encode(&out[encIdx], c, strict);
} }
return out; return out;
} }
template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>, class TFromAlloc = std::allocator<TFromElem>> template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>, class TFromAlloc = std::allocator<TFromElem>>
inline TTo& convert(TTo& out, const std::basic_string<TFromElem, TFromTraits, TFromAlloc>& in, bool strict = true) { TTo& convert(TTo& out, const std::basic_string<TFromElem, TFromTraits, TFromAlloc>& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) {
return convert(out, std::basic_string_view<TFromElem, TFromTraits>(in), strict); return convert(out, std::basic_string_view<TFromElem, TFromTraits>(in), pfnCharMap, strict);
} }
template<class TTo, class TFromElem, typename = std::enable_if_t<std::is_integral_v<TFromElem>>> template<class TTo, class TFromElem, typename = std::enable_if_t<std::is_integral_v<TFromElem>>>
inline TTo& convert(TTo& out, const TFromElem* in, size_t length = (std::numeric_limits<size_t>::max)(), bool strict = true) { TTo& convert(TTo& out, const TFromElem* in, size_t length = (std::numeric_limits<size_t>::max)(), char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) {
if (length == (std::numeric_limits<size_t>::max)()) if (length == (std::numeric_limits<size_t>::max)())
length = std::char_traits<TFromElem>::length(in); length = std::char_traits<TFromElem>::length(in);
return convert(out, std::basic_string_view<TFromElem>(in, length), strict); return convert(out, std::basic_string_view<TFromElem>(in, length), pfnCharMap, strict);
} }
template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>> template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>>
inline TTo convert(const std::basic_string_view<TFromElem, TFromTraits>& in, bool strict = true) { TTo convert(const std::basic_string_view<TFromElem, TFromTraits>& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) {
TTo out{}; TTo out{};
return convert(out, in, strict); return convert(out, in, pfnCharMap, strict);
} }
template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>, class TFromAlloc = std::allocator<TFromElem>> template<class TTo, class TFromElem, class TFromTraits = std::char_traits<TFromElem>, class TFromAlloc = std::allocator<TFromElem>>
inline TTo convert(const std::basic_string<TFromElem, TFromTraits, TFromAlloc>& in, bool strict = true) { TTo convert(const std::basic_string<TFromElem, TFromTraits, TFromAlloc>& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) {
TTo out{}; TTo out{};
return convert(out, std::basic_string_view<TFromElem, TFromTraits>(in), strict); return convert(out, std::basic_string_view<TFromElem, TFromTraits>(in), pfnCharMap, strict);
} }
template<class TTo, class TFromElem, typename = std::enable_if_t<std::is_integral_v<TFromElem>>> template<class TTo, class TFromElem, typename = std::enable_if_t<std::is_integral_v<TFromElem>>>
inline TTo convert(const TFromElem* in, size_t length = (std::numeric_limits<size_t>::max)(), bool strict = true) { TTo convert(const TFromElem* in, size_t length = (std::numeric_limits<size_t>::max)(), char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) {
if (length == (std::numeric_limits<size_t>::max)()) if (length == (std::numeric_limits<size_t>::max)())
length = std::char_traits<TFromElem>::length(in); length = std::char_traits<TFromElem>::length(in);
TTo out{}; TTo out{};
return convert(out, std::basic_string_view<TFromElem>(in, length), strict); return convert(out, std::basic_string_view<TFromElem>(in, length), pfnCharMap, strict);
} }
inline const std::u8string& convert(const std::u8string& in) { return in; }
inline const std::u16string& convert(const std::u16string& in) { return in; }
inline const std::u32string& convert(const std::u32string& in) { return in; }
inline const std::string& convert(const std::string& in) { return in; }
inline const std::wstring& convert(const std::wstring& in) { return in; }
} }

View file

@ -463,6 +463,17 @@ std::vector<std::wstring> utils::get_env_list(const wchar_t* pcszName) {
return res; return res;
} }
template<>
std::vector<std::string> utils::get_env_list(const wchar_t* pcszName) {
const auto src = utils::get_env<std::string>(pcszName);
auto res = utils::split(src, ",");
for (auto& s : res)
s = utils::trim(s);
if (res.size() == 1 && res[0].empty())
return {};
return res;
}
bool utils::is_running_on_linux() { bool utils::is_running_on_linux() {
if (get_env<bool>(L"XL_WINEONLINUX")) if (get_env<bool>(L"XL_WINEONLINUX"))
return true; return true;

View file

@ -243,6 +243,9 @@ namespace utils {
template<> template<>
std::vector<std::wstring> get_env_list(const wchar_t* pcwzName); std::vector<std::wstring> get_env_list(const wchar_t* pcwzName);
template<>
std::vector<std::string> get_env_list(const wchar_t* pcwzName);
template<typename T> template<typename T>
std::vector<T> get_env_list(const char* pcszName) { std::vector<T> get_env_list(const char* pcszName) {
return get_env_list<T>(unicode::convert<std::wstring>(pcszName).c_str()); return get_env_list<T>(unicode::convert<std::wstring>(pcszName).c_str());

View file

@ -2,7 +2,7 @@
#include "xivfixes.h" #include "xivfixes.h"
#include "bootconfig.h" #include "DalamudStartInfo.h"
#include "hooks.h" #include "hooks.h"
#include "logging.h" #include "logging.h"
#include "utils.h" #include "utils.h"
@ -17,8 +17,6 @@ void xivfixes::unhook_dll(bool bApply) {
static const auto LogTag = "[xivfixes:unhook_dll]"; static const auto LogTag = "[xivfixes:unhook_dll]";
static const auto LogTagW = L"[xivfixes:unhook_dll]"; static const auto LogTagW = L"[xivfixes:unhook_dll]";
const auto targetDllNames = bootconfig::gamefix_unhookdll_list();
if (!bApply) if (!bApply)
return; return;
@ -60,13 +58,7 @@ void xivfixes::unhook_dll(bool bApply) {
return; return;
} }
auto doRestore = false; const auto doRestore = g_startInfo.BootUnhookDlls.contains(unicode::convert<std::string>(path.filename().u8string()));
for (const auto& targetDllName : targetDllNames) {
if (0 == _wcsicmp(path.filename().wstring().c_str(), targetDllName.c_str())) {
doRestore = true;
break;
}
}
std::optional<utils::memory_tenderizer> tenderizer; std::optional<utils::memory_tenderizer> tenderizer;
for (size_t i = 0, instructionLength = 1, printed = 0; i < buf.size(); i += instructionLength) { for (size_t i = 0, instructionLength = 1, printed = 0; i < buf.size(); i += instructionLength) {
@ -192,7 +184,7 @@ void xivfixes::prevent_devicechange_crashes(bool bApply) {
static std::optional<hooks::wndproc_hook> s_hookWndProc; static std::optional<hooks::wndproc_hook> s_hookWndProc;
if (bApply) { if (bApply) {
if (!bootconfig::gamefix_is_enabled(L"prevent_devicechange_crashes")) { if (!g_startInfo.BootEnabledGameFixes.contains("prevent_devicechange_crashes")) {
logging::I("{} Turned off via environment variable.", LogTag); logging::I("{} Turned off via environment variable.", LogTag);
return; return;
} }
@ -304,7 +296,7 @@ void xivfixes::disable_game_openprocess_access_check(bool bApply) {
static std::optional<hooks::import_hook<decltype(OpenProcess)>> s_hook; static std::optional<hooks::import_hook<decltype(OpenProcess)>> s_hook;
if (bApply) { if (bApply) {
if (!bootconfig::gamefix_is_enabled(L"disable_game_openprocess_access_check")) { if (!g_startInfo.BootEnabledGameFixes.contains("disable_game_openprocess_access_check")) {
logging::I("{} Turned off via environment variable.", LogTag); logging::I("{} Turned off via environment variable.", LogTag);
return; return;
} }
@ -345,7 +337,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
static std::set<DWORD> s_silenceSet; static std::set<DWORD> s_silenceSet;
if (bApply) { if (bApply) {
if (!bootconfig::gamefix_is_enabled(L"redirect_openprocess")) { if (!g_startInfo.BootEnabledGameFixes.contains("redirect_openprocess")) {
logging::I("{} Turned off via environment variable.", LogTag); logging::I("{} Turned off via environment variable.", LogTag);
return; return;
} }
@ -354,7 +346,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
return; return;
} }
if (bootconfig::dotnet_openprocess_hook_mode() == bootconfig::ImportHooks) { if (g_startInfo.BootDotnetOpenProcessHookMode == DalamudStartInfo::DotNetOpenProcessHookMode::ImportHooks) {
auto hook = std::make_shared<hooks::global_import_hook<decltype(OpenProcess)>>("kernel32.dll!OpenProcess (global import, redirect_openprocess)", L"kernel32.dll", "OpenProcess"); auto hook = std::make_shared<hooks::global_import_hook<decltype(OpenProcess)>>("kernel32.dll!OpenProcess (global import, redirect_openprocess)", L"kernel32.dll", "OpenProcess");
hook->set_detour([hook = hook.get()](DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)->HANDLE { hook->set_detour([hook = hook.get()](DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)->HANDLE {
if (dwProcessId == GetCurrentProcessId()) { if (dwProcessId == GetCurrentProcessId()) {

22091
lib/nlohmann-json/json.hpp Normal file

File diff suppressed because it is too large Load diff