mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Sanitize PDB root name from loaded modules (#1687)
This commit is contained in:
parent
8e5a84792e
commit
3d59fa3da0
10 changed files with 181 additions and 39 deletions
|
|
@ -58,7 +58,7 @@
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<AdditionalDependencies>Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Version.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\lib\CoreCLR;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\lib\CoreCLR;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
@ -137,6 +137,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="ntdll.cpp" />
|
||||||
<ClCompile Include="unicode.cpp">
|
<ClCompile Include="unicode.cpp">
|
||||||
<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>
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
<ClInclude Include="DalamudStartInfo.h" />
|
<ClInclude Include="DalamudStartInfo.h" />
|
||||||
<ClInclude Include="hooks.h" />
|
<ClInclude Include="hooks.h" />
|
||||||
<ClInclude Include="logging.h" />
|
<ClInclude Include="logging.h" />
|
||||||
|
<ClInclude Include="ntdll.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
<ClInclude Include="unicode.h" />
|
<ClInclude Include="unicode.h" />
|
||||||
<ClInclude Include="utils.h" />
|
<ClInclude Include="utils.h" />
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@
|
||||||
<ClCompile Include="DalamudStartInfo.cpp">
|
<ClCompile Include="DalamudStartInfo.cpp">
|
||||||
<Filter>Dalamud.Boot DLL</Filter>
|
<Filter>Dalamud.Boot DLL</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ntdll.cpp">
|
||||||
|
<Filter>Dalamud.Boot DLL</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\lib\CoreCLR\CoreCLR.h">
|
<ClInclude Include="..\lib\CoreCLR\CoreCLR.h">
|
||||||
|
|
@ -140,6 +143,9 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
<ClInclude Include="crashhandler_shared.h" />
|
<ClInclude Include="crashhandler_shared.h" />
|
||||||
|
<ClInclude Include="ntdll.h">
|
||||||
|
<Filter>Dalamud.Boot DLL</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="Dalamud.Boot.rc" />
|
<ResourceCompile Include="Dalamud.Boot.rc" />
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,9 @@
|
||||||
|
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
|
|
||||||
|
#include "ntdll.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
enum {
|
|
||||||
LDR_DLL_NOTIFICATION_REASON_LOADED = 1,
|
|
||||||
LDR_DLL_NOTIFICATION_REASON_UNLOADED = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LDR_DLL_UNLOADED_NOTIFICATION_DATA {
|
|
||||||
ULONG Flags; //Reserved.
|
|
||||||
const UNICODE_STRING* FullDllName; //The full path name of the DLL module.
|
|
||||||
const UNICODE_STRING* BaseDllName; //The base file name of the DLL module.
|
|
||||||
PVOID DllBase; //A pointer to the base address for the DLL in memory.
|
|
||||||
ULONG SizeOfImage; //The size of the DLL image, in bytes.
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LDR_DLL_LOADED_NOTIFICATION_DATA {
|
|
||||||
ULONG Flags; //Reserved.
|
|
||||||
const UNICODE_STRING* FullDllName; //The full path name of the DLL module.
|
|
||||||
const UNICODE_STRING* BaseDllName; //The base file name of the DLL module.
|
|
||||||
PVOID DllBase; //A pointer to the base address for the DLL in memory.
|
|
||||||
ULONG SizeOfImage; //The size of the DLL image, in bytes.
|
|
||||||
};
|
|
||||||
|
|
||||||
union LDR_DLL_NOTIFICATION_DATA {
|
|
||||||
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
|
|
||||||
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
|
|
||||||
};
|
|
||||||
|
|
||||||
using PLDR_DLL_NOTIFICATION_FUNCTION = VOID CALLBACK(_In_ ULONG NotificationReason, _In_ const LDR_DLL_NOTIFICATION_DATA* NotificationData, _In_opt_ PVOID Context);
|
|
||||||
|
|
||||||
static const auto LdrRegisterDllNotification = utils::loaded_module(GetModuleHandleW(L"ntdll.dll")).get_exported_function<NTSTATUS(NTAPI)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID* Cookie)>("LdrRegisterDllNotification");
|
|
||||||
static const auto LdrUnregisterDllNotification = utils::loaded_module(GetModuleHandleW(L"ntdll.dll")).get_exported_function<NTSTATUS(NTAPI)(PVOID Cookie)>("LdrUnregisterDllNotification");
|
|
||||||
|
|
||||||
hooks::getprocaddress_singleton_import_hook::getprocaddress_singleton_import_hook()
|
hooks::getprocaddress_singleton_import_hook::getprocaddress_singleton_import_hook()
|
||||||
: m_pfnGetProcAddress(GetProcAddress)
|
: m_pfnGetProcAddress(GetProcAddress)
|
||||||
, m_thunk("kernel32!GetProcAddress(Singleton Import Hook)",
|
, m_thunk("kernel32!GetProcAddress(Singleton Import Hook)",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
|
||||||
15
Dalamud.Boot/ntdll.cpp
Normal file
15
Dalamud.Boot/ntdll.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "ntdll.h"
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
NTSTATUS LdrRegisterDllNotification(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID* Cookie) {
|
||||||
|
static const auto pfn = utils::loaded_module(GetModuleHandleW(L"ntdll.dll")).get_exported_function<NTSTATUS(NTAPI)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID* Cookie)>("LdrRegisterDllNotification");
|
||||||
|
return pfn(Flags, NotificationFunction, Context, Cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS LdrUnregisterDllNotification(PVOID Cookie) {
|
||||||
|
static const auto pfn = utils::loaded_module(GetModuleHandleW(L"ntdll.dll")).get_exported_function<NTSTATUS(NTAPI)(PVOID Cookie)>("LdrUnregisterDllNotification");
|
||||||
|
return pfn(Cookie);
|
||||||
|
}
|
||||||
33
Dalamud.Boot/ntdll.h
Normal file
33
Dalamud.Boot/ntdll.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ntdll exports
|
||||||
|
enum {
|
||||||
|
LDR_DLL_NOTIFICATION_REASON_LOADED = 1,
|
||||||
|
LDR_DLL_NOTIFICATION_REASON_UNLOADED = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LDR_DLL_UNLOADED_NOTIFICATION_DATA {
|
||||||
|
ULONG Flags; //Reserved.
|
||||||
|
const UNICODE_STRING* FullDllName; //The full path name of the DLL module.
|
||||||
|
const UNICODE_STRING* BaseDllName; //The base file name of the DLL module.
|
||||||
|
PVOID DllBase; //A pointer to the base address for the DLL in memory.
|
||||||
|
ULONG SizeOfImage; //The size of the DLL image, in bytes.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LDR_DLL_LOADED_NOTIFICATION_DATA {
|
||||||
|
ULONG Flags; //Reserved.
|
||||||
|
const UNICODE_STRING* FullDllName; //The full path name of the DLL module.
|
||||||
|
const UNICODE_STRING* BaseDllName; //The base file name of the DLL module.
|
||||||
|
PVOID DllBase; //A pointer to the base address for the DLL in memory.
|
||||||
|
ULONG SizeOfImage; //The size of the DLL image, in bytes.
|
||||||
|
};
|
||||||
|
|
||||||
|
union LDR_DLL_NOTIFICATION_DATA {
|
||||||
|
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
|
||||||
|
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PLDR_DLL_NOTIFICATION_FUNCTION = VOID CALLBACK(_In_ ULONG NotificationReason, _In_ const LDR_DLL_NOTIFICATION_DATA* NotificationData, _In_opt_ PVOID Context);
|
||||||
|
|
||||||
|
NTSTATUS LdrRegisterDllNotification(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID* Cookie);
|
||||||
|
NTSTATUS LdrUnregisterDllNotification(PVOID Cookie);
|
||||||
|
|
@ -15,14 +15,20 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
// Windows Header Files (2)
|
// Windows Header Files (2)
|
||||||
|
#include <DbgHelp.h>
|
||||||
#include <Dbt.h>
|
#include <Dbt.h>
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
#include <PathCch.h>
|
#include <PathCch.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
#include <ShlObj.h>
|
#include <ShlObj.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
#include <SubAuth.h>
|
#include <SubAuth.h>
|
||||||
#include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
|
|
||||||
|
// Windows Header Files (3)
|
||||||
|
#include <icmpapi.h> // Must be loaded after iphlpapi.h
|
||||||
|
|
||||||
// MSVC Compiler Intrinsic
|
// MSVC Compiler Intrinsic
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
|
||||||
|
|
@ -30,6 +36,7 @@
|
||||||
#include <comdef.h>
|
#include <comdef.h>
|
||||||
|
|
||||||
// C++ Standard Libraries
|
// C++ Standard Libraries
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,8 @@
|
||||||
#include "DalamudStartInfo.h"
|
#include "DalamudStartInfo.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include "ntdll.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <iphlpapi.h>
|
|
||||||
#include <icmpapi.h>
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::span<T> assume_nonempty_span(std::span<T> t, const char* descr) {
|
static std::span<T> assume_nonempty_span(std::span<T> t, const char* descr) {
|
||||||
|
|
@ -546,6 +545,109 @@ void xivfixes::prevent_icmphandle_crashes(bool bApply) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xivfixes::symbol_load_patches(bool bApply) {
|
||||||
|
static const char* LogTag = "[xivfixes:symbol_load_patches]";
|
||||||
|
|
||||||
|
static std::optional<hooks::import_hook<decltype(SymInitialize)>> s_hookSymInitialize;
|
||||||
|
static PVOID s_dllNotificationCookie = nullptr;
|
||||||
|
|
||||||
|
static const auto RemoveFullPathPdbInfo = [](const utils::loaded_module& mod) {
|
||||||
|
const auto ddva = mod.data_directory(IMAGE_DIRECTORY_ENTRY_DEBUG).VirtualAddress;
|
||||||
|
if (!ddva)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto& ddir = mod.ref_as<IMAGE_DEBUG_DIRECTORY>(ddva);
|
||||||
|
if (ddir.Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
|
||||||
|
// The Visual C++ debug information.
|
||||||
|
// Ghidra calls it "DotNetPdbInfo".
|
||||||
|
static constexpr DWORD DotNetPdbInfoSignatureValue = 0x53445352;
|
||||||
|
struct DotNetPdbInfo {
|
||||||
|
DWORD Signature; // RSDS
|
||||||
|
GUID Guid;
|
||||||
|
DWORD Age;
|
||||||
|
char PdbPath[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto& pdbref = mod.ref_as<DotNetPdbInfo>(ddir.AddressOfRawData);
|
||||||
|
if (pdbref.Signature == DotNetPdbInfoSignatureValue) {
|
||||||
|
const auto pathSpan = std::string_view(pdbref.PdbPath, strlen(pdbref.PdbPath));
|
||||||
|
const auto pathWide = unicode::convert<std::wstring>(pathSpan);
|
||||||
|
std::wstring windowsDirectory(GetWindowsDirectoryW(nullptr, 0) + 1, L'\0');
|
||||||
|
windowsDirectory.resize(
|
||||||
|
GetWindowsDirectoryW(windowsDirectory.data(), static_cast<UINT>(windowsDirectory.size())));
|
||||||
|
if (!PathIsRelativeW(pathWide.c_str()) && !PathIsSameRootW(windowsDirectory.c_str(), pathWide.c_str())) {
|
||||||
|
utils::memory_tenderizer pathOverwrite(&pdbref.PdbPath, pathSpan.size(), PAGE_READWRITE);
|
||||||
|
auto sep = std::find(pathSpan.rbegin(), pathSpan.rend(), '/');
|
||||||
|
if (sep == pathSpan.rend())
|
||||||
|
sep = std::find(pathSpan.rbegin(), pathSpan.rend(), '\\');
|
||||||
|
if (sep != pathSpan.rend()) {
|
||||||
|
logging::I(
|
||||||
|
"{} Stripping pdb path folder: {} to {}",
|
||||||
|
LogTag,
|
||||||
|
pathSpan,
|
||||||
|
&*sep + 1);
|
||||||
|
memmove(const_cast<char*>(pathSpan.data()), &*sep + 1, sep - pathSpan.rbegin() + 1);
|
||||||
|
} else {
|
||||||
|
logging::I("{} Leaving pdb path unchanged: {}", LogTag, pathSpan);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logging::I("{} Leaving pdb path unchanged: {}", LogTag, pathSpan);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logging::I("{} CODEVIEW struct signature mismatch: got {:08X} instead.", LogTag, pdbref.Signature);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logging::I("{} Debug directory: type {} is unsupported.", LogTag, ddir.Type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bApply) {
|
||||||
|
if (!g_startInfo.BootEnabledGameFixes.contains("symbol_load_patches")) {
|
||||||
|
logging::I("{} Turned off via environment variable.", LogTag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& mod : utils::loaded_module::all_modules())
|
||||||
|
RemoveFullPathPdbInfo(mod);
|
||||||
|
|
||||||
|
if (!s_dllNotificationCookie) {
|
||||||
|
const auto res = LdrRegisterDllNotification(
|
||||||
|
0,
|
||||||
|
[](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* /* context */) {
|
||||||
|
if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED)
|
||||||
|
RemoveFullPathPdbInfo(pData->Loaded.DllBase);
|
||||||
|
},
|
||||||
|
nullptr,
|
||||||
|
&s_dllNotificationCookie);
|
||||||
|
|
||||||
|
if (res != STATUS_SUCCESS) {
|
||||||
|
logging::E("{} LdrRegisterDllNotification failure: 0x{:08X}", LogTag, res);
|
||||||
|
s_dllNotificationCookie = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_hookSymInitialize.emplace("dbghelp.dll!SymInitialize (import, symbol_load_patches)", "dbghelp.dll", "SymInitialize", 0);
|
||||||
|
s_hookSymInitialize->set_detour([](HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess) noexcept {
|
||||||
|
logging::I("{} Suppressed SymInitialize.", LogTag);
|
||||||
|
SetLastError(ERROR_NOT_SUPPORTED);
|
||||||
|
return FALSE;
|
||||||
|
});
|
||||||
|
|
||||||
|
logging::I("{} Enable", LogTag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (s_hookSymInitialize) {
|
||||||
|
logging::I("{} Disable", LogTag);
|
||||||
|
s_hookSymInitialize.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_dllNotificationCookie) {
|
||||||
|
(void)LdrUnregisterDllNotification(s_dllNotificationCookie);
|
||||||
|
s_dllNotificationCookie = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void xivfixes::apply_all(bool bApply) {
|
void xivfixes::apply_all(bool bApply) {
|
||||||
for (const auto& [taskName, taskFunction] : std::initializer_list<std::pair<const char*, void(*)(bool)>>
|
for (const auto& [taskName, taskFunction] : std::initializer_list<std::pair<const char*, void(*)(bool)>>
|
||||||
{
|
{
|
||||||
|
|
@ -554,7 +656,8 @@ void xivfixes::apply_all(bool bApply) {
|
||||||
{ "disable_game_openprocess_access_check", &disable_game_openprocess_access_check },
|
{ "disable_game_openprocess_access_check", &disable_game_openprocess_access_check },
|
||||||
{ "redirect_openprocess", &redirect_openprocess },
|
{ "redirect_openprocess", &redirect_openprocess },
|
||||||
{ "backup_userdata_save", &backup_userdata_save },
|
{ "backup_userdata_save", &backup_userdata_save },
|
||||||
{ "prevent_icmphandle_crashes", &prevent_icmphandle_crashes }
|
{ "prevent_icmphandle_crashes", &prevent_icmphandle_crashes },
|
||||||
|
{ "symbol_load_patches", &symbol_load_patches },
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ namespace xivfixes {
|
||||||
void redirect_openprocess(bool bApply);
|
void redirect_openprocess(bool bApply);
|
||||||
void backup_userdata_save(bool bApply);
|
void backup_userdata_save(bool bApply);
|
||||||
void prevent_icmphandle_crashes(bool bApply);
|
void prevent_icmphandle_crashes(bool bApply);
|
||||||
|
void symbol_load_patches(bool bApply);
|
||||||
|
|
||||||
void apply_all(bool bApply);
|
void apply_all(bool bApply);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -395,9 +395,15 @@ namespace Dalamud.Injector
|
||||||
startInfo.BootShowConsole = args.Contains("--console");
|
startInfo.BootShowConsole = args.Contains("--console");
|
||||||
startInfo.BootEnableEtw = args.Contains("--etw");
|
startInfo.BootEnableEtw = args.Contains("--etw");
|
||||||
startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);
|
startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);
|
||||||
startInfo.BootEnabledGameFixes = new List<string> {
|
startInfo.BootEnabledGameFixes = new()
|
||||||
"prevent_devicechange_crashes", "disable_game_openprocess_access_check",
|
{
|
||||||
"redirect_openprocess", "backup_userdata_save", "prevent_icmphandle_crashes",
|
// See: xivfixes.h, xivfixes.cpp
|
||||||
|
"prevent_devicechange_crashes",
|
||||||
|
"disable_game_openprocess_access_check",
|
||||||
|
"redirect_openprocess",
|
||||||
|
"backup_userdata_save",
|
||||||
|
"prevent_icmphandle_crashes",
|
||||||
|
"symbol_load_patches",
|
||||||
};
|
};
|
||||||
startInfo.BootDotnetOpenProcessHookMode = 0;
|
startInfo.BootDotnetOpenProcessHookMode = 0;
|
||||||
startInfo.BootWaitMessageBox |= args.Contains("--msgbox1") ? 1 : 0;
|
startInfo.BootWaitMessageBox |= args.Contains("--msgbox1") ? 1 : 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue