diff --git a/BigBaseV2/src/detour_hook.cc b/BigBaseV2/src/detour_hook.cc index f887163b..f64e9947 100644 --- a/BigBaseV2/src/detour_hook.cc +++ b/BigBaseV2/src/detour_hook.cc @@ -6,10 +6,28 @@ namespace big { + detour_hook::detour_hook(std::string name, void* detour) : + m_name(std::move(name)), + m_detour(detour) + { + + } + detour_hook::detour_hook(std::string name, void* target, void* detour) : m_name(std::move(name)), m_target(target), m_detour(detour) + { + create_hook(); + } + + void detour_hook::set_target_and_create_hook(void* target) + { + m_target = target; + create_hook(); + } + + void detour_hook::create_hook() { fix_hook_address(); if (auto status = MH_CreateHook(m_target, m_detour, &m_original); status != MH_OK) diff --git a/BigBaseV2/src/detour_hook.hpp b/BigBaseV2/src/detour_hook.hpp index 76c0b6eb..04a89ca1 100644 --- a/BigBaseV2/src/detour_hook.hpp +++ b/BigBaseV2/src/detour_hook.hpp @@ -5,7 +5,8 @@ namespace big class detour_hook { public: - explicit detour_hook(std::string name, void *target, void *detour); + explicit detour_hook(std::string name, void* detour); + explicit detour_hook(std::string name, void *target, void* detour); ~detour_hook() noexcept; detour_hook(detour_hook&& that) = delete; @@ -13,23 +14,25 @@ namespace big detour_hook(detour_hook const&) = delete; detour_hook& operator=(detour_hook const&) = delete; + void set_target_and_create_hook(void* target); + void enable(); void disable(); template - T get_original(); + T get_original() + { + return static_cast(m_original); + } void fix_hook_address(); - private: - std::string m_name; - void *m_target; - void *m_detour; - void *m_original{}; - }; - template - inline T detour_hook::get_original() - { - return static_cast(m_original); - } + private: + void create_hook(); + + std::string m_name; + void *m_original{}; + void* m_target{}; + void* m_detour{}; + }; } diff --git a/BigBaseV2/src/hooking.cpp b/BigBaseV2/src/hooking.cpp index 09aec601..7cd6c383 100644 --- a/BigBaseV2/src/hooking.cpp +++ b/BigBaseV2/src/hooking.cpp @@ -18,62 +18,57 @@ namespace big { hooking::hooking() : // Swapchain - m_swapchain_hook(*g_pointers->m_swapchain, hooks::swapchain_num_funcs), - - // Script Hook - m_run_script_threads_hook("SH", g_pointers->m_run_script_threads, &hooks::run_script_threads), - - // Get Label Text - m_get_label_text("GLT", g_pointers->m_get_label_text, &hooks::get_label_text), - - // Multiplayer chat filter - m_multiplayer_chat_filter("MCF", g_pointers->m_multiplayer_chat_filter, &hooks::multiplayer_chat_filter), - - // Write Player Game State Data Node - m_write_player_game_state_data_node_hook("WPGSDN", g_pointers->m_write_player_game_state_data_node, &hooks::write_player_game_state_data_node), - - // GTA Thead Start - m_gta_thread_start_hook("GTS", g_pointers->m_gta_thread_start, &hooks::gta_thread_start), - // GTA Thread Kill - m_gta_thread_kill_hook("GTK", g_pointers->m_gta_thread_kill, &hooks::gta_thread_kill), - - // Network Player Mgr Init - m_network_player_mgr_init_hook("NPMI", g_pointers->m_network_player_mgr_init, &hooks::network_player_mgr_init), - // Network Player Mgr Shutdown - m_network_player_mgr_shutdown_hook("NPMS", g_pointers->m_network_player_mgr_shutdown, &hooks::network_player_mgr_shutdown), - - // Network Group Override - m_network_group_override("NGO", g_pointers->m_network_group_override, &hooks::network_group_override), - - // Received Event - m_received_event_hook("RE", g_pointers->m_received_event, &hooks::received_event), - - // Send NET Info to Lobby - m_send_net_info_to_lobby("SNITL", g_pointers->m_send_net_info_to_lobby, &hooks::send_net_info_to_lobby), - - // Assign Physical Index - m_assign_physical_index_hook("API", g_pointers->m_assign_physical_index, &hooks::assign_physical_index), - // Receive Net Message - m_receive_net_message_hook("RNM", g_pointers->m_receive_net_message, &hooks::receive_net_message), - // Received clone sync - m_received_clone_sync_hook("RCS", g_pointers->m_received_clone_sync, &hooks::received_clone_sync), - //Get Network Event Data - m_get_network_event_data_hook("GNED", g_pointers->m_get_network_event_data, &hooks::get_network_event_data), - m_write_player_gamer_data_node_hook("WPGDN", g_pointers->m_write_player_gamer_data_node, &hooks::write_player_gamer_data_node), - - // Format Metric For Sending - m_format_metric_for_sending("FMFS", g_pointers->m_format_metric_for_sending, &hooks::format_metric_for_sending) + m_swapchain_hook(*g_pointers->m_swapchain, hooks::swapchain_num_funcs) { m_swapchain_hook.hook(hooks::swapchain_present_index, &hooks::swapchain_present); m_swapchain_hook.hook(hooks::swapchain_resizebuffers_index, &hooks::swapchain_resizebuffers); + // The only instances in that vector at this point should only be the "lazy" hooks + // aka the ones that still don't have their m_target assigned + for (auto& detour_hook_helper : m_detour_hook_helpers) + { + detour_hook_helper->m_detour_hook->set_target_and_create_hook(detour_hook_helper->m_on_hooking_available()); + } + + detour_hook_helper::add("SH", g_pointers->m_run_script_threads); + + detour_hook_helper::add("GLT", g_pointers->m_get_label_text); + + detour_hook_helper::add("MCF", g_pointers->m_multiplayer_chat_filter); + + detour_hook_helper::add("WPGSDN", g_pointers->m_write_player_game_state_data_node); + + detour_hook_helper::add("GTS", g_pointers->m_gta_thread_start); + detour_hook_helper::add("GTK", g_pointers->m_gta_thread_kill); + + detour_hook_helper::add("NPMI", g_pointers->m_network_player_mgr_init); + detour_hook_helper::add("NPMS", g_pointers->m_network_player_mgr_shutdown); + + detour_hook_helper::add("NGO", g_pointers->m_network_group_override); + + detour_hook_helper::add("RE", g_pointers->m_received_event); + + detour_hook_helper::add("SNITL", g_pointers->m_send_net_info_to_lobby); + + detour_hook_helper::add("API", g_pointers->m_assign_physical_index); + + detour_hook_helper::add("RNM", g_pointers->m_receive_net_message); + detour_hook_helper::add("RCS", g_pointers->m_received_clone_sync); + + detour_hook_helper::add("GNED", g_pointers->m_get_network_event_data); + detour_hook_helper::add("WPGDN", g_pointers->m_write_player_gamer_data_node); + + detour_hook_helper::add("FMFS", g_pointers->m_format_metric_for_sending); + g_hooking = this; } hooking::~hooking() { if (m_enabled) + { disable(); + } g_hooking = nullptr; } @@ -83,23 +78,10 @@ namespace big m_swapchain_hook.enable(); m_og_wndproc = WNDPROC(SetWindowLongPtrW(g_pointers->m_hwnd, GWLP_WNDPROC, LONG_PTR(&hooks::wndproc))); - m_run_script_threads_hook.enable(); - m_get_label_text.enable(); - m_multiplayer_chat_filter.enable(); - m_gta_thread_start_hook.enable(); - m_gta_thread_kill_hook.enable(); - m_network_group_override.enable(); - m_network_player_mgr_init_hook.enable(); - m_network_player_mgr_shutdown_hook.enable(); - m_assign_physical_index_hook.enable(); - m_received_event_hook.enable(); - m_send_net_info_to_lobby.enable(); - m_receive_net_message_hook.enable(); - m_get_network_event_data_hook.enable(); - m_received_clone_sync_hook.enable(); - m_write_player_gamer_data_node_hook.enable(); - m_write_player_game_state_data_node_hook.enable(); - m_format_metric_for_sending.enable(); + for (const auto& detour_hook_helper : m_detour_hook_helpers) + { + detour_hook_helper->m_detour_hook->enable(); + } MH_ApplyQueued(); @@ -110,28 +92,40 @@ namespace big { m_enabled = false; - m_format_metric_for_sending.disable(); - m_write_player_game_state_data_node_hook.disable(); - m_write_player_gamer_data_node_hook.disable(); - m_received_clone_sync_hook.disable(); - m_get_network_event_data_hook.disable(); - m_receive_net_message_hook.disable(); - m_send_net_info_to_lobby.disable(); - m_received_event_hook.disable(); - m_assign_physical_index_hook.disable(); - m_network_player_mgr_init_hook.disable(); - m_network_player_mgr_shutdown_hook.disable(); - m_network_group_override.disable(); - m_gta_thread_kill_hook.disable(); - m_gta_thread_start_hook.disable(); - m_multiplayer_chat_filter.disable(); - m_get_label_text.disable(); - m_run_script_threads_hook.disable(); - - MH_ApplyQueued(); + for (const auto& detour_hook_helper : m_detour_hook_helpers) + { + detour_hook_helper->m_detour_hook->disable(); + } SetWindowLongPtrW(g_pointers->m_hwnd, GWLP_WNDPROC, reinterpret_cast(m_og_wndproc)); m_swapchain_hook.disable(); + + MH_ApplyQueued(); + + for (const auto& detour_hook_helper : m_detour_hook_helpers) + { + delete detour_hook_helper; + } + m_detour_hook_helpers.clear(); + } + + hooking::detour_hook_helper::~detour_hook_helper() + { + delete m_detour_hook; + } + + void hooking::detour_hook_helper::enable_hook_if_hooking_is_already_running() + { + if (g_hooking && g_hooking->m_enabled) + { + if (m_on_hooking_available) + { + m_detour_hook->set_target_and_create_hook(m_on_hooking_available()); + } + + m_detour_hook->enable(); + MH_ApplyQueued(); + } } bool hooks::run_script_threads(std::uint32_t ops_to_execute) @@ -143,6 +137,6 @@ namespace big g_script_mgr.tick(); } - return g_hooking->m_run_script_threads_hook.get_original()(ops_to_execute); + return g_hooking->get_original()(ops_to_execute); } } diff --git a/BigBaseV2/src/hooking.hpp b/BigBaseV2/src/hooking.hpp index a79f9cef..988cf971 100644 --- a/BigBaseV2/src/hooking.hpp +++ b/BigBaseV2/src/hooking.hpp @@ -90,6 +90,65 @@ namespace big void enable(); void disable(); + class detour_hook_helper + { + friend hooking; + + using ret_ptr_fn = std::function; + + ret_ptr_fn m_on_hooking_available = nullptr; + + detour_hook* m_detour_hook = nullptr; + + ~detour_hook_helper(); + + void enable_hook_if_hooking_is_already_running(); + + template + struct hook_to_detour_hook_helper + { + static inline detour_hook* m_detour_hook; + }; + + template + static detour_hook_helper* add_internal(detour_hook* dh) + { + auto d = new detour_hook_helper(); + d->m_detour_hook = dh; + + m_detour_hook_helpers.push_back(d); + hook_to_detour_hook_helper::m_detour_hook = dh; + + return d; + } + + public: + template + static void add(const std::string& name, void* target) + { + auto d = add_internal(new detour_hook(name, target, detour_function)); + + d->enable_hook_if_hooking_is_already_running(); + } + + template + static void* add_lazy(const std::string& name, detour_hook_helper::ret_ptr_fn on_hooking_available) + { + auto d = add_internal(new detour_hook(name, detour_function)); + d->m_on_hooking_available = on_hooking_available; + + d->enable_hook_if_hooking_is_already_running(); + + return nullptr; + } + }; + + template + static auto get_original() + { + return detour_hook_helper::hook_to_detour_hook_helper::m_detour_hook->get_original(); + } + private: bool m_enabled{}; minhook_keepalive m_minhook_keepalive; @@ -98,33 +157,8 @@ namespace big WNDPROC m_og_wndproc = nullptr; - detour_hook m_run_script_threads_hook; - - detour_hook m_get_label_text; - detour_hook m_multiplayer_chat_filter; - - detour_hook m_gta_thread_start_hook; - detour_hook m_gta_thread_kill_hook; - - detour_hook m_network_player_mgr_init_hook; - detour_hook m_network_player_mgr_shutdown_hook; - - detour_hook m_network_group_override; - - detour_hook m_assign_physical_index_hook; - - detour_hook m_received_event_hook; - detour_hook m_received_clone_sync_hook; - - detour_hook m_send_net_info_to_lobby; - detour_hook m_receive_net_message_hook; - detour_hook m_get_network_event_data_hook; - - detour_hook m_format_metric_for_sending; - - detour_hook m_write_player_gamer_data_node_hook; - detour_hook m_write_player_game_state_data_node_hook; + static inline std::vector m_detour_hook_helpers; }; - inline hooking *g_hooking{}; + inline hooking* g_hooking{}; } diff --git a/BigBaseV2/src/hooks/info/get_network_event_data.cpp b/BigBaseV2/src/hooks/info/get_network_event_data.cpp index a40b2831..7e9184f5 100644 --- a/BigBaseV2/src/hooks/info/get_network_event_data.cpp +++ b/BigBaseV2/src/hooks/info/get_network_event_data.cpp @@ -12,6 +12,6 @@ namespace big } } - return g_hooking->m_get_network_event_data_hook.get_original()(unk, net_event); + return g_hooking->get_original()(unk, net_event); } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/misc/get_label_text.cpp b/BigBaseV2/src/hooks/misc/get_label_text.cpp index 43373879..52efe20c 100644 --- a/BigBaseV2/src/hooks/misc/get_label_text.cpp +++ b/BigBaseV2/src/hooks/misc/get_label_text.cpp @@ -8,6 +8,6 @@ namespace big if (const auto text = g_custom_text_service->get_text(label); text) return text; - return g_hooking->m_get_label_text.get_original()(unk, label); + return g_hooking->get_original()(unk, label); } } diff --git a/BigBaseV2/src/hooks/misc/multiplayer_chat_filter.cpp b/BigBaseV2/src/hooks/misc/multiplayer_chat_filter.cpp index 5924625b..0a83fcc6 100644 --- a/BigBaseV2/src/hooks/misc/multiplayer_chat_filter.cpp +++ b/BigBaseV2/src/hooks/misc/multiplayer_chat_filter.cpp @@ -8,6 +8,6 @@ namespace big { return -1; } - return g_hooking->m_multiplayer_chat_filter.get_original()(chat_type, input, output); + return g_hooking->get_original()(chat_type, input, output); } } diff --git a/BigBaseV2/src/hooks/native_hooks/gta_thread_kill.cpp b/BigBaseV2/src/hooks/native_hooks/gta_thread_kill.cpp index ce5b22ad..6cdb3117 100644 --- a/BigBaseV2/src/hooks/native_hooks/gta_thread_kill.cpp +++ b/BigBaseV2/src/hooks/native_hooks/gta_thread_kill.cpp @@ -5,15 +5,15 @@ namespace big { rage::eThreadState hooks::gta_thread_kill(GtaThread* thread) { - const auto result = g_hooking->m_gta_thread_kill_hook.get_original()(thread); + const auto result = g_hooking->get_original()(thread); if (g->notifications.gta_thread_kill.log) LOG(INFO) << "Script Thread '" << thread->m_name << "' terminated."; if (g->notifications.gta_thread_kill.notify) g_notification_service->push("Script Thread Termination", std::format("Script Thread '{}' terminated.", thread->m_name)); - + g_native_hooks->do_cleanup_for_thread(thread); return result; } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/native_hooks/gta_thread_start.cpp b/BigBaseV2/src/hooks/native_hooks/gta_thread_start.cpp index 122c8724..a0eef795 100644 --- a/BigBaseV2/src/hooks/native_hooks/gta_thread_start.cpp +++ b/BigBaseV2/src/hooks/native_hooks/gta_thread_start.cpp @@ -5,7 +5,7 @@ namespace big { GtaThread* hooks::gta_thread_start(unsigned int** a1, unsigned int a2) { - GtaThread* new_thread = g_hooking->m_gta_thread_start_hook.get_original()(a1, a2); + GtaThread* new_thread = g_hooking->get_original()(a1, a2); if (const char* name = new_thread->m_name; strlen(name) > 0) { @@ -20,4 +20,4 @@ namespace big return new_thread; } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/player_management/assign_physical_index.cpp b/BigBaseV2/src/hooks/player_management/assign_physical_index.cpp index dfd43ec5..6b55ca3d 100644 --- a/BigBaseV2/src/hooks/player_management/assign_physical_index.cpp +++ b/BigBaseV2/src/hooks/player_management/assign_physical_index.cpp @@ -6,9 +6,9 @@ namespace big { void* hooks::assign_physical_index(CNetworkPlayerMgr* netPlayerMgr, CNetGamePlayer* player, uint8_t new_index) { - const auto result = g_hooking->m_assign_physical_index_hook.get_original()(netPlayerMgr, player, new_index); + const auto result = g_hooking->get_original()(netPlayerMgr, player, new_index); const auto* net_player_data = player->get_net_data(); - + if (new_index == static_cast(-1)) { g_player_service->player_leave(player); @@ -43,4 +43,4 @@ namespace big } return result; } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/player_management/network_player_mgr.cpp b/BigBaseV2/src/hooks/player_management/network_player_mgr.cpp index 8edbf92f..e6e97b09 100644 --- a/BigBaseV2/src/hooks/player_management/network_player_mgr.cpp +++ b/BigBaseV2/src/hooks/player_management/network_player_mgr.cpp @@ -10,7 +10,7 @@ namespace big if (g->notifications.network_player_mgr_init.notify) g_notification_service->push("Network Player Manager", "Entering session and initializing player data."); - g_hooking->m_network_player_mgr_init_hook.get_original()(_this, a2, a3, a4); + g_hooking->get_original()(_this, a2, a3, a4); g_player_service->player_join(_this->m_local_net_player); } @@ -24,6 +24,6 @@ namespace big if (g->notifications.network_player_mgr_shutdown.notify) g_notification_service->push("Network Player Manager", "Leaving session and cleaning up player data."); - g_hooking->m_network_player_mgr_shutdown_hook.get_original()(_this); + g_hooking->get_original()(_this); } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/protections/network_group_override.cpp b/BigBaseV2/src/hooks/protections/network_group_override.cpp index a29bd3d3..42495164 100644 --- a/BigBaseV2/src/hooks/protections/network_group_override.cpp +++ b/BigBaseV2/src/hooks/protections/network_group_override.cpp @@ -13,6 +13,6 @@ namespace big } // original - return g_hooking->m_network_group_override.get_original()(a1, a2, a3); + return g_hooking->get_original()(a1, a2, a3); } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/protections/receive_net_message.cpp b/BigBaseV2/src/hooks/protections/receive_net_message.cpp index a8ffaf25..24ece2b3 100644 --- a/BigBaseV2/src/hooks/protections/receive_net_message.cpp +++ b/BigBaseV2/src/hooks/protections/receive_net_message.cpp @@ -91,6 +91,6 @@ namespace big } } - return g_hooking->m_receive_net_message_hook.get_original()(netConnectionManager, a2, frame); + return g_hooking->get_original()(netConnectionManager, a2, frame); } } diff --git a/BigBaseV2/src/hooks/protections/received_clone_sync.cpp b/BigBaseV2/src/hooks/protections/received_clone_sync.cpp index bda93e63..71b6e912 100644 --- a/BigBaseV2/src/hooks/protections/received_clone_sync.cpp +++ b/BigBaseV2/src/hooks/protections/received_clone_sync.cpp @@ -20,7 +20,7 @@ namespace big CantApplyData_NetworkClosed = 7, // Can't apply data - network closed SuccessfullSync = 8 }; - + int64_t hooks::received_clone_sync(CNetworkObjectMgr* mgr, CNetGamePlayer* src, CNetGamePlayer* dst, eObjType sync_type, uint16_t obj_id, rage::datBitBuffer* buffer, uint16_t unk, uint32_t timestamp) { if (auto sync_tree = g_pointers->m_get_sync_tree_for_type(mgr, sync_type); sync_tree && *g_pointers->m_is_session_started) { @@ -68,8 +68,8 @@ namespace big return SyncResponse::WrongOwner; } } - return g_hooking->m_received_clone_sync_hook.get_original()(mgr, src, dst, sync_type, obj_id, buffer, unk, timestamp); + return g_hooking->get_original()(mgr, src, dst, sync_type, obj_id, buffer, unk, timestamp); } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/protections/received_event.cpp b/BigBaseV2/src/hooks/protections/received_event.cpp index 1a7b64e7..f3a3c275 100644 --- a/BigBaseV2/src/hooks/protections/received_event.cpp +++ b/BigBaseV2/src/hooks/protections/received_event.cpp @@ -178,6 +178,6 @@ namespace big break; } - return g_hooking->m_received_event_hook.get_original()(event_manager, source_player, target_player, event_id, event_index, event_handled_bitset, unk, buffer); + return g_hooking->get_original()(event_manager, source_player, target_player, event_id, event_index, event_handled_bitset, unk, buffer); } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/spoofing/send_net_info_to_lobby.cpp b/BigBaseV2/src/hooks/spoofing/send_net_info_to_lobby.cpp index 43373b58..6a8d1b25 100644 --- a/BigBaseV2/src/hooks/spoofing/send_net_info_to_lobby.cpp +++ b/BigBaseV2/src/hooks/spoofing/send_net_info_to_lobby.cpp @@ -32,7 +32,7 @@ namespace big g_notification_service->push("Player Info Spoofing", "Sent spoofed values to lobby host."); } - const auto result = g_hooking->m_send_net_info_to_lobby.get_original()(player, a2, a3, a4); + const auto result = g_hooking->get_original()(player, a2, a3, a4); // restore player name to prevent detection of spoofed name if (is_local_player && g->spoofing.spoof_username) @@ -40,4 +40,4 @@ namespace big return result; } -} \ No newline at end of file +} diff --git a/BigBaseV2/src/hooks/spoofing/write_player_game_state_data_node.cpp b/BigBaseV2/src/hooks/spoofing/write_player_game_state_data_node.cpp index 15e8f735..04da2213 100644 --- a/BigBaseV2/src/hooks/spoofing/write_player_game_state_data_node.cpp +++ b/BigBaseV2/src/hooks/spoofing/write_player_game_state_data_node.cpp @@ -4,7 +4,7 @@ namespace big { bool hooks::write_player_game_state_data_node(rage::netObject* player, CPlayerGameStateDataNode* node) { - auto ret = g_hooking->m_write_player_game_state_data_node_hook.get_original()(player, node); + auto ret = g_hooking->get_original()(player, node); if (g->spoofing.spoof_hide_god) node->m_is_invincible = false; diff --git a/BigBaseV2/src/hooks/spoofing/write_player_gamer_data_node.cpp b/BigBaseV2/src/hooks/spoofing/write_player_gamer_data_node.cpp index 6b342f3d..b33877e9 100644 --- a/BigBaseV2/src/hooks/spoofing/write_player_gamer_data_node.cpp +++ b/BigBaseV2/src/hooks/spoofing/write_player_gamer_data_node.cpp @@ -4,7 +4,7 @@ namespace big { void hooks::write_player_gamer_data_node(rage::netObject* player, CPlayerGamerDataNode* node) { - g_hooking->m_write_player_gamer_data_node_hook.get_original()(player, node); + g_hooking->get_original()(player, node); if (g->spoofing.spoof_crew_data) {