CommonLib
Loading...
Searching...
No Matches
HookingUserCall.h File Reference
#include <bit>
#include <optional>
#include <typeindex>
#include <vector>

Go to the source code of this file.

Classes

struct  hedgedev::csl::hook::UserCallInfo

Namespaces

namespace  hedgedev
namespace  hedgedev::csl
namespace  hedgedev::csl::hook

Macros

#define __usercall   0
#define __userpurge   1
#define USER_REGISTER(REGISTER)
#define USER_RETURN_VOID   USER_REGISTER(None)
#define USER_RETURN(REGISTER)
#define USER_PARAM(INDEX, REGISTER)
#define USER_FUNCTION_PTR(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, REGISTERS, PARAM_COUNT, ...)
#define USER_HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, REGISTERS, PARAM_COUNT, ...)
#define STATIC_USER_HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, REGISTERS, PARAM_COUNT, ...)
#define INSTALL_USER_HOOK(FUNCTION_NAME)
#define INSTALL_USER_HOOK_EXPLICIT(FUNCTION_NAME, ADDRESS)
#define UNINSTALL_USER_HOOK(FUNCTION_NAME)

Enumerations

enum class  hedgedev::csl::hook::UserRegister : uint64_t {
  hedgedev::csl::hook::None , hedgedev::csl::hook::EAX , hedgedev::csl::hook::ECX , hedgedev::csl::hook::EDX ,
  hedgedev::csl::hook::EBX , hedgedev::csl::hook::ESP , hedgedev::csl::hook::EBP , hedgedev::csl::hook::ESI ,
  hedgedev::csl::hook::EDI , hedgedev::csl::hook::ST0 , hedgedev::csl::hook::ST1 , hedgedev::csl::hook::ST2 ,
  hedgedev::csl::hook::ST3 , hedgedev::csl::hook::ST4 , hedgedev::csl::hook::ST5 , hedgedev::csl::hook::ST6 ,
  hedgedev::csl::hook::ST7 , hedgedev::csl::hook::XMM0 , hedgedev::csl::hook::XMM1 , hedgedev::csl::hook::XMM2 ,
  hedgedev::csl::hook::XMM3 , hedgedev::csl::hook::XMM4 , hedgedev::csl::hook::XMM5 , hedgedev::csl::hook::XMM6 ,
  hedgedev::csl::hook::XMM7 , hedgedev::csl::hook::Count
}
enum class  hedgedev::csl::hook::Register : uint64_t {
  hedgedev::csl::hook::None , hedgedev::csl::hook::AL = UserRegister::EAX , hedgedev::csl::hook::AX = UserRegister::EAX , hedgedev::csl::hook::EAX = UserRegister::EAX ,
  hedgedev::csl::hook::CL = UserRegister::ECX , hedgedev::csl::hook::CX = UserRegister::ECX , hedgedev::csl::hook::ECX = UserRegister::ECX , hedgedev::csl::hook::DL = UserRegister::EDX ,
  hedgedev::csl::hook::DX = UserRegister::EDX , hedgedev::csl::hook::EDX = UserRegister::EDX , hedgedev::csl::hook::BL = UserRegister::EBX , hedgedev::csl::hook::BX = UserRegister::EBX ,
  hedgedev::csl::hook::EBX = UserRegister::EBX , hedgedev::csl::hook::SPL = UserRegister::ESP , hedgedev::csl::hook::SP = UserRegister::ESP , hedgedev::csl::hook::ESP = UserRegister::ESP ,
  hedgedev::csl::hook::BPL = UserRegister::EBP , hedgedev::csl::hook::BP = UserRegister::EBP , hedgedev::csl::hook::EBP = UserRegister::EBP , hedgedev::csl::hook::SIL = UserRegister::ESI ,
  hedgedev::csl::hook::SI = UserRegister::ESI , hedgedev::csl::hook::ESI = UserRegister::ESI , hedgedev::csl::hook::DIL = UserRegister::EDI , hedgedev::csl::hook::DI = UserRegister::EDI ,
  hedgedev::csl::hook::EDI = UserRegister::EDI , hedgedev::csl::hook::ST0 = UserRegister::ST0 , hedgedev::csl::hook::ST1 = UserRegister::ST1 , hedgedev::csl::hook::ST2 = UserRegister::ST2 ,
  hedgedev::csl::hook::ST3 = UserRegister::ST3 , hedgedev::csl::hook::ST4 = UserRegister::ST4 , hedgedev::csl::hook::ST5 = UserRegister::ST5 , hedgedev::csl::hook::ST6 = UserRegister::ST6 ,
  hedgedev::csl::hook::ST7 = UserRegister::ST7 , hedgedev::csl::hook::XMM0 = UserRegister::XMM0 , hedgedev::csl::hook::XMM1 = UserRegister::XMM1 , hedgedev::csl::hook::XMM2 = UserRegister::XMM2 ,
  hedgedev::csl::hook::XMM3 = UserRegister::XMM3 , hedgedev::csl::hook::XMM4 = UserRegister::XMM4 , hedgedev::csl::hook::XMM5 = UserRegister::XMM5 , hedgedev::csl::hook::XMM6 = UserRegister::XMM6 ,
  hedgedev::csl::hook::XMM7 = UserRegister::XMM7 , hedgedev::csl::hook::Count
}
enum class  hedgedev::csl::hook::UserRegisterFamily : uint64_t { hedgedev::csl::hook::None , hedgedev::csl::hook::GPR = UserRegister::EAX , hedgedev::csl::hook::FPU = UserRegister::ST0 , hedgedev::csl::hook::SSE = UserRegister::XMM0 }

