mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2024-12-29 08:05:46 +03:00
adaddda871
Hookers Refactoring Removed __MAKE_VHOOK Fix compilation under linux with ICC 17 (GCC 6.2)
175 lines
6.7 KiB
C++
175 lines
6.7 KiB
C++
#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
|