diff --git a/src/core/kernel/support/Emu.cpp b/src/core/kernel/support/Emu.cpp index 1a6b9a0df..d63f72ca1 100644 --- a/src/core/kernel/support/Emu.cpp +++ b/src/core/kernel/support/Emu.cpp @@ -384,6 +384,46 @@ int ExitException(LPEXCEPTION_POINTERS e) return EXCEPTION_CONTINUE_SEARCH; } +// Exception Mananger class; Any custom exceptions must be above this line. +ExceptionManager *g_ExceptionManager = nullptr; + +ExceptionManager::ExceptionManager() +{ + accept_request = true; +} + +ExceptionManager::~ExceptionManager() +{ + for (auto i_handle : veh_handles) { + RemoveVectoredExceptionHandler(i_handle); + } + veh_handles.clear(); +} + +// Require to be set right before we call xbe's entry point. +void ExceptionManager::EmuX86_Init() +{ + accept_request = false; // Do not allow add VEH during emulation. +} + +bool ExceptionManager::AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler) +{ + return AddVEH(first, veh_handler, false); +} + +bool ExceptionManager::AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler, bool override_request) +{ + bool isSuccess = false; + if (accept_request || override_request) { + void* veh_handle = AddVectoredExceptionHandler(first, veh_handler); + if (veh_handle) { + veh_handles.push_back(veh_handle); + isSuccess = true; + } + } + return isSuccess; +} + #ifdef _DEBUG // print call stack trace void EmuPrintStackTrace(PCONTEXT ContextRecord) diff --git a/src/core/kernel/support/Emu.h b/src/core/kernel/support/Emu.h index 2e3b543a3..05119e42e 100644 --- a/src/core/kernel/support/Emu.h +++ b/src/core/kernel/support/Emu.h @@ -37,6 +37,22 @@ std::string FormatTitleId(uint32_t title_id); // exception handler extern LONG NTAPI lleException(EXCEPTION_POINTERS *e); int EmuException(EXCEPTION_POINTERS *e); +class ExceptionManager { +public: + ExceptionManager(); + virtual ~ExceptionManager(); + // We want to make sure the core's exception is trigger front and last of exception management. For two reasons: + // Performance wise for LLE emulation and general emulation, to remove false positive exception from drivers, before we show an actual fatal error message. + void EmuX86_Init(); + // If any custom VEH should be add here than try on their own. See private AddVEH function's comment. + bool AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler); +private: + std::vector veh_handles; + bool accept_request; + // Since Vectored Exception Handlers are global than per thread, we only need to register once. + bool AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler, bool override_request); +}; +extern class ExceptionManager* g_ExceptionManager; // print call stack trace #ifdef _DEBUG