mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Update logging to reflect msvc updates on std::format (#883)
This commit is contained in:
parent
c6cf47ea2d
commit
2f4c0bbc97
15 changed files with 238 additions and 183 deletions
|
|
@ -25,7 +25,7 @@
|
||||||
<PropertyGroup Label="Configuration">
|
<PropertyGroup Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<OutDir>..\bin\$(Configuration)\</OutDir>
|
<OutDir>..\bin\$(Configuration)\</OutDir>
|
||||||
|
|
|
||||||
|
|
@ -13,32 +13,32 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
||||||
ConsoleSetup(L"Dalamud Boot");
|
ConsoleSetup(L"Dalamud Boot");
|
||||||
|
|
||||||
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())
|
||||||
logging::print<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, !bootconfig::is_show_console());
|
||||||
logging::print<logging::I>(L"Logging to file: {}", logFilePath);
|
logging::I("Logging to file: {}", logFilePath);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
logging::print<logging::E>(L"Couldn't open log file: {}", logFilePath);
|
logging::E("Couldn't open log file: {}", logFilePath);
|
||||||
logging::print<logging::E>("Error: {} / {}", errno, e.what());
|
logging::E("Error: {} / {}", errno, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logging::print<logging::I>("Dalamud.Boot Injectable, (c) 2021 XIVLauncher Contributors");
|
logging::I("Dalamud.Boot Injectable, (c) 2021 XIVLauncher Contributors");
|
||||||
logging::print<logging::I>("Built at: " __DATE__ "@" __TIME__);
|
logging::I("Built at: " __DATE__ "@" __TIME__);
|
||||||
|
|
||||||
if (bootconfig::wait_messagebox() & bootconfig::WaitMessageboxFlags::BeforeInitialize)
|
if (bootconfig::wait_messagebox() & bootconfig::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);
|
||||||
|
|
||||||
logging::print<logging::I>("Applying fixes...");
|
logging::I("Applying fixes...");
|
||||||
xivfixes::apply_all(true);
|
xivfixes::apply_all(true);
|
||||||
logging::print<logging::I>("Fixes OK");
|
logging::I("Fixes OK");
|
||||||
|
|
||||||
if (bootconfig::is_wait_debugger()) {
|
if (bootconfig::is_wait_debugger()) {
|
||||||
logging::print<logging::I>("Waiting for debugger to attach...");
|
logging::I("Waiting for debugger to attach...");
|
||||||
while (!IsDebuggerPresent())
|
while (!IsDebuggerPresent())
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
logging::print<logging::I>("Debugger attached.");
|
logging::I("Debugger attached.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto fs_module_path = utils::get_module_path(g_hModule);
|
const auto fs_module_path = utils::get_module_path(g_hModule);
|
||||||
|
|
@ -47,7 +47,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
||||||
|
|
||||||
// ============================== CLR ========================================= //
|
// ============================== CLR ========================================= //
|
||||||
|
|
||||||
logging::print<logging::I>("Calling InitializeClrAndGetEntryPoint");
|
logging::I("Calling InitializeClrAndGetEntryPoint");
|
||||||
|
|
||||||
void* entrypoint_vfn;
|
void* entrypoint_vfn;
|
||||||
int result = InitializeClrAndGetEntryPoint(
|
int result = InitializeClrAndGetEntryPoint(
|
||||||
|
|
@ -67,16 +67,16 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
||||||
|
|
||||||
// ============================== VEH ======================================== //
|
// ============================== VEH ======================================== //
|
||||||
|
|
||||||
logging::print<logging::I>("Initializing VEH...");
|
logging::I("Initializing VEH...");
|
||||||
if (utils::is_running_on_linux()) {
|
if (utils::is_running_on_linux()) {
|
||||||
logging::print<logging::I>("=> VEH was disabled, running on linux");
|
logging::I("=> VEH was disabled, running on linux");
|
||||||
} else if (bootconfig::is_veh_enabled()) {
|
} else if (bootconfig::is_veh_enabled()) {
|
||||||
if (veh::add_handler(bootconfig::is_veh_full()))
|
if (veh::add_handler(bootconfig::is_veh_full()))
|
||||||
logging::print<logging::I>("=> Done!");
|
logging::I("=> Done!");
|
||||||
else
|
else
|
||||||
logging::print<logging::I>("=> Failed!");
|
logging::I("=> Failed!");
|
||||||
} else {
|
} else {
|
||||||
logging::print<logging::I>("VEH was disabled manually");
|
logging::I("VEH was disabled manually");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================== Dalamud ==================================== //
|
// ============================== Dalamud ==================================== //
|
||||||
|
|
@ -91,9 +91,9 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
||||||
|
|
||||||
utils::wait_for_game_window();
|
utils::wait_for_game_window();
|
||||||
|
|
||||||
logging::print<logging::I>("Initializing Dalamud...");
|
logging::I("Initializing Dalamud...");
|
||||||
entrypoint_fn(lpParam, hMainThreadContinue);
|
entrypoint_fn(lpParam, hMainThreadContinue);
|
||||||
logging::print<logging::I>("Done!");
|
logging::I("Done!");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ BOOL APIENTRY DllMain(const HMODULE hModule, const DWORD dwReason, LPVOID lpRese
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
g_hModule = hModule;
|
g_hModule = hModule;
|
||||||
if (const auto mhStatus = MH_Initialize(); MH_OK != mhStatus) {
|
if (const auto mhStatus = MH_Initialize(); MH_OK != mhStatus) {
|
||||||
logging::print<logging::E>("Failed to initialize MinHook (status={})", static_cast<int>(mhStatus));
|
logging::E("Failed to initialize MinHook (status={})", static_cast<int>(mhStatus));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ BOOL APIENTRY DllMain(const HMODULE hModule, const DWORD dwReason, LPVOID lpRese
|
||||||
xivfixes::apply_all(false);
|
xivfixes::apply_all(false);
|
||||||
|
|
||||||
if (const auto mhStatus = MH_Uninitialize(); MH_OK != mhStatus) {
|
if (const auto mhStatus = MH_Uninitialize(); MH_OK != mhStatus) {
|
||||||
logging::print<logging::E>("Failed to uninitialize MinHook (status={})", static_cast<int>(mhStatus));
|
logging::E("Failed to uninitialize MinHook (status={})", static_cast<int>(mhStatus));
|
||||||
__fastfail(logging::MinHookUnload);
|
__fastfail(logging::MinHookUnload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ void hooks::getprocaddress_singleton_import_hook::initialize() {
|
||||||
LdrRegisterDllNotification(0, [](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* context) {
|
LdrRegisterDllNotification(0, [](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* context) {
|
||||||
if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED) {
|
if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED) {
|
||||||
const auto dllName = unicode::convert<std::string>(pData->Loaded.FullDllName->Buffer);
|
const auto dllName = unicode::convert<std::string>(pData->Loaded.FullDllName->Buffer);
|
||||||
logging::print<logging::I>(R"({} "{}" has been loaded at 0x{:X} ~ 0x{:X} (0x{:X}); finding import table items to hook.)",
|
logging::I(R"({} "{}" has been loaded at 0x{:X} ~ 0x{:X} (0x{:X}); finding import table items to hook.)",
|
||||||
LogTag, dllName,
|
LogTag, dllName,
|
||||||
reinterpret_cast<size_t>(pData->Loaded.DllBase),
|
reinterpret_cast<size_t>(pData->Loaded.DllBase),
|
||||||
reinterpret_cast<size_t>(pData->Loaded.DllBase) + pData->Loaded.SizeOfImage,
|
reinterpret_cast<size_t>(pData->Loaded.DllBase) + pData->Loaded.SizeOfImage,
|
||||||
|
|
@ -111,7 +111,7 @@ void hooks::getprocaddress_singleton_import_hook::initialize() {
|
||||||
reinterpret_cast<getprocaddress_singleton_import_hook*>(context)->hook_module(utils::loaded_module(pData->Loaded.DllBase));
|
reinterpret_cast<getprocaddress_singleton_import_hook*>(context)->hook_module(utils::loaded_module(pData->Loaded.DllBase));
|
||||||
} else if (notiReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED) {
|
} else if (notiReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED) {
|
||||||
const auto dllName = unicode::convert<std::string>(pData->Unloaded.FullDllName->Buffer);
|
const auto dllName = unicode::convert<std::string>(pData->Unloaded.FullDllName->Buffer);
|
||||||
logging::print<logging::I>(R"({} "{}" has been unloaded.)", LogTag, dllName);
|
logging::I(R"({} "{}" has been unloaded.)", LogTag, dllName);
|
||||||
}
|
}
|
||||||
}, this, &m_ldrDllNotificationCookie);
|
}, this, &m_ldrDllNotificationCookie);
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +119,7 @@ void hooks::getprocaddress_singleton_import_hook::initialize() {
|
||||||
FARPROC hooks::getprocaddress_singleton_import_hook::get_proc_address_handler(HMODULE hModule, LPCSTR lpProcName) {
|
FARPROC hooks::getprocaddress_singleton_import_hook::get_proc_address_handler(HMODULE hModule, LPCSTR lpProcName) {
|
||||||
if (const auto it1 = m_targetFns.find(hModule); it1 != m_targetFns.end()) {
|
if (const auto it1 = m_targetFns.find(hModule); it1 != m_targetFns.end()) {
|
||||||
if (const auto it2 = it1->second.find(lpProcName); it2 != it1->second.end()) {
|
if (const auto it2 = it1->second.find(lpProcName); it2 != it1->second.end()) {
|
||||||
logging::print<logging::I>(R"({} Redirecting GetProcAddress("{}", "{}"))", LogTag, m_dllNameMap[hModule], lpProcName);
|
logging::I(R"({} Redirecting GetProcAddress("{}", "{}"))", LogTag, m_dllNameMap[hModule], lpProcName);
|
||||||
|
|
||||||
return reinterpret_cast<FARPROC>(it2->second);
|
return reinterpret_cast<FARPROC>(it2->second);
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +139,7 @@ void hooks::getprocaddress_singleton_import_hook::hook_module(const utils::loade
|
||||||
if (void* pGetProcAddressImport; mod.find_imported_function_pointer(dllName.c_str(), targetFn.c_str(), 0, pGetProcAddressImport)) {
|
if (void* pGetProcAddressImport; mod.find_imported_function_pointer(dllName.c_str(), targetFn.c_str(), 0, pGetProcAddressImport)) {
|
||||||
auto& hook = m_hooks[hModule][targetFn][mod];
|
auto& hook = m_hooks[hModule][targetFn][mod];
|
||||||
if (!hook) {
|
if (!hook) {
|
||||||
logging::print<logging::I>("{} Hooking {}!{} imported by {}", LogTag, dllName, targetFn, unicode::convert<std::string>(mod.path().wstring()));
|
logging::I("{} Hooking {}!{} imported by {}", LogTag, dllName, targetFn, unicode::convert<std::string>(mod.path().wstring()));
|
||||||
|
|
||||||
hook.emplace(std::format("getprocaddress_singleton_import_hook::hook_module({}!{})", dllName, targetFn), static_cast<void**>(pGetProcAddressImport), pfnThunk);
|
hook.emplace(std::format("getprocaddress_singleton_import_hook::hook_module({}!{})", dllName, targetFn), static_cast<void**>(pGetProcAddressImport), pfnThunk);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,28 +10,66 @@ static bool s_bLoaded = false;
|
||||||
static bool s_bSkipLogFileWrite = false;
|
static bool s_bSkipLogFileWrite = false;
|
||||||
static std::shared_ptr<void> s_hLogFile;
|
static std::shared_ptr<void> s_hLogFile;
|
||||||
|
|
||||||
void logging::print(Level level, const char* s) {
|
void logging::start_file_logging(const std::filesystem::path& path, bool redirect_stderrout) {
|
||||||
|
if (s_hLogFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (exists(path) && file_size(path) > 1048576) {
|
||||||
|
auto oldPath = std::filesystem::path(path);
|
||||||
|
oldPath.replace_extension(".log.old");
|
||||||
|
if (exists(oldPath))
|
||||||
|
remove(oldPath);
|
||||||
|
rename(path, oldPath);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
// whatever
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto h = CreateFile(path.wstring().c_str(),
|
||||||
|
GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
nullptr, OPEN_ALWAYS, 0, nullptr);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
throw std::runtime_error(std::format("Win32 error {}(0x{:x})", GetLastError(), GetLastError()));
|
||||||
|
|
||||||
|
SetFilePointer(h, 0, 0, FILE_END);
|
||||||
|
s_hLogFile = {h, &CloseHandle};
|
||||||
|
|
||||||
|
if (redirect_stderrout) {
|
||||||
|
SetStdHandle(STD_ERROR_HANDLE, h);
|
||||||
|
SetStdHandle(STD_OUTPUT_HANDLE, h);
|
||||||
|
s_bSkipLogFileWrite = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void logging::update_dll_load_status(bool loaded) {
|
||||||
|
s_bLoaded = loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void logging::print<char>(Level level, const char* s) {
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
GetLocalTime(&st);
|
GetLocalTime(&st);
|
||||||
|
|
||||||
std::string estr;
|
std::string estr;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case Verbose:
|
case Level::Verbose:
|
||||||
estr = std::format("[{:02}:{:02}:{:02} CPP/VRB] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
estr = std::format("[{:02}:{:02}:{:02} CPP/VRB] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
||||||
break;
|
break;
|
||||||
case Debug:
|
case Level::Debug:
|
||||||
estr = std::format("[{:02}:{:02}:{:02} CPP/DBG] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
estr = std::format("[{:02}:{:02}:{:02} CPP/DBG] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
||||||
break;
|
break;
|
||||||
case Info:
|
case Level::Info:
|
||||||
estr = std::format("[{:02}:{:02}:{:02} CPP/INF] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
estr = std::format("[{:02}:{:02}:{:02} CPP/INF] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
||||||
break;
|
break;
|
||||||
case Warning:
|
case Level::Warning:
|
||||||
estr = std::format("[{:02}:{:02}:{:02} CPP/WRN] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
estr = std::format("[{:02}:{:02}:{:02} CPP/WRN] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
||||||
break;
|
break;
|
||||||
case Error:
|
case Level::Error:
|
||||||
estr = std::format("[{:02}:{:02}:{:02} CPP/ERR] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
estr = std::format("[{:02}:{:02}:{:02} CPP/ERR] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
||||||
break;
|
break;
|
||||||
case Fatal:
|
case Level::Fatal:
|
||||||
estr = std::format("[{:02}:{:02}:{:02} CPP/FTL] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
estr = std::format("[{:02}:{:02}:{:02} CPP/FTL] {}\n", st.wHour, st.wMinute, st.wSecond, s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -51,40 +89,3 @@ void logging::print(Level level, const char* s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void logging::start_file_logging(const std::filesystem::path& path, bool redirect_stderrout) {
|
|
||||||
if (s_hLogFile)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (exists(path) && file_size(path) > 1048576) {
|
|
||||||
auto oldPath = std::filesystem::path(path);
|
|
||||||
oldPath.replace_extension(".log.old");
|
|
||||||
if (exists(oldPath))
|
|
||||||
remove(oldPath);
|
|
||||||
rename(path, oldPath);
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
// whatever
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto h = CreateFile(path.wstring().c_str(),
|
|
||||||
GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
nullptr, OPEN_ALWAYS, 0, nullptr);
|
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
|
||||||
throw std::runtime_error(std::format("Win32 error {}(0x{:x})", GetLastError(), GetLastError()));
|
|
||||||
|
|
||||||
SetFilePointer(h, 0, 0, FILE_END);
|
|
||||||
s_hLogFile = { h, &CloseHandle };
|
|
||||||
|
|
||||||
if (redirect_stderrout) {
|
|
||||||
SetStdHandle(STD_ERROR_HANDLE, h);
|
|
||||||
SetStdHandle(STD_OUTPUT_HANDLE, h);
|
|
||||||
s_bSkipLogFileWrite = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void logging::update_dll_load_status(bool loaded) {
|
|
||||||
s_bLoaded = loaded;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,18 @@
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <numeric>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "unicode.h"
|
#include "unicode.h"
|
||||||
|
|
||||||
namespace logging {
|
namespace logging {
|
||||||
enum Level : int {
|
enum class Level : int {
|
||||||
Verbose = 0,
|
Verbose = 0,
|
||||||
V = 0,
|
|
||||||
Debug = 1,
|
Debug = 1,
|
||||||
D = 1,
|
|
||||||
Info = 2,
|
Info = 2,
|
||||||
I = 2,
|
|
||||||
Warning = 3,
|
Warning = 3,
|
||||||
W = 3,
|
|
||||||
Error = 4,
|
Error = 4,
|
||||||
E = 4,
|
|
||||||
Fatal = 5,
|
Fatal = 5,
|
||||||
F = 5,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FastFailErrorCode : int {
|
enum FastFailErrorCode : int {
|
||||||
|
|
@ -28,42 +21,105 @@ namespace logging {
|
||||||
MinHookUnload,
|
MinHookUnload,
|
||||||
};
|
};
|
||||||
|
|
||||||
void print(Level level, const char* s);
|
/**
|
||||||
|
* @brief Starts writing log to specified file.
|
||||||
inline void print(Level level, const wchar_t* s) {
|
*/
|
||||||
const auto cs = unicode::convert<std::string>(s);
|
|
||||||
print(level, cs.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void print(Level level, const std::string& s) {
|
|
||||||
print(level, s.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void print(Level level, const std::wstring& s) {
|
|
||||||
print(level, s.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Level level, typename T>
|
|
||||||
inline void print(const T* s) {
|
|
||||||
print(level, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Arg, typename...Args>
|
|
||||||
inline void print(Level level, const char* pcszFormat, Arg arg1, Args...args) {
|
|
||||||
print(level, std::format(pcszFormat, std::forward<Arg>(arg1), std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Arg, typename...Args>
|
|
||||||
inline void print(Level level, const wchar_t* pcszFormat, Arg arg1, Args...args) {
|
|
||||||
print(level, std::format(pcszFormat, std::forward<Arg>(arg1), std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Level level, typename T, typename Arg, typename...Args, typename = std::enable_if_t<std::is_integral_v<T>>>
|
|
||||||
inline void print(const T* pcszFormat, Arg arg1, Args...args) {
|
|
||||||
print(level, std::format(pcszFormat, std::forward<Arg>(arg1), std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
void start_file_logging(const std::filesystem::path& path, bool redirect_stderrout = false);
|
void start_file_logging(const std::filesystem::path& path, bool redirect_stderrout = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Marks this DLL either as loaded or unloaded, top prevent accessing handles when the DLL is not loaded.
|
||||||
|
*/
|
||||||
void update_dll_load_status(bool loaded);
|
void update_dll_load_status(bool loaded);
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* @brief Prints log, unformatted.
|
||||||
|
* @param level Log level.
|
||||||
|
* @param s Log to print, as a C-string.
|
||||||
|
*/
|
||||||
|
template<typename TElem>
|
||||||
|
void print(Level level, const TElem* s) { print(level, unicode::convert<std::string>(s).c_str()); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints log, unformatted.
|
||||||
|
* @param level Log level.
|
||||||
|
* @param s Log to print, as a basic_string.
|
||||||
|
*/
|
||||||
|
template<typename TElem, typename TTraits = std::char_traits<TElem>, typename TAlloc = std::allocator<TElem>>
|
||||||
|
void print(Level level, const std::basic_string<TElem, TTraits, TAlloc>& s) { print(level, s.c_str()); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints log, unformatted.
|
||||||
|
* @param level Log level.
|
||||||
|
* @param s Log to print, as a basic_string_view.
|
||||||
|
*/
|
||||||
|
template<typename TElem, typename TTraits = std::char_traits<TElem>>
|
||||||
|
void print(Level level, const std::basic_string_view<TElem, TTraits>& s) { print(level, unicode::convert<std::string>(s).c_str()); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void print<char>(Level level, const char* s);
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
struct is_basic_string : std::false_type {};
|
||||||
|
|
||||||
|
template<typename TElem, typename TTraits, typename TAlloc>
|
||||||
|
struct is_basic_string<std::basic_string<TElem, TTraits, TAlloc>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr auto is_basic_string_v = is_basic_string<T>::value;
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
struct is_basic_string_view : std::false_type {};
|
||||||
|
|
||||||
|
template<typename TElem, typename TTraits, typename TAlloc>
|
||||||
|
struct is_basic_string_view<std::basic_string<TElem, TTraits, TAlloc>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr auto is_basic_string_view_v = is_basic_string_view<T>::value;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto to_format_arg(T&& x) {
|
||||||
|
using Td = std::remove_cvref_t<T>;
|
||||||
|
if constexpr (std::is_pointer_v<Td>) {
|
||||||
|
using Tdd = std::remove_cvref_t<std::remove_pointer_t<Td>>;
|
||||||
|
if constexpr (std::is_same_v<Tdd, wchar_t> || std::is_same_v<Tdd, char8_t> || std::is_same_v<Tdd, char16_t> || std::is_same_v<Tdd, char32_t>)
|
||||||
|
return unicode::convert<std::string>(x);
|
||||||
|
else
|
||||||
|
return std::forward<T>(x);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if constexpr (is_basic_string_v<Td> || is_basic_string_view_v<Td>) {
|
||||||
|
using Tdd = Td::value_type;
|
||||||
|
if constexpr (std::is_same_v<Tdd, wchar_t> || std::is_same_v<Tdd, char8_t> || std::is_same_v<Tdd, char16_t> || std::is_same_v<Tdd, char32_t>)
|
||||||
|
return unicode::convert<std::string>(x);
|
||||||
|
else
|
||||||
|
return std::forward<T>(x);
|
||||||
|
|
||||||
|
} else if constexpr (std::is_same_v<Td, std::filesystem::path>) {
|
||||||
|
auto u8s = x.u8string();
|
||||||
|
return std::move(*reinterpret_cast<std::string*>(&u8s));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return std::forward<T>(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints log, formatted.
|
||||||
|
* @param level Log level.
|
||||||
|
* @param fmt C-string.
|
||||||
|
* @param arg1 First format parameter.
|
||||||
|
* @param args Second and further format parameters, if any.
|
||||||
|
*/
|
||||||
|
template<typename Arg, typename...Args>
|
||||||
|
void print(Level level, const char* fmt, Arg&& arg1, Args&&...args) {
|
||||||
|
print(level, std::vformat(fmt, std::make_format_args(to_format_arg(std::forward<Arg>(arg1)), to_format_arg(std::forward<Args>(args))...)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...Args> void V(Args&&...args) { print(Level::Verbose, std::forward<Args>(args)...); }
|
||||||
|
template<typename...Args> void D(Args&&...args) { print(Level::Debug, std::forward<Args>(args)...); }
|
||||||
|
template<typename...Args> void I(Args&&...args) { print(Level::Info, std::forward<Args>(args)...); }
|
||||||
|
template<typename...Args> void W(Args&&...args) { print(Level::Warning, std::forward<Args>(args)...); }
|
||||||
|
template<typename...Args> void E(Args&&...args) { print(Level::Error, std::forward<Args>(args)...); }
|
||||||
|
template<typename...Args> void F(Args&&...args) { print(Level::Fatal, std::forward<Args>(args)...); }
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ void* get_mapped_image_base_address(HANDLE hProcess, const std::filesystem::path
|
||||||
return mbi.AllocationBase;
|
return mbi.AllocationBase;
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
logging::print<logging::W>("Failed to check memory block 0x{:X}(len=0x{:X}): {}", mbi.BaseAddress, mbi.RegionSize, e.what());
|
logging::W("Failed to check memory block 0x{:X}(len=0x{:X}): {}", mbi.BaseAddress, mbi.RegionSize, e.what());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ namespace unicode {
|
||||||
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 = unicode::decode(c, &in[decIdx], in.size() - decIdx, strict)); decIdx += decLen) {
|
||||||
const auto encIdx = out.size();
|
const auto encIdx = out.size();
|
||||||
const auto encLen = unicode::encode<TTo::value_type>(nullptr, c, strict);
|
const auto encLen = unicode::encode<typename TTo::value_type>(nullptr, c, strict);
|
||||||
out.resize(encIdx + encLen);
|
out.resize(encIdx + encLen);
|
||||||
unicode::encode(&out[encIdx], c, strict);
|
unicode::encode(&out[encIdx], c, strict);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ std::span<char> utils::loaded_module::section(const char* pcszSectionName) const
|
||||||
|
|
||||||
template<typename TEntryType>
|
template<typename TEntryType>
|
||||||
static bool find_imported_function_pointer_helper(const char* pcBaseAddress, const IMAGE_IMPORT_DESCRIPTOR& desc, const IMAGE_DATA_DIRECTORY& dir, std::string_view reqFunc, uint32_t hintOrOrdinal, void*& ppFunctionAddress) {
|
static bool find_imported_function_pointer_helper(const char* pcBaseAddress, const IMAGE_IMPORT_DESCRIPTOR& desc, const IMAGE_DATA_DIRECTORY& dir, std::string_view reqFunc, uint32_t hintOrOrdinal, void*& ppFunctionAddress) {
|
||||||
const auto importLookupsOversizedSpan = std::span(reinterpret_cast<const TEntryType*>(&pcBaseAddress[desc.OriginalFirstThunk]), (dir.Size - desc.OriginalFirstThunk) / sizeof TEntryType);
|
const auto importLookupsOversizedSpan = std::span(reinterpret_cast<const TEntryType*>(&pcBaseAddress[desc.OriginalFirstThunk]), (dir.Size - desc.OriginalFirstThunk) / sizeof(TEntryType));
|
||||||
const auto importAddressesOversizedSpan = std::span(reinterpret_cast<const TEntryType*>(&pcBaseAddress[desc.FirstThunk]), (dir.Size - desc.FirstThunk) / sizeof TEntryType);
|
const auto importAddressesOversizedSpan = std::span(reinterpret_cast<const TEntryType*>(&pcBaseAddress[desc.FirstThunk]), (dir.Size - desc.FirstThunk) / sizeof(TEntryType));
|
||||||
|
|
||||||
for (size_t i = 0, i_ = (std::min)(importLookupsOversizedSpan.size(), importAddressesOversizedSpan.size()); i < i_ && importLookupsOversizedSpan[i] && importAddressesOversizedSpan[i]; i++) {
|
for (size_t i = 0, i_ = (std::min)(importLookupsOversizedSpan.size(), importAddressesOversizedSpan.size()); i < i_ && importLookupsOversizedSpan[i] && importAddressesOversizedSpan[i]; i++) {
|
||||||
const auto& importLookup = importLookupsOversizedSpan[i];
|
const auto& importLookup = importLookupsOversizedSpan[i];
|
||||||
|
|
|
||||||
|
|
@ -218,9 +218,7 @@ namespace utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T get_env(const wchar_t* pcwzName) {
|
T get_env(const wchar_t* pcwzName) = delete;
|
||||||
static_assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
std::wstring get_env(const wchar_t* pcwzName);
|
std::wstring get_env(const wchar_t* pcwzName);
|
||||||
|
|
@ -240,9 +238,7 @@ namespace utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::vector<T> get_env_list(const wchar_t* pcwzName) {
|
std::vector<T> get_env_list(const wchar_t* pcwzName) = delete;
|
||||||
static_assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
std::vector<std::wstring> get_env_list(const wchar_t* pcwzName);
|
std::vector<std::wstring> get_env_list(const wchar_t* pcwzName);
|
||||||
|
|
|
||||||
|
|
@ -269,16 +269,18 @@ LONG exception_handler(EXCEPTION_POINTERS* ex)
|
||||||
L"Dalamud.EntryPoint+VehDelegate, Dalamud",
|
L"Dalamud.EntryPoint+VehDelegate, Dalamud",
|
||||||
nullptr, nullptr, &fn)))
|
nullptr, nullptr, &fn)))
|
||||||
{
|
{
|
||||||
const auto msg = L"An error within the game has occurred.\n\n"
|
const auto formatted = std::format(
|
||||||
|
L"An error within the game has occurred.\n\n"
|
||||||
L"This may be caused by a faulty plugin, a broken TexTools modification, any other third-party tool or simply a bug in the game.\n"
|
L"This may be caused by a faulty plugin, a broken TexTools modification, any other third-party tool or simply a bug in the game.\n"
|
||||||
L"Please try \"Start Over\" or \"Download Index Backup\" in TexTools, an integrity check in the XIVLauncher settings, and disabling plugins you don't need.\n\n"
|
L"Please try \"Start Over\" or \"Download Index Backup\" in TexTools, an integrity check in the XIVLauncher settings, and disabling plugins you don't need.\n\n"
|
||||||
L"The log file is located at:\n"
|
L"The log file is located at:\n"
|
||||||
L"{1}\n\n"
|
L"{1}\n\n"
|
||||||
L"Press OK to exit the application.\n\nFailed to read stack trace: {2:08x}";
|
L"Press OK to exit the application.\n\nFailed to read stack trace: {2:08x}",
|
||||||
|
dmp_path, log_path, err);
|
||||||
|
|
||||||
// show in another thread to prevent messagebox from pumping messages of current thread
|
// show in another thread to prevent messagebox from pumping messages of current thread
|
||||||
std::thread([&]() {
|
std::thread([&]() {
|
||||||
MessageBoxW(nullptr, std::format(msg, dmp_path, log_path, err).c_str(), L"Dalamud Error", MB_OK | MB_ICONERROR | MB_TOPMOST);
|
MessageBoxW(nullptr, formatted.c_str(), L"Dalamud Error", MB_OK | MB_ICONERROR | MB_TOPMOST);
|
||||||
}).join();
|
}).join();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
std::filesystem::path path;
|
std::filesystem::path path;
|
||||||
try {
|
try {
|
||||||
path = mod.path();
|
path = mod.path();
|
||||||
logging::print<logging::I>(L"{} [{}/{}] Module 0x{:X} ~ 0x{:X} (0x{:X}): \"{}\"", LogTagW, i + 1, mods.size(), mod.address_int(), mod.address_int() + mod.image_size(), mod.image_size(), path.wstring());
|
logging::I("{} [{}/{}] Module 0x{:X} ~ 0x{:X} (0x{:X}): \"{}\"", LogTagW, i + 1, mods.size(), mod.address_int(), mod.address_int() + mod.image_size(), mod.image_size(), path.wstring());
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
logging::print<logging::W>("{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}", LogTag, i + 1, mods.size(), mod.address_int(), e.what());
|
logging::W("{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}", LogTag, i + 1, mods.size(), mod.address_int(), e.what());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
const auto section = assume_nonempty_span(mod.span_as<char>(sectionHeader.VirtualAddress, sectionHeader.Misc.VirtualSize), ".text[VA:VA+VS]");
|
const auto section = assume_nonempty_span(mod.span_as<char>(sectionHeader.VirtualAddress, sectionHeader.Misc.VirtualSize), ".text[VA:VA+VS]");
|
||||||
auto hFsDllRaw = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
auto hFsDllRaw = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
if (hFsDllRaw == INVALID_HANDLE_VALUE) {
|
if (hFsDllRaw == INVALID_HANDLE_VALUE) {
|
||||||
logging::print<logging::W>("{} Module loaded in current process but could not open file: Win32 error {}", LogTag, GetLastError());
|
logging::W("{} Module loaded in current process but could not open file: Win32 error {}", LogTag, GetLastError());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto hFsDll = std::unique_ptr<void, decltype(CloseHandle)*>(hFsDllRaw, &CloseHandle);
|
auto hFsDll = std::unique_ptr<void, decltype(CloseHandle)*>(hFsDllRaw, &CloseHandle);
|
||||||
|
|
@ -53,11 +53,11 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
SetFilePointer(hFsDll.get(), sectionHeader.PointerToRawData, nullptr, FILE_CURRENT);
|
SetFilePointer(hFsDll.get(), sectionHeader.PointerToRawData, nullptr, FILE_CURRENT);
|
||||||
if (DWORD read{}; ReadFile(hFsDll.get(), &buf[0], static_cast<DWORD>(buf.size()), &read, nullptr)) {
|
if (DWORD read{}; ReadFile(hFsDll.get(), &buf[0], static_cast<DWORD>(buf.size()), &read, nullptr)) {
|
||||||
if (read < section.size_bytes()) {
|
if (read < section.size_bytes()) {
|
||||||
logging::print<logging::W>(L"{} ReadFile: read {} bytes < requested {} bytes", LogTagW, read, section.size_bytes());
|
logging::W("{} ReadFile: read {} bytes < requested {} bytes", LogTagW, read, section.size_bytes());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logging::print<logging::I>(L"{} ReadFile: Win32 error {}", LogTagW, GetLastError());
|
logging::I("{} ReadFile: Win32 error {}", LogTagW, GetLastError());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
if (!nmd_x86_decode(§ion[i], section.size() - i, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL)) {
|
if (!nmd_x86_decode(§ion[i], section.size() - i, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL)) {
|
||||||
instructionLength = 1;
|
instructionLength = 1;
|
||||||
if (printed < 64) {
|
if (printed < 64) {
|
||||||
logging::print<logging::W>("{} {}+0x{:0X}: dd {:02X}", LogTag, moduleName, rva, static_cast<uint8_t>(section[i]));
|
logging::W("{} {}+0x{:0X}: dd {:02X}", LogTag, moduleName, rva, static_cast<uint8_t>(section[i]));
|
||||||
printed++;
|
printed++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -102,16 +102,16 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
if (const char* pcszName = mod.address_as<char>(names[j]); pcszName < mod.address() || pcszName >= mod.address() + mod.image_size()) {
|
if (const char* pcszName = mod.address_as<char>(names[j]); pcszName < mod.address() || pcszName >= mod.address() + mod.image_size()) {
|
||||||
if (IsBadReadPtr(pcszName, 256)) {
|
if (IsBadReadPtr(pcszName, 256)) {
|
||||||
logging::print<logging::W>("{} Name #{} points to an invalid address outside the executable. Skipping.", LogTag, j);
|
logging::W("{} Name #{} points to an invalid address outside the executable. Skipping.", LogTag, j);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = std::string_view(pcszName, strnlen(pcszName, 256));
|
name = std::string_view(pcszName, strnlen(pcszName, 256));
|
||||||
logging::print<logging::W>("{} Name #{} points to a seemingly valid address outside the executable: {}", LogTag, j, name);
|
logging::W("{} Name #{} points to a seemingly valid address outside the executable: {}", LogTag, j, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ordinals[j] >= functions.size()) {
|
if (ordinals[j] >= functions.size()) {
|
||||||
logging::print<logging::W>("{} Ordinal #{} points to function index #{} >= #{}. Skipping.", LogTag, j, ordinals[j], functions.size());
|
logging::W("{} Ordinal #{} points to function index #{} >= #{}. Skipping.", LogTag, j, ordinals[j], functions.size());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,7 +122,7 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logging::print<logging::W>("{} {}+0x{:0X}{}: {}", LogTag, moduleName, rva, resolvedExportName, formatBuf);
|
logging::W("{} {}+0x{:0X}{}: {}", LogTag, moduleName, rva, resolvedExportName, formatBuf);
|
||||||
printed++;
|
printed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,12 +135,12 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tenderizer)
|
if (tenderizer)
|
||||||
logging::print<logging::I>("{} Verification and overwriting complete.", LogTag);
|
logging::I("{} Verification and overwriting complete.", LogTag);
|
||||||
else if (doRestore)
|
else if (doRestore)
|
||||||
logging::print<logging::I>("{} Verification complete. Overwriting was not required.", LogTag);
|
logging::I("{} Verification complete. Overwriting was not required.", LogTag);
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
logging::print<logging::W>("{} Error: {}", LogTag, e.what());
|
logging::W("{} Error: {}", LogTag, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +180,7 @@ void xivfixes::prevent_devicechange_crashes(bool bApply) {
|
||||||
|
|
||||||
if (bApply) {
|
if (bApply) {
|
||||||
if (!bootconfig::gamefix_is_enabled(L"prevent_devicechange_crashes")) {
|
if (!bootconfig::gamefix_is_enabled(L"prevent_devicechange_crashes")) {
|
||||||
logging::print<logging::I>("{} Turned off via environment variable.", LogTag);
|
logging::I("{} Turned off via environment variable.", LogTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ void xivfixes::prevent_devicechange_crashes(bool bApply) {
|
||||||
|| 0 != strcmp(lpClassName, "FFXIVGAME"))
|
|| 0 != strcmp(lpClassName, "FFXIVGAME"))
|
||||||
return hWnd;
|
return hWnd;
|
||||||
|
|
||||||
logging::print<logging::I>(R"({} CreateWindow(0x{:08X}, "{}", "{}", 0x{:08X}, {}, {}, {}, {}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}) called; unhooking CreateWindowExA and hooking WndProc.)",
|
logging::I(R"({} CreateWindow(0x{:08X}, "{}", "{}", 0x{:08X}, {}, {}, {}, {}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}) called; unhooking CreateWindowExA and hooking WndProc.)",
|
||||||
LogTag, dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, reinterpret_cast<size_t>(hWndParent), reinterpret_cast<size_t>(hMenu), reinterpret_cast<size_t>(hInstance), reinterpret_cast<size_t>(lpParam));
|
LogTag, dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, reinterpret_cast<size_t>(hWndParent), reinterpret_cast<size_t>(hMenu), reinterpret_cast<size_t>(hInstance), reinterpret_cast<size_t>(lpParam));
|
||||||
|
|
||||||
s_hookCreateWindowExA.reset();
|
s_hookCreateWindowExA.reset();
|
||||||
|
|
@ -202,7 +202,7 @@ void xivfixes::prevent_devicechange_crashes(bool bApply) {
|
||||||
s_hookWndProc->set_detour([](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -> LRESULT {
|
s_hookWndProc->set_detour([](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -> LRESULT {
|
||||||
if (uMsg == WM_DEVICECHANGE && wParam == DBT_DEVNODES_CHANGED) {
|
if (uMsg == WM_DEVICECHANGE && wParam == DBT_DEVNODES_CHANGED) {
|
||||||
if (!GetGetInputDeviceManager(hWnd)()) {
|
if (!GetGetInputDeviceManager(hWnd)()) {
|
||||||
logging::print<logging::I>("{} WndProc(0x{:X}, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, {}) called but the game does not have InputDeviceManager initialized; doing nothing.", LogTag, reinterpret_cast<size_t>(hWnd), lParam);
|
logging::I("{} WndProc(0x{:X}, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, {}) called but the game does not have InputDeviceManager initialized; doing nothing.", LogTag, reinterpret_cast<size_t>(hWnd), lParam);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -213,17 +213,17 @@ void xivfixes::prevent_devicechange_crashes(bool bApply) {
|
||||||
return hWnd;
|
return hWnd;
|
||||||
});
|
});
|
||||||
|
|
||||||
logging::print<logging::I>("{} Enable", LogTag);
|
logging::I("{} Enable", LogTag);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (s_hookCreateWindowExA) {
|
if (s_hookCreateWindowExA) {
|
||||||
logging::print<logging::I>("{} Disable CreateWindowExA", LogTag);
|
logging::I("{} Disable CreateWindowExA", LogTag);
|
||||||
s_hookCreateWindowExA.reset();
|
s_hookCreateWindowExA.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will effectively revert any other WndProc alterations, including Dalamud.
|
// This will effectively revert any other WndProc alterations, including Dalamud.
|
||||||
if (s_hookWndProc) {
|
if (s_hookWndProc) {
|
||||||
logging::print<logging::I>("{} Disable WndProc", LogTag);
|
logging::I("{} Disable WndProc", LogTag);
|
||||||
s_hookWndProc.reset();
|
s_hookWndProc.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -235,18 +235,18 @@ void xivfixes::disable_game_openprocess_access_check(bool bApply) {
|
||||||
|
|
||||||
if (bApply) {
|
if (bApply) {
|
||||||
if (!bootconfig::gamefix_is_enabled(L"disable_game_openprocess_access_check")) {
|
if (!bootconfig::gamefix_is_enabled(L"disable_game_openprocess_access_check")) {
|
||||||
logging::print<logging::I>("{} Turned off via environment variable.", LogTag);
|
logging::I("{} Turned off via environment variable.", LogTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_hook.emplace("kernel32.dll!OpenProcess (import, disable_game_openprocess_access_check)", "kernel32.dll", "OpenProcess", 0);
|
s_hook.emplace("kernel32.dll!OpenProcess (import, disable_game_openprocess_access_check)", "kernel32.dll", "OpenProcess", 0);
|
||||||
s_hook->set_detour([](DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)->HANDLE {
|
s_hook->set_detour([](DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)->HANDLE {
|
||||||
logging::print<logging::I>("{} OpenProcess(0x{:08X}, {}, {}) was invoked by thread {}.", LogTag, dwDesiredAccess, bInheritHandle, dwProcessId, GetCurrentThreadId());
|
logging::I("{} OpenProcess(0x{:08X}, {}, {}) was invoked by thread {}.", LogTag, dwDesiredAccess, bInheritHandle, dwProcessId, GetCurrentThreadId());
|
||||||
|
|
||||||
if (dwProcessId == GetCurrentProcessId()) {
|
if (dwProcessId == GetCurrentProcessId()) {
|
||||||
// Prevent game from feeling unsafe that it restarts
|
// Prevent game from feeling unsafe that it restarts
|
||||||
if (dwDesiredAccess & PROCESS_VM_WRITE) {
|
if (dwDesiredAccess & PROCESS_VM_WRITE) {
|
||||||
logging::print<logging::I>("{} Returning failure with last error code set to ERROR_ACCESS_DENIED(5).", LogTag);
|
logging::I("{} Returning failure with last error code set to ERROR_ACCESS_DENIED(5).", LogTag);
|
||||||
SetLastError(ERROR_ACCESS_DENIED);
|
SetLastError(ERROR_ACCESS_DENIED);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -255,10 +255,10 @@ void xivfixes::disable_game_openprocess_access_check(bool bApply) {
|
||||||
return s_hook->call_original(dwDesiredAccess, bInheritHandle, dwProcessId);
|
return s_hook->call_original(dwDesiredAccess, bInheritHandle, dwProcessId);
|
||||||
});
|
});
|
||||||
|
|
||||||
logging::print<logging::I>("{} Enable", LogTag);
|
logging::I("{} Enable", LogTag);
|
||||||
} else {
|
} else {
|
||||||
if (s_hook) {
|
if (s_hook) {
|
||||||
logging::print<logging::I>("{} Disable OpenProcess", LogTag);
|
logging::I("{} Disable OpenProcess", LogTag);
|
||||||
s_hook.reset();
|
s_hook.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -272,7 +272,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
||||||
|
|
||||||
if (bApply) {
|
if (bApply) {
|
||||||
if (!bootconfig::gamefix_is_enabled(L"redirect_openprocess")) {
|
if (!bootconfig::gamefix_is_enabled(L"redirect_openprocess")) {
|
||||||
logging::print<logging::I>("{} Turned off via environment variable.", LogTag);
|
logging::I("{} Turned off via environment variable.", LogTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,7 +281,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
||||||
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()) {
|
||||||
if (s_silenceSet.emplace(GetCurrentThreadId()).second)
|
if (s_silenceSet.emplace(GetCurrentThreadId()).second)
|
||||||
logging::print<logging::I>("{} OpenProcess(0x{:08X}, {}, {}) was invoked by thread {}. Redirecting to DuplicateHandle.", LogTag, dwDesiredAccess, bInheritHandle, dwProcessId, GetCurrentThreadId());
|
logging::I("{} OpenProcess(0x{:08X}, {}, {}) was invoked by thread {}. Redirecting to DuplicateHandle.", LogTag, dwDesiredAccess, bInheritHandle, dwProcessId, GetCurrentThreadId());
|
||||||
|
|
||||||
if (HANDLE res; DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &res, dwDesiredAccess, bInheritHandle, 0))
|
if (HANDLE res; DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &res, dwDesiredAccess, bInheritHandle, 0))
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -292,14 +292,14 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
||||||
});
|
});
|
||||||
s_hook = std::dynamic_pointer_cast<hooks::base_untyped_hook>(std::move(hook));
|
s_hook = std::dynamic_pointer_cast<hooks::base_untyped_hook>(std::move(hook));
|
||||||
|
|
||||||
logging::print<logging::I>("{} Enable via import_hook", LogTag);
|
logging::I("{} Enable via import_hook", LogTag);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
auto hook = std::make_shared<hooks::direct_hook<decltype(OpenProcess)>>("kernel32.dll!OpenProcess (direct, redirect_openprocess)", OpenProcess);
|
auto hook = std::make_shared<hooks::direct_hook<decltype(OpenProcess)>>("kernel32.dll!OpenProcess (direct, redirect_openprocess)", 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()) {
|
||||||
if (s_silenceSet.emplace(GetCurrentThreadId()).second)
|
if (s_silenceSet.emplace(GetCurrentThreadId()).second)
|
||||||
logging::print<logging::I>("{} OpenProcess(0x{:08X}, {}, {}) was invoked by thread {}. Redirecting to DuplicateHandle.", LogTag, dwDesiredAccess, bInheritHandle, dwProcessId, GetCurrentThreadId());
|
logging::I("{} OpenProcess(0x{:08X}, {}, {}) was invoked by thread {}. Redirecting to DuplicateHandle.", LogTag, dwDesiredAccess, bInheritHandle, dwProcessId, GetCurrentThreadId());
|
||||||
|
|
||||||
if (HANDLE res; DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &res, dwDesiredAccess, bInheritHandle, 0))
|
if (HANDLE res; DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &res, dwDesiredAccess, bInheritHandle, 0))
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -310,7 +310,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
||||||
});
|
});
|
||||||
s_hook = std::dynamic_pointer_cast<hooks::base_untyped_hook>(std::move(hook));
|
s_hook = std::dynamic_pointer_cast<hooks::base_untyped_hook>(std::move(hook));
|
||||||
|
|
||||||
logging::print<logging::I>("{} Enable via direct_hook", LogTag);
|
logging::I("{} Enable via direct_hook", LogTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::thread([]() {
|
//std::thread([]() {
|
||||||
|
|
@ -321,7 +321,7 @@ void xivfixes::redirect_openprocess(bool bApply) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (s_hook) {
|
if (s_hook) {
|
||||||
logging::print<logging::I>("{} Disable OpenProcess", LogTag);
|
logging::I("{} Disable OpenProcess", LogTag);
|
||||||
s_hook.reset();
|
s_hook.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,16 +341,16 @@ void xivfixes::apply_all(bool bApply) {
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
if (bApply)
|
if (bApply)
|
||||||
logging::print<logging::W>("Error trying to activate fixup [{}]: {}", taskName, e.what());
|
logging::W("Error trying to activate fixup [{}]: {}", taskName, e.what());
|
||||||
else
|
else
|
||||||
logging::print<logging::W>("Error trying to deactivate fixup [{}]: {}", taskName, e.what());
|
logging::W("Error trying to deactivate fixup [{}]: {}", taskName, e.what());
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bApply)
|
if (bApply)
|
||||||
logging::print<logging::I>("Fixup [{}] activated.", taskName);
|
logging::I("Fixup [{}] activated.", taskName);
|
||||||
else
|
else
|
||||||
logging::print<logging::I>("Fixup [{}] deactivated.", taskName);
|
logging::I("Fixup [{}] deactivated.", taskName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<PropertyGroup Label="Configuration">
|
<PropertyGroup Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<OutDir>..\bin\$(Configuration)\</OutDir>
|
<OutDir>..\bin\$(Configuration)\</OutDir>
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
int wmain(int argc, wchar_t** argv)
|
int wmain(int argc, wchar_t** argv)
|
||||||
{
|
{
|
||||||
logging::print<logging::I>("Dalamud Injector, (c) 2021 XIVLauncher Contributors");
|
logging::I("Dalamud Injector, (c) 2021 XIVLauncher Contributors");
|
||||||
logging::print<logging::I>("Built at : " __DATE__ "@" __TIME__);
|
logging::I("Built at : " __DATE__ "@" __TIME__);
|
||||||
|
|
||||||
wchar_t _module_path[MAX_PATH];
|
wchar_t _module_path[MAX_PATH];
|
||||||
GetModuleFileNameW(NULL, _module_path, sizeof _module_path / 2);
|
GetModuleFileNameW(NULL, _module_path, sizeof _module_path / 2);
|
||||||
|
|
@ -37,9 +37,9 @@ int wmain(int argc, wchar_t** argv)
|
||||||
typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(int, wchar_t**);
|
typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(int, wchar_t**);
|
||||||
custom_component_entry_point_fn entrypoint_fn = reinterpret_cast<custom_component_entry_point_fn>(entrypoint_vfn);
|
custom_component_entry_point_fn entrypoint_fn = reinterpret_cast<custom_component_entry_point_fn>(entrypoint_vfn);
|
||||||
|
|
||||||
logging::print<logging::I>("Running Dalamud Injector...");
|
logging::I("Running Dalamud Injector...");
|
||||||
entrypoint_fn(argc, argv);
|
entrypoint_fn(argc, argv);
|
||||||
logging::print<logging::I>("Done!");
|
logging::I("Done!");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ int CoreCLR::load_runtime(const std::wstring& runtime_config_path, const struct
|
||||||
// Success_HostAlreadyInitialized
|
// Success_HostAlreadyInitialized
|
||||||
if (result == 1)
|
if (result == 1)
|
||||||
{
|
{
|
||||||
logging::print<logging::I>("Success_HostAlreadyInitialized (0x1)");
|
logging::I("Success_HostAlreadyInitialized (0x1)");
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ int InitializeClrAndGetEntryPoint(
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
logging::print<logging::E>("Unable to get RoamingAppData path (err={})", result);
|
logging::E("Unable to get RoamingAppData path (err={})", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,13 +73,13 @@ int InitializeClrAndGetEntryPoint(
|
||||||
|
|
||||||
// =========================================================================== //
|
// =========================================================================== //
|
||||||
|
|
||||||
logging::print<logging::I>(L"with dotnet_path: {}", dotnet_path);
|
logging::I("with dotnet_path: {}", dotnet_path);
|
||||||
logging::print<logging::I>(L"with config_path: {}", runtimeconfig_path.c_str());
|
logging::I("with config_path: {}", runtimeconfig_path);
|
||||||
logging::print<logging::I>(L"with module_path: {}", module_path.c_str());
|
logging::I("with module_path: {}", module_path);
|
||||||
|
|
||||||
if (!std::filesystem::exists(dotnet_path))
|
if (!std::filesystem::exists(dotnet_path))
|
||||||
{
|
{
|
||||||
logging::print<logging::E>("Error: Unable to find .NET runtime path");
|
logging::E("Error: Unable to find .NET runtime path");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,13 +90,13 @@ int InitializeClrAndGetEntryPoint(
|
||||||
dotnet_path,
|
dotnet_path,
|
||||||
};
|
};
|
||||||
|
|
||||||
logging::print<logging::I>("Loading hostfxr...");
|
logging::I("Loading hostfxr...");
|
||||||
if ((result = g_clr->load_hostfxr(&init_parameters)) != 0)
|
if ((result = g_clr->load_hostfxr(&init_parameters)) != 0)
|
||||||
{
|
{
|
||||||
logging::print<logging::E>("Failed to load the `hostfxr` library (err=0x{:08x})", result);
|
logging::E("Failed to load the `hostfxr` library (err=0x{:08x})", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
logging::print<logging::I>("Done!");
|
logging::I("Done!");
|
||||||
|
|
||||||
// =========================================================================== //
|
// =========================================================================== //
|
||||||
|
|
||||||
|
|
@ -107,17 +107,17 @@ int InitializeClrAndGetEntryPoint(
|
||||||
dotnet_path,
|
dotnet_path,
|
||||||
};
|
};
|
||||||
|
|
||||||
logging::print<logging::I>("Loading coreclr... ");
|
logging::I("Loading coreclr... ");
|
||||||
if ((result = g_clr->load_runtime(runtimeconfig_path, &runtime_parameters)) != 0)
|
if ((result = g_clr->load_runtime(runtimeconfig_path, &runtime_parameters)) != 0)
|
||||||
{
|
{
|
||||||
logging::print<logging::E>("Failed to load coreclr (err=0x{:08X})", static_cast<uint32_t>(result));
|
logging::E("Failed to load coreclr (err=0x{:08X})", static_cast<uint32_t>(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
logging::print<logging::I>("Done!");
|
logging::I("Done!");
|
||||||
|
|
||||||
// =========================================================================== //
|
// =========================================================================== //
|
||||||
|
|
||||||
logging::print<logging::I>("Loading module...");
|
logging::I("Loading module...");
|
||||||
if ((result = g_clr->load_assembly_and_get_function_pointer(
|
if ((result = g_clr->load_assembly_and_get_function_pointer(
|
||||||
module_path.c_str(),
|
module_path.c_str(),
|
||||||
entrypoint_assembly_name.c_str(),
|
entrypoint_assembly_name.c_str(),
|
||||||
|
|
@ -125,10 +125,10 @@ int InitializeClrAndGetEntryPoint(
|
||||||
entrypoint_delegate_type_name.c_str(),
|
entrypoint_delegate_type_name.c_str(),
|
||||||
nullptr, entrypoint_fn)) != 0)
|
nullptr, entrypoint_fn)) != 0)
|
||||||
{
|
{
|
||||||
logging::print<logging::E>("Failed to load module (err={})", result);
|
logging::E("Failed to load module (err={})", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
logging::print<logging::I>("Done!");
|
logging::I("Done!");
|
||||||
|
|
||||||
// =========================================================================== //
|
// =========================================================================== //
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue