mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-09 11:28:40 +00:00
Remove CDetour
This commit is contained in:
parent
1c5183dd18
commit
1339f38008
@ -1,147 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id: detourhelpers.h 248 2008-08-27 00:56:22Z pred $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_DETOURHELPERS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_DETOURHELPERS_H_
|
|
||||||
|
|
||||||
#if defined PLATFORM_POSIX
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <amtl/am-bits.h>
|
|
||||||
#include <jit/x86/x86_macros.h>
|
|
||||||
#include <amtl/os/am-system-errors.h>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
struct patch_t
|
|
||||||
{
|
|
||||||
patch_t()
|
|
||||||
{
|
|
||||||
patch[0] = 0;
|
|
||||||
bytes = 0;
|
|
||||||
}
|
|
||||||
unsigned char patch[20];
|
|
||||||
size_t bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void ProtectMemory(void *addr, int length, int prot)
|
|
||||||
{
|
|
||||||
char error[256];
|
|
||||||
#if defined PLATFORM_POSIX
|
|
||||||
long pageSize = sysconf(_SC_PAGESIZE);
|
|
||||||
void *startPage = ke::AlignedBase(addr, pageSize);
|
|
||||||
void *endPage = ke::AlignedBase((void *)((intptr_t)addr + length), pageSize);
|
|
||||||
if (mprotect(startPage, ((intptr_t)endPage - (intptr_t)startPage) + pageSize, prot) == -1) {
|
|
||||||
ke::FormatSystemError(error, sizeof(error));
|
|
||||||
fprintf(stderr, "mprotect: %s\n", error);
|
|
||||||
}
|
|
||||||
#elif defined PLATFORM_WINDOWS
|
|
||||||
DWORD old_prot;
|
|
||||||
if (!VirtualProtect(addr, length, prot, &old_prot)) {
|
|
||||||
ke::FormatSystemError(error, sizeof(error));
|
|
||||||
fprintf(stderr, "VirtualProtect: %s\n", error);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SetMemPatchable(void *address, size_t size)
|
|
||||||
{
|
|
||||||
ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void PatchRelJump32(unsigned char *target, void *callback)
|
|
||||||
{
|
|
||||||
SetMemPatchable(target, 5);
|
|
||||||
|
|
||||||
// jmp <32-bit displacement>
|
|
||||||
target[0] = IA32_JMP_IMM32;
|
|
||||||
*(int32_t *)(&target[1]) = int32_t((unsigned char *)callback - (target + 5));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void PatchAbsJump64(unsigned char *target, void *callback)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
SetMemPatchable(target, 14);
|
|
||||||
|
|
||||||
// push <lower 32-bits> ; allocates 64-bit stack space on x64
|
|
||||||
// mov [rsp+4], <upper 32-bits> ; unnecessary if upper bits are 0
|
|
||||||
// ret ; jump to address on stack
|
|
||||||
target[i++] = IA32_PUSH_IMM32;
|
|
||||||
*(int32_t *)(&target[i]) = int32_t(int64_t(callback));
|
|
||||||
i += 4;
|
|
||||||
if ((int64_t(callback) >> 32) != 0)
|
|
||||||
{
|
|
||||||
target[i++] = IA32_MOV_RM_IMM32;
|
|
||||||
target[i++] = ia32_modrm(MOD_DISP8, 0, kREG_SIB);
|
|
||||||
target[i++] = ia32_sib(NOSCALE, kREG_NOIDX, kREG_ESP);
|
|
||||||
target[i++] = 0x04;
|
|
||||||
*(int32_t *)(&target[i]) = (int64_t(callback) >> 32);
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
target[i] = IA32_RET;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void DoGatePatch(unsigned char *target, void *callback)
|
|
||||||
{
|
|
||||||
#if defined(_WIN64) || defined(__x86_64__)
|
|
||||||
int64_t diff = int64_t(callback) - (int64_t(target) + 5);
|
|
||||||
int32_t upperBits = (diff >> 32);
|
|
||||||
if (upperBits == 0 || upperBits == -1)
|
|
||||||
PatchRelJump32(target, callback);
|
|
||||||
else
|
|
||||||
PatchAbsJump64(target, callback);
|
|
||||||
#else
|
|
||||||
PatchRelJump32(target, callback);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore)
|
|
||||||
{
|
|
||||||
unsigned char *addr = (unsigned char *)address + offset;
|
|
||||||
SetMemPatchable(addr, patch->bytes);
|
|
||||||
|
|
||||||
if (restore)
|
|
||||||
{
|
|
||||||
for (size_t i=0; i<patch->bytes; i++)
|
|
||||||
{
|
|
||||||
restore->patch[i] = addr[i];
|
|
||||||
}
|
|
||||||
restore->bytes = patch->bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0; i<patch->bytes; i++)
|
|
||||||
{
|
|
||||||
addr[i] = patch->patch[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_DETOURHELPERS_H_
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
#include "detours.h"
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
ISourcePawnEngine *CDetourManager::spengine = NULL;
|
|
||||||
IGameConfig *CDetourManager::gameconf = NULL;
|
|
||||||
|
|
||||||
void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
|
|
||||||
{
|
|
||||||
CDetourManager::spengine = spengine;
|
|
||||||
CDetourManager::gameconf = gameconf;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame)
|
|
||||||
{
|
|
||||||
void* pAddress;
|
|
||||||
if (!gameconf->GetMemSig(signame, &pAddress))
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "Signature for %s not found in gamedata", signame);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pAddress)
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "Sigscan for %s failed", signame);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateDetour(callbackfunction, trampoline, pAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
CDetour *CDetourManager::CreateDetour(void *callbackFunction, void **trampoline, void *pAddress)
|
|
||||||
{
|
|
||||||
CDetour* detour = new CDetour(callbackFunction, trampoline, pAddress);
|
|
||||||
|
|
||||||
auto result = safetyhook::InlineHook::create(pAddress, callbackFunction, safetyhook::InlineHook::Flags::StartDisabled);
|
|
||||||
if(result)
|
|
||||||
{
|
|
||||||
detour->m_hook = std::move(result.value());
|
|
||||||
*trampoline = detour->m_hook.original<void*>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto err = result.error();
|
|
||||||
switch(err.type)
|
|
||||||
{
|
|
||||||
case safetyhook::InlineHook::Error::BAD_ALLOCATION:
|
|
||||||
if(err.allocator_error == safetyhook::Allocator::Error::BAD_VIRTUAL_ALLOC)
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "BAD_VIRTUAL_ALLOC hook %p", pAddress);
|
|
||||||
}
|
|
||||||
else if(err.allocator_error == safetyhook::Allocator::Error::NO_MEMORY_IN_RANGE)
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "NO_MEMORY_IN_RANGE hook %p", pAddress);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "BAD_ALLOCATION hook %p errnum %i", pAddress, err.allocator_error);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case safetyhook::InlineHook::Error::FAILED_TO_DECODE_INSTRUCTION:
|
|
||||||
g_pSM->LogError(myself, "FAILED_TO_DECODE_INSTRUCTION hook %p ip %p", pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
case safetyhook::InlineHook::Error::SHORT_JUMP_IN_TRAMPOLINE:
|
|
||||||
g_pSM->LogError(myself, "SHORT_JUMP_IN_TRAMPOLINE hook %p ip %p", pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
case safetyhook::InlineHook::Error::IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE:
|
|
||||||
g_pSM->LogError(myself, "IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE hook %p ip %p", pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
case safetyhook::InlineHook::Error::UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE:
|
|
||||||
g_pSM->LogError(myself, "UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE hook %p ip %p", pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
case safetyhook::InlineHook::Error::FAILED_TO_UNPROTECT:
|
|
||||||
g_pSM->LogError(myself, "FAILED_TO_UNPROTECT hook %p ip %p", pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
case safetyhook::InlineHook::Error::NOT_ENOUGH_SPACE:
|
|
||||||
g_pSM->LogError(myself, "NOT_ENOUGH_SPACE hook %p ip %p", pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_pSM->LogError(myself, "Unknown error %i hook %p ip %p", err.type, pAddress, err.ip);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete detour;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return detour;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDetour::CDetour(void* callbackFunction, void **trampoline, void *pAddress)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDetour::IsEnabled()
|
|
||||||
{
|
|
||||||
return m_hook.enabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDetour::EnableDetour()
|
|
||||||
{
|
|
||||||
m_hook.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDetour::DisableDetour()
|
|
||||||
{
|
|
||||||
m_hook.disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDetour::Destroy()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
@ -1,273 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_DETOURS_H_
|
|
||||||
|
|
||||||
#include "safetyhook.hpp"
|
|
||||||
#include <smsdk_ext.h>
|
|
||||||
|
|
||||||
#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual)
|
|
||||||
#define DETOUR_STATIC_CALL(name) (name##_Actual)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC0(name, ret) \
|
|
||||||
ret (*name##_Actual)(void) = NULL; \
|
|
||||||
ret name(void)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC1(name, ret, p1type, p1name) \
|
|
||||||
ret (*name##_Actual)(p1type) = NULL; \
|
|
||||||
ret name(p1type p1name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC2(name, ret, p1type, p1name, p2type, p2name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type, p3type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC5(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC6(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC7(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_STATIC8(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name) \
|
|
||||||
ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type) = NULL; \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER0(name, ret) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(); \
|
|
||||||
static ret (name##Class::* name##_Actual)(void); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(void) = NULL; \
|
|
||||||
ret name##Class::name()
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER1(name, ret, p1type, p1name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER2(name, ret, p1type, p1name, p2type, p2name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER5(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER6(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER7(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name)
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER8(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name)
|
|
||||||
|
|
||||||
|
|
||||||
#define GET_MEMBER_CALLBACK(name) (void *)GetCodeAddress(&name##Class::name)
|
|
||||||
#define GET_MEMBER_TRAMPOLINE(name) (void **)(&name##Class::name##_Actual)
|
|
||||||
|
|
||||||
#define GET_STATIC_CALLBACK(name) (void *)&name
|
|
||||||
#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual
|
|
||||||
|
|
||||||
#define DETOUR_CREATE_MEMBER(name, gamedata) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata);
|
|
||||||
#define DETOUR_CREATE_STATIC(name, gamedata) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata);
|
|
||||||
|
|
||||||
|
|
||||||
class GenericClass {};
|
|
||||||
typedef void (GenericClass::*VoidFunc)();
|
|
||||||
|
|
||||||
inline void *GetCodeAddr(VoidFunc mfp)
|
|
||||||
{
|
|
||||||
return *(void **)&mfp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a member function pointer to a void pointer.
|
|
||||||
* This relies on the assumption that the code address lies at mfp+0
|
|
||||||
* This is the case for both g++ and later MSVC versions on non virtual functions but may be different for other compilers
|
|
||||||
* Based on research by Don Clugston : http://www.codeproject.com/cpp/FastDelegate.asp
|
|
||||||
*/
|
|
||||||
#define GetCodeAddress(mfp) GetCodeAddr(reinterpret_cast<VoidFunc>(mfp))
|
|
||||||
|
|
||||||
class CDetourManager;
|
|
||||||
|
|
||||||
class CDetour
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool IsEnabled();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These would be somewhat self-explanatory I hope
|
|
||||||
*/
|
|
||||||
void EnableDetour();
|
|
||||||
void DisableDetour();
|
|
||||||
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
friend class CDetourManager;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CDetour(void*callbackfunction, void **trampoline, void *pAddress);
|
|
||||||
private:
|
|
||||||
SafetyHookInline m_hook{};
|
|
||||||
};
|
|
||||||
|
|
||||||
class CDetourManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static void Init(ISourcePawnEngine *spengine, IGameConfig *gameconf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new detour
|
|
||||||
*
|
|
||||||
* @param callbackfunction Void pointer to your detour callback function.
|
|
||||||
* @param trampoline Address of the trampoline pointer
|
|
||||||
* @param signame Section name containing a signature to fetch from the gamedata file.
|
|
||||||
* @return A new CDetour pointer to control your detour.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int)
|
|
||||||
*
|
|
||||||
* Define a new class with the required function and a member function pointer to the same type:
|
|
||||||
*
|
|
||||||
* class CBaseServerDetour
|
|
||||||
* {
|
|
||||||
* public:
|
|
||||||
* bool ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int);
|
|
||||||
* static bool (CBaseServerDetour::* ConnectClient_Actual)(void *netaddr_s, int, int, int, char const*, char const*, char const*, int);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* void *callbackfunc = GetCodeAddress(&CBaseServerDetour::ConnectClient);
|
|
||||||
* void **trampoline = (void **)(&CBaseServerDetour::ConnectClient_Actual);
|
|
||||||
*
|
|
||||||
* Creation:
|
|
||||||
* CDetourManager::CreateDetour(callbackfunc, trampoline, "ConnectClient");
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
*
|
|
||||||
* CBaseServerDetour::ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int)
|
|
||||||
* {
|
|
||||||
* //pre hook code
|
|
||||||
* bool result = (this->*ConnectClient_Actual)(netaddr_s, rest of params);
|
|
||||||
* //post hook code
|
|
||||||
* return result;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* Note we changed the netadr_s reference into a void* to avoid needing to define the type
|
|
||||||
*/
|
|
||||||
static CDetour *CreateDetour(void *callbackFunction, void **trampoline, const char *signame);
|
|
||||||
static CDetour *CreateDetour(void *callbackFunction, void **trampoline, void *pAddress);
|
|
||||||
|
|
||||||
friend class CDetour;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static ISourcePawnEngine *spengine;
|
|
||||||
static IGameConfig *gameconf;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_DETOURS_H_
|
|
||||||
Loading…
Reference in New Issue
Block a user