CommonLib
Loading...
Searching...
No Matches
hook_win32.h File Reference
#include <functional>
#include "../thirdparty/Detours/src/detours.h"
#include "host/common.h"
#include "mem/mem.h"
#include "ut/os/preprocessor_win32.h"
#include "hook_usercall_win32.h"

Go to the source code of this file.

Namespaces

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

Macros

#define FUNCTION_PTR(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, ...)
#define DLL_IMPORT_FUNCTION_PTR(RETURN_TYPE, LIBRARY_NAME, FUNCTION_NAME, ...)
#define HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, ...)
#define STATIC_HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, ...)
#define GET_STATIC_HOOK_RESULT(FUNCTION_NAME)
#define THISCALL   __fastcall
#define THISCALL_PARAMS(CLASS_NAME)
 Expands to the necessary function parameters required by __thiscall calling convention.
#define THISCALL_RETURN_PARAMS
 Expands to the necessary function arguments required by __thiscall calling convention for calling the original function.
#define VFTABLE_HOOK(RETURN_TYPE, CALLING_CONVENTION, CLASS_NAME, FUNCTION_NAME, FUNCTION_INDEX, ...)
#define ASM_HOOK(NAME, ADDRESS)
 Creates an assembly hook.
#define STATIC_ASM_HOOK(NAME, ADDRESS)
 Creates an assembly hook, and installs it upon initialisation.
#define ASM_HOOK(NAME, ADDRESS)
 Creates an assembly hook.
#define STATIC_ASM_HOOK(NAME, ADDRESS)
 Creates an assembly hook, and installs it upon initialisation.
#define ASM_HOOK_RETURN(NAME)
 Returns from an assembly hook and executes the original code.
#define ASM_HOOK_BRANCH(NAME)
 Returns from an assembly hook and skips the original code.
#define INSTALL_HOOK(NAME)
#define INSTALL_HOOK_EXPLICIT(NAME, ADDRESS)
#define UNINSTALL_HOOK(NAME)
#define INSTALL_VFTABLE_HOOK(INSTANCE, CLASS_NAME, FUNCTION_NAME)
#define INSTALL_VFTABLE_HOOK_EXPLICIT(INSTANCE, CLASS_NAME, FUNCTION_NAME, FUNCTION_INDEX)
#define UNINSTALL_VFTABLE_HOOK(CLASS_NAME, FUNCTION_NAME)

Functions

void * hedgedev::csl::hook::_get_post_hook_address (void *in_hook)

Macro Definition Documentation

◆ ASM_HOOK [1/2]

#define ASM_HOOK ( NAME,
ADDRESS )

Creates an assembly hook.

Parameters
NAMEThe name of the hook.
ADDRESSThe address to hook.
Note
For x64: The body must be defined in an *.asm file using MASM. This macro creates a scope for members of the hook to be declared in. If no members are needed, close the scope immediately using empty braces.

Examples

x86

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
static uint32_t g_my_hook_member = 0x900DF00D;
__asm
{
mov eax, [g_my_hook_member]
}
ASM_HOOK_BRANCH(my_asm_hook)
}
#define ASM_HOOK_BRANCH(NAME)
Returns from an assembly hook and skips the original code.
Definition hook_win32.h:311
#define ASM_HOOK(NAME, ADDRESS)
Creates an assembly hook.
Definition hook_win32.h:279

x64

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
uint64_t g_my_hook_member = 0x900DF00D;
}

my_asm_hook.asm

include CommonLib.masm.inc
EXTERN g_my_hook_member : QWORD
ASM_HOOK_START my_asm_hook
mov rax, [g_my_hook_member]
ASM_HOOK_BRANCH my_asm_hook
ASM_HOOK_END my_asm_hook
END

◆ ASM_HOOK [2/2]

#define ASM_HOOK ( NAME,
ADDRESS )

Creates an assembly hook.

Parameters
NAMEThe name of the hook.
ADDRESSThe address to hook.
Note
For x64: The body must be defined in an *.asm file using MASM. This macro creates a scope for members of the hook to be declared in. If no members are needed, close the scope immediately using empty braces.

