#pragma once #include #include #include #include #include #include #include #ifdef HOOK_GAMEDLL #define private public #define protected public template class MethodThunk { public: void Constructor(TArgs ... args) { new(this) T(args ...); } void Destructor() { (*(T *)this).~T(); } }; namespace MsvcMethod { namespace Detail { using Counter = std::size_t(*)(); template std::size_t GetIndex() { return N; } template constexpr auto GenerateCounters_Helper(std::index_sequence) { // There is no make_array (and/or deduction guides), so we need to explicitly define array template params return std::array { &GetIndex ... }; } template auto counters = GenerateCounters_Helper(std::make_index_sequence{}); struct VIndexGetter {}; struct ThisGetter { decltype(auto) GetThis() const { return this; } decltype(auto) GetThis(...) const { return this; } }; template class Singleton { public: static T &GetInstance() { static T instance = {}; return instance; } }; // primary template template struct is_variadic_function : std::false_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template struct is_variadic_function : std::true_type {}; template constexpr bool is_variadic_function_v = is_variadic_function::value; template constexpr bool is_function_v = std::is_function::value; } // namespace Detail static constexpr auto& counters = Detail::counters<256>; template std::enable_if_t, std::uintptr_t> GetVirtualIndex(TMethod T::*method) { decltype(auto) pcounters = counters.data(); decltype(auto) vIndexGetter = (Detail::VIndexGetter *)&pcounters; using VIndexGetterFunction = std::conditional_t, std::size_t (Detail::VIndexGetter::*)(...) const, std::size_t(Detail::VIndexGetter::*)() const>; VIndexGetterFunction vIndexGetterFunction; { *(std::uintptr_t *)&vIndexGetterFunction = *(std::uintptr_t *)&method; } return (vIndexGetter->*vIndexGetterFunction)(); } template std::enable_if_t, std::uintptr_t> GetVirtualAddress(TMethod T::*method) { using ThisGetterFunction = std::conditional_t, const T *(T::*)(...) const, const T *(T::*)() const>; ThisGetterFunction thisGetterFunction = *(ThisGetterFunction *)&method; { decltype(auto) m = static_cast, const Detail::ThisGetter *(Detail::ThisGetter::*)(...) const, const Detail::ThisGetter *(Detail::ThisGetter::*)() const>>(&Detail::ThisGetter::GetThis); *(std::uintptr_t *)&thisGetterFunction = *(std::uintptr_t *)&m; } return *(*(std::uintptr_t **)(Detail::Singleton::GetInstance().*thisGetterFunction)() + GetVirtualIndex(method)); } template std::enable_if_t, std::uintptr_t> GetVirtualAddressHierarc(TMethod T::*method, void *instance) { using ThisGetterFunction = std::conditional_t, const T *(T::*)(...) const, const T *(T::*)() const>; ThisGetterFunction thisGetterFunction = *(ThisGetterFunction *)&method; { decltype(auto) m = static_cast, const Detail::ThisGetter *(Detail::ThisGetter::*)(...) const, const Detail::ThisGetter *(Detail::ThisGetter::*)() const>>(&Detail::ThisGetter::GetThis); *(std::uintptr_t *)&thisGetterFunction = *(std::uintptr_t *)&m; } return *(*(std::uintptr_t **)(((T *)instance)->*thisGetterFunction)() + GetVirtualIndex(method)); } template std::enable_if_t, std::uintptr_t> GetAddress(TMethod (T::*method)) { return (std::uintptr_t &)method; } template std::enable_if_t, std::uintptr_t> GetAddress(TMethod (*method)) { return (std::uintptr_t &)method; } } // namespace MsvcMethod #ifdef _MSC_VER #define VTABLE_LINK(offset, vtable, count) { offset, vtable, count } #define GLOBALVAR_LINK(offset, symbol, var, ...) { offset, symbol, (size_t)&##var, __VA_ARGS__ } #define HOOK_SYMBOLDEF(offset, symbol, func, ...) { offset, symbol, MsvcMethod::GetAddress<__VA_ARGS__>(&func) } #define HOOK_SYMBOL_VIRTUAL_DEF(offset, symbol, func, ...) { offset, symbol, MsvcMethod::GetVirtualAddress<__VA_ARGS__>(&func) } #define HOOK_SYMBOL_VIRTUAL_HIERARC_DEF(offset, childclass, symbol, func, ...) { offset, symbol, MsvcMethod::GetVirtualAddressHierarc<__VA_ARGS__>(&func, &MsvcMethod::Detail::Singleton::GetInstance()) } #define HOOK_DEF(offset, func, ...) HOOK_SYMBOLDEF(offset, #func, func, __VA_ARGS__) #define HOOK_VIRTUAL_DEF(offset, func, ...) HOOK_SYMBOL_VIRTUAL_DEF(offset, func, func, __VA_ARGS__) #else #error Hooking stuff is only available using MSVC compiler. #endif // _MSC_VER #endif // HOOK_GAMEDLL