#pragma once #include <iostream> #include <functional> #include <string> #include <memory> #include <vector> #include <array> #include <utility> #ifdef HOOK_GAMEDLL #define private public #define protected public template <typename T, typename ... TArgs> 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 N> std::size_t GetIndex() { return N; } template <std::size_t ... TIndices> constexpr auto GenerateCounters_Helper(std::index_sequence<TIndices ...>) { // There is no make_array (and/or deduction guides), so we need to explicitly define array template params return std::array<Counter, sizeof ... (TIndices)> { &GetIndex<TIndices> ... }; } template<std::size_t N> auto counters = GenerateCounters_Helper(std::make_index_sequence<N>{}); struct VIndexGetter {}; struct ThisGetter { decltype(auto) GetThis() const { return this; } decltype(auto) GetThis(...) const { return this; } }; template <class T> class Singleton { public: static T &GetInstance() { static T instance = {}; return instance; } }; // primary template template<class> struct is_variadic_function : std::false_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...)> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) const> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) volatile> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) const volatile> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) &> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) const &> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) volatile &> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) const volatile &> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) &&> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) const &&> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) volatile &&> : std::true_type {}; template<class R, class ... TArgs> struct is_variadic_function<R (TArgs ..., ...) const volatile &&> : std::true_type {}; template<class T> constexpr bool is_variadic_function_v = is_variadic_function<T>::value; template<class T> constexpr bool is_function_v = std::is_function<T>::value; } // namespace Detail static constexpr auto& counters = Detail::counters<256>; template <typename TMethod, typename T> std::enable_if_t<Detail::is_function_v<TMethod>, std::uintptr_t> GetVirtualIndex(TMethod T::*method) { decltype(auto) pcounters = counters.data(); decltype(auto) vIndexGetter = (Detail::VIndexGetter *)&pcounters; using VIndexGetterFunction = std::conditional_t<Detail::is_variadic_function_v<TMethod>, 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 <typename TMethod, typename T> std::enable_if_t<Detail::is_function_v<TMethod>, std::uintptr_t> GetVirtualAddress(TMethod T::*method) { using ThisGetterFunction = std::conditional_t<Detail::is_variadic_function_v<TMethod>, const T *(T::*)(...) const, const T *(T::*)() const>; ThisGetterFunction thisGetterFunction = *(ThisGetterFunction *)&method; { decltype(auto) m = static_cast<std::conditional_t<Detail::is_variadic_function_v<TMethod>, 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<T>::GetInstance().*thisGetterFunction)() + GetVirtualIndex(method)); } template <typename TMethod, typename T> std::enable_if_t<Detail::is_function_v<TMethod>, std::uintptr_t> GetVirtualAddressHierarc(TMethod T::*method, void *instance) { using ThisGetterFunction = std::conditional_t<Detail::is_variadic_function_v<TMethod>, const T *(T::*)(...) const, const T *(T::*)() const>; ThisGetterFunction thisGetterFunction = *(ThisGetterFunction *)&method; { decltype(auto) m = static_cast<std::conditional_t<Detail::is_variadic_function_v<TMethod>, 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 <typename TMethod, typename T> std::enable_if_t<Detail::is_function_v<TMethod>, std::uintptr_t> GetAddress(TMethod (T::*method)) { return (std::uintptr_t &)method; } template <typename TMethod> std::enable_if_t<Detail::is_function_v<TMethod>, 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<childclass>::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