From 0c050d82c9d240f822785794edddd5dc57803aff Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 10 Jul 2023 19:01:34 +0200 Subject: [PATCH] Log GTA error message boxes and don't make them close the game. (#1671) * refactor: move utf 16 to code page string conversion to its own util file * feat(error-handling): log error message box generated from gta. --- src/function_types.hpp | 2 ++ src/gta_pointers.hpp | 4 +++ src/hooking.cpp | 2 ++ src/hooking.hpp | 2 ++ src/hooks/misc/log_message_error_box.cpp | 41 ++++++++++++++++++++++++ src/pointers.cpp | 18 +++++++++++ src/services/gta_data/yim_fipackfile.cpp | 30 ++--------------- src/util/string_conversions.hpp | 31 ++++++++++++++++++ src/views/debug/view_debug_misc.cpp | 7 ++++ 9 files changed, 109 insertions(+), 28 deletions(-) create mode 100644 src/hooks/misc/log_message_error_box.cpp create mode 100644 src/util/string_conversions.hpp diff --git a/src/function_types.hpp b/src/function_types.hpp index 4eb902a0..b3ec1de9 100644 --- a/src/function_types.hpp +++ b/src/function_types.hpp @@ -147,4 +147,6 @@ namespace big::functions using update_language = void (*)(bool); using get_host_array_handler_by_index = rage::netArrayHandlerBase* (*)(CGameScriptHandlerNetComponent* component, int index); + + using get_title_caption_error_message_box = const wchar_t* (*)(rage::joaat_t joaated_error_code); } diff --git a/src/gta_pointers.hpp b/src/gta_pointers.hpp index 732d81f9..422f8df1 100644 --- a/src/gta_pointers.hpp +++ b/src/gta_pointers.hpp @@ -267,6 +267,10 @@ namespace big PVOID m_model_spawn_bypass{}; functions::get_host_array_handler_by_index m_get_host_array_handler_by_index; + + PVOID m_error_message_box{}; + + functions::get_title_caption_error_message_box m_get_title_caption_error_message_box{}; }; #pragma pack(pop) static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); diff --git a/src/hooking.cpp b/src/hooking.cpp index f6391943..135eaf6b 100644 --- a/src/hooking.cpp +++ b/src/hooking.cpp @@ -114,6 +114,8 @@ namespace big detour_hook_helper::add("NHM", g_pointers->m_gta.m_netfilter_handle_message); + detour_hook_helper::add("E0MBH", g_pointers->m_gta.m_error_message_box); + g_hooking = this; } diff --git a/src/hooking.hpp b/src/hooking.hpp index bf90c286..b7d425e7 100644 --- a/src/hooking.hpp +++ b/src/hooking.hpp @@ -150,6 +150,8 @@ namespace big static bool allow_weapons_in_vehicle(int64_t unk, int weaponinfo_group); static int netfilter_handle_message(__int64 filter, char* message, int flags); + + static void log_error_message_box(rage::joaat_t joaated_error_code, char a2); }; class minhook_keepalive diff --git a/src/hooks/misc/log_message_error_box.cpp b/src/hooks/misc/log_message_error_box.cpp new file mode 100644 index 00000000..e00fb883 --- /dev/null +++ b/src/hooks/misc/log_message_error_box.cpp @@ -0,0 +1,41 @@ +#include "hooking.hpp" +#include "pointers.hpp" +#include "util/string_conversions.hpp" +#include "logger/stack_trace.hpp" + +namespace big +{ + static stack_trace trace; + + static int log_stack_trace_filter(EXCEPTION_POINTERS* ep) + { + trace.new_stack_trace(ep); + + LOG(FATAL) << trace; + Logger::FlushQueue(); + + return EXCEPTION_EXECUTE_HANDLER; + } + + static void log_stack_trace() + { + __try + { + // On purpose to print a stack trace. + *reinterpret_cast(0xDEAD) = 0; + } + __except (log_stack_trace_filter(GetExceptionInformation())) + { + } + } + + void hooks::log_error_message_box(rage::joaat_t joaated_error_code, char a2) + { + LOG(WARNING) << "Error Code: " << + string_conversions::utf_16_to_code_page( + CP_UTF8, + g_pointers->m_gta.m_get_title_caption_error_message_box(joaated_error_code)); + + log_stack_trace(); + } +} diff --git a/src/pointers.cpp b/src/pointers.cpp index aa454a6e..1cf6deb8 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -1344,6 +1344,24 @@ namespace big { g_pointers->m_gta.m_model_spawn_bypass = ptr.add(8).as(); } + }, + // ERROR message box + { + "E0MB", + "E8 ? ? ? ? CC FF 15", + [](memory::handle ptr) + { + g_pointers->m_gta.m_error_message_box = ptr.add(1).rip().as(); + } + }, + // Get title caption for ERROR message box + { + "GTCE0MB", + "E8 ? ? ? ? 48 83 CB FF 48 8D 8D", + [](memory::handle ptr) + { + g_pointers->m_gta.m_get_title_caption_error_message_box = ptr.add(1).rip().as(); + } } >(); // don't leave a trailing comma at the end diff --git a/src/services/gta_data/yim_fipackfile.cpp b/src/services/gta_data/yim_fipackfile.cpp index 6357417f..b2b97be8 100644 --- a/src/services/gta_data/yim_fipackfile.cpp +++ b/src/services/gta_data/yim_fipackfile.cpp @@ -3,6 +3,7 @@ #include "gta/fidevice.hpp" #include "pointers.hpp" #include "script.hpp" +#include "util/string_conversions.hpp" namespace big { @@ -86,33 +87,6 @@ namespace big packfile.ClosePackfile(); } - static std::string UTF16ToCP(uint32_t code_page, std::wstring_view input) - { - if (input.empty()) - return {}; - - const auto size = WideCharToMultiByte(code_page, 0, input.data(), static_cast(input.size()), nullptr, 0, nullptr, nullptr); - - std::string output(size, '\0'); - - if (size - != WideCharToMultiByte(code_page, - 0, - input.data(), - static_cast(input.size()), - output.data(), - static_cast(output.size()), - nullptr, - nullptr)) - { - const auto error_code = GetLastError(); - LOG(WARNING) << "WideCharToMultiByte Error in String " << error_code; - return {}; - } - - return output; - } - static std::filesystem::path get_game_folder_path() { std::wstring game_module_path(MAX_PATH, '\0'); @@ -166,7 +140,7 @@ namespace big if (rel_path.empty()) continue; - const auto utf8_path = UTF16ToCP(CP_UTF8, entry.path().native()); + const auto utf8_path = string_conversions::utf_16_to_code_page(CP_UTF8, entry.path().native()); if (utf8_path.empty()) continue; diff --git a/src/util/string_conversions.hpp b/src/util/string_conversions.hpp new file mode 100644 index 00000000..a9329f58 --- /dev/null +++ b/src/util/string_conversions.hpp @@ -0,0 +1,31 @@ +#pragma once + +namespace big::string_conversions +{ + inline std::string utf_16_to_code_page(uint32_t code_page, std::wstring_view input) + { + if (input.empty()) + return {}; + + const auto size = WideCharToMultiByte(code_page, 0, input.data(), static_cast(input.size()), nullptr, 0, nullptr, nullptr); + + std::string output(size, '\0'); + + if (size + != WideCharToMultiByte(code_page, + 0, + input.data(), + static_cast(input.size()), + output.data(), + static_cast(output.size()), + nullptr, + nullptr)) + { + const auto error_code = GetLastError(); + LOG(WARNING) << "WideCharToMultiByte Error in String " << error_code; + return {}; + } + + return output; + } +} \ No newline at end of file diff --git a/src/views/debug/view_debug_misc.cpp b/src/views/debug/view_debug_misc.cpp index 7f96f45e..ace434ec 100644 --- a/src/views/debug/view_debug_misc.cpp +++ b/src/views/debug/view_debug_misc.cpp @@ -11,6 +11,8 @@ #include "util/system.hpp" #include "view_debug.hpp" +#include "hooking.hpp" + namespace big { void debug::misc() @@ -26,6 +28,11 @@ namespace big g_fiber_pool->reset(); } + if (components::button("Trigger GTA Error Message Box")) + { + hooks::log_error_message_box(0xBAFD530B, 1); + } + if (components::button("DUMP_ENTRYPOINTS"_T.data())) { system::dump_entry_points();