2010-07-22 05:09:03 +02:00
|
|
|
#include "detours.h"
|
2024-05-21 03:53:44 +02:00
|
|
|
#include <cstdio>
|
2010-07-22 05:09:03 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
void* pAddress;
|
|
|
|
if (!gameconf->GetMemSig(signame, &pAddress))
|
2010-07-22 05:09:03 +02:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
g_pSM->LogError(myself, "Signature for %s not found in gamedata", signame);
|
|
|
|
return NULL;
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
if (!pAddress)
|
2015-01-31 18:44:18 +01:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
g_pSM->LogError(myself, "Sigscan for %s failed", signame);
|
|
|
|
return NULL;
|
2015-01-31 18:44:18 +01:00
|
|
|
}
|
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
return CreateDetour(callbackfunction, trampoline, pAddress);
|
2015-01-31 18:44:18 +01:00
|
|
|
}
|
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
CDetour *CDetourManager::CreateDetour(void *callbackFunction, void **trampoline, void *pAddress)
|
2010-07-22 05:09:03 +02:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
CDetour* detour = new CDetour(callbackFunction, trampoline, pAddress);
|
2010-07-22 05:09:03 +02:00
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
auto result = safetyhook::InlineHook::create(pAddress, callbackFunction, safetyhook::InlineHook::Flags::StartDisabled);
|
|
|
|
if(result)
|
2010-07-22 05:09:03 +02:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
detour->m_hook = std::move(result.value());
|
|
|
|
*trampoline = detour->m_hook.original<void*>();
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
2024-05-21 03:53:44 +02:00
|
|
|
else
|
2015-01-31 18:44:18 +01:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
auto err = result.error();
|
|
|
|
switch(err.type)
|
2020-02-26 01:25:53 +01:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
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;
|
2020-02-26 01:25:53 +01:00
|
|
|
}
|
2024-05-21 03:53:44 +02:00
|
|
|
|
|
|
|
delete detour;
|
|
|
|
return NULL;
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
return detour;
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
CDetour::CDetour(void* callbackFunction, void **trampoline, void *pAddress)
|
2010-07-22 05:09:03 +02:00
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
}
|
2010-07-22 05:09:03 +02:00
|
|
|
|
2024-05-21 03:53:44 +02:00
|
|
|
bool CDetour::IsEnabled()
|
|
|
|
{
|
|
|
|
return m_hook.enabled();
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CDetour::EnableDetour()
|
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
m_hook.enable();
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CDetour::DisableDetour()
|
|
|
|
{
|
2024-05-21 03:53:44 +02:00
|
|
|
m_hook.disable();
|
2010-07-22 05:09:03 +02:00
|
|
|
}
|
2024-05-21 03:53:44 +02:00
|
|
|
|
|
|
|
void CDetour::Destroy()
|
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
}
|