44#include " filesystem.hpp"
55#include " utils.hpp"
66#include " core.hpp"
7+ #include " config.hpp"
78
89#include < tier0/dbg.h>
910#include < chrono>
1415#include < scanning/symbolfinder.hpp>
1516#include < detouring/hook.hpp>
1617
17- #if SYSTEM_IS_WINDOWS
18- #if ARCHITECTURE_IS_X86
19- #define GMCOMMON_CALLING_CONVENTION __stdcall
20- #else
21- #define GMCOMMON_CALLING_CONVENTION __fastcall
22- #endif
23- #else
24- #define GMCOMMON_CALLING_CONVENTION
25- #endif
26-
2718namespace Symbols {
28- typedef void (GMCOMMON_CALLING_CONVENTION *HandleFileChange_t)(const std::string& path);
19+ typedef void (GMCOMMON_CALLING_CONVENTION_STD *HandleFileChange_t)(const std::string& path);
2920
3021 std::vector<Symbol> HandleFileChange = {
3122#if ARCHITECTURE_IS_X86
3223 #if SYSTEM_IS_WINDOWS
33- Symbol::FromSignature (" \x55\x8b\xec\x83\xec\x60\x56\x8b\x75\x08\x8d\x45\xd0\x57\ x56\x50\xe8\x2A\x2A\x2A\x00 \x83\xc4\x08\x83\x7d\xe0\x00\x0f\x84\x60\x02 " ),
24+ Symbol::FromSignature (" \x55\x8b\xec\x83\xec\x60\x56\x8b\x75\x08\x8d\x45\xd0\x56\x50\xe8\x2A\x2A\x2A\x2A \x83\xc4\x08\x83\x7d\xe0\x00\x0f\x84 " ),
3425 #elif SYSTEM_IS_LINUX
35- Symbol::FromSignature (" \x55\x89\xe5\x57\x56\x53\x8d\x5d\x98\x83\xec\x7c\x8b\x75\x08\x89\x1c\x24\x89\x74\x24\x04\xe8\x2A\x2A\x2A\x00 \x8b\x45\x98\x83\xec " ),
26+ Symbol::FromSignature (" \x55\x89\xe5\x57\x56\x53\x8d\x5d\x98\x83\xec\x7c\x8b\x75\x08\x89\x1c\x24\x89\x74\x24\x04\xe8\x2A\x2A\x2A\x2A \x8b\x45\x98\x83\xec\x04\x8b\x50\xf4\x85\xd2\x0f\x84 " ),
3627 #endif
3728#elif ARCHITECTURE_IS_X86_64
3829 #if SYSTEM_IS_WINDOWS
39- Symbol::FromSignature (" \x48\x89\x5c\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7c\x24\x20\x55\x48\x8d\x6c\x24\xa9\x48\x81\xec\xb0\x00\x00\x00\x48\x8b\x05\x2A " ),
30+ Symbol::FromSignature (" \x48\x89\x5c\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7c\x24\x20\x55\x48\x8d\x6c\x24\xa9\x48\x81\xec\xb0\x00\x00\x00\x48\x8b\x05\x2A\x2A\x2A\x2A\x48\x33\xc4\x48\x89\x45\x47\x48\x8b\xf9\x48\x8b\xd1\x48\x8d\x4d\xc7\xe8\x2A\x2A\x2A\x2A\x48\x83\x7d\xd7\x00\x0f\x84 " ),
4031 #elif SYSTEM_IS_LINUX
41- Symbol::FromSignature (" \x55\x48\x89\xfe\x48\x89\xe5\x41\x57\x41\x56\x41\x55\x41\x54\x4c\x8d\x65\x80\x53\x48\x89\xfb\x4c\x89\xe7\x48\x83\xec\x68\xe8\x2A " )
32+ Symbol::FromSignature (" \x55\x48\x89\xfe\x48\x89\xe5\x41\x57\x41\x56\x41\x55\x41\x54\x4c\x8d\x65\x80\x53\x48\x89\xfb\x4c\x89\xe7\x48\x83\xec\x68\xe8\x2A\x2A\x2A\x2A\x48\x8b\x45\x80\x48\x83\x78\xe8\x00\x75 " )
4233 #elif SYSTEM_IS_MACOSX
43- Symbol::FromSignature (" \x55\x48\x89\xe5\x53\x48\x81\xec\x88\x00\x00\x00\x48\x89\xfb\x48\x8d\x7d\xc8\x48\x89\xde\xe8\x2A\x2A\x2A\x00 \x8a\x4d\xc8\x89\xc8 " ),
34+ Symbol::FromSignature (" \x55\x48\x89\xe5\x53\x48\x81\xec\x88\x00\x00\x00\x48\x89\xfb\x48\x8d\x7d\xc8\x48\x89\xde\xe8\x2A\x2A\x2A\x2A \x8a\x4d\xc8\x89\xc8\x24\x01\x74 " ),
4435 #endif
4536#endif
4637 };
4738
4839 static SymbolFinder finder;
4940 template <typename T>
50- static inline T ResolveSymbol (SourceSDK::FactoryLoader& loader, const Symbol& symbol) {
51- return reinterpret_cast <T>( finder.Resolve (loader.GetModule (), symbol.name .c_str (), symbol.length ) );
41+ static inline std::vector<T> ResolveSymbol (SourceSDK::FactoryLoader& loader, const Symbol& symbol) {
42+ static_assert (std::is_pointer<T>::value, " T must be a pointer" );
43+
44+ // vector used to catch if signature eventually find more than one function
45+ // I'm still new into signatures, so they may be wrong
46+ std::vector<T> pointers;
47+ void * ptr = nullptr ;
48+ while (ptr = finder.Resolve (loader.GetModule (), symbol.name .c_str (), symbol.length , ptr)) {
49+ pointers.push_back ( reinterpret_cast <T>(ptr) );
50+ ptr = reinterpret_cast <void *>(reinterpret_cast <char *>(ptr) + 1 );
51+ }
52+ return pointers;
5253 }
5354
5455 template <typename T>
55- static inline T ResolveSymbols (SourceSDK::FactoryLoader& loader, const std::vector<Symbol>& symbols) {
56- T ptr = nullptr ;
56+ static inline std::vector<T> ResolveSymbols (SourceSDK::FactoryLoader& loader, const std::vector<Symbol>& symbols) {
5757 for (const auto & symbol : symbols) {
58- ptr = ResolveSymbol<T>(loader, symbol);
59- if (ptr != nullptr )
60- break ;
58+ auto pointers = ResolveSymbol<T>(loader, symbol);
59+ if (!pointers. empty () )
60+ return pointers ;
6161 }
62- return ptr ;
62+ return {} ;
6363 }
6464}
6565
@@ -86,14 +86,22 @@ void WatchdogListener::handleFileAction(efsw::WatchID watchid, const std::string
8686Watchdog::Watchdog (std::shared_ptr<Core> core, std::shared_ptr<Filesystem> fs)
8787 : core(core), fs(fs)
8888{
89+ m_HandleFileChangeHook = std::make_unique<Detouring::Hook>();
8990 SourceSDK::FactoryLoader server_loader (" server" );
90- auto HandleFileChange_original = Symbols::ResolveSymbols<Symbols::HandleFileChange_t>(server_loader, Symbols::HandleFileChange);
91- if (HandleFileChange_original == nullptr )
92- throw std::runtime_error (" Failed to resolve HandleFileChange" );
9391
94- m_HandleFileChangeHook = std::make_unique<Detouring::Hook>((void *)HandleFileChange_original, (void *)HandleFileChange_detour);
95- if (!m_HandleFileChangeHook->Enable ())
96- throw std::runtime_error (" Failed to hook HandleFileChange" );
92+ auto HandleFileChange_pointers = Symbols::ResolveSymbols<Symbols::HandleFileChange_t>(server_loader, Symbols::HandleFileChange);
93+ if (HandleFileChange_pointers.size () == 1 ) {
94+ auto HandleFileChange_original = HandleFileChange_pointers[0 ];
95+ if (m_HandleFileChangeHook->Create ((void *)HandleFileChange_original, (void *)HandleFileChange_detour) && m_HandleFileChangeHook->Enable ()) {
96+ DevMsg (" [Moonloader] HandleFileChange: %p\n " , HandleFileChange_original);
97+ } else {
98+ core->LUA ->ErrorNoHalt (" [Moonloader] Failed to hook HandleFileChange function! Autorefresh won't work properly.\n\t Please, report to " MOONLOADER_URL " /issues\n " );
99+ }
100+ } else if (HandleFileChange_pointers.empty ()) {
101+ core->LUA ->ErrorNoHalt (" [Moonloader] HandleFileChange not found! Autorefresh won't work properly.\n\t Please, report to " MOONLOADER_URL " /issues\n " );
102+ } else {
103+ core->LUA ->ErrorNoHalt (" [Moonloader] Too many functions were found for HandleFileChange signature! Autorefresh won't work properly.\n\t Please, report to " MOONLOADER_URL " /issues\n " );
104+ }
97105}
98106
99107void Watchdog::Start () {
@@ -103,7 +111,6 @@ void Watchdog::Start() {
103111
104112Watchdog::~Watchdog () {
105113 m_HandleFileChangeHook->Disable ();
106- m_HandleFileChangeHook->Destroy ();
107114}
108115
109116void Watchdog::OnFileModified (const std::string& path) {
@@ -189,5 +196,9 @@ void Watchdog::HandleFileChange(const std::string& path) {
189196}
190197
191198void Watchdog::RefreshFile (const std::string& path) {
192- m_HandleFileChangeHook->GetTrampoline <Symbols::HandleFileChange_t>()(path);
199+ if (m_HandleFileChangeHook->IsValid ()) {
200+ m_HandleFileChangeHook->GetTrampoline <Symbols::HandleFileChange_t>()(path);
201+ } else {
202+ // TODO: use lua_refresh_file?
203+ }
193204}
0 commit comments