/** * Ashita SDK - Copyright (c) 2023 Ashita Development Team * Contact: https://www.ashitaxi.com/ * Contact: https://discord.gg/Ashita * * This file is part of Ashita. * * Ashita is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Ashita is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Ashita. If not, see . */ #ifndef ASHITA_SDK_ERRORHANDLING_H_INCLUDED #define ASHITA_SDK_ERRORHANDLING_H_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif #include #include #include /** * Missing Status Code Defines */ #ifndef STATUS_POSSIBLE_DEADLOCK #define STATUS_POSSIBLE_DEADLOCK 0xC0000194 #endif /** * Helper Macros */ #define CASE(e) \ case e: \ this->m_Exception = #e; \ break; namespace Ashita::ErrorHandling { class Exception { uint32_t m_Id; const char* m_Exception; char m_Message[2048]; _EXCEPTION_POINTERS* m_Pointers; public: explicit Exception(const uint32_t id, _EXCEPTION_POINTERS* pointers) : m_Id(id) , m_Exception(nullptr) , m_Message{0} , m_Pointers(pointers) { switch (this->m_Id) { CASE(EXCEPTION_ACCESS_VIOLATION); CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); CASE(EXCEPTION_BREAKPOINT); CASE(EXCEPTION_DATATYPE_MISALIGNMENT); CASE(EXCEPTION_FLT_DENORMAL_OPERAND); CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO); CASE(EXCEPTION_FLT_INEXACT_RESULT); CASE(EXCEPTION_FLT_INVALID_OPERATION); CASE(EXCEPTION_FLT_OVERFLOW); CASE(EXCEPTION_FLT_STACK_CHECK); CASE(EXCEPTION_FLT_UNDERFLOW); CASE(EXCEPTION_GUARD_PAGE); CASE(EXCEPTION_ILLEGAL_INSTRUCTION); CASE(EXCEPTION_IN_PAGE_ERROR); CASE(EXCEPTION_INT_DIVIDE_BY_ZERO); CASE(EXCEPTION_INT_OVERFLOW); CASE(EXCEPTION_INVALID_DISPOSITION); CASE(EXCEPTION_INVALID_HANDLE); CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION); CASE(EXCEPTION_POSSIBLE_DEADLOCK); CASE(EXCEPTION_PRIV_INSTRUCTION); CASE(EXCEPTION_SINGLE_STEP); CASE(EXCEPTION_STACK_OVERFLOW); default: this->m_Exception = "(Unknown Exception)"; break; } const auto ptr = pointers != nullptr && pointers->ExceptionRecord != nullptr ? pointers->ExceptionRecord->ExceptionAddress : nullptr; // Create a formatted message of the exception.. sprintf_s(this->m_Message, 2048, "%s (%08X). [Ptr: %08p]", this->m_Exception, id, ptr); } ~Exception(void) {} /** * Returns the exception id. * * @return {uint32_t} The exception id. */ uint32_t GetId(void) const { return this->m_Id; } /** * Returns the exception type. * * @return {const char*} The exception type. */ const char* GetException(void) const { return this->m_Message; } /** * Returns the exception message. * * @return {const char*} The exception message. */ const char* what(void) const { return this->m_Message; } /** * Returns the exception pointers information. * * @return {_EXCEPTION_POINTERS*} The exception pointers. */ _EXCEPTION_POINTERS* GetPointers(void) const { return this->m_Pointers; } }; class ScopedTranslator { _se_translator_function m_Function; public: ScopedTranslator(void) { this->m_Function = ::_set_se_translator(&ScopedTranslator::ScopedTranslatorFunction); } ~ScopedTranslator(void) { if (this->m_Function != nullptr) ::_set_se_translator(this->m_Function); this->m_Function = nullptr; } private: /** * Catches and rethrows an exception as an Ashita wrapped exception. * * @param {uint32_t} id - The id of the exception. * @param {_EXCEPTION_POINTERS*} pointers - The pointer information of the exception. */ static void ScopedTranslatorFunction(const uint32_t id, struct _EXCEPTION_POINTERS* pointers) { throw Ashita::ErrorHandling::Exception(id, pointers); } }; } // namespace Ashita::ErrorHandling #endif // ASHITA_SDK_ERRORHANDLING_H_INCLUDED