1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-13 07:54:13 +01:00
HLMetaModOfficial/core/sourcehook/sourcehook_hookmangen.cpp
2024-08-03 12:15:53 -04:00

108 lines
2.8 KiB
C++

/* ======== SourceHook ========
* Copyright (C) 2004-2010 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): Pavol "PM OnoTo" Marko
* Contributor(s): Borja "faluco" Ferav (many thanks for assitance!)
* David "BAILOPAN" Anderson
* ============================
*/
// recommended literature:
// http://www.cs.umbc.edu/~chang/cs313.s02/stack.shtml
// http://www.angelcode.com/dev/callconv/callconv.html
// http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-1.html
#include <stdio.h>
#include "sourcehook_impl.h"
#include "sourcehook_hookmangen.h"
#if defined( PLATFORM_64BITS ) && !defined( _LINUX )
#include "sourcehook_hookmangen_x86_64.h"
typedef SourceHook::Impl::x64GenContext SHGenContext;
#else
#include "sourcehook_hookmangen_x86.h"
typedef SourceHook::Impl::GenContext SHGenContext;
#endif
#include "sh_memory.h"
#include <stdarg.h> // we might need the address of vsnprintf
#if SH_COMP == SH_COMP_MSVC
# define GCC_ONLY(x)
# define MSVC_ONLY(x) x
#elif SH_COMP == SH_COMP_GCC
# define GCC_ONLY(x) x
# define MSVC_ONLY(x)
#endif
// :TODO: test BIG vtable indices
namespace SourceHook
{
CPageAlloc Asm::GenBuffer::ms_Allocator(16);
namespace Impl
{
// *********************************** class GenContextContainer
CHookManagerAutoGen::CHookManagerAutoGen(ISourceHook *pSHPtr) : m_pSHPtr(pSHPtr) { }
CHookManagerAutoGen::~CHookManagerAutoGen() { }
int CHookManagerAutoGen::GetIfaceVersion()
{
return SH_HOOKMANAUTOGEN_IFACE_VERSION;
}
int CHookManagerAutoGen::GetImplVersion()
{
return SH_HOOKMANAUTOGEN_IMPL_VERSION;
}
HookManagerPubFunc CHookManagerAutoGen::MakeHookMan(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx)
{
#if defined( PLATFORM_64BITS ) && defined( _LINUX )
return nullptr;
#else
CProto mproto(proto);
for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
{
if (iter->m_GenContext->Equal(mproto, vtbl_offs, vtbl_idx))
{
iter->m_RefCnt++;
return iter->m_GenContext->GetPubFunc();
}
}
// Not found yet -> new one
StoredContext sctx;
sctx.m_RefCnt = 1;
sctx.m_GenContext = std::make_unique<SHGenContext>(proto, vtbl_offs, vtbl_idx, m_pSHPtr);
auto pubFunc = sctx.m_GenContext->GetPubFunc();
if (pubFunc != nullptr)
{
m_Contexts.emplace_back(std::move(sctx));
}
return pubFunc;
#endif
}
void CHookManagerAutoGen::ReleaseHookMan(HookManagerPubFunc pubFunc)
{
for (auto iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter)
{
if (iter->m_GenContext->Equal(pubFunc))
{
iter->m_RefCnt--;
if (iter->m_RefCnt == 0)
{
iter = m_Contexts.erase(iter);
}
break;
}
}
}
}
}