Skip to content

Commit c59f2b4

Browse files
authored
Fix Application shutdown (#120)
Previously we used the `red::Main` function, which was changing the hash every few updates, so we changed the offset to `WinMain` in 45d49e0. `WinMain` as a `quick_exit` function, which prevents our hook from catching the return value, and by extension not calling `App::Shutdown` at all.
1 parent ef44371 commit c59f2b4

File tree

8 files changed

+179
-108
lines changed

8 files changed

+179
-108
lines changed

src/dll/App.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
#include "Hooks/ExecuteProcess.hpp"
1212
#include "Hooks/InitScripts.hpp"
1313
#include "Hooks/LoadScripts.hpp"
14-
#include "Hooks/Main_Hooks.hpp"
14+
#include "Hooks/QuickExit.hpp"
1515
#include "Hooks/ValidateScripts.hpp"
16+
#include "Hooks/WinMain.hpp"
1617
#include "Hooks/gsmState_SessionActive.hpp"
1718

1819
namespace
@@ -124,9 +125,10 @@ void App::Destruct()
124125
DetourTransaction transaction;
125126
if (transaction.IsValid())
126127
{
127-
auto success = Hooks::CGameApplication::Detach() && Hooks::Main::Detach() && Hooks::ExecuteProcess::Detach() &&
128-
Hooks::InitScripts::Detach() && Hooks::LoadScripts::Detach() &&
129-
Hooks::ValidateScripts::Detach() && Hooks::AssertionFailed::Detach() &&
128+
auto success = Hooks::WinMain::Detach() && Hooks::QuickExit::Detach() && Hooks::CGameApplication::Detach() &&
129+
Hooks::ExecuteProcess::Detach() && Hooks::InitScripts::Detach() &&
130+
Hooks::LoadScripts::Detach() && Hooks::ValidateScripts::Detach() &&
131+
Hooks::AssertionFailed::Detach() && Hooks::CollectSaveableSystems::Detach() &&
130132
Hooks::gsmState_SessionActive::Detach();
131133
if (success)
132134
{
@@ -222,10 +224,10 @@ bool App::AttachHooks() const
222224
return false;
223225
}
224226

225-
auto success = Hooks::Main::Attach() && Hooks::CGameApplication::Attach() && Hooks::ExecuteProcess::Attach() &&
226-
Hooks::InitScripts::Attach() && Hooks::LoadScripts::Attach() && Hooks::ValidateScripts::Attach() &&
227-
Hooks::AssertionFailed::Attach() && Hooks::CollectSaveableSystems::Attach() &&
228-
Hooks::gsmState_SessionActive::Attach();
227+
auto success = Hooks::WinMain::Attach() && Hooks::QuickExit::Attach() && Hooks::CGameApplication::Attach() &&
228+
Hooks::ExecuteProcess::Attach() && Hooks::InitScripts::Attach() && Hooks::LoadScripts::Attach() &&
229+
Hooks::ValidateScripts::Attach() && Hooks::AssertionFailed::Attach() &&
230+
Hooks::CollectSaveableSystems::Attach() && Hooks::gsmState_SessionActive::Attach();
229231
if (success)
230232
{
231233
return transaction.Commit();

src/dll/Detail/AddressHashes.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
namespace Hashes
55
{
6+
constexpr std::uint32_t WinMain = 240386859ul;
7+
constexpr std::uint32_t QuickExit = 388826167ul;
8+
69
constexpr std::uint32_t AssertionFailed = 4285205681UL;
710

811
constexpr std::uint32_t CBaseEngine_InitScripts = 2875532677UL;
@@ -15,6 +18,5 @@ constexpr std::uint32_t Global_ExecuteProcess = 2203918127UL;
1518
constexpr std::uint32_t GsmState_SessionActive_ReportErrorCode = 2141394294UL;
1619

1720
constexpr std::uint32_t IGameSystem_vtbl = 1854670959UL;
18-
constexpr std::uint32_t Main = 240386859UL;
1921
constexpr std::uint32_t ScriptValidator_Validate = 898639042UL;
2022
} // namespace Hashes

src/dll/Hooks/Main_Hooks.cpp

Lines changed: 0 additions & 92 deletions
This file was deleted.

src/dll/Hooks/Main_Hooks.hpp

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/dll/Hooks/QuickExit.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "QuickExit.hpp"
2+
#include "App.hpp"
3+
#include "Detail/AddressHashes.hpp"
4+
#include "Hook.hpp"
5+
6+
#include <cstdint>
7+
8+
namespace
9+
{
10+
bool isAttached = false;
11+
12+
int WINAPI _QuickExit_fnc(std::int32_t aExitCode);
13+
Hook<decltype(&_QuickExit_fnc)> _QuickExit(Hashes::QuickExit, &_QuickExit_fnc);
14+
15+
int WINAPI _QuickExit_fnc(std::int32_t aExitCode)
16+
{
17+
try
18+
{
19+
auto app = App::Get();
20+
if (app)
21+
{
22+
app->Shutdown();
23+
}
24+
}
25+
catch (const std::exception& e)
26+
{
27+
SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE("An exception occurred while RED4ext was shutting down.\n\n{}",
28+
Utils::Widen(e.what()));
29+
}
30+
catch (...)
31+
{
32+
SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE("An unknown exception occurred while RED4ext was shutting down.");
33+
}
34+
35+
return _QuickExit(aExitCode);
36+
}
37+
} // namespace
38+
39+
bool Hooks::QuickExit::Attach()
40+
{
41+
spdlog::trace("Trying to attach the hook for the 'quick_exit' function at {:#x}...", _QuickExit.GetAddress());
42+
43+
auto result = _QuickExit.Attach();
44+
if (result != NO_ERROR)
45+
{
46+
spdlog::error("Could not attach the hook for the 'quick_exit' function. Detour error code: {}", result);
47+
}
48+
else
49+
{
50+
spdlog::trace("The hook for the 'quick_exit' function was attached");
51+
}
52+
53+
isAttached = result == NO_ERROR;
54+
return isAttached;
55+
}
56+
57+
bool Hooks::QuickExit::Detach()
58+
{
59+
if (!isAttached)
60+
{
61+
return false;
62+
}
63+
64+
spdlog::trace("Trying to detach the hook for the 'quick_exit' function at {:#x}...", _QuickExit.GetAddress());
65+
66+
auto result = _QuickExit.Detach();
67+
if (result != NO_ERROR)
68+
{
69+
spdlog::error("Could not detach the hook for the 'quick_exit' function. Detour error code: {}", result);
70+
}
71+
else
72+
{
73+
spdlog::trace("The hook for the 'quick_exit' function was detached");
74+
}
75+
76+
isAttached = result != NO_ERROR;
77+
return !isAttached;
78+
}

src/dll/Hooks/QuickExit.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
namespace Hooks::QuickExit
4+
{
5+
bool Attach();
6+
bool Detach();
7+
} // namespace Hooks::QuickExit

src/dll/Hooks/WinMain.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "WinMain.hpp"
2+
#include "Addresses.hpp"
3+
#include "App.hpp"
4+
#include "Detail/AddressHashes.hpp"
5+
#include "Hook.hpp"
6+
7+
namespace
8+
{
9+
bool isAttached = false;
10+
11+
int WINAPI WinMain_fnc(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
12+
Hook<decltype(&WinMain_fnc)> _WinMain(Hashes::WinMain, &WinMain_fnc);
13+
14+
int WINAPI WinMain_fnc(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
15+
{
16+
try
17+
{
18+
auto app = App::Get();
19+
app->Startup();
20+
}
21+
catch (const std::exception& e)
22+
{
23+
SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE("An exception occurred while RED4ext was starting up.\n\n{}",
24+
Utils::Widen(e.what()));
25+
}
26+
catch (...)
27+
{
28+
SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE("An unknown exception occurred while RED4ext was starting up.");
29+
}
30+
31+
return _WinMain(hInstance, hPrevInstance, pCmdLine, nCmdShow);
32+
}
33+
} // namespace
34+
35+
bool Hooks::WinMain::Attach()
36+
{
37+
spdlog::trace("Trying to attach the hook for the WinMain function at {:#x}...", _WinMain.GetAddress());
38+
39+
auto result = _WinMain.Attach();
40+
if (result != NO_ERROR)
41+
{
42+
spdlog::error("Could not attach the hook for the WinMain function. Detour error code: {}", result);
43+
}
44+
else
45+
{
46+
spdlog::trace("The hook for the WinMain function was attached");
47+
}
48+
49+
isAttached = result == NO_ERROR;
50+
return isAttached;
51+
}
52+
53+
bool Hooks::WinMain::Detach()
54+
{
55+
if (!isAttached)
56+
{
57+
return false;
58+
}
59+
60+
spdlog::trace("Trying to detach the hook for the WinMain function at {:#x}...", _WinMain.GetAddress());
61+
62+
auto result = _WinMain.Detach();
63+
if (result != NO_ERROR)
64+
{
65+
spdlog::error("Could not detach the hook for the WinMain function. Detour error code: {}", result);
66+
}
67+
else
68+
{
69+
spdlog::trace("The hook for the WinMain function was detached");
70+
}
71+
72+
isAttached = result != NO_ERROR;
73+
return !isAttached;
74+
}

src/dll/Hooks/WinMain.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
namespace Hooks::WinMain
4+
{
5+
bool Attach();
6+
bool Detach();
7+
} // namespace Hooks::WinMain

0 commit comments

Comments
 (0)