62 lines
1.8 KiB
C++
62 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
|
|
#include "../../sdk/virtual.hpp"
|
|
|
|
#include <funchook/src/funchook.h>
|
|
|
|
#define HOOK_FUNCTION(hook) hook, #hook
|
|
|
|
inline funchook_t *g_funchookCtx = nullptr;
|
|
inline bool g_isShuttingDown = false;
|
|
|
|
template <typename T>
|
|
class CHook {
|
|
|
|
public:
|
|
std::add_pointer_t<T> m_pOriginal;
|
|
// Template has been used to avoid casts.
|
|
template <typename OriginalT, typename HookT>
|
|
void Hook(OriginalT _pOriginalFn, HookT &pHookFn, const char *szHookName) {
|
|
if (this->m_pOriginal) {
|
|
LOG("%s tried rehooking.\n", szHookName);
|
|
return;
|
|
}
|
|
|
|
void *pOriginalFn = static_cast<void *>(_pOriginalFn);
|
|
if (!pOriginalFn) {
|
|
LOG("%s tried hooking null.\n", szHookName);
|
|
return;
|
|
}
|
|
|
|
this->m_pOriginal =
|
|
reinterpret_cast<decltype(this->m_pOriginal)>(pOriginalFn);
|
|
int rv = funchook_prepare(g_funchookCtx,
|
|
reinterpret_cast<void **>(&this->m_pOriginal),
|
|
reinterpret_cast<void *>(pHookFn));
|
|
|
|
if (rv == FUNCHOOK_ERROR_SUCCESS) {
|
|
LOG("%s hooked successfully. [ %p -> %p ]\n", szHookName,
|
|
pOriginalFn, pHookFn);
|
|
} else {
|
|
this->m_pOriginal = nullptr;
|
|
LOG("%s hook failed. [ %s ]\n", szHookName,
|
|
funchook_error_message(g_funchookCtx));
|
|
}
|
|
}
|
|
|
|
template <typename HookT>
|
|
void HookVirtual(void *pClass, int index, HookT &pHookFn,
|
|
const char *szHookName) {
|
|
this->Hook(vmt::GetVMethod(index, pClass), pHookFn, szHookName);
|
|
}
|
|
|
|
// Shorthand for calling original.
|
|
template <typename... Args>
|
|
auto operator()(Args &&...args) {
|
|
return std::invoke(this->m_pOriginal, std::forward<Args>(args)...);
|
|
}
|
|
|
|
};
|