diff --git a/Dalamud.Boot/Dalamud.Boot.vcxproj b/Dalamud.Boot/Dalamud.Boot.vcxproj
index b1158d85a..95eb9d12c 100644
--- a/Dalamud.Boot/Dalamud.Boot.vcxproj
+++ b/Dalamud.Boot/Dalamud.Boot.vcxproj
@@ -47,6 +47,7 @@
Windows
true
false
+ dbghelp.lib;%(AdditionalDependencies)
..\lib\CoreCLR;%(AdditionalLibraryDirectories)
diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp
index a454b4431..1f99c2246 100644
--- a/Dalamud.Boot/dllmain.cpp
+++ b/Dalamud.Boot/dllmain.cpp
@@ -3,10 +3,146 @@
#include
#include
+#include
+#include
+#include
#include "..\lib\CoreCLR\CoreCLR.h"
#include "..\lib\CoreCLR\boot.h"
+#include
HMODULE g_hModule;
+BOOL g_isExcept = false;
+
+LONG WINAPI VectoredHandler(struct _EXCEPTION_POINTERS* ExceptionInfo)
+{
+ auto record = ExceptionInfo->ExceptionRecord;
+ auto context = ExceptionInfo->ContextRecord;
+
+ if (record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ if (!g_isExcept)
+ {
+ g_isExcept = true;
+
+ #pragma region Setup base path
+
+ wchar_t base_path_arr[MAX_PATH];
+ GetModuleFileNameW(g_hModule, base_path_arr, MAX_PATH);
+ std::filesystem::path base_path(base_path_arr);
+ base_path = base_path.remove_filename();
+
+ #if defined(NDEBUG)
+ base_path = base_path / L".." / L".." / L"..";
+ #endif
+
+ #pragma endregion
+
+ #pragma region Write to dalamud.log
+
+ wchar_t dalamud_log_path_arr[MAX_PATH];
+ wcsncpy_s(dalamud_log_path_arr, base_path_arr, MAX_PATH);
+ std::filesystem::path dalamud_log_path(dalamud_log_path_arr);
+ dalamud_log_path /= L"dalamud.log";
+
+ auto base_address = (unsigned long long)GetModuleHandleW(nullptr);
+ auto ex_address = (unsigned long long)record->ExceptionAddress;
+ auto actual_address = ex_address - base_address + 0x140000000;
+
+ FILE* log_handle;
+ errno_t result = _wfopen_s(&log_handle, dalamud_log_path.c_str(), L"a");
+ if (!result)
+ {
+ MessageBox(NULL, L"Could not open dalamud.log for writing.", L"Dalamud", MB_OK | MB_ICONERROR | MB_TOPMOST);
+ }
+ else
+ {
+
+ fwprintf_s(log_handle, L"--------------------------------------------------------------------------------\n");
+ fwprintf_s(log_handle, L"An internal error in Dalamud or a plugin occurred. 0x%X at 0x%p (0x%p)", record->ExceptionCode, record->ExceptionAddress, actual_address);
+ fwprintf_s(log_handle, L"Rax=%p R08=%p", context->Rax, context->R8);
+ fwprintf_s(log_handle, L"Rcx=%p R09=%p", context->Rcx, context->R9);
+ fwprintf_s(log_handle, L"Rdx=%p R10=%p", context->Rdx, context->R10);
+ fwprintf_s(log_handle, L"Rbx=%p R11=%p", context->Rbx, context->R11);
+ fwprintf_s(log_handle, L"Rsp=%p R12=%p", context->Rsp, context->R12);
+ fwprintf_s(log_handle, L"Rbp=%p R13=%p", context->Rbp, context->R13);
+ fwprintf_s(log_handle, L"Rsi=%p R14=%p", context->Rsi, context->R14);
+ fwprintf_s(log_handle, L"Rdi=%p R15=%p", context->Rdi, context->R15);
+ fwprintf_s(log_handle, L"Xmm00=%f Xmm08=%f", context->Xmm0, context->Xmm8);
+ fwprintf_s(log_handle, L"Xmm01=%f Xmm09=%f", context->Xmm1, context->Xmm9);
+ fwprintf_s(log_handle, L"Xmm02=%f Xmm10=%f", context->Xmm2, context->Xmm10);
+ fwprintf_s(log_handle, L"Xmm03=%f Xmm11=%f", context->Xmm3, context->Xmm11);
+ fwprintf_s(log_handle, L"Xmm04=%f Xmm12=%f", context->Xmm4, context->Xmm12);
+ fwprintf_s(log_handle, L"Xmm05=%f Xmm13=%f", context->Xmm5, context->Xmm13);
+ fwprintf_s(log_handle, L"Xmm06=%f Xmm14=%f", context->Xmm6, context->Xmm14);
+ fwprintf_s(log_handle, L"Xmm07=%f Xmm15=%f", context->Xmm7, context->Xmm15);
+ fwprintf_s(log_handle, L"--------------------------------------------------------------------------------\n");
+ fclose(log_handle);
+ }
+
+ #pragma endregion
+
+ wchar_t pszMessage[1024] = { 0 };
+ swprintf_s(pszMessage, L"An internal error in Dalamud or a plugin occurred.\nThe game must close.\n\nDo you wish to save a memory dump?\n\nReasoning: 0x%X at 0x%p (0x%p)", record->ExceptionCode, record->ExceptionAddress, actual_address);
+
+ auto result = MessageBox(NULL, pszMessage, L"Dalamud", MB_YESNO | MB_ICONERROR | MB_TOPMOST);
+ if (result == IDYES)
+ {
+ #pragma region Write minidump
+
+ SYSTEMTIME t;
+ GetSystemTime(&t);
+
+ wchar_t file_name[30] = { 0 };
+ swprintf_s(file_name, L"MiniDump-%04d%02d%02d-%02d%02d%02d.dmp", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
+
+ wchar_t minidump_path_arr[MAX_PATH];
+ wcsncpy_s(minidump_path_arr, base_path_arr, MAX_PATH);
+ std::filesystem::path minidump_path(minidump_path_arr);
+ minidump_path /= file_name;
+
+ HANDLE hFile = CreateFileW(minidump_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
+ {
+ wprintf_s(L"CreateFile failed. Error: %u \n", GetLastError());
+ }
+ else
+ {
+ MINIDUMP_EXCEPTION_INFORMATION mdei{};
+ mdei.ThreadId = GetCurrentThreadId();
+ mdei.ExceptionPointers = ExceptionInfo;
+ mdei.ClientPointers = TRUE;
+
+ BOOL success = MiniDumpWriteDump(
+ GetCurrentProcess(), GetCurrentProcessId(),
+ hFile, (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithDataSegs | MiniDumpWithThreadInfo),
+ ExceptionInfo != 0 ? &mdei : 0, 0, 0);
+
+ if (success)
+ swprintf_s(pszMessage, L"Minidump created.\n");
+ else
+ swprintf_s(pszMessage, L"MiniDumpWriteDump failed. Error: %u\n", GetLastError());
+
+ MessageBox(NULL, pszMessage, L"Dalamud", MB_OK | MB_ICONINFORMATION | MB_TOPMOST);
+
+ // Close the file
+ CloseHandle(hFile);
+ }
+
+ #pragma endregion
+ }
+
+ exit(-1);
+ }
+
+ PCONTEXT Context;
+ Context = ExceptionInfo->ContextRecord;
+ Context->Rip++;
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
DllExport DWORD WINAPI Initialize(LPVOID lpParam)
{
@@ -19,14 +155,14 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
std::filesystem::path fs_module_path(_module_path);
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());
+ std::wstring base_path = _wcsdup(fs_module_path.replace_filename(L"Dalamud.dll").c_str());
// =========================================================================== //
void* entrypoint_vfn;
int result = InitializeClrAndGetEntryPoint(
runtimeconfig_path,
- module_path,
+ base_path,
L"Dalamud.EntryPoint, Dalamud",
L"Initialize",
L"Dalamud.EntryPoint+InitDelegate, Dalamud",
@@ -38,12 +174,16 @@ 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 exception handler...");
+ //AddVectoredExceptionHandler(99, VectoredHandler);
+ printf("Done!\n");
+
printf("Initializing Dalamud... ");
entrypoint_fn(lpParam);
printf("Done!\n");
// =========================================================================== //
-
+
#if !defined(NDEBUG)
FreeConsole();
#endif