From 11fcbf207d826297acc49d4e0ae53f024ccb7e7b Mon Sep 17 00:00:00 2001 From: "Tessio.cpp" <50866332+Tessio@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:01:21 -0600 Subject: [PATCH] Fix(core): Unload crash fixes and unload button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - main.cpp: fixed destruction order (ScriptMgr→NativeHooks→FiberPool→Hooking) - AnticheatBypass.cpp: prevent duplicate hooks with s_HooksInitialized - Hooking.cpp: improved cleanup process - DetourHook.hpp: use MH_RemoveHook in destructor - NativeHooks.cpp: clear registered programs and hooks - ScriptMgr.cpp: add 100ms delay for clean script shutdown - Settings.cpp: add unload button in Hotkeys category --- src/core/backend/ScriptMgr.cpp | 3 +++ src/core/hooking/DetourHook.hpp | 5 ++++- src/core/hooking/Hooking.cpp | 2 +- src/game/backend/AnticheatBypass.cpp | 8 +++++++- src/game/backend/NativeHooks.cpp | 5 +++++ src/game/features/settings/UnloadMenu.cpp | 19 +++++++++++++++++++ src/game/frontend/submenus/Settings.cpp | 3 ++- src/main.cpp | 7 ++++++- 8 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/game/features/settings/UnloadMenu.cpp diff --git a/src/core/backend/ScriptMgr.cpp b/src/core/backend/ScriptMgr.cpp index e663bf3b..eb109d4a 100644 --- a/src/core/backend/ScriptMgr.cpp +++ b/src/core/backend/ScriptMgr.cpp @@ -54,6 +54,9 @@ namespace YimMenu void ScriptMgr::DestroyImpl() { std::lock_guard lock(m_Mutex); + + std::this_thread::sleep_for(100ms); + m_Scripts.clear(); } diff --git a/src/core/hooking/DetourHook.hpp b/src/core/hooking/DetourHook.hpp index 178875a5..fcccfa2d 100644 --- a/src/core/hooking/DetourHook.hpp +++ b/src/core/hooking/DetourHook.hpp @@ -50,7 +50,10 @@ namespace YimMenu template inline DetourHook::~DetourHook() { - DisableNow(); + if (m_OriginalFunc) + { + MH_RemoveHook(m_TargetFunc); + } } template diff --git a/src/core/hooking/Hooking.cpp b/src/core/hooking/Hooking.cpp index f1967fd5..f2d0a21c 100644 --- a/src/core/hooking/Hooking.cpp +++ b/src/core/hooking/Hooking.cpp @@ -79,7 +79,7 @@ namespace YimMenu { BaseHook::DisableAll(); m_MinHook.ApplyQueued(); - + for (auto it : BaseHook::Hooks()) { delete it; diff --git a/src/game/backend/AnticheatBypass.cpp b/src/game/backend/AnticheatBypass.cpp index c2267900..d545a9cc 100644 --- a/src/game/backend/AnticheatBypass.cpp +++ b/src/game/backend/AnticheatBypass.cpp @@ -13,6 +13,8 @@ using FnBattlEyeBypass = bool (*)(); namespace YimMenu { + static bool HooksInitialized = false; + static bool CheckForFSL() { int num_versions = 0; @@ -50,7 +52,11 @@ namespace YimMenu void AnticheatBypass::RunScriptImpl() { - NativeHooks::AddHook("shop_controller"_J, NativeIndex::NET_GAMESERVER_BEGIN_SERVICE, &TransactionHook); + if (!HooksInitialized) + { + NativeHooks::AddHook("shop_controller"_J, NativeIndex::NET_GAMESERVER_BEGIN_SERVICE, &TransactionHook); + HooksInitialized = true; + } m_IsFSLLoaded = CheckForFSL(); m_BattlEyeRunning = (NETWORK::_NETWORK_GET_GAME_RESTART_REASON() == 0 && GetModuleHandleA("BEClient_x64.dll")) && !m_IsFSLLoaded; diff --git a/src/game/backend/NativeHooks.cpp b/src/game/backend/NativeHooks.cpp index b9944fe3..3d363ca9 100644 --- a/src/game/backend/NativeHooks.cpp +++ b/src/game/backend/NativeHooks.cpp @@ -129,6 +129,11 @@ namespace YimMenu void NativeHooks::DestroyImpl() { for (auto& [_, program] : m_RegisteredPrograms) + { program->Cleanup(); + } + m_RegisteredPrograms.clear(); + + m_RegisteredHooks.clear(); } } \ No newline at end of file diff --git a/src/game/features/settings/UnloadMenu.cpp b/src/game/features/settings/UnloadMenu.cpp new file mode 100644 index 00000000..d3aadf3a --- /dev/null +++ b/src/game/features/settings/UnloadMenu.cpp @@ -0,0 +1,19 @@ +#include "core/commands/Command.hpp" +#include "game/backend/Self.hpp" +#include "core/commands/Commands.hpp" + +namespace YimMenu::Features +{ + class UnloadMenu : public Command + { + using Command::Command; + + virtual void OnCall() override + { + Commands::Shutdown(); + g_Running = false; + } + }; + + static UnloadMenu _UnloadMenu{"unloadmenu", "Unload", "Unload YimMenuV2."}; +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Settings.cpp b/src/game/frontend/submenus/Settings.cpp index 8121aa64..99e27a28 100644 --- a/src/game/frontend/submenus/Settings.cpp +++ b/src/game/frontend/submenus/Settings.cpp @@ -20,7 +20,7 @@ namespace YimMenu::Submenus ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); - + // this assumes we can't add new commands in runtime, but a lot of other subsystems assume that too static std::map sortedCommands; static bool commandsSorted = []() { @@ -101,6 +101,7 @@ namespace YimMenu::Submenus chat->AddItem(std::make_shared("clearchat"_J)); + gui->AddItem(std::make_shared("unloadmenu"_J)); game->AddItem(playerEsp); game->AddItem(pedEsp); game->AddItem(objectEsp); diff --git a/src/main.cpp b/src/main.cpp index b4b62659..29c81ff4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -95,14 +95,19 @@ namespace YimMenu } LOG(INFO) << "Unloading"; + + ScriptMgr::Destroy(); + NativeHooks::Destroy(); + FiberPool::Destroy(); - ScriptMgr::Destroy(); + Hooking::Destroy(); CallSiteHook::Destroy(); EARLY_UNLOAD: g_Running = false; + Renderer::Destroy(); LogHelper::Destroy();