Functions

UserRegisterFamily hedgedev::csl::hook::GetRegisterFamily (UserRegister in_register)
int hedgedev::csl::hook::GetRegisterID (UserRegister in_register)
void * hedgedev::csl::hook::EmitUserTrampoline (const UserCallInfo &in_rInfo, const size_t in_address, bool in_isToOriginal=false)

Macro Definition Documentation

◆ __usercall

#define __usercall   0

A custom calling convention that stores arguments in optimised locations before falling back to using the stack, similar to __fastcall.

This calling convention puts the responsibility of cleaning up stack arguments on the caller.

This identifier cannot be used as a standard calling convention.

◆ __userpurge

#define __userpurge   1

A custom calling convention that stores arguments in optimised locations before falling back to using the stack, similar to __fastcall.

This calling convention puts the responsibility of cleaning up stack arguments on the callee.

This identifier cannot be used as a standard calling convention.

◆ INSTALL_USER_HOOK

#define INSTALL_USER_HOOK ( FUNCTION_NAME)
Value:
INSTALL_USER_HOOK_EXPLICIT(FUNCTION_NAME, info_##FUNCTION_NAME.fpDetour)
#define INSTALL_USER_HOOK_EXPLICIT(FUNCTION_NAME, ADDRESS)
Definition HookingUserCall.h:123

Installs a hook defined with USER_HOOK.

Parameters
FUNCTION_NAMEThe name of the function to call before the original.
Returns
true if the installation succeeeded, or if the hook was already installed. Otherwise, false.

◆ INSTALL_USER_HOOK_EXPLICIT

#define INSTALL_USER_HOOK_EXPLICIT ( FUNCTION_NAME,
ADDRESS )
Value:
std::invoke([&]() \
{ \
const auto& rInfo = info_##FUNCTION_NAME; \
\
if (!rInfo.fpDetour && !(ADDRESS)) \
return false; \
\
*(void**)&rInfo.fpDetour = (void*)(ADDRESS); \
\
DetourTransactionBegin(); \
DetourUpdateThread(GetCurrentThread()); \
DetourAttach((void**)&rInfo.fpDetour, trampolineToHook_##FUNCTION_NAME); \
\
const auto result = DetourTransactionCommit() == NO_ERROR; \
\
*(void**)&original_##FUNCTION_NAME = hedgedev::csl::hook::EmitUserTrampoline(rInfo, size_t(&rInfo.fpDetour), true); \
\
return result; \
})
void * EmitUserTrampoline(const UserCallInfo &in_rInfo, const size_t in_address, bool in_isToOriginal=false)
Definition HookingUserCall.h:411

Installs a hook defined with USER_HOOK at an explicit address.

Parameters
FUNCTION_NAMEThe name of the function to call before the original.
ADDRESSThe address of the function to hook.
Returns
true if the installation succeeeded, or if the hook was already installed. Otherwise, false.

◆ STATIC_USER_HOOK

#define STATIC_USER_HOOK ( RETURN_TYPE,
CALLING_CONVENTION,
FUNCTION_NAME,
ADDRESS,
REGISTERS,
PARAM_COUNT,
... )
Value:
USER_HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, REGISTERS, PARAM_COUNT, __VA_ARGS__); \
__CMNLIB_INTERNAL_STATIC_HOOK_IMPL(FUNCTION_NAME, ADDRESS, INSTALL_USER_HOOK) \
RETURN_TYPE __cdecl impl_##FUNCTION_NAME(__VA_ARGS__)
#define USER_HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, REGISTERS, PARAM_COUNT,...)
Definition HookingUserCall.h:83
#define INSTALL_USER_HOOK(FUNCTION_NAME)
Definition HookingUserCall.h:112

