sourcemod/public/CDetour/detours.cpp
Benoist e07c120cab
CDetour safetyhook (#2162)
* Add safetyhook, remove libudis86

Co-authored-by: bottiger1 <55270538+bottiger1@users.noreply.github.com>

* Add modified CDetour

Co-authored-by: bottiger1 <55270538+bottiger1@users.noreply.github.com>

* Add CDetour [Safetyhook] to build script

* Re-enable loader/core/corelogic, and fix new C++20 error

* Reenable all extensions (except dhooks)

* Make cstrike compile against new CDetour

* Remove unused variable in sdktools output?

* Make sdktools compile against new cdetour

* Downgrade to C++17

* remove auto

* fix compilation on linux

* Re-enable dhooks

* Re-authorise old compilers

* Fix invalid downgrade of std::optional

* readd libudis86 for dhooks only

---------

Co-authored-by: Kenzzer <kenzzer@users.noreply.github.com>
Co-authored-by: bottiger1 <55270538+bottiger1@users.noreply.github.com>
2024-05-21 01:53:44 +00:00

112 lines
3.2 KiB
C++

#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;
}