diff --git a/Dalamud.Boot/Dalamud.Boot.vcxproj b/Dalamud.Boot/Dalamud.Boot.vcxproj
index 2fa9255f4..5955eac56 100644
--- a/Dalamud.Boot/Dalamud.Boot.vcxproj
+++ b/Dalamud.Boot/Dalamud.Boot.vcxproj
@@ -32,6 +32,8 @@
obj\$(Configuration)\
+
+
Level3
@@ -81,21 +83,38 @@
-
-
-
-
-
-
+
+ NotUsing
+ NotUsing
+
+
+ NotUsing
+ NotUsing
+
+
+ Create
+ Create
+
+
+ Use
+ Use
+
+
+ Use
+ Use
+
+
+ Use
+ Use
+
-
-
+
diff --git a/Dalamud.Boot/Dalamud.Boot.vcxproj.filters b/Dalamud.Boot/Dalamud.Boot.vcxproj.filters
index 1f8a03bbe..0106f0589 100644
--- a/Dalamud.Boot/Dalamud.Boot.vcxproj.filters
+++ b/Dalamud.Boot/Dalamud.Boot.vcxproj.filters
@@ -1,63 +1,59 @@
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
-
{18be40ac-9367-46ff-b848-4c528aa97a8d}
lib
+
+ {dc468303-865e-43bd-908f-a3542c4bb669}
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
- Source Files
+ Dalamud.Boot DLL
-
- Source Files
-
-
- Source Files
-
-
- Source Files
+
+ Dalamud.Boot DLL
- Source Files
+ Dalamud.Boot DLL
- Source Files
+ Dalamud.Boot DLL
+
+
+ CoreCLR
+
+
+ CoreCLR
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
- Header Files
-
-
- Header Files
-
-
- Header Files
+ CoreCLR
- Header Files
+ CoreCLR
+
+
+ CoreCLR
+
+
+ CoreCLR
+
+
+ CoreCLR
- Header Files
+ Dalamud.Boot DLL
+
+
+ Dalamud.Boot DLL
diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp
index 377ed088c..1226bd278 100644
--- a/Dalamud.Boot/dllmain.cpp
+++ b/Dalamud.Boot/dllmain.cpp
@@ -1,10 +1,5 @@
-#define WIN32_LEAN_AND_MEAN
-#define DllExport extern "C" __declspec(dllexport)
+#include "pch.h"
-#include
-#include
-#include "..\lib\CoreCLR\CoreCLR.h"
-#include "..\lib\CoreCLR\boot.h"
#include "veh.h"
HMODULE g_hModule;
@@ -69,7 +64,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
std::wstring runtimeconfig_path = _wcsdup(fs_module_path.replace_filename(L"Dalamud.runtimeconfig.json").c_str());
std::wstring module_path = _wcsdup(fs_module_path.replace_filename(L"Dalamud.dll").c_str());
- // =========================================================================== //
+ // ============================== CLR ========================================= //
void* entrypoint_vfn;
int result = InitializeClrAndGetEntryPoint(
@@ -86,10 +81,6 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(LPVOID);
custom_component_entry_point_fn entrypoint_fn = reinterpret_cast(entrypoint_vfn);
- printf("Initializing Dalamud... ");
- entrypoint_fn(lpParam);
- printf("Done!\n");
-
// ============================== VEH ======================================== //
printf("Initializing VEH... ");
@@ -108,7 +99,11 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
printf("VEH was disabled manually\n");
}
- // =========================================================================== //
+ // ============================== Dalamud ==================================== //
+
+ printf("Initializing Dalamud... ");
+ entrypoint_fn(lpParam);
+ printf("Done!\n");
#ifndef NDEBUG
fclose(stdin);
diff --git a/lib/CoreCLR/pch.cpp b/Dalamud.Boot/pch.cpp
similarity index 100%
rename from lib/CoreCLR/pch.cpp
rename to Dalamud.Boot/pch.cpp
diff --git a/Dalamud.Boot/pch.h b/Dalamud.Boot/pch.h
new file mode 100644
index 000000000..3c2bd6c4b
--- /dev/null
+++ b/Dalamud.Boot/pch.h
@@ -0,0 +1,41 @@
+// pch.h: This is a precompiled header file.
+// Files listed below are compiled only once, improving build performance for future builds.
+// This also affects IntelliSense performance, including code completion and many code browsing features.
+// However, files listed here are ALL re-compiled if any one of them is updated between builds.
+// Do not add files here that you will be updating frequently as this negates the performance advantage.
+
+#ifndef PCH_H
+#define PCH_H
+
+// Exclude rarely-used stuff from Windows headers
+#define WIN32_LEAN_AND_MEAN
+
+// Windows Header Files
+#include
+#include
+#include
+#include
+#include
+#include
+
+// C++ Standard Libraries
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// https://github.com/dotnet/coreclr
+#include "..\lib\CoreCLR\CoreCLR.h"
+#include "..\lib\CoreCLR\boot.h"
+
+// Commonly used macros
+#define DllExport extern "C" __declspec(dllexport)
+
+// Global variables
+extern HMODULE g_hModule;
+extern std::optional g_clr;
+
+#endif //PCH_H
diff --git a/Dalamud.Boot/rewrite_entrypoint.cpp b/Dalamud.Boot/rewrite_entrypoint.cpp
index 589942e6f..93df1d93e 100644
--- a/Dalamud.Boot/rewrite_entrypoint.cpp
+++ b/Dalamud.Boot/rewrite_entrypoint.cpp
@@ -1,15 +1,5 @@
-#define WIN32_LEAN_AND_MEAN
-#define DllExport extern "C" __declspec(dllexport)
+#include "pch.h"
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-extern HMODULE g_hModule;
DllExport DWORD WINAPI Initialize(LPVOID lpParam);
struct RewrittenEntryPointParameters {
diff --git a/Dalamud.Boot/veh.cpp b/Dalamud.Boot/veh.cpp
index 7f080b7e2..16ea2ab8f 100644
--- a/Dalamud.Boot/veh.cpp
+++ b/Dalamud.Boot/veh.cpp
@@ -1,12 +1,6 @@
-#define WIN32_LEAN_AND_MEAN
+#include "pch.h"
+
#include "veh.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
bool is_whitelist_exception(const DWORD code)
{
@@ -51,14 +45,16 @@ bool is_whitelist_exception(const DWORD code)
}
-bool get_module_file_and_base(const DWORD64 address, DWORD64* module_base, std::filesystem::path& module_file)
+bool get_module_file_and_base(const DWORD64 address, DWORD64& module_base, std::filesystem::path& module_file)
{
HMODULE handle;
if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(address), &handle))
{
- if (wchar_t path[1024]; GetModuleFileNameW(handle, path, sizeof path / 2) > 0)
+ std::wstring path(PATHCCH_MAX_CCH, L'\0');
+ path.resize(GetModuleFileNameW(handle, &path[0], static_cast(path.size())));
+ if (!path.empty())
{
- *module_base = reinterpret_cast(handle);
+ module_base = reinterpret_cast(handle);
module_file = path;
return true;
}
@@ -70,22 +66,24 @@ bool get_module_file_and_base(const DWORD64 address, DWORD64* module_base, std::
bool is_ffxiv_address(const DWORD64 address)
{
DWORD64 module_base;
- if (std::filesystem::path module_path; get_module_file_and_base(address, &module_base, module_path))
+ if (std::filesystem::path module_path; get_module_file_and_base(address, module_base, module_path))
return _wcsicmp(module_path.filename().c_str(), L"ffxiv_dx11.exe") == 0;
return false;
}
-bool get_sym_from_addr(const DWORD64 address, DWORD64* displacement, std::wstring& symbol_name)
+bool get_sym_from_addr(const DWORD64 address, DWORD64& displacement, std::wstring& symbol_name)
{
- char buffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME * sizeof(wchar_t)];
- auto symbol = reinterpret_cast(buffer);
- symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- symbol->MaxNameLen = MAX_SYM_NAME;
+ union {
+ char buffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME * sizeof(wchar_t)]{};
+ SYMBOL_INFOW symbol;
+ };
+ symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol.MaxNameLen = MAX_SYM_NAME;
- if (SymFromAddrW(GetCurrentProcess(), address, displacement, symbol))
+ if (SymFromAddrW(GetCurrentProcess(), address, &displacement, &symbol) && symbol.Name[0])
{
- symbol_name.assign(_wcsdup(symbol->Name));
+ symbol_name = symbol.Name;
return true;
}
return false;
@@ -96,7 +94,7 @@ std::wstring to_address_string(const DWORD64 address, const bool try_ptrderef =
{
DWORD64 module_base;
std::filesystem::path module_path;
- bool is_mod_addr = get_module_file_and_base(address, &module_base, module_path);
+ bool is_mod_addr = get_module_file_and_base(address, module_base, module_path);
DWORD64 value = 0;
if(try_ptrderef && address > 0x10000 && address < 0x7FFFFFFE0000)
@@ -109,14 +107,32 @@ std::wstring to_address_string(const DWORD64 address, const bool try_ptrderef =
std::format(L"{:X}", address);
DWORD64 displacement;
- if (std::wstring symbol; get_sym_from_addr(address, &displacement, symbol))
+ if (std::wstring symbol; get_sym_from_addr(address, displacement, symbol))
return std::format(L"{}\t({})", addr_str, displacement != 0 ? std::format(L"{}+0x{:X}", symbol, displacement) : std::format(L"{}", symbol));
return value != 0 ? std::format(L"{} [{}]", addr_str, to_address_string(value, false)) : addr_str;
}
-void print_exception_info(const EXCEPTION_POINTERS* ex, std::wofstream& log)
+void print_exception_info(const EXCEPTION_POINTERS* ex, std::wostringstream& log)
{
+ size_t rec_index = 0;
+ for (auto rec = ex->ExceptionRecord; rec; rec = rec->ExceptionRecord)
+ {
+ log << std::format(L"\nException Info #{}\n", ++rec_index);
+ log << std::format(L"Address: {:X}\n", rec->ExceptionCode);
+ log << std::format(L"Flags: {:X}\n", rec->ExceptionFlags);
+ log << std::format(L"Address: {:X}\n", reinterpret_cast(rec->ExceptionAddress));
+ if (!rec->NumberParameters)
+ continue;
+ log << L"Parameters: ";
+ for (DWORD i = 0; i < rec->NumberParameters; ++i)
+ {
+ if (i != 0)
+ log << L", ";
+ log << std::format(L"{:X}", rec->ExceptionInformation[i]);
+ }
+ }
+
log << L"\nCall Stack\n{";
STACKFRAME64 sf;
@@ -140,7 +156,7 @@ void print_exception_info(const EXCEPTION_POINTERS* ex, std::wofstream& log)
} while (sf.AddrReturn.Offset != 0 && sf.AddrPC.Offset != sf.AddrReturn.Offset);
- log << L"\n}" << std::endl;
+ log << L"\n}\n";
ctx = *ex->ContextRecord;
@@ -167,15 +183,15 @@ void print_exception_info(const EXCEPTION_POINTERS* ex, std::wofstream& log)
log << L"\n}" << std::endl;
- if(ctx.Rsp <= 0x10000 || ctx.Rsp >= 0x7FFFFFFE0000)
- return;
+ if(0x10000 < ctx.Rsp && ctx.Rsp < 0x7FFFFFFE0000)
+ {
+ log << L"\nStack\n{";
- log << L"\nStack\n{";
+ for(DWORD64 i = 0; i < 16; i++)
+ log << std::format(L"\n [RSP+{:X}]\t{}", i * 8, to_address_string(*reinterpret_cast(ctx.Rsp + i * 8ull)));
- for(DWORD64 i = 0; i < 16; i++)
- log << std::format(L"\n [RSP+{:X}]\t{}", i * 8, to_address_string(*reinterpret_cast(ctx.Rsp + i * 8ull)));
-
- log << L"\n}" << std::endl;
+ log << L"\n}\n";
+ }
log << L"\nModules\n{";
@@ -194,17 +210,12 @@ void print_exception_info(const EXCEPTION_POINTERS* ex, std::wofstream& log)
CloseHandle(snap);
}
- log << L"\n}" << std::endl;
+ log << L"\n}\n";
}
-
-bool g_veh_message_open;
-
LONG exception_handler(EXCEPTION_POINTERS* ex)
{
- //block any further exceptions while the message box is open
- if (g_veh_message_open)
- for (;;) Sleep(1);
+ static std::mutex s_exception_handler_mutex;
if (!is_whitelist_exception(ex->ExceptionRecord->ExceptionCode))
return EXCEPTION_CONTINUE_SEARCH;
@@ -212,20 +223,21 @@ LONG exception_handler(EXCEPTION_POINTERS* ex)
if (!is_ffxiv_address(ex->ContextRecord->Rip))
return EXCEPTION_CONTINUE_SEARCH;
+ // block any other exceptions hitting the veh while the messagebox is open
+ const auto lock = std::lock_guard(s_exception_handler_mutex);
+
DWORD64 module_base;
std::filesystem::path module_path;
- get_module_file_and_base(reinterpret_cast(&exception_handler), &module_base, module_path);
+ get_module_file_and_base(reinterpret_cast(&exception_handler), module_base, module_path);
#ifndef NDEBUG
- std::wstring dmp_path = _wcsdup(module_path.replace_filename(L"dalamud_appcrashd.dmp").wstring().c_str());
+ std::wstring dmp_path = module_path.replace_filename(L"dalamud_appcrashd.dmp").wstring();
#else
- std::wstring dmp_path = _wcsdup(module_path.replace_filename(L"dalamud_appcrash.dmp").wstring().c_str());
+ std::wstring dmp_path = module_path.replace_filename(L"dalamud_appcrash.dmp").wstring();
#endif
- std::wstring log_path = _wcsdup(module_path.replace_filename(L"dalamud_appcrash.log").wstring().c_str());
-
- std::wofstream log;
- log.open(log_path, std::ios::trunc);
+ std::wstring log_path = module_path.replace_filename(L"dalamud_appcrash.log").wstring();
+ std::wostringstream log;
log << std::format(L"Unhandled native exception occurred at {}", to_address_string(ex->ContextRecord->Rip, false)) << std::endl;
log << std::format(L"Code: {:X}", ex->ExceptionRecord->ExceptionCode) << std::endl;
log << std::format(L"Dump at: {}", dmp_path) << std::endl;
@@ -234,8 +246,6 @@ LONG exception_handler(EXCEPTION_POINTERS* ex)
SymRefreshModuleList(GetCurrentProcess());
print_exception_info(ex, log);
- log.close();
-
MINIDUMP_EXCEPTION_INFORMATION ex_info;
ex_info.ClientPointers = false;
ex_info.ExceptionPointers = ex;
@@ -244,32 +254,43 @@ LONG exception_handler(EXCEPTION_POINTERS* ex)
HANDLE file = CreateFileW(dmp_path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpWithDataSegs, &ex_info, nullptr, nullptr);
CloseHandle(file);
+
+ void* fn;
+ if (const auto err = static_cast(g_clr->get_function_pointer(
+ L"Dalamud.EntryPoint, Dalamud",
+ L"VehCallback",
+ L"Dalamud.EntryPoint+VehDelegate, Dalamud",
+ nullptr, nullptr, &fn)))
+ {
+ const auto msg = 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"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"{1}\n\n"
+ L"Press OK to exit the application.\n\nFailed to read stack trace: {2:08x}";
- auto msg = 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"Please try \"Start Over\" 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"{1}\n\n"
- L"Press OK to exit the application.";
-
- auto formatted = std::format(msg, dmp_path, log_path);
-
- // block any other exceptions hitting the veh while the messagebox is open
- g_veh_message_open = true;
- MessageBoxW(nullptr, formatted.c_str(), L"Dalamud Error", MB_OK | MB_ICONERROR | MB_TOPMOST);
- g_veh_message_open = false;
+ // show in another thread to prevent messagebox from pumping messages of current thread
+ std::thread([&]() {
+ MessageBoxW(nullptr, std::format(msg, dmp_path, log_path, err).c_str(), L"Dalamud Error", MB_OK | MB_ICONERROR | MB_TOPMOST);
+ }).join();
+ }
+ else
+ {
+ ((void(__stdcall*)(const void*, const void*, const void*))fn)(dmp_path.c_str(), log_path.c_str(), log.str().c_str());
+ }
return EXCEPTION_CONTINUE_SEARCH;
}
-PVOID g_veh_handle;
+PVOID g_veh_handle = nullptr;
bool veh::add_handler()
{
if (g_veh_handle)
return false;
- g_veh_handle = AddVectoredExceptionHandler(0, exception_handler);
+ g_veh_handle = AddVectoredExceptionHandler(1, exception_handler);
+ SetUnhandledExceptionFilter(nullptr);
return g_veh_handle != nullptr;
}
diff --git a/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj b/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj
index b035ba848..66b55feb2 100644
--- a/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj
+++ b/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj
@@ -90,15 +90,12 @@
-
-
-
@@ -110,4 +107,4 @@
-
+
\ No newline at end of file
diff --git a/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj.filters b/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj.filters
index 47f80ab3e..45bf1b970 100644
--- a/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj.filters
+++ b/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj.filters
@@ -31,9 +31,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -42,15 +39,9 @@
-
- Header Files
-
Header Files
-
- Header Files
-
Header Files
diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs
index e9df6be92..37cbcb473 100644
--- a/Dalamud/EntryPoint.cs
+++ b/Dalamud/EntryPoint.cs
@@ -34,6 +34,14 @@ namespace Dalamud
/// Pointer to a serialized data.
public delegate void InitDelegate(IntPtr infoPtr);
+ ///
+ /// A delegate used from VEH handler on exception which CoreCLR will fast fail by default.
+ ///
+ /// Path to minidump file created in UTF-16.
+ /// Path to log file to create in UTF-16.
+ /// Log text in UTF-16.
+ public delegate void VehDelegate(IntPtr dumpPath, IntPtr logPath, IntPtr log);
+
///
/// Initialize Dalamud.
///
@@ -46,6 +54,57 @@ namespace Dalamud
new Thread(() => RunThread(info)).Start();
}
+ ///
+ /// Show error message along with stack trace and exit.
+ ///
+ /// Path to minidump file created in UTF-16.
+ /// Path to log file to create in UTF-16.
+ /// Log text in UTF-16.
+ public static void VehCallback(IntPtr dumpPath, IntPtr logPath, IntPtr log)
+ {
+ string stackTrace;
+ try
+ {
+ stackTrace = Environment.StackTrace;
+ }
+ catch (Exception e)
+ {
+ stackTrace = "Fail: " + e.ToString();
+ }
+
+ var msg = "An error within the game has occurred.\n\n"
+ + "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"
+ + "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"
+ + "The log file is located at:\n"
+ + "{1}\n\n"
+ + "Press OK to exit the application.\n\nStack trace:\n{2}";
+
+ try
+ {
+ File.WriteAllText(
+ Marshal.PtrToStringUni(logPath),
+ "Stack trace:\n" + stackTrace + "\n\n" + Marshal.PtrToStringUni(log));
+ }
+ catch (Exception e)
+ {
+ msg += "\n\nAdditionally, failed to write file: " + e.ToString();
+ }
+
+ // Show in another thread to prevent messagebox from pumping messages of current thread.
+ var msgThread = new Thread(() =>
+ {
+ Utility.Util.Fatal(
+ msg.Format(
+ Marshal.PtrToStringUni(dumpPath),
+ Marshal.PtrToStringUni(logPath),
+ stackTrace),
+ "Dalamud Error",
+ false);
+ });
+ msgThread.Start();
+ msgThread.Join();
+ }
+
///
/// Initialize all Dalamud subsystems and start running on the main thread.
///
diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs
index ba7822f5e..fb2d53c3f 100644
--- a/Dalamud/Utility/Util.cs
+++ b/Dalamud/Utility/Util.cs
@@ -326,12 +326,14 @@ namespace Dalamud.Utility
///
/// MessageBox body.
/// MessageBox caption (title).
- public static void Fatal(string message, string caption)
+ /// Specify whether to exit immediately.
+ public static void Fatal(string message, string caption, bool exit = true)
{
- var flags = NativeFunctions.MessageBoxType.Ok | NativeFunctions.MessageBoxType.IconError;
+ var flags = NativeFunctions.MessageBoxType.Ok | NativeFunctions.MessageBoxType.IconError | NativeFunctions.MessageBoxType.Topmost;
_ = NativeFunctions.MessageBoxW(Process.GetCurrentProcess().MainWindowHandle, message, caption, flags);
- Environment.Exit(-1);
+ if (exit)
+ Environment.Exit(-1);
}
///
diff --git a/lib/CoreCLR/CoreCLR.cpp b/lib/CoreCLR/CoreCLR.cpp
index ec8e548cd..6f4d337b8 100644
--- a/lib/CoreCLR/CoreCLR.cpp
+++ b/lib/CoreCLR/CoreCLR.cpp
@@ -72,7 +72,17 @@ bool CoreCLR::load_runtime(const std::wstring& runtime_config_path, const struct
hdt_load_assembly_and_get_function_pointer,
reinterpret_cast(&m_load_assembly_and_get_function_pointer_fptr));
- if (result != 0 || m_load_assembly_and_get_function_pointer_fptr == nullptr)
+ if (result != 0 || m_load_assembly_and_get_function_pointer_fptr == nullptr) {
+ m_hostfxr_close_fptr(context);
+ return result;
+ }
+
+ result = m_hostfxr_get_runtime_delegate_fptr(
+ context,
+ hdt_get_function_pointer,
+ reinterpret_cast(&m_get_function_pointer_fptr));
+
+ if (result != 0 || m_get_function_pointer_fptr == nullptr)
{
m_hostfxr_close_fptr(context);
return result;
@@ -99,6 +109,22 @@ int CoreCLR::load_assembly_and_get_function_pointer(
return result;
};
+int CoreCLR::get_function_pointer(
+ const wchar_t* type_name,
+ const wchar_t* method_name,
+ const wchar_t* delegate_type_name,
+ void* load_context,
+ void* reserved,
+ void** delegate) const
+{
+ int result = m_get_function_pointer_fptr(type_name, method_name, delegate_type_name, load_context, reserved, delegate);
+
+ if (result != 0)
+ delegate = nullptr;
+
+ return result;
+}
+
/* Helpers */
uint64_t CoreCLR::load_library(const wchar_t* path)
{
diff --git a/lib/CoreCLR/CoreCLR.h b/lib/CoreCLR/CoreCLR.h
index c2395d07d..235bf9923 100644
--- a/lib/CoreCLR/CoreCLR.h
+++ b/lib/CoreCLR/CoreCLR.h
@@ -24,12 +24,20 @@ class CoreCLR {
const wchar_t* delegate_type_name,
void* reserved,
void** delegate) const;
+ int get_function_pointer(
+ const wchar_t* type_name,
+ const wchar_t* method_name,
+ const wchar_t* delegate_type_name,
+ void* load_context,
+ void* reserved,
+ void** delegate) const;
private:
/* HostFXR delegates. */
hostfxr_initialize_for_runtime_config_fn m_hostfxr_initialize_for_runtime_config_fptr{};
hostfxr_get_runtime_delegate_fn m_hostfxr_get_runtime_delegate_fptr{};
hostfxr_close_fn m_hostfxr_close_fptr{};
+ get_function_pointer_fn m_get_function_pointer_fptr = nullptr;
load_assembly_and_get_function_pointer_fn m_load_assembly_and_get_function_pointer_fptr = nullptr;
/* Helper functions. */
diff --git a/lib/CoreCLR/boot.cpp b/lib/CoreCLR/boot.cpp
index d6fc0f604..2fde7e221 100644
--- a/lib/CoreCLR/boot.cpp
+++ b/lib/CoreCLR/boot.cpp
@@ -23,6 +23,8 @@ void ConsoleTeardown()
FreeConsole();
}
+std::optional g_clr;
+
int InitializeClrAndGetEntryPoint(
std::wstring runtimeconfig_path,
std::wstring module_path,
@@ -31,8 +33,9 @@ int InitializeClrAndGetEntryPoint(
std::wstring entrypoint_delegate_type_name,
void** entrypoint_fn)
{
+ g_clr = CoreCLR();
+
int result;
- CoreCLR clr;
SetEnvironmentVariable(L"DOTNET_MULTILEVEL_LOOKUP", L"0");
//SetEnvironmentVariable(L"COMPlus_legacyCorruptedStateExceptionsPolicy", L"1");
SetEnvironmentVariable(L"DOTNET_legacyCorruptedStateExceptionsPolicy", L"1");
@@ -85,7 +88,7 @@ int InitializeClrAndGetEntryPoint(
};
printf("Loading hostfxr... ");
- if ((result = clr.load_hostfxr(&init_parameters)) != 0)
+ if ((result = g_clr->load_hostfxr(&init_parameters)) != 0)
{
printf("\nError: Failed to load the `hostfxr` library (err=%d)\n", result);
return result;
@@ -102,7 +105,7 @@ int InitializeClrAndGetEntryPoint(
};
printf("Loading coreclr... ");;
- if ((result = clr.load_runtime(runtimeconfig_path, &runtime_parameters)) != 0)
+ if ((result = g_clr->load_runtime(runtimeconfig_path, &runtime_parameters)) != 0)
{
printf("\nError: Failed to load coreclr (err=%d)\n", result);
return result;
@@ -112,7 +115,7 @@ int InitializeClrAndGetEntryPoint(
// =========================================================================== //
printf("Loading module... ");
- if ((result = clr.load_assembly_and_get_function_pointer(
+ if ((result = g_clr->load_assembly_and_get_function_pointer(
module_path.c_str(),
entrypoint_assembly_name.c_str(),
entrypoint_method_name.c_str(),
diff --git a/lib/CoreCLR/framework.h b/lib/CoreCLR/framework.h
deleted file mode 100644
index 8bb54776a..000000000
--- a/lib/CoreCLR/framework.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-
-// Exclude rarely-used stuff from Windows headers
-#define WIN32_LEAN_AND_MEAN
-
-// Windows Header Files
-#include
diff --git a/lib/CoreCLR/pch.h b/lib/CoreCLR/pch.h
deleted file mode 100644
index 885d5d62e..000000000
--- a/lib/CoreCLR/pch.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// pch.h: This is a precompiled header file.
-// Files listed below are compiled only once, improving build performance for future builds.
-// This also affects IntelliSense performance, including code completion and many code browsing features.
-// However, files listed here are ALL re-compiled if any one of them is updated between builds.
-// Do not add files here that you will be updating frequently as this negates the performance advantage.
-
-#ifndef PCH_H
-#define PCH_H
-
-// add headers that you want to pre-compile here
-#include "framework.h"
-
-#endif //PCH_H