Defines the body of a hook for a function with custom calling convention in memory, and installs it upon initialisation.

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function, such as __usercall or __userpurge.
FUNCTION_NAMEThe name of the function.
ADDRESSThe address of the function.
REGISTERSThe registers used by the return value and parameters.
PARAM_COUNTThe total number of parameters in __VA_ARGS__.
__VA_ARGS__The parameters of the function.

◆ UNINSTALL_USER_HOOK

#define UNINSTALL_USER_HOOK ( FUNCTION_NAME)
Value:
std::invoke([&]() \
{ \
const auto& rInfo = info_##FUNCTION_NAME; \
\
if (rInfo.fpOriginal == rInfo.fpDetour) \
return true; \
\
DetourTransactionBegin(); \
DetourUpdateThread(GetCurrentThread()); \
DetourDetach((void**)&rInfo.fpDetour, trampolineToHook_##FUNCTION_NAME); \
\
return DetourTransactionCommit() == NO_ERROR; \
})

Uninstalls a hook installed with INSTALL_USER_HOOK.

Parameters
FUNCTION_NAMEThe name of the function to unhook.
Returns
true if the uninstallation succeeeded, or if the hook was already uninstalled. Otherwise, false.

◆ USER_FUNCTION_PTR

#define USER_FUNCTION_PTR ( RETURN_TYPE,
CALLING_CONVENTION,
FUNCTION_NAME,
ADDRESS,
REGISTERS,
PARAM_COUNT,
... )
Value:
hedgedev::csl::hook::UserCallInfo info_##FUNCTION_NAME { typeid(RETURN_TYPE), sizeof(RETURN_TYPE), CALLING_CONVENTION, (void*)(ADDRESS), (void*)(ADDRESS), REGISTERS, PARAM_COUNT }; \
void* trampoline_##FUNCTION_NAME = hedgedev::csl::hook::EmitUserTrampoline(info_##FUNCTION_NAME, size_t(&info_##FUNCTION_NAME.fpOriginal), true); \
FUNCTION_PTR(RETURN_TYPE, __cdecl, FUNCTION_NAME, trampoline_##FUNCTION_NAME, __VA_ARGS__)
Definition HookingUserCall.h:299

Declares a pointer to a function with custom calling convention in memory.

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function, such as __usercall or __userpurge.
FUNCTION_NAMEThe name of the function.
ADDRESSThe address of the function.
REGISTERSThe registers used by the return value and parameters.
PARAM_COUNTThe total number of parameters in __VA_ARGS__.
__VA_ARGS__The parameters of the function.

◆ USER_HOOK

#define USER_HOOK ( RETURN_TYPE,
CALLING_CONVENTION,
FUNCTION_NAME,
ADDRESS,
REGISTERS,
PARAM_COUNT,
... )
Value:
hedgedev::csl::hook::UserCallInfo info_##FUNCTION_NAME { typeid(RETURN_TYPE), sizeof(RETURN_TYPE), CALLING_CONVENTION, (void*)(ADDRESS), (void*)(ADDRESS), REGISTERS, PARAM_COUNT }; \
RETURN_TYPE __cdecl impl_##FUNCTION_NAME(__VA_ARGS__); \
void* trampolineToHook_##FUNCTION_NAME = hedgedev::csl::hook::EmitUserTrampoline(info_##FUNCTION_NAME, size_t(&impl_##FUNCTION_NAME)); \
HOOK(RETURN_TYPE, __cdecl, FUNCTION_NAME, nullptr, __VA_ARGS__)

Defines the body of a hook for a function with custom calling convention in memory.

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function, such as __usercall or __userpurge.
FUNCTION_NAMEThe name of the function.
ADDRESSThe address of the function.
REGISTERSThe registers used by the return value and parameters.
PARAM_COUNTThe total number of parameters in __VA_ARGS__.
__VA_ARGS__The parameters of the function.

◆ USER_PARAM

#define USER_PARAM ( INDEX,
REGISTER )
Value:
(USER_REGISTER(REGISTER) << ((INDEX + 1) * hedgedev::csl::hook::g_kUserRegisterSize))
#define USER_REGISTER(REGISTER)
Definition HookingUserCall.h:30

Specify the register to use for a specific parameter.

Parameters
INDEXThe index of the parameter.
REGISTERThe register to use for the parameter.

◆ USER_REGISTER

#define USER_REGISTER ( REGISTER)
Value:
((uint64_t)(hedgedev::csl::hook::UserRegister(hedgedev::csl::hook::Register::REGISTER)))
UserRegister
Definition HookingUserCall.h:175

◆ USER_RETURN

#define USER_RETURN ( REGISTER)
Value:
USER_REGISTER(REGISTER)

Specify the register to use for the return value.

Parameters
REGISTERThe register to use for the return value.

◆ USER_RETURN_VOID

#define USER_RETURN_VOID   USER_REGISTER(None)

Specifies the hook has no return value.