Examples

x86

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
static uint32_t g_my_hook_member = 0x900DF00D;
__asm
{
mov eax, [g_my_hook_member]
}
ASM_HOOK_BRANCH(my_asm_hook)
}

x64

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
uint64_t g_my_hook_member = 0x900DF00D;
}

my_asm_hook.asm

include CommonLib.masm.inc
EXTERN g_my_hook_member : QWORD
ASM_HOOK_START my_asm_hook
mov rax, [g_my_hook_member]
ASM_HOOK_BRANCH my_asm_hook
ASM_HOOK_END my_asm_hook
END

◆ ASM_HOOK_BRANCH

#define ASM_HOOK_BRANCH ( NAME)

Returns from an assembly hook and skips the original code.

Parameters
NAMEThe name of the hook.
Note
For x64: This macro can be accessed in an *.asm file by including CommonLib.masm.inc.

◆ ASM_HOOK_RETURN

#define ASM_HOOK_RETURN ( NAME)

Returns from an assembly hook and executes the original code.

Parameters
NAMEThe name of the hook.
Note
For x64: This macro can be accessed in an *.asm file by including CommonLib.masm.inc.

◆ DLL_IMPORT_FUNCTION_PTR

#define DLL_IMPORT_FUNCTION_PTR ( RETURN_TYPE,
LIBRARY_NAME,
FUNCTION_NAME,
... )
Value:
typedef RETURN_TYPE FUNCTION_NAME##_t(__VA_ARGS__); \
FUNCTION_NAME##_t* FUNCTION_NAME = reinterpret_cast<FUNCTION_NAME##_t*>(DLL_IMPORT_EXPLICIT(LIBRARY_NAME, #FUNCTION_NAME));
#define DLL_IMPORT_EXPLICIT(LIBRARY_NAME, MEMBER_NAME)
Definition preprocessor_win32.h:19

Loads a dynamic link library into memory and declares a pointer to an exported function from it.

Parameters
RETURN_TYPEThe return type of the function.
LIBRARY_NAMEThe name of the dynamic link library.
FUNCTION_NAMEThe name of the exported function.
__VA_ARGS__The parameters of the exported function.

◆ FUNCTION_PTR

#define FUNCTION_PTR ( RETURN_TYPE,
CALLING_CONVENTION,
FUNCTION_NAME,
ADDRESS,
... )
Value:
RETURN_TYPE (CALLING_CONVENTION* FUNCTION_NAME)(__VA_ARGS__) = (RETURN_TYPE (CALLING_CONVENTION*)(__VA_ARGS__))(ADDRESS)

Declares a pointer to a function in memory.

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function (e.g. __cdecl, __stdcall, __fastcall, etc). For custom calling conventions on x86, such as __usercall or __userpurge, see hook_usercall_win32.h.
FUNCTION_NAMEThe name of the function.
ADDRESSThe address of the function.
__VA_ARGS__The parameters of the function.

◆ GET_STATIC_HOOK_RESULT

#define GET_STATIC_HOOK_RESULT ( FUNCTION_NAME)
Value:
g_result_##FUNCTION_NAME

Gets the installation result of a hook defined with STATIC_HOOK, STATIC_USER_HOOK or STATIC_ASM_HOOK.

Parameters
FUNCTION_NAMEThe name of the function that was hooked.
Returns
true if the installation succeeeded. Otherwise, false.

◆ HOOK

#define HOOK ( RETURN_TYPE,
CALLING_CONVENTION,
FUNCTION_NAME,
ADDRESS,
... )
Value:
void* g_address_##FUNCTION_NAME = reinterpret_cast<void*>(ADDRESS); \
void* g_address_post_hook_##FUNCTION_NAME{}; \
typedef RETURN_TYPE CALLING_CONVENTION FUNCTION_NAME(__VA_ARGS__); \
FUNCTION_NAME* original_##FUNCTION_NAME = reinterpret_cast<FUNCTION_NAME*>(g_address_##FUNCTION_NAME); \
RETURN_TYPE CALLING_CONVENTION impl_##FUNCTION_NAME(__VA_ARGS__)

