109 lines
2.3 KiB
C++
109 lines
2.3 KiB
C++
#pragma once
|
|
|
|
#include "../../../external/kiero/minhook/include/MinHook.h"
|
|
#include <cstdint>
|
|
// @source: popular github minhook instance
|
|
template <typename T>
|
|
class CInlineHookObj
|
|
{
|
|
public:
|
|
/// setup hook and replace function
|
|
/// @returns: true if hook has been successfully created, false otherwise
|
|
bool Add(void* pFunction, void* pDetour)
|
|
{
|
|
if (pFunction == nullptr || pDetour == nullptr)
|
|
return false;
|
|
|
|
pBaseFn = pFunction;
|
|
pReplaceFn = pDetour;
|
|
|
|
if (const MH_STATUS status = MH_CreateHook(pBaseFn, pReplaceFn, &pOriginalFn); status != MH_OK)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!Replace())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// patch memory to jump to our function instead of original
|
|
/// @returns: true if hook has been successfully applied, false otherwise
|
|
bool Replace()
|
|
{
|
|
// check is hook has been created
|
|
if (pBaseFn == nullptr)
|
|
return false;
|
|
|
|
// check that function isn't already hooked
|
|
if (bIsHooked)
|
|
return false;
|
|
|
|
if (const MH_STATUS status = MH_EnableHook(pBaseFn); status != MH_OK)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// switch hook state
|
|
bIsHooked = true;
|
|
return true;
|
|
}
|
|
|
|
/// restore original function call and cleanup hook data
|
|
/// @returns: true if hook has been successfully removed, false otherwise
|
|
bool Remove()
|
|
{
|
|
// restore it at first
|
|
if (!Restore())
|
|
return false;
|
|
|
|
if (const MH_STATUS status = MH_RemoveHook(pBaseFn); status != MH_OK)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// restore patched memory to original function call
|
|
/// @returns: true if hook has been successfully restored, false otherwise
|
|
bool Restore()
|
|
{
|
|
// check that function is hooked
|
|
if (!bIsHooked)
|
|
return false;
|
|
|
|
if (const MH_STATUS status = MH_DisableHook(pBaseFn); status != MH_OK)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// switch hook state
|
|
bIsHooked = false;
|
|
return true;
|
|
}
|
|
|
|
/// @returns: original, unwrapped function that would be called without the hook
|
|
inline T GetOriginal()
|
|
{
|
|
return reinterpret_cast<T>(pOriginalFn);
|
|
}
|
|
|
|
/// @returns: true if hook is applied at the time, false otherwise
|
|
inline bool IsHooked() const
|
|
{
|
|
return bIsHooked;
|
|
}
|
|
|
|
private:
|
|
// current hook state
|
|
bool bIsHooked = false;
|
|
// function base handle
|
|
void* pBaseFn = nullptr;
|
|
// function that being replace the original call
|
|
void* pReplaceFn = nullptr;
|
|
// original function
|
|
void* pOriginalFn = nullptr;
|
|
};
|