mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-12-07 10:28:30 +00:00
Added manual hooks. I hope that I haven't broken binary compatibility - someone might want to test it.
--HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40158
This commit is contained in:
parent
20beff0636
commit
8cc68b35fb
File diff suppressed because it is too large
Load Diff
@ -133,6 +133,17 @@ namespace SourceHook
|
|||||||
*/
|
*/
|
||||||
typedef int Plugin;
|
typedef int Plugin;
|
||||||
|
|
||||||
|
struct ProtoInfo
|
||||||
|
{
|
||||||
|
ProtoInfo(int rtsz, int nop, const int *p) : beginningNull(0), retTypeSize(rtsz), numOfParams(nop), params(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
int beginningNull; //!< To distinguish from old protos (which never begin with 0)
|
||||||
|
int retTypeSize; //!< 0 if void
|
||||||
|
int numOfParams; //!< number of parameters
|
||||||
|
const int *params; //!< params[0]=0 (or -1 for vararg), params[1]=size of first param, ...
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Specifies the actions for hook managers
|
* @brief Specifies the actions for hook managers
|
||||||
*/
|
*/
|
||||||
@ -363,6 +374,14 @@ namespace SourceHook
|
|||||||
virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer
|
virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer
|
||||||
virtual void SetOverrideRetPtr(const void *ptr) = 0; //!< Sets the override result pointer
|
virtual void SetOverrideRetPtr(const void *ptr) = 0; //!< Sets the override result pointer
|
||||||
virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit
|
virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug.
|
||||||
|
*
|
||||||
|
* @param plug The owner of the hook manager
|
||||||
|
* @param pubFunc The hook manager's info function
|
||||||
|
*/
|
||||||
|
virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,6 +417,14 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
shptr->ReleaseCallClass(reinterpret_cast<SourceHook::GenericCallClass*>(ptr));
|
shptr->ReleaseCallClass(reinterpret_cast<SourceHook::GenericCallClass*>(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \
|
||||||
|
do { \
|
||||||
|
SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \
|
||||||
|
SH_MFHCls(hookname)::ms_MFI.thisptroffs = pthisptroffs; \
|
||||||
|
SH_MFHCls(hookname)::ms_MFI.vtblindex = pvtblindex; \
|
||||||
|
SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define SH_GET_CALLCLASS(ptr) SH_GET_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
|
#define SH_GET_CALLCLASS(ptr) SH_GET_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
|
||||||
#define SH_RELEASE_CALLCLASS(ptr) SH_RELEASE_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
|
#define SH_RELEASE_CALLCLASS(ptr) SH_RELEASE_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
|
||||||
|
|
||||||
@ -417,6 +444,22 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \
|
#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \
|
||||||
SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||||
|
|
||||||
|
|
||||||
|
#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \
|
||||||
|
__SourceHook_FHMAdd##hookname(reinterpret_cast<void*>(ifaceptr), post, handler)
|
||||||
|
#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \
|
||||||
|
SH_ADD_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler), post)
|
||||||
|
#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \
|
||||||
|
SH_ADD_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||||
|
|
||||||
|
#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \
|
||||||
|
__SourceHook_FHMRemove##hookname(reinterpret_cast<void*>(ifaceptr), post, handler)
|
||||||
|
#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \
|
||||||
|
SH_REMOVE_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler), post)
|
||||||
|
#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \
|
||||||
|
SH_REMOVE_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||||
|
|
||||||
|
|
||||||
#define SH_NOATTRIB
|
#define SH_NOATTRIB
|
||||||
|
|
||||||
|
|
||||||
@ -435,6 +478,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
||||||
|
#define SH_MFHCls(hookname) __SourceHook_MFHCls_##hookname
|
||||||
|
|
||||||
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload)() \
|
SH_FHCls(ifacetype,ifacefunc,overload)() \
|
||||||
@ -452,7 +496,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
\
|
\
|
||||||
if (action == HA_GetInfo) \
|
if (action == HA_GetInfo) \
|
||||||
{ \
|
{ \
|
||||||
param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, ms_Proto); \
|
param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \
|
||||||
|
reinterpret_cast<const char*>(&ms_Proto)); \
|
||||||
\
|
\
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
||||||
@ -483,15 +528,14 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
||||||
static ::SourceHook::MemFuncInfo ms_MFI; \
|
static ::SourceHook::MemFuncInfo ms_MFI; \
|
||||||
static ::SourceHook::IHookManagerInfo *ms_HI; \
|
static ::SourceHook::IHookManagerInfo *ms_HI; \
|
||||||
static const char *ms_Proto; \
|
static ::SourceHook::ProtoInfo ms_Proto; \
|
||||||
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
||||||
|
|
||||||
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, funcptr) \
|
||||||
}; \
|
}; \
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
||||||
::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \
|
::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \
|
||||||
::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
||||||
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
|
||||||
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
||||||
{ \
|
{ \
|
||||||
@ -519,6 +563,77 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \
|
SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
#define SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \
|
||||||
|
struct SH_MFHCls(hookname) \
|
||||||
|
{ \
|
||||||
|
static SH_MFHCls(hookname) ms_Inst; \
|
||||||
|
static ::SourceHook::MemFuncInfo ms_MFI; \
|
||||||
|
static ::SourceHook::IHookManagerInfo *ms_HI; \
|
||||||
|
static ::SourceHook::ProtoInfo ms_Proto; \
|
||||||
|
\
|
||||||
|
SH_MFHCls(hookname)() \
|
||||||
|
{ \
|
||||||
|
ms_MFI.isVirtual = true; \
|
||||||
|
ms_MFI.thisptroffs = pthisptroffs; \
|
||||||
|
ms_MFI.vtblindex = pvtblidx; \
|
||||||
|
ms_MFI.vtbloffs = pvtbloffs; \
|
||||||
|
} \
|
||||||
|
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \
|
||||||
|
{ \
|
||||||
|
using namespace ::SourceHook; \
|
||||||
|
/* we don't set ms_MFI here because manual hookmans can be reconfigured */ \
|
||||||
|
/* :FIXME: possible problem: someone adding a hook from a constructor of a global entity */ \
|
||||||
|
/* which is construced before SH_MFHCls(hookname)() gets called? */ \
|
||||||
|
/* Verify interface version */ \
|
||||||
|
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
if (action == HA_GetInfo) \
|
||||||
|
{ \
|
||||||
|
param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, \
|
||||||
|
reinterpret_cast<const char*>(&ms_Proto)); \
|
||||||
|
\
|
||||||
|
MemFuncInfo mfi; \
|
||||||
|
GetFuncInfo(&SH_MFHCls(hookname)::Func, mfi); \
|
||||||
|
param->SetHookfuncVfnptr( \
|
||||||
|
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
else if (action == HA_Register) \
|
||||||
|
{ \
|
||||||
|
ms_HI = param; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
else if (action == HA_Unregister) \
|
||||||
|
{ \
|
||||||
|
ms_HI = NULL; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \
|
||||||
|
}; \
|
||||||
|
SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \
|
||||||
|
::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \
|
||||||
|
::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \
|
||||||
|
bool __SourceHook_FHMAdd##hookname(void *iface, bool post, \
|
||||||
|
SH_MFHCls(hookname)::FD handler) \
|
||||||
|
{ \
|
||||||
|
return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \
|
||||||
|
SH_MFHCls(hookname)::HookManPubFunc, \
|
||||||
|
new ::SourceHook::CSHDelegate<SH_MFHCls(hookname)::FD>(handler), post); \
|
||||||
|
} \
|
||||||
|
bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \
|
||||||
|
SH_MFHCls(hookname)::FD handler) \
|
||||||
|
{ \
|
||||||
|
::SourceHook::CSHDelegate<SH_MFHCls(hookname)::FD> tmp(handler); \
|
||||||
|
return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \
|
||||||
|
SH_MFHCls(hookname)::HookManPubFunc, &tmp, post); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
#define SH_SETUPCALLS(rettype, paramtypes, params) \
|
#define SH_SETUPCALLS(rettype, paramtypes, params) \
|
||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
@ -580,7 +695,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params) \
|
#define SH_CALL_ORIG(rettype, paramtypes, params) \
|
||||||
if (status != MRES_SUPERCEDE) \
|
if (status != MRES_SUPERCEDE) \
|
||||||
{ \
|
{ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
@ -594,10 +709,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
SH_GLOB_SHPTR->HookLoopEnd(); \
|
SH_GLOB_SHPTR->HookLoopEnd(); \
|
||||||
return status >= MRES_OVERRIDE ? override_ret : orig_ret;
|
return status >= MRES_OVERRIDE ? override_ret : orig_ret;
|
||||||
|
|
||||||
#define SH_HANDLEFUNC(ifacetype, ifacefunc, paramtypes, params, rettype) \
|
#define SH_HANDLEFUNC(paramtypes, params, rettype) \
|
||||||
SH_SETUPCALLS(rettype, paramtypes, params) \
|
SH_SETUPCALLS(rettype, paramtypes, params) \
|
||||||
SH_CALL_HOOKS(pre, params) \
|
SH_CALL_HOOKS(pre, params) \
|
||||||
SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params) \
|
SH_CALL_ORIG(rettype, paramtypes, params) \
|
||||||
SH_CALL_HOOKS(post, params) \
|
SH_CALL_HOOKS(post, params) \
|
||||||
SH_RETURN()
|
SH_RETURN()
|
||||||
|
|
||||||
@ -656,7 +771,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params) \
|
#define SH_CALL_ORIG_void(paramtypes, params) \
|
||||||
if (status != MRES_SUPERCEDE) \
|
if (status != MRES_SUPERCEDE) \
|
||||||
{ \
|
{ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
@ -667,26 +782,26 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
#define SH_RETURN_void() \
|
#define SH_RETURN_void() \
|
||||||
SH_GLOB_SHPTR->HookLoopEnd();
|
SH_GLOB_SHPTR->HookLoopEnd();
|
||||||
|
|
||||||
#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, paramtypes, params) \
|
#define SH_HANDLEFUNC_void(paramtypes, params) \
|
||||||
SH_SETUPCALLS_void(paramtypes, params) \
|
SH_SETUPCALLS_void(paramtypes, params) \
|
||||||
SH_CALL_HOOKS_void(pre, params) \
|
SH_CALL_HOOKS_void(pre, params) \
|
||||||
SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params) \
|
SH_CALL_ORIG_void(paramtypes, params) \
|
||||||
SH_CALL_HOOKS_void(post, params) \
|
SH_CALL_HOOKS_void(post, params) \
|
||||||
SH_RETURN_void()
|
SH_RETURN_void()
|
||||||
|
|
||||||
|
|
||||||
// Special vafmt handlers
|
// Special vafmt handlers
|
||||||
#define SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, paramtypes, params_orig, params_plug, rettype) \
|
#define SH_HANDLEFUNC_vafmt(paramtypes, params_orig, params_plug, rettype) \
|
||||||
SH_SETUPCALLS(rettype, paramtypes, params_orig) \
|
SH_SETUPCALLS(rettype, paramtypes, params_orig) \
|
||||||
SH_CALL_HOOKS(pre, params_plug) \
|
SH_CALL_HOOKS(pre, params_plug) \
|
||||||
SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params_orig) \
|
SH_CALL_ORIG(rettype, paramtypes, params_orig) \
|
||||||
SH_CALL_HOOKS(post, params_plug) \
|
SH_CALL_HOOKS(post, params_plug) \
|
||||||
SH_RETURN()
|
SH_RETURN()
|
||||||
|
|
||||||
#define SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, paramtypes, params_orig, params_plug) \
|
#define SH_HANDLEFUNC_void_vafmt(paramtypes, params_orig, params_plug) \
|
||||||
SH_SETUPCALLS_void(paramtypes, params_orig) \
|
SH_SETUPCALLS_void(paramtypes, params_orig) \
|
||||||
SH_CALL_HOOKS_void(pre, params_plug) \
|
SH_CALL_HOOKS_void(pre, params_plug) \
|
||||||
SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params_orig) \
|
SH_CALL_ORIG_void(paramtypes, params_orig) \
|
||||||
SH_CALL_HOOKS_void(post, params_plug) \
|
SH_CALL_HOOKS_void(post, params_plug) \
|
||||||
SH_RETURN_void()
|
SH_RETURN_void()
|
||||||
|
|
||||||
@ -699,18 +814,27 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
(&ifacetype::ifacefunc))) \
|
(&ifacetype::ifacefunc))) \
|
||||||
typedef fastdelegate::FastDelegate@$@<@param%%|, @@, @rettype> FD; \
|
typedef fastdelegate::FastDelegate@$@<@param%%|, @@, @rettype> FD; \
|
||||||
virtual rettype Func(@param%% p%%|, @) \
|
virtual rettype Func(@param%% p%%|, @) \
|
||||||
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (@param%%|, @), (@p%%|, @), rettype); } \
|
{ SH_HANDLEFUNC((@param%%|, @), (@p%%|, @), rettype); } \
|
||||||
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype @"|" #param%%| @, \
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \
|
||||||
(static_cast<rettype (ifacetype::*)(@param%%|, @) attr>(&ifacetype::ifacefunc)))
|
(static_cast<rettype (ifacetype::*)(@param%%|, @) attr>(&ifacetype::ifacefunc))) \
|
||||||
|
\
|
||||||
|
const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0@, sizeof(param%%)@ }; \
|
||||||
|
::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \
|
||||||
|
@$@, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload);
|
||||||
|
|
||||||
#define SH_DECL_HOOK@$@_void(ifacetype, ifacefunc, attr, overload@, param%%@) \
|
#define SH_DECL_HOOK@$@_void(ifacetype, ifacefunc, attr, overload@, param%%@) \
|
||||||
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(@param%%|, @) attr> \
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(@param%%|, @) attr> \
|
||||||
(&ifacetype::ifacefunc))) \
|
(&ifacetype::ifacefunc))) \
|
||||||
typedef fastdelegate::FastDelegate@$@<@param%%|, @> FD; \
|
typedef fastdelegate::FastDelegate@$@<@param%%|, @> FD; \
|
||||||
virtual void Func(@param%% p%%|, @) \
|
virtual void Func(@param%% p%%|, @) \
|
||||||
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (@param%%|, @), (@p%%|, @)); } \
|
{ SH_HANDLEFUNC_void((@param%%|, @), (@p%%|, @)); } \
|
||||||
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr @"|" #param%%| @, \
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \
|
||||||
(static_cast<void (ifacetype::*)(@param%%|, @) attr>(&ifacetype::ifacefunc)))
|
(static_cast<void (ifacetype::*)(@param%%|, @) attr>(&ifacetype::ifacefunc))) \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { 0@, sizeof(param%%)@ }; \
|
||||||
|
::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \
|
||||||
|
@$@, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload);
|
||||||
|
|
||||||
#define SH_DECL_HOOK@$@_vafmt(ifacetype, ifacefunc, attr, overload, rettype@, param%%@) \
|
#define SH_DECL_HOOK@$@_vafmt(ifacetype, ifacefunc, attr, overload, rettype@, param%%@) \
|
||||||
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(@param%%|, @@, @const char *, ...) attr> \
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(@param%%|, @@, @const char *, ...) attr> \
|
||||||
@ -723,10 +847,14 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
va_start(ap, fmt); \
|
va_start(ap, fmt); \
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
va_end(ap); \
|
va_end(ap); \
|
||||||
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (@param%%|, @@, @...), (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf), rettype); \
|
SH_HANDLEFUNC_vafmt((@param%%|, @@, @...), (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf), rettype); \
|
||||||
} \
|
} \
|
||||||
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype @"|" #param%%| @ "|const char*|...", \
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \
|
||||||
(static_cast<rettype (ifacetype::*)(@param%%|, @@, @const char *, ...) attr>(&ifacetype::ifacefunc)))
|
(static_cast<rettype (ifacetype::*)(@param%%|, @@, @const char *, ...) attr>(&ifacetype::ifacefunc))) \
|
||||||
|
\
|
||||||
|
const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1@, sizeof(param%%)@ }; \
|
||||||
|
::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(sizeof(rettype), \
|
||||||
|
@$@, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload);
|
||||||
|
|
||||||
#define SH_DECL_HOOK@$@_void_vafmt(ifacetype, ifacefunc, attr, overload@, param%%@) \
|
#define SH_DECL_HOOK@$@_void_vafmt(ifacetype, ifacefunc, attr, overload@, param%%@) \
|
||||||
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(@param%%|, @@, @const char *, ...) attr> \
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(@param%%|, @@, @const char *, ...) attr> \
|
||||||
@ -739,10 +867,36 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
va_start(ap, fmt); \
|
va_start(ap, fmt); \
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
va_end(ap); \
|
va_end(ap); \
|
||||||
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (@param%%|, @@, @...), (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf)); \
|
SH_HANDLEFUNC_void_vafmt((@param%%|, @@, @...), (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf)); \
|
||||||
} \
|
} \
|
||||||
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr @"|" #param%%| @ "|const char*|...", \
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \
|
||||||
(static_cast<void (ifacetype::*)(@param%%|, @@, @const char *, ...) attr>(&ifacetype::ifacefunc)))
|
(static_cast<void (ifacetype::*)(@param%%|, @@, @const char *, ...) attr>(&ifacetype::ifacefunc))) \
|
||||||
|
\
|
||||||
|
const int __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload[] = { -1@, sizeof(param%%)@ }; \
|
||||||
|
::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto(0, \
|
||||||
|
@$@, __SourceHook_ParamSizes_##ifacetype##ifacefunc##overload);
|
||||||
|
|
||||||
|
#define SH_DECL_MANUALHOOK@$@(hookname, vtblidx, vtbloffs, thisptroffs, rettype@, param%%@) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
|
||||||
|
typedef fastdelegate::FastDelegate@$@<@param%%|, @@, @rettype> FD; \
|
||||||
|
virtual rettype Func(@param%% p%%|, @) \
|
||||||
|
{ SH_HANDLEFUNC((@param%%|, @), (@p%%|, @), rettype); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
|
||||||
|
\
|
||||||
|
const int __SourceHook_ParamSizesM_##hookname[] = { 0@, sizeof(param%%)@ }; \
|
||||||
|
::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \
|
||||||
|
@$@, __SourceHook_ParamSizesM_##hookname);
|
||||||
|
|
||||||
|
#define SH_DECL_MANUALHOOK@$@_void(hookname, vtblidx, vtbloffs, thisptroffs@, param%%@) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
|
||||||
|
typedef fastdelegate::FastDelegate@$@<@param%%|, @> FD; \
|
||||||
|
virtual void Func(@param%% p%%|, @) \
|
||||||
|
{ SH_HANDLEFUNC_void((@param%%|, @), (@p%%|, @)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
|
||||||
|
\
|
||||||
|
const int __SourceHook_ParamSizesM_##hookname[] = { 0@, sizeof(param%%)@ }; \
|
||||||
|
::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \
|
||||||
|
@$@, __SourceHook_ParamSizesM_##hookname);
|
||||||
|
|
||||||
@ENDARGS@
|
@ENDARGS@
|
||||||
|
|
||||||
|
|||||||
@ -182,6 +182,93 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSourceHookImpl::RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc)
|
||||||
|
{
|
||||||
|
// Moo!
|
||||||
|
|
||||||
|
CHookManagerInfo tmp;
|
||||||
|
if (pubFunc(HA_GetInfo, &tmp) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HookManInfoList::iterator hmil_iter = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
||||||
|
tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||||
|
|
||||||
|
if (hmil_iter == m_HookMans.end())
|
||||||
|
{
|
||||||
|
// Moo ?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stillInUse = false;
|
||||||
|
List<RemoveHookInfo> hookstoremove;
|
||||||
|
|
||||||
|
// Iterate through all of the hook manager's hooks. Remove all hooks from the hookman's plugin.
|
||||||
|
#define TMP_CHECK_LIST(name, ispost) \
|
||||||
|
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||||
|
if (hook_iter->plug == plug) \
|
||||||
|
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \
|
||||||
|
hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost)); \
|
||||||
|
else \
|
||||||
|
stillInUse = true; \
|
||||||
|
|
||||||
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||||
|
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
|
{
|
||||||
|
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||||
|
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||||
|
{
|
||||||
|
List<HookInfo>::iterator hook_iter;
|
||||||
|
TMP_CHECK_LIST(m_PreHooks, false);
|
||||||
|
TMP_CHECK_LIST(m_PostHooks, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef TMP_CHECK_LIST
|
||||||
|
|
||||||
|
for (List<RemoveHookInfo>::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter)
|
||||||
|
RemoveHook(*rmiter);
|
||||||
|
|
||||||
|
CHookManagerInfo info = *hmil_iter;
|
||||||
|
|
||||||
|
// Unlink the hook manager from the list
|
||||||
|
m_HookMans.erase(hmil_iter);
|
||||||
|
|
||||||
|
// If there were any hooks from other plugins, find a new suitable hook manager.
|
||||||
|
if (stillInUse)
|
||||||
|
{
|
||||||
|
// Find a suitable hook manager in an other plugin
|
||||||
|
HookManInfoList::iterator newHookMan = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
||||||
|
info.m_Proto, info.m_VtblOffs, info.m_VtblIdx);
|
||||||
|
|
||||||
|
// This should _never_ happen.
|
||||||
|
// If there is a hook from an other plugin, the plugin must have provided a hook manager as well.
|
||||||
|
SH_ASSERT(newHookMan != m_HookMans.end(),
|
||||||
|
("Could not find a suitable hook manager in an other plugin!"));
|
||||||
|
|
||||||
|
// AddHook should make sure that every plugin only has _one_ hook manager for _one_ proto/vi/vo
|
||||||
|
SH_ASSERT(newHookMan->m_Plug != plug, ("New hook manager from same plugin!"));
|
||||||
|
|
||||||
|
// The first hook manager should be always used - so the new hook manager has to be empty
|
||||||
|
SH_ASSERT(newHookMan->m_VfnPtrs.empty(), ("New hook manager not empty!"));
|
||||||
|
|
||||||
|
// Move the vfnptrs from the old hook manager to the new one
|
||||||
|
newHookMan->m_VfnPtrs = info.m_VfnPtrs;
|
||||||
|
|
||||||
|
// Unregister the old one, register the new one
|
||||||
|
info.m_Func(HA_Unregister, NULL);
|
||||||
|
newHookMan->m_Func(HA_Register, &(*newHookMan));
|
||||||
|
|
||||||
|
// Go through all vfnptrs in this hookman and patch them to point to the new manager's handler!
|
||||||
|
// or whatever
|
||||||
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = newHookMan->m_VfnPtrs.begin();
|
||||||
|
vfnptr_iter != newHookMan->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
|
{
|
||||||
|
// And DEREFERENCE newHookMan->m_HookfuncVfnptr!
|
||||||
|
// otherwise it will be executing the vtable... had to find out the hard way
|
||||||
|
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = *reinterpret_cast<void**>(newHookMan->m_HookfuncVfnptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSourceHookImpl::CompleteShutdown()
|
void CSourceHookImpl::CompleteShutdown()
|
||||||
{
|
{
|
||||||
List<RemoveHookInfo> hookstoremove;
|
List<RemoveHookInfo> hookstoremove;
|
||||||
@ -214,17 +301,22 @@ namespace SourceHook
|
|||||||
bool CSourceHookImpl::AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
bool CSourceHookImpl::AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
||||||
{
|
{
|
||||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
||||||
|
|
||||||
// 1) Get info about the hook manager
|
// 1) Get info about the hook manager
|
||||||
CHookManagerInfo tmp;
|
CHookManagerInfo tmp;
|
||||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||||
|
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||||
|
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||||
|
|
||||||
// Add the proposed hook manager to the _end_ of the list if the plugin doesn't have a hook manager
|
// Add the proposed hook manager to the _end_ of the list if the plugin doesn't have a hook manager
|
||||||
// with this proto/vo/vi registered
|
// with this proto/vo/vi registered
|
||||||
HookManInfoList::iterator hkmi_iter;
|
HookManInfoList::iterator hkmi_iter;
|
||||||
for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter)
|
for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter)
|
||||||
{
|
{
|
||||||
if (hkmi_iter->m_Plug == plug && strcmp(hkmi_iter->m_Proto, tmp.m_Proto) == 0 &&
|
if (hkmi_iter->m_Plug == plug && ProtosEquiv(hkmi_iter->m_Proto, tmp.m_Proto) &&
|
||||||
hkmi_iter->m_VtblOffs == tmp.m_VtblOffs && hkmi_iter->m_VtblIdx == tmp.m_VtblIdx)
|
hkmi_iter->m_VtblOffs == tmp.m_VtblOffs && hkmi_iter->m_VtblIdx == tmp.m_VtblIdx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -241,14 +333,21 @@ namespace SourceHook
|
|||||||
tmp.m_VtblOffs, tmp.m_VtblIdx);
|
tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||||
SH_ASSERT(hookman != m_HookMans.end(), ("No hookman found - but if there was none, we've just added one!"));
|
SH_ASSERT(hookman != m_HookMans.end(), ("No hookman found - but if there was none, we've just added one!"));
|
||||||
|
|
||||||
|
// Check whether there is already an other hook manager for the same vfnptr but with other values before
|
||||||
|
// If yes, it means that the two are incompatible, so return false.
|
||||||
|
for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter)
|
||||||
|
{
|
||||||
|
if (hkmi_iter != hookman)
|
||||||
|
{
|
||||||
|
if (hkmi_iter->m_VfnPtrs.find(cur_vfnptr) != hkmi_iter->m_VfnPtrs.end())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tell it to store the pointer if it's not already active
|
// Tell it to store the pointer if it's not already active
|
||||||
if (hookman->m_VfnPtrs.empty())
|
if (hookman->m_VfnPtrs.empty())
|
||||||
hookman->m_Func(HA_Register, &(*hookman));
|
hookman->m_Func(HA_Register, &(*hookman));
|
||||||
|
|
||||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
|
||||||
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
|
||||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
|
||||||
|
|
||||||
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||||
|
|
||||||
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||||
@ -486,7 +585,7 @@ namespace SourceHook
|
|||||||
HookManInfoList::iterator hookmaniter;
|
HookManInfoList::iterator hookmaniter;
|
||||||
for (hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
for (hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
||||||
{
|
{
|
||||||
if (strcmp(hookmaniter->m_Proto, proto) == 0 && hookmaniter->m_VtblOffs == vtblofs &&
|
if (ProtosEquiv(hookmaniter->m_Proto, proto) && hookmaniter->m_VtblOffs == vtblofs &&
|
||||||
hookmaniter->m_VtblIdx == vtblidx)
|
hookmaniter->m_VtblIdx == vtblidx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -658,6 +757,65 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSourceHookImpl::ProtosEquiv(const char *p1, const char *p2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Old protos look like this:
|
||||||
|
|
||||||
|
0_void:
|
||||||
|
"attrib"
|
||||||
|
1_void:
|
||||||
|
"attrib|param1_type"
|
||||||
|
2_void:
|
||||||
|
"attrib|param1_type|param2_type
|
||||||
|
0:
|
||||||
|
"attrib|ret_type"
|
||||||
|
1:
|
||||||
|
"attrib|ret_type|param1_type"
|
||||||
|
2:
|
||||||
|
"attrib|ret_type|param2_type"
|
||||||
|
|
||||||
|
New protos are in fact pointers to the ProtoInfo sturcture (see sourcehook.h for details)
|
||||||
|
|
||||||
|
Old protos _never_ begin with a null character
|
||||||
|
New protos _always_ begin with a null character
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (*p1 && *p2) // Case1: Both old
|
||||||
|
{
|
||||||
|
// As in old versions
|
||||||
|
return strcmp(p1, p2) == 0;
|
||||||
|
}
|
||||||
|
else if (!*p1 && !*p2) // Case2: Both new
|
||||||
|
{
|
||||||
|
const ProtoInfo *pi1 = reinterpret_cast<const ProtoInfo*>(p1);
|
||||||
|
const ProtoInfo *pi2 = reinterpret_cast<const ProtoInfo*>(p2);
|
||||||
|
|
||||||
|
if (pi1->retTypeSize == pi2->retTypeSize &&
|
||||||
|
pi1->numOfParams == pi2->numOfParams)
|
||||||
|
{
|
||||||
|
// params[0] is 0 for "normal" functions and -1 for vararg functions
|
||||||
|
// params[1] is size of first parameter
|
||||||
|
// params[2] is size of second parameter ...
|
||||||
|
for (int i = 0; i <= pi1->numOfParams; ++i)
|
||||||
|
{
|
||||||
|
if (pi1->params[i] != pi2->params[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Case3: Mixed old/new
|
||||||
|
{
|
||||||
|
// Trust the user
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
// CHookManagerInfo
|
// CHookManagerInfo
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@ -686,6 +844,8 @@ namespace SourceHook
|
|||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// If you get a crash here, the ptr passed is invalid
|
||||||
|
// This usually means a SH_DECL_MANUALHOOK* with wrong thisptroffs/vtbloffs/vtblidx
|
||||||
CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr) : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(ptr))
|
CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr) : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(ptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -241,6 +241,8 @@ namespace SourceHook
|
|||||||
|
|
||||||
void SetPluginPaused(Plugin plug, bool paused);
|
void SetPluginPaused(Plugin plug, bool paused);
|
||||||
|
|
||||||
|
bool ProtosEquiv(const char *p1, const char *p2);
|
||||||
|
|
||||||
HookLoopInfoStack m_HLIStack;
|
HookLoopInfoStack m_HLIStack;
|
||||||
public:
|
public:
|
||||||
CSourceHookImpl();
|
CSourceHookImpl();
|
||||||
@ -357,6 +359,14 @@ namespace SourceHook
|
|||||||
void SetOrigRetPtr(const void *ptr); //!< Sets the original return pointer
|
void SetOrigRetPtr(const void *ptr); //!< Sets the original return pointer
|
||||||
void SetOverrideRetPtr(const void *ptr); //!< Sets the override result pointer
|
void SetOverrideRetPtr(const void *ptr); //!< Sets the override result pointer
|
||||||
bool ShouldContinue(); //!< Returns false if the hook loop should exit
|
bool ShouldContinue(); //!< Returns false if the hook loop should exit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug.
|
||||||
|
*
|
||||||
|
* @param plug The owner of the hook manager
|
||||||
|
* @param pubFunc The hook manager's info function
|
||||||
|
*/
|
||||||
|
virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,6 +74,7 @@ DO_TEST(ThisPtrOffs);
|
|||||||
DO_TEST(PlugSys);
|
DO_TEST(PlugSys);
|
||||||
DO_TEST(Bail);
|
DO_TEST(Bail);
|
||||||
DO_TEST(Reentr);
|
DO_TEST(Reentr);
|
||||||
|
DO_TEST(Manual);
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|||||||
@ -268,6 +268,15 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\testlist.cpp">
|
RelativePath=".\testlist.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\testmanual.cpp">
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
GeneratePreprocessedFile="0"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\testreentr.cpp">
|
RelativePath=".\testreentr.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user