Defines the body of a hook for a function in memory.

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function (e.g. __cdecl, __stdcall, __fastcall, etc). For custom calling conventions on x86, such as __usercall or __userpurge, see hook_usercall_win32.h.
FUNCTION_NAMEThe name of the function.
ADDRESSThe address of the function.
__VA_ARGS__The parameters of the function.

◆ INSTALL_HOOK

#define INSTALL_HOOK ( NAME)
Value:
INSTALL_HOOK_EXPLICIT(NAME, original_##NAME)
#define INSTALL_HOOK_EXPLICIT(NAME, ADDRESS)
Definition hook_win32.h:335

Installs a hook defined with HOOK or ASM_HOOK.

Parameters
NAMEThe name of the hook to install.
Returns
true if the installation succeeeded, or if the hook was already installed. Otherwise, false.

◆ INSTALL_HOOK_EXPLICIT

#define INSTALL_HOOK_EXPLICIT ( NAME,
ADDRESS )
Value:
std::invoke([&]() -> bool \
{ \
if (!original_##NAME && !(ADDRESS)) \
return false; \
\
*reinterpret_cast<void**>(&original_##NAME) = reinterpret_cast<void*>(ADDRESS); \
\
DetourTransactionBegin(); \
DetourUpdateThread(GetCurrentThread()); \
DetourAttach(reinterpret_cast<void**>(&original_##NAME), &impl_##NAME); \
\
const auto result = DetourTransactionCommit() == NO_ERROR; \
\
if (result) \
{ \
g_address_post_hook_##NAME = \
hedgedev::csl::hook::_get_post_hook_address(reinterpret_cast<void*>(g_address_##NAME)); \
} \
\
return result; \
})

Installs a hook defined with HOOK or ASM_HOOK at an explicit address.

Parameters
NAMEThe name of the hook to install.
ADDRESSThe address to install the hook to.
Returns
true if the installation succeeeded, or if the hook was already installed. Otherwise, false.

◆ INSTALL_VFTABLE_HOOK

#define INSTALL_VFTABLE_HOOK ( INSTANCE,
CLASS_NAME,
FUNCTION_NAME )
Value:
INSTALL_VFTABLE_HOOK_EXPLICIT(INSTANCE, CLASS_NAME, FUNCTION_NAME, k_index_of_##CLASS_NAME##_##FUNCTION_NAME)
#define INSTALL_VFTABLE_HOOK_EXPLICIT(INSTANCE, CLASS_NAME, FUNCTION_NAME, FUNCTION_INDEX)
Definition hook_win32.h:405

Installs a hook defined with VFTABLE_HOOK.

Parameters
INSTANCEA pointer to an instance of the class to extract the virtual function table pointer from.
CLASS_NAMEThe name of the class that owns the function being hooked.
FUNCTION_NAMEThe name of the function being hooked.
Returns
true if the installation succeeeded, or if the hook was already installed. Otherwise, false.

◆ INSTALL_VFTABLE_HOOK_EXPLICIT

#define INSTALL_VFTABLE_HOOK_EXPLICIT ( INSTANCE,
CLASS_NAME,
FUNCTION_NAME,
FUNCTION_INDEX )
Value:
std::invoke([&]() -> bool \
{ \
if (original_##CLASS_NAME##_##FUNCTION_NAME) \
return true; \
\
original_##CLASS_NAME##_##FUNCTION_NAME = *reinterpret_cast<CLASS_NAME##_##FUNCTION_NAME***>(INSTANCE)[FUNCTION_INDEX]; \
\
DetourTransactionBegin(); \
DetourUpdateThread(GetCurrentThread()); \
DetourAttach(reinterpret_cast<void**>(&original_##CLASS_NAME##_##FUNCTION_NAME), impl_##CLASS_NAME##_##FUNCTION_NAME); \
\
const auto result = DetourTransactionCommit() == NO_ERROR; \
\
if (result) \
{ \
g_address_post_hook_##CLASS_NAME##_##FUNCTION_NAME = \
hedgedev::csl::hook::_get_post_hook_address(reinterpret_cast<void*>(g_address_##CLASS_NAME##_##FUNCTION_NAME)); \
} \
\
return result; \
})

Installs a hook defined with VFTABLE_HOOK at an explicit index.

Parameters
INSTANCEA pointer to an instance of the class to extract the virtual function table pointer from.
CLASS_NAMEThe name of the class that owns the function being hooked.
FUNCTION_NAMEThe name of the function being hooked.
FUNCTION_INDEXThe index of the function in the virtual function table.
Returns
true if the installation succeeeded, or if the hook was already installed. Otherwise, false.

◆ STATIC_ASM_HOOK [1/2]

#define STATIC_ASM_HOOK ( NAME,
ADDRESS )

Creates an assembly hook, and installs it upon initialisation.

Parameters
NAMEThe name of the hook.
ADDRESSThe address to hook.
Note
For x64: The body must be defined in an *.asm file using MASM. This macro creates a scope for members of the hook to be declared in. If no members are needed, close the scope immediately using empty braces.

Examples

x86

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
static uint32_t g_my_hook_member = 0x900DF00D;
__asm
{
mov eax, [g_my_hook_member]
}
ASM_HOOK_BRANCH(my_asm_hook)
}

x64

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
uint64_t g_my_hook_member = 0x900DF00D;
}

my_asm_hook.asm

include CommonLib.masm.inc
EXTERN g_my_hook_member : QWORD
ASM_HOOK_START my_asm_hook
mov rax, [g_my_hook_member]
ASM_HOOK_BRANCH my_asm_hook
ASM_HOOK_END my_asm_hook
END

◆ STATIC_ASM_HOOK [2/2]

#define STATIC_ASM_HOOK ( NAME,
ADDRESS )

Creates an assembly hook, and installs it upon initialisation.

Parameters
NAMEThe name of the hook.
ADDRESSThe address to hook.
Note
For x64: The body must be defined in an *.asm file using MASM. This macro creates a scope for members of the hook to be declared in. If no members are needed, close the scope immediately using empty braces.

Examples

x86

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
static uint32_t g_my_hook_member = 0x900DF00D;
__asm
{
mov eax, [g_my_hook_member]
}
ASM_HOOK_BRANCH(my_asm_hook)
}

x64

mod.cpp

ASM_HOOK(my_asm_hook, 0xDEADBEEF)
{
uint64_t g_my_hook_member = 0x900DF00D;
}

my_asm_hook.asm

include CommonLib.masm.inc
EXTERN g_my_hook_member : QWORD
ASM_HOOK_START my_asm_hook
mov rax, [g_my_hook_member]
ASM_HOOK_BRANCH my_asm_hook
ASM_HOOK_END my_asm_hook
END

◆ STATIC_HOOK

#define STATIC_HOOK ( RETURN_TYPE,
CALLING_CONVENTION,
FUNCTION_NAME,
ADDRESS,
... )
Value:
HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS, __VA_ARGS__); \
__CMNLIB_INTERNAL_STATIC_HOOK_IMPL(FUNCTION_NAME, ADDRESS, INSTALL_HOOK) \
RETURN_TYPE CALLING_CONVENTION impl_##FUNCTION_NAME(__VA_ARGS__)
#define INSTALL_HOOK(NAME)
Definition hook_win32.h:323
#define HOOK(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS,...)
Definition hook_win32.h:63

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

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function (e.g. __cdecl, __stdcall, __fastcall, etc). For custom calling conventions on x86, such as __usercall or __userpurge, see hook_usercall_win32.h.
FUNCTION_NAMEThe name of the function.
ADDRESSThe address of the function.
__VA_ARGS__The parameters of the function.
Returns
Use GET_STATIC_HOOK_RESULT.

◆ THISCALL

#define THISCALL   __fastcall

An alias for __fastcall.

This is intended for use with the other THISCALL macros to make setting up function pointers and hooks with this calling convention easier.

__thiscall is a calling convention that stores a pointer to this in ECX, before falling back to using the stack, similar to __fastcall.

Note
For x64: This calling convention is always __fastcall regardless, with the class pointer stored in RCX.

◆ THISCALL_PARAMS

#define THISCALL_PARAMS ( CLASS_NAME)

Expands to the necessary function parameters required by __thiscall calling convention.

Parameters
CLASS_NAMEThe name of the class this function is from.
Note
For x86: This macro creates a discard parameter to fill in for EDX, allowing the rest of the arguments to be pushed onto the stack.
For x64: This macro uses standard __fastcall conventions.

Examples

FUNCTION_PTR(int, THISCALL, my_class_function, 0xDEADBEEF, THISCALL_PARAMS(my_class_name), int in_second_param);
#define FUNCTION_PTR(RETURN_TYPE, CALLING_CONVENTION, FUNCTION_NAME, ADDRESS,...)
Definition hook_win32.h:42
#define THISCALL_PARAMS(CLASS_NAME)
Expands to the necessary function parameters required by __thiscall calling convention.
Definition hook_win32.h:152
#define THISCALL
Definition hook_win32.h:107

◆ THISCALL_RETURN_PARAMS

#define THISCALL_RETURN_PARAMS

Expands to the necessary function arguments required by __thiscall calling convention for calling the original function.

Note
For x86: This macro creates a discard parameter to fill in for EDX, allowing the rest of the arguments to be pushed onto the stack.
For x64: This macro uses standard __fastcall conventions.

Examples

HOOK(int, THISCALL, my_class_function_hook, 0xDEADBEEF, THISCALL_PARAMS(my_class_name), int in_second_param)
{
return original_my_class_function_hook(THISCALL_RETURN_PARAMS, in_secondParam);
}
#define THISCALL_RETURN_PARAMS
Expands to the necessary function arguments required by __thiscall calling convention for calling the...
Definition hook_win32.h:153

◆ UNINSTALL_HOOK

#define UNINSTALL_HOOK ( NAME)
Value:
std::invoke([&]() -> bool \
{ \
if (g_address_##NAME == original_##NAME) \
return true; \
\
DetourTransactionBegin(); \
DetourUpdateThread(GetCurrentThread()); \
DetourDetach(reinterpret_cast<void**>(&original_##NAME), &impl_##NAME); \
\
return DetourTransactionCommit() == NO_ERROR; \
})

Uninstalls a hook installed with INSTALL_HOOK.

Parameters
NAMEThe name of the hook to uninstall.
Returns
true if the uninstallation succeeeded, or if the hook was already uninstalled. Otherwise, false.

◆ UNINSTALL_VFTABLE_HOOK

#define UNINSTALL_VFTABLE_HOOK ( CLASS_NAME,
FUNCTION_NAME )
Value:
UNINSTALL_HOOK(CLASS_NAME##_##FUNCTION_NAME)
#define UNINSTALL_HOOK(NAME)
Definition hook_win32.h:366

Uninstalls a hook installed with INSTALL_VFTABLE_HOOK.

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

◆ VFTABLE_HOOK

#define VFTABLE_HOOK ( RETURN_TYPE,
CALLING_CONVENTION,
CLASS_NAME,
FUNCTION_NAME,
FUNCTION_INDEX,
... )
Value:
const size_t k_index_of_##CLASS_NAME##_##FUNCTION_NAME = size_t(FUNCTION_INDEX); \
HOOK(RETURN_TYPE, CALLING_CONVENTION, CLASS_NAME##_##FUNCTION_NAME, nullptr, __VA_ARGS__)

Defines the body of a hook for a function in a virtual function table in memory.

Parameters
RETURN_TYPEThe return type of the function.
CALLING_CONVENTIONThe calling convention of the function (e.g. __cdecl, __stdcall, __fastcall, etc). This does not support optimised calling conventions, such as __usercall or __userpurge.
CLASS_NAMEThe name of the class that contains the function being hooked.
FUNCTION_NAMEThe name of the function.
FUNCTION_INDEXThe index of the function in the virtual function table.
__VA_ARGS__The parameters of the function.