mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Write Dalamud.Boot log to TEMP, then CWD (#886)
This commit is contained in:
parent
cd41fda202
commit
ce49874935
13 changed files with 22375 additions and 98 deletions
|
|
@ -121,6 +121,7 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DalamudStartInfo.cpp" />
|
||||
<ClCompile Include="hooks.cpp" />
|
||||
<ClCompile Include="logging.cpp">
|
||||
<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\table64.h" />
|
||||
<ClInclude Include="..\lib\TsudaKageyu-minhook\src\trampoline.h" />
|
||||
<ClInclude Include="bootconfig.h" />
|
||||
<ClInclude Include="DalamudStartInfo.h" />
|
||||
<ClInclude Include="hooks.h" />
|
||||
<ClInclude Include="logging.h" />
|
||||
<ClInclude Include="unicode.h" />
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@
|
|||
<ClCompile Include="hooks.cpp">
|
||||
<Filter>Dalamud.Boot DLL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DalamudStartInfo.cpp">
|
||||
<Filter>Dalamud.Boot DLL</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\lib\CoreCLR\CoreCLR.h">
|
||||
|
|
@ -99,7 +102,7 @@
|
|||
<ClInclude Include="hooks.h">
|
||||
<Filter>Dalamud.Boot DLL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bootconfig.h">
|
||||
<ClInclude Include="DalamudStartInfo.h">
|
||||
<Filter>Dalamud.Boot DLL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="xivfixes.h">
|
||||
|
|
|
|||
113
Dalamud.Boot/DalamudStartInfo.cpp
Normal file
113
Dalamud.Boot/DalamudStartInfo.cpp
Normal 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));
|
||||
}
|
||||
48
Dalamud.Boot/DalamudStartInfo.h
Normal file
48
Dalamud.Boot/DalamudStartInfo.h
Normal 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;
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
#include "pch.h"
|
||||
|
||||
#include "bootconfig.h"
|
||||
#include "DalamudStartInfo.h"
|
||||
#include "logging.h"
|
||||
#include "utils.h"
|
||||
#include "veh.h"
|
||||
#include "xivfixes.h"
|
||||
|
||||
|
|
@ -9,30 +10,69 @@ HMODULE g_hModule;
|
|||
HINSTANCE g_hGameInstance = GetModuleHandleW(nullptr);
|
||||
|
||||
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");
|
||||
|
||||
logging::update_dll_load_status(true);
|
||||
|
||||
auto attemptFallbackLog = false;
|
||||
if (const auto logFilePath = utils::get_env<std::wstring>("DALAMUD_BOOT_LOGFILE"); logFilePath.empty()) {
|
||||
if (!bootconfig::is_show_console() && !bootconfig::is_disable_fallback_console())
|
||||
ConsoleSetup(L"Dalamud Boot - Fallback Console");
|
||||
attemptFallbackLog = true;
|
||||
|
||||
logging::I("No log file path given; not logging to file.");
|
||||
} else {
|
||||
try {
|
||||
logging::start_file_logging(logFilePath, !bootconfig::is_show_console());
|
||||
logging::start_file_logging(logFilePath, !g_startInfo.BootShowConsole);
|
||||
logging::I("Logging to file: {}", logFilePath);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
if (!bootconfig::is_show_console() && !bootconfig::is_disable_fallback_console())
|
||||
ConsoleSetup(L"Dalamud Boot - Fallback Console");
|
||||
attemptFallbackLog = true;
|
||||
|
||||
logging::E("Couldn't open log file: {}", logFilePath);
|
||||
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;
|
||||
if (const auto mhStatus = MH_Initialize(); mhStatus == MH_OK) {
|
||||
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("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);
|
||||
|
||||
if (minHookLoaded) {
|
||||
|
|
@ -58,7 +98,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
|||
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...");
|
||||
while (!IsDebuggerPresent())
|
||||
Sleep(100);
|
||||
|
|
@ -94,8 +134,8 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
|||
logging::I("Initializing VEH...");
|
||||
if (utils::is_running_on_linux()) {
|
||||
logging::I("=> VEH was disabled, running on linux");
|
||||
} else if (bootconfig::is_veh_enabled()) {
|
||||
if (veh::add_handler(bootconfig::is_veh_full()))
|
||||
} else if (g_startInfo.BootVehEnabled) {
|
||||
if (veh::add_handler(g_startInfo.BootVehFull))
|
||||
logging::I("=> Done!");
|
||||
else
|
||||
logging::I("=> Failed!");
|
||||
|
|
@ -105,7 +145,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
|||
|
||||
// ============================== 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);
|
||||
|
||||
if (hMainThreadContinue) {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@
|
|||
#include "../lib/CoreCLR/CoreCLR.h"
|
||||
#include "../lib/CoreCLR/boot.h"
|
||||
|
||||
// https://github.com/nlohmann/json
|
||||
#include "../lib/nlohmann-json/json.hpp"
|
||||
|
||||
#include "unicode.h"
|
||||
|
||||
// Commonly used macros
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,52 +41,68 @@ namespace unicode {
|
|||
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>>
|
||||
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]));
|
||||
|
||||
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 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);
|
||||
unicode::encode(&out[encIdx], c, strict);
|
||||
encode(&out[encIdx], c, strict);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
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) {
|
||||
return convert(out, std::basic_string_view<TFromElem, TFromTraits>(in), strict);
|
||||
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), pfnCharMap, strict);
|
||||
}
|
||||
|
||||
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)())
|
||||
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>>
|
||||
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{};
|
||||
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>>
|
||||
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{};
|
||||
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>>>
|
||||
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)())
|
||||
length = std::char_traits<TFromElem>::length(in);
|
||||
|
||||
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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -463,6 +463,17 @@ std::vector<std::wstring> utils::get_env_list(const wchar_t* pcszName) {
|
|||
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() {
|
||||
if (get_env<bool>(L"XL_WINEONLINUX"))
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -243,6 +243,9 @@ namespace utils {
|
|||
template<>
|
||||
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>
|
||||
std::vector<T> get_env_list(const char* pcszName) {
|
||||
return get_env_list<T>(unicode::convert<std::wstring>(pcszName).c_str());
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "xivfixes.h"
|
||||
|
||||
#include "bootconfig.h"
|
||||
#include "DalamudStartInfo.h"
|
||||
#include "hooks.h"
|
||||
#include "logging.h"
|
||||
#include "utils.h"
|
||||
|
|
@ -17,8 +17,6 @@ void xivfixes::unhook_dll(bool bApply) {
|
|||
static const auto LogTag = "[xivfixes:unhook_dll]";
|
||||
static const auto LogTagW = L"[xivfixes:unhook_dll]";
|
||||
|
||||
const auto targetDllNames = bootconfig::gamefix_unhookdll_list();
|
||||
|
||||
if (!bApply)
|
||||
return;
|
||||
|
||||
|
|
@ -60,13 +58,7 @@ void xivfixes::unhook_dll(bool bApply) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto doRestore = false;
|
||||
for (const auto& targetDllName : targetDllNames) {
|
||||
if (0 == _wcsicmp(path.filename().wstring().c_str(), targetDllName.c_str())) {
|
||||
doRestore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const auto doRestore = g_startInfo.BootUnhookDlls.contains(unicode::convert<std::string>(path.filename().u8string()));
|
||||
|
||||
std::optional<utils::memory_tenderizer> tenderizer;
|
||||
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;
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
|
@ -304,7 +296,7 @@ void xivfixes::disable_game_openprocess_access_check(bool bApply) {
|
|||
static std::optional<hooks::import_hook<decltype(OpenProcess)>> s_hook;
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
|
@ -345,7 +337,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
|||
static std::set<DWORD> s_silenceSet;
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
|
@ -354,7 +346,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
|||
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");
|
||||
hook->set_detour([hook = hook.get()](DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)->HANDLE {
|
||||
if (dwProcessId == GetCurrentProcessId()) {
|
||||
|
|
|
|||
22091
lib/nlohmann-json/json.hpp
Normal file
22091
lib/nlohmann-json/json.hpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue