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.
This commit is contained in:
Quentin 2023-07-10 19:01:34 +02:00 committed by GitHub
parent b8a7c9be70
commit 17d647dfa5
9 changed files with 109 additions and 28 deletions

View File

@ -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);
}

View File

@ -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");

View File

@ -114,6 +114,8 @@ namespace big
detour_hook_helper::add<hooks::netfilter_handle_message>("NHM", g_pointers->m_gta.m_netfilter_handle_message);
detour_hook_helper::add<hooks::log_error_message_box>("E0MBH", g_pointers->m_gta.m_error_message_box);
g_hooking = this;
}

View File

@ -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

View File

@ -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<int*>(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();
}
}

View File

@ -1344,6 +1344,24 @@ namespace big
{
g_pointers->m_gta.m_model_spawn_bypass = ptr.add(8).as<PVOID>();
}
},
// ERROR message box
{
"E0MB",
"E8 ? ? ? ? CC FF 15",
[](memory::handle ptr)
{
g_pointers->m_gta.m_error_message_box = ptr.add(1).rip().as<PVOID>();
}
},
// 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<functions::get_title_caption_error_message_box>();
}
}
>(); // don't leave a trailing comma at the end

View File

@ -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<int>(input.size()), nullptr, 0, nullptr, nullptr);
std::string output(size, '\0');
if (size
!= WideCharToMultiByte(code_page,
0,
input.data(),
static_cast<int>(input.size()),
output.data(),
static_cast<int>(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;

View File

@ -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<int>(input.size()), nullptr, 0, nullptr, nullptr);
std::string output(size, '\0');
if (size
!= WideCharToMultiByte(code_page,
0,
input.data(),
static_cast<int>(input.size()),
output.data(),
static_cast<int>(output.size()),
nullptr,
nullptr))
{
const auto error_code = GetLastError();
LOG(WARNING) << "WideCharToMultiByte Error in String " << error_code;
return {};
}
return output;
}
}

View File

@ -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();