From bb2cb311add114a9746baa9c79fef1d82d62e615 Mon Sep 17 00:00:00 2001 From: Pavol Marko Date: Fri, 29 Apr 2005 20:29:46 +0000 Subject: [PATCH] Completly redone templates, added "vfnptrs" --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%4042 --- sourcehook/generate/sourcehook.hxx | 350 +++++++---- sourcehook/sourcehook.cpp | 529 +++++++---------- sourcehook/sourcehook.h | 906 ++++++++++++++++++++--------- sourcehook/sourcehook_impl.h | 59 +- sourcehook/test/main.cpp | 32 +- 5 files changed, 1146 insertions(+), 730 deletions(-) diff --git a/sourcehook/generate/sourcehook.hxx b/sourcehook/generate/sourcehook.hxx index 95b0839..eacfbff 100755 --- a/sourcehook/generate/sourcehook.hxx +++ b/sourcehook/generate/sourcehook.hxx @@ -20,7 +20,7 @@ #define SH_GLOB_PLUGPTR g_PLID #endif -#define SH_ASSERT(x) if (!(x)) __asm { int 3 } +#define SH_ASSERT(x, info) if (!(x)) __asm { int 3 } // System #define SH_SYS_WIN32 1 @@ -54,6 +54,8 @@ #include "sh_memfuncinfo.h" #include "sh_memory.h" #include +#include +#include #include // Good old metamod! @@ -73,6 +75,13 @@ namespace SourceHook { const int STRBUF_LEN=8192; // In bytes, for "vafmt" functions + /** + * @brief An empty class. No inheritance used. Used for original-function-call hacks + */ + class EmptyClass + { + }; + /** * @brief A plugin typedef * @@ -136,66 +145,61 @@ namespace SourceHook */ struct HookManagerInfo { - struct Iface + struct VfnPtr { - struct Hook + struct Iface { - ISHDelegate *handler; //!< Pointer to the handler - bool paused; //!< If true, the hook should not be executed - Plugin plug; //!< The owner plugin + struct Hook + { + ISHDelegate *handler; //!< Pointer to the handler + bool paused; //!< If true, the hook should not be executed + Plugin plug; //!< The owner plugin + }; + void *ptr; //!< Pointer to the interface instance + std::list hooks_pre; //!< A list of pre-hooks + std::list hooks_post; //!< A list of post-hooks + bool operator ==(void *other) const + { + return ptr == other; + } }; - void *callclass; //!< Stores a call class for this interface - void *ptr; //!< Pointer to the interface instance + + void *vfnptr; //!< Pointer to the function void *orig_entry; //!< The original vtable entry - std::list hooks_pre; //!< A list of pre-hooks - std::list hooks_post; //!< A list of post-hooks - bool operator ==(void *other) const + + typedef std::list IfaceList; + typedef IfaceList::iterator IfaceListIter; + IfaceList ifaces; + + bool operator ==(void *other) { - return ptr == other; + return vfnptr == other; } }; Plugin plug; //!< The owner plugin const char *proto; //!< The prototype of the function the hook manager is responsible for int vtbl_idx; //!< The vtable index int vtbl_offs; //!< The vtable offset - int thisptr_offs; //!< The this-pointer-adjuster HookManagerPubFunc func; //!< The interface to the hook manager - int hookfunc_vtbl_idx; //!< the vtable index of the hookfunc - int hookfunc_vtbl_offs; //!< the vtable offset of the hookfunc - void *hookfunc_inst; //!< Instance of the class the hookfunc is in + void *hookfunc_vfnptr; //!< Pointer to the hookfunc impl - std::list ifaces; //!< List of hooked interfaces + typedef std::list VfnPtrList; + typedef VfnPtrList::iterator VfnPtrListIter; + VfnPtrList vfnptrs; //!< List of hooked interfaces }; - /** - * @brief Structure describing a callclass - */ - struct CallClass + typedef std::vector OrigFuncs; + typedef std::map OrigVTables; + + template struct CallClass { - struct VTable - { - void *ptr; - int actsize; - std::list patches; //!< Already patched entries - bool operator ==(void *other) const - { - return ptr == other; - } - }; - void *iface; //!< The iface pointer this callclass belongs to - size_t size; //!< The size of the callclass - void *ptr; //!< The actual "object" - typedef std::list VTableList; - VTableList vtables; //!< Already known vtables - int refcounter; //!< How many times it was requested - - bool operator ==(void *other) const - { - return ptr == other; - } + B *ptr; + OrigVTables vt; }; + typedef CallClass GenericCallClass; + /** * @brief The main SourceHook interface */ @@ -214,7 +218,7 @@ namespace SourceHook * @param handler A pointer to a FastDelegate containing the hook handler * @param post Set to true if you want a post handler */ - virtual bool AddHook(Plugin plug, void *iface, int ifacesize, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; + virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; /** * @brief Removes a hook. @@ -227,7 +231,7 @@ namespace SourceHook * @param handler A pointer to a FastDelegate containing the hook handler * @param post Set to true if you want a post handler */ - virtual bool RemoveHook(Plugin plug, void *iface, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; + virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; /** * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins @@ -242,14 +246,14 @@ namespace SourceHook * @param iface The interface pointer * @param size Size of the class */ - virtual void *GetCallClass(void *iface, size_t size) = 0; + virtual GenericCallClass *GetCallClass(void *iface) = 0; /** * @brief Release a callclass * * @param ptr Pointer to the callclass */ - virtual void ReleaseCallClass(void *ptr) = 0; + virtual void ReleaseCallClass(GenericCallClass *ptr) = 0; virtual void SetRes(META_RES res) = 0; //!< Sets the meta result virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the previously called handler @@ -284,11 +288,16 @@ namespace SourceHook /** * @brief Get/generate callclass for an interface pointer * -* @param ifacetype The type of the interface * @param ifaceptr The interface pointer */ -#define SH_GET_CALLCLASS(ifacetype, ifaceptr) reinterpret_cast(SH_GLOB_SHPTR->GetCallClass(ifaceptr, sizeof(ifacetype))) -#define SH_RELEASE_CALLCLASS(ptr) SH_GLOB_SHPTR->ReleaseCallClass(reinterpret_cast(ptr)) +template +inline SourceHook::CallClass *SH_GET_CALLCLASS(ifacetype *ptr) +{ + return reinterpret_cast*>( + SH_GLOB_SHPTR->GetCallClass(reinterpret_cast(ptr))); +} + +#define SH_RELEASE_CALLCLASS(ptr) SH_GLOB_SHPTR->ReleaseCallClass(reinterpret_cast(ptr)) #define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ SourceHook::SH_FHAdd##ifacetype##ifacefunc((void*)ifaceptr, post, handler) @@ -307,6 +316,18 @@ namespace SourceHook #define SH_NOATTRIB + +#if SH_COMP == SH_COMP_MSVC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr.orig_entry; +#elif SH_COMP == SH_COMP_GCC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr.orig_entry; \ + reinterpret_cast(&mfp)[1] = 0; +#else +# error Not supported yet. +#endif + ////////////////////////////////////////////////////////////////////////// #define SH_FHCls(ift, iff, ov) FHCls_##ift##iff##ov @@ -320,13 +341,10 @@ namespace SourceHook GetFuncInfo(funcptr, mfi); \ param->vtbl_idx = mfi.vtblindex; \ param->vtbl_offs = mfi.vtbloffs; \ - param->thisptr_offs = mfi.thisptroffs; \ - if (param->thisptr_offs < 0) \ - return 2; /*No virtual inheritance supported*/ \ + \ GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ - param->hookfunc_vtbl_idx = mfi.vtblindex; \ - param->hookfunc_vtbl_offs = mfi.vtbloffs; \ - param->hookfunc_inst = (void*)&ms_Inst; \ + param->hookfunc_vfnptr = \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]; \ return 0; \ } \ else if (action == HA_Register) \ @@ -353,7 +371,7 @@ namespace SourceHook static const char *ms_Proto; \ SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) -#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto) \ +#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \ }; \ const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \ SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ @@ -361,42 +379,67 @@ namespace SourceHook bool SH_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \ SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ { \ - return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, sizeof(ifacetype), \ + MemFuncInfo mfi; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ new CSHDelegate(handler), post); \ } \ bool SH_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ { \ + MemFuncInfo mfi; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ CSHDelegate tmp(handler); \ - return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ } \ } -#define SH_SETUPCALLS(rettype) \ - /* 1) Find the iface ptr */ \ - /* 1.1) Adjust to original this pointer */ \ - void *origthis = this - ms_HI->thisptr_offs; \ - std::list::iterator ifaceiter = std::find(ms_HI->ifaces.begin(), \ - ms_HI->ifaces.end(), origthis); \ - SH_ASSERT(ifaceiter != ms_HI->ifaces.end()); \ - HookManagerInfo::Iface &ci = *ifaceiter; \ +#define SH_SETUPCALLS(rettype, paramtypes, params) \ + /* 1) Find the vfnptr */ \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \ + \ + HookManagerInfo::VfnPtrListIter vfptriter = std::find(ms_HI->vfnptrs.begin(), \ + ms_HI->vfnptrs.end(), ourvfnptr); \ + if (vfptriter == ms_HI->vfnptrs.end()) \ + { \ + /* Bleh? Should be impossible! */ \ + SH_ASSERT(0, "Called with vfnptr 0x%p which couldn't be found in the list"); \ + } \ + HookManagerInfo::VfnPtr &vfnptr = *vfptriter; \ + /* 2) Find the iface */ \ + HookManagerInfo::VfnPtr::IfaceListIter ifiter = std::find(vfnptr.ifaces.begin(), vfnptr.ifaces.end(), this); \ + if (ifiter == vfnptr.ifaces.end()) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + return (reinterpret_cast(this)->*mfp)params; \ + } \ + HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \ /* 2) Declare some vars and set it up */ \ - std::list &prelist = ci.hooks_pre; \ - std::list &postlist = ci.hooks_post; \ + std::list &prelist = ci.hooks_pre; \ + std::list &postlist = ci.hooks_post; \ rettype orig_ret, override_ret, plugin_ret; \ META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \ META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \ META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \ status = MRES_IGNORED; \ - SH_GLOB_SHPTR->SetIfacePtr(ci.ptr); \ + SH_GLOB_SHPTR->SetIfacePtr(this); \ SH_GLOB_SHPTR->SetOrigRet(reinterpret_cast(&orig_ret)); \ SH_GLOB_SHPTR->SetOverrideRet(NULL); #define SH_CALL_HOOKS(post, params) \ prev_res = MRES_IGNORED; \ - for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ + for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ @@ -411,44 +454,64 @@ namespace SourceHook } \ } -#define SH_CALL_ORIG(ifacetype, ifacefunc, params) \ +#define SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params) \ if (status != MRES_SUPERCEDE) \ - orig_ret = reinterpret_cast(ci.callclass)->ifacefunc params; \ + { \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + orig_ret = (reinterpret_cast(ci.ptr)->*mfp)params; \ + } \ else \ orig_ret = override_ret; #define SH_RETURN() \ return status >= MRES_OVERRIDE ? override_ret : orig_ret; -#define SH_HANDLEFUNC(ifacetype, ifacefunc, params, rettype) \ - SH_SETUPCALLS(rettype) \ +#define SH_HANDLEFUNC(ifacetype, ifacefunc, paramtypes, params, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params) \ SH_CALL_HOOKS(pre, params) \ - SH_CALL_ORIG(ifacetype, ifacefunc, params) \ + SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params) \ SH_CALL_HOOKS(post, params) \ SH_RETURN() ////////////////////////////////////////////////////////////////////////// -#define SH_SETUPCALLS_void() \ - /* 1) Find the iface ptr */ \ - /* 1.1) Adjust to original this pointer */ \ - void *origthis = this - ms_HI->thisptr_offs; \ - std::list::iterator ifaceiter = std::find(ms_HI->ifaces.begin(), \ - ms_HI->ifaces.end(), origthis); \ - SH_ASSERT(ifaceiter != ms_HI->ifaces.end()); \ - HookManagerInfo::Iface &ci = *ifaceiter; \ +#define SH_SETUPCALLS_void(paramtypes, params) \ + /* 1) Find the vfnptr */ \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \ + \ + HookManagerInfo::VfnPtrListIter vfptriter = std::find(ms_HI->vfnptrs.begin(), \ + ms_HI->vfnptrs.end(), ourvfnptr); \ + if (vfptriter == ms_HI->vfnptrs.end()) \ + { \ + /* Bleh? Should be impossible! */ \ + SH_ASSERT(0, "Called with vfnptr 0x%p which couldn't be found in the list"); \ + } \ + HookManagerInfo::VfnPtr &vfnptr = *vfptriter; \ + /* 2) Find the iface */ \ + HookManagerInfo::VfnPtr::IfaceListIter ifiter = std::find(vfnptr.ifaces.begin(), vfnptr.ifaces.end(), this); \ + if (ifiter == vfnptr.ifaces.end()) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + return; \ + } \ + HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \ /* 2) Declare some vars and set it up */ \ - std::list &prelist = ci.hooks_pre; \ - std::list &postlist = ci.hooks_post; \ + std::list &prelist = ci.hooks_pre; \ + std::list &postlist = ci.hooks_post; \ META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \ META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \ META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \ status = MRES_IGNORED; \ - SH_GLOB_SHPTR->SetIfacePtr(ci.ptr); \ + SH_GLOB_SHPTR->SetIfacePtr(this); \ SH_GLOB_SHPTR->SetOverrideRet(NULL); #define SH_CALL_HOOKS_void(post, params) \ prev_res = MRES_IGNORED; \ - for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ + for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ @@ -458,54 +521,60 @@ namespace SourceHook status = cur_res; \ } -#define SH_CALL_ORIG_void(ifacetype, ifacefunc, params) \ +#define SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params) \ if (status != MRES_SUPERCEDE) \ - reinterpret_cast(ci.callclass)->ifacefunc params; + { \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(ci.ptr)->*mfp)params; \ + } #define SH_RETURN_void() -#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, params) \ - SH_SETUPCALLS_void() \ +#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, paramtypes, params) \ + SH_SETUPCALLS_void(paramtypes, params) \ SH_CALL_HOOKS_void(pre, params) \ - SH_CALL_ORIG_void(ifacetype, ifacefunc, params) \ + SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params) \ SH_CALL_HOOKS_void(post, params) \ SH_RETURN_void() // Special vafmt handlers -#define SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, params_orig, params_plug, rettype) \ - SH_SETUPCALLS(rettype) \ +#define SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, paramtypes, params_orig, params_plug, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params_orig) \ SH_CALL_HOOKS(pre, params_plug) \ - SH_CALL_ORIG(ifacetype, ifacefunc, params_orig) \ + SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params_orig) \ SH_CALL_HOOKS(post, params_plug) \ SH_RETURN() -#define SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, params_orig, params_plug) \ - SH_SETUPCALLS_void() \ +#define SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, paramtypes, params_orig, params_plug) \ + SH_SETUPCALLS_void(paramtypes, params_orig) \ SH_CALL_HOOKS_void(pre, params_plug) \ - SH_CALL_ORIG_void(ifacetype, ifacefunc, params_orig) \ + SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params_orig) \ SH_CALL_HOOKS_void(post, params_plug) \ SH_RETURN_void() ////////////////////////////////////////////////////////////////////////// @VARARGS@ -// ********* +// ********* Support for @$@ arguments ********* #define SH_DECL_HOOK@$@(ifacetype, ifacefunc, attr, overload, rettype@, param%%@) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate@$@<@param%%|, @@, @rettype> FD; \ virtual rettype Func(@param%% p%%|, @) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (@p%%|, @), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype @"|" #param%%| @) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (@param%%|, @), (@p%%|, @), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype @"|" #param%%| @, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK@$@_void(ifacetype, ifacefunc, attr, overload@, param%%@) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate@$@<@param%%|, @> FD; \ virtual void Func(@param%% p%%|, @) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (@p%%|, @)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr @"|" #param%%| @) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (@param%%|, @), (@p%%|, @)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr @"|" #param%%| @, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK@$@_vafmt(ifacetype, ifacefunc, attr, overload, rettype@, param%%@) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -518,9 +587,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (@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, #attr "|" #rettype @"|" #param%%| @ "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK@$@_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype@, param%%@) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -533,22 +603,70 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (@param%%|, @@, @...), (@p%%|, @@, @"%s", buf), (@p%%|, @@, @buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr @"|" #param%%| @ "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr @"|" #param%%| @ "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) @ENDARGS@ -/* -#define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload) \ - typedef fastdelegate::FastDelegate1 FD; \ - virtual rettype Func(param1 p1) \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1) - -*/ +////////////////////////////////////////////////////////////////////////// +// SH_CALL + + +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + MemFuncInfo mfi; \ + MFI_Impl::GetFuncInfo(m_MFP, mfi); \ + OrigVTables::const_iterator iter = m_CC->vt.find(mfi.vtbloffs); \ + if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->second.size() || iter->second[mfi.vtblindex] == NULL) \ + return (m_CC->ptr->*m_MFP)call; \ + \ + /* It's hooked. Call the original function. */ \ + union \ + { \ + RetType(EmptyClass::*mfpnew)prms; \ + void *addr; \ + } u; \ + u.addr = iter->second[mfi.vtblindex]; \ + \ + return (reinterpret_cast(m_CC->ptr)->*u.mfpnew)call; \ +} + + +namespace SourceHook +{ + template class ExecutableClass + { + CCType *m_CC; + MFPType m_MFP; + public: + ExecutableClass(CCType *cc, MFPType mfp) : m_CC(cc), m_MFP(mfp) + { + } + +@VARARGS@ + // Support for @$@ arguments + template<@class Param%%|, @> RetType operator()(@Param%% p%%|, @) const + SH_MAKE_EXECUTABLECLASS_OB((@p%%@), (@Param%%@)) + +@ENDARGS@ + }; +} + +@VARARGS@ +// Support for @$@ arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(@Param%%|, @)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(@Param%%|, @)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(@Param%%|, @)>(ptr, mfp); +} + +@ENDARGS@ + +#undef SH_MAKE_EXECUTABLECLASS_BODY #endif // The pope is dead. -> :( \ No newline at end of file diff --git a/sourcehook/sourcehook.cpp b/sourcehook/sourcehook.cpp index 621d31f..e4f3892 100644 --- a/sourcehook/sourcehook.cpp +++ b/sourcehook/sourcehook.cpp @@ -16,93 +16,38 @@ #include #include "sourcehook_impl.h" -#if SH_SYS == SH_SYS_WIN32 -# include -#elif SH_SYS == SH_SYS_LINUX -# include -# include -# include -# ifndef PAGESIZE -# define PAGESIZE 4096 -# endif -#endif - -#if SH_RUNTIME_CODEGEN == 1 -# if SH_COMP == SH_COMP_GCC -# define SH_CCC_CODESIZE 15 - // :TODO: - //void SH_CCC_MakeGate(void *origthisptr, unsigned char* &ptr, void *origvtable, int i) - //{ - //} -# elif SH_COMP == SH_COMP_MSVC -# define SH_CCC_CODESIZE 19 - void SH_CCC_MakeGate(void *origthisptr, void *ccthisptr, unsigned char* ptr, void *origfunc) - { - // --Subtract old this pointer to get the offset - // 00417EDF 81 E9 A1 7B 33 01 sub ecx,1337BA1h - *ptr++ = 0x81; - *ptr++ = 0xE9; - *reinterpret_cast(ptr) = ccthisptr; - ptr += sizeof(void*); - // --Add it to the new this pointer - // 00417EE5 81 C1 37 13 37 13 add ecx,13371337h - *ptr++ = 0x81; - *ptr++ = 0xC1; - *reinterpret_cast(ptr) = origthisptr; - ptr += sizeof(void*); - // --Prepare address - // 00417EEB B8 EF BE AD DE mov eax,0DEADBEEFh - *ptr++ = 0xB8; - *reinterpret_cast(ptr) = origfunc; - ptr += sizeof(void*); - // -- Do actual jump - // 00417EF0 FF E0 jmp eax - *ptr++ = 0xFF; - *ptr++ = 0xE0; - } -# endif -#endif - - namespace SourceHook { CSourceHookImpl::CSourceHookImpl() { - // Get page size -#if SH_SYS == SH_SYS_WIN32 - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - m_PageSize = sysinfo.dwPageSize; -#elif SH_SYS == SH_SYS_LINUX - m_PageSize = PAGESIZE; -#else -# error Unsupported system -#endif } CSourceHookImpl::~CSourceHookImpl() { - } bool CSourceHookImpl::IsPluginInUse(Plugin plug) { // Iterate through all hook managers which are in this plugin - // Iterate through their hooks + // Iterate through their vfnptrs, ifaces, hooks // If a hook from an other plugin is found, return true // Return false otherwise #define TMP_CHECK_LIST(name) \ - for (iter3 = iter2->name.begin(); iter3 != iter2->name.end(); ++iter3) \ - if (iter3->plug == plug) \ + for (hook_iter = iface_iter->name.begin(); hook_iter != iface_iter->name.end(); ++hook_iter) \ + if (hook_iter->plug == plug) \ return true; - for (HookManInfoList::iterator iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) + for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter) { - if (iter->plug == plug && !iter->ifaces.empty()) + if (hmil_iter->plug != plug) + continue; + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->vfnptrs.begin(); + vfnptr_iter != hmil_iter->vfnptrs.end(); ++vfnptr_iter) { - for (std::list::iterator iter2 = iter->ifaces.begin(); iter2 != iter->ifaces.end(); ++iter2) + for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin(); + iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter) { - std::list::iterator iter3; + std::list::iterator hook_iter; TMP_CHECK_LIST(hooks_pre); TMP_CHECK_LIST(hooks_post); } @@ -116,24 +61,29 @@ namespace SourceHook { // 1) Manually remove all hooks by this plugin std::list hookstoremove; - - for (HookManInfoList::iterator iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) +#define TMP_CHECK_LIST(name, ispost) \ + for (hook_iter = iface_iter->name.begin(); hook_iter != iface_iter->name.end(); ++hook_iter) \ + if (hook_iter->plug == plug) \ + hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->ptr, \ + hmil_iter->func, hook_iter->handler, ispost)) + for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter) { - for (std::list::iterator iter2 = iter->ifaces.begin(); iter2 != iter->ifaces.end(); - ++iter2) + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->vfnptrs.begin(); + vfnptr_iter != hmil_iter->vfnptrs.end(); ++vfnptr_iter) { - for (std::list::iterator iter3 = iter2->hooks_pre.begin(); iter3 != iter2->hooks_pre.end(); ++iter3) - if (iter3->plug == plug) - hookstoremove.push_back(RemoveHookInfo(iter3->plug, iter2->ptr, iter->func, iter3->handler, false)); - - for (std::list::iterator iter3 = iter2->hooks_post.begin(); iter3 != iter2->hooks_post.end(); ++iter3) - if (iter3->plug == plug) - hookstoremove.push_back(RemoveHookInfo(iter3->plug, iter2->ptr, iter->func, iter3->handler, true)); + for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin(); + iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter) + { + std::list::iterator hook_iter; + TMP_CHECK_LIST(hooks_pre, false); + TMP_CHECK_LIST(hooks_post, true); + } } } +#undef TMP_CHECK_LIST for (std::list::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter) - RemoveHook(rmiter->plug, rmiter->iface, rmiter->hpf, rmiter->handler, rmiter->post); + RemoveHook(*rmiter); // 2) Other plugins may use hook managers in this plugin. // Get a list of hook managers that are in this plugin and are used by other plugins @@ -141,16 +91,16 @@ namespace SourceHook HookManInfoList tmphookmans; bool erase = false; - for (HookManInfoList::iterator iter = m_HookMans.begin(); iter != m_HookMans.end(); - erase ? iter=m_HookMans.erase(iter) : ++iter) + for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); + erase ? hmil_iter=m_HookMans.erase(hmil_iter) : ++hmil_iter) { - if (iter->plug == plug) + if (hmil_iter->plug == plug) { - if (!iter->ifaces.empty()) + if (!hmil_iter->vfnptrs.empty()) { // All hooks by this plugin are already removed - // So if there is an iface, it has to be used by an other plugin - tmphookmans.push_back(*iter); + // So if there is a vfnptr, it has to be used by an other plugin + tmphookmans.push_back(*hmil_iter); } erase = true; } @@ -159,29 +109,28 @@ namespace SourceHook } // For each hook manager: - for (HookManInfoList::iterator iter = tmphookmans.begin(); iter != tmphookmans.end(); ++iter) + for (HookManInfoList::iterator hmil_iter = tmphookmans.begin(); hmil_iter != tmphookmans.end(); ++hmil_iter) { // Find a suitable hook manager in an other plugin HookManInfoList::iterator newHookMan = FindHookMan(m_HookMans.begin(), m_HookMans.end(), - iter->proto, iter->vtbl_offs, iter->vtbl_idx, iter->thisptr_offs); - if (newHookMan == m_HookMans.end()) - { - // 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(0); - } + hmil_iter->proto, hmil_iter->vtbl_offs, hmil_iter->vtbl_idx); - // AddHook should make sure that every plugin only has _one_ hook manager for _one_ proto/vi/vo/thisptroffs - SH_ASSERT(newHookMan->plug != plug); + // 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!"); - // The first hooker should be always used - so the new hook manager has to be empty - SH_ASSERT(newHookMan->ifaces.empty()); + // AddHook should make sure that every plugin only has _one_ hook manager for _one_ proto/vi/vo + SH_ASSERT(newHookMan->plug != plug, "New hook manager from same plugin!"); - // Move the ifaces from the old hook manager to the new one - newHookMan->ifaces = iter->ifaces; + // The first hook manager should be always used - so the new hook manager has to be empty + SH_ASSERT(newHookMan->vfnptrs.empty(), "New hook manager not empty!"); + + // Move the vfnptrs from the old hook manager to the new one + newHookMan->vfnptrs = hmil_iter->vfnptrs; // Unregister the old one, register the new one - iter->func(HA_Unregister, NULL); + hmil_iter->func(HA_Unregister, NULL); newHookMan->func(HA_Register, &(*newHookMan)); } } @@ -189,43 +138,49 @@ namespace SourceHook void CSourceHookImpl::CompleteShutdown() { std::list hookstoremove; - - for (HookManInfoList::iterator iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) +#define TMP_CHECK_LIST(name, ispost) \ + for (hook_iter = iface_iter->name.begin(); hook_iter != iface_iter->name.end(); ++hook_iter) \ + hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->ptr, \ + hmil_iter->func, hook_iter->handler, ispost)) + for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter) { - for (std::list::iterator iter2 = iter->ifaces.begin(); iter2 != iter->ifaces.end(); - ++iter2) + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->vfnptrs.begin(); + vfnptr_iter != hmil_iter->vfnptrs.end(); ++vfnptr_iter) { - for (std::list::iterator iter3 = iter2->hooks_pre.begin(); iter3 != iter2->hooks_pre.end(); ++iter3) - hookstoremove.push_back(RemoveHookInfo(iter3->plug, iter2->ptr, iter->func, iter3->handler, false)); - - for (std::list::iterator iter3 = iter2->hooks_post.begin(); iter3 != iter2->hooks_post.end(); ++iter3) - hookstoremove.push_back(RemoveHookInfo(iter3->plug, iter2->ptr, iter->func, iter3->handler, true)); + for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin(); + iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter) + { + std::list::iterator hook_iter; + TMP_CHECK_LIST(hooks_pre, false); + TMP_CHECK_LIST(hooks_post, true); + } } } +#undef TMP_CHECK_LIST for (std::list::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter) - RemoveHook(rmiter->plug, rmiter->iface, rmiter->hpf, rmiter->handler, rmiter->post); + RemoveHook(*rmiter); m_HookMans.clear(); } - bool CSourceHookImpl::AddHook(Plugin plug, void *iface, int ifacesize, 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(reinterpret_cast(iface) + thisptr_offs); // 1) Get info about the hook manager HookManagerInfo tmp; if (myHookMan(HA_GetInfo, &tmp) != 0) return false; // 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 - HookManInfoList::iterator hookmaniter; - for (hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter) + HookManInfoList::iterator hkmi_iter; + for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter) { - if (hookmaniter->plug == plug && strcmp(hookmaniter->proto, tmp.proto) == 0 && - hookmaniter->vtbl_offs == tmp.vtbl_offs && hookmaniter->vtbl_idx == tmp.vtbl_idx && - hookmaniter->thisptr_offs == tmp.thisptr_offs) + if (hkmi_iter->plug == plug && strcmp(hkmi_iter->proto, tmp.proto) == 0 && + hkmi_iter->vtbl_offs == tmp.vtbl_offs && hkmi_iter->vtbl_idx == tmp.vtbl_idx) break; } - if (hookmaniter == m_HookMans.end()) + if (hkmi_iter == m_HookMans.end()) { // No such hook manager from this plugin yet, add it! tmp.func = myHookMan; @@ -234,47 +189,70 @@ namespace SourceHook } // Then, search for a suitable hook manager (from the beginning) - HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(), tmp.proto, tmp.vtbl_offs, tmp.vtbl_idx, tmp.thisptr_offs); - SH_ASSERT(hookman != m_HookMans.end()); + HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(), tmp.proto, tmp.vtbl_offs, tmp.vtbl_idx); + SH_ASSERT(hookman != m_HookMans.end(), "No hookman found - but if there was none, we've just added one!"); // Tell it to store the pointer if it's not already active - if (hookman->ifaces.empty()) + if (hookman->vfnptrs.empty()) hookman->func(HA_Register, &(*hookman)); - std::list::iterator ifsiter = std::find(hookman->ifaces.begin(), hookman->ifaces.end(), iface); + void **cur_vtptr = *reinterpret_cast( + reinterpret_cast(adjustediface) + tmp.vtbl_offs); + void *cur_vfnptr = reinterpret_cast(cur_vtptr + tmp.vtbl_idx); - if (ifsiter == hookman->ifaces.end()) + HookManagerInfo::VfnPtrListIter vfnptr_iter = std::find( + hookman->vfnptrs.begin(), hookman->vfnptrs.end(), cur_vfnptr); + + if (vfnptr_iter == hookman->vfnptrs.end()) { - HookManagerInfo::Iface ifs; - ifs.ptr = iface; - ifs.callclass = GetCallClass(iface, ifacesize); - void *vtableptr = *reinterpret_cast(reinterpret_cast(iface) + hookman->vtbl_offs); - SetMemAccess(vtableptr, sizeof(void*) * hookman->vtbl_idx, SH_MEM_READ | SH_MEM_WRITE); - ifs.orig_entry = (*reinterpret_cast(reinterpret_cast(iface) + hookman->vtbl_offs))[hookman->vtbl_idx]; - (*reinterpret_cast(reinterpret_cast(iface) + hookman->vtbl_offs))[hookman->vtbl_idx] = - (*reinterpret_cast(reinterpret_cast(hookman->hookfunc_inst) + hookman->hookfunc_vtbl_offs))[hookman->hookfunc_vtbl_idx]; - hookman->ifaces.push_back(ifs); - ifsiter = hookman->ifaces.end(); - --ifsiter; + // Add a new one + HookManagerInfo::VfnPtr vfp; + vfp.vfnptr = cur_vfnptr; + vfp.orig_entry = *reinterpret_cast(cur_vfnptr); + hookman->vfnptrs.push_back(vfp); + + // Alter vtable entry + SetMemAccess(cur_vtptr, sizeof(void*) * tmp.vtbl_idx, SH_MEM_READ | SH_MEM_WRITE); + *reinterpret_cast(cur_vfnptr) = *reinterpret_cast(hookman->hookfunc_vfnptr); + + // Make vfnptr_iter point to the new element + vfnptr_iter = hookman->vfnptrs.end(); + --vfnptr_iter; } - HookManagerInfo::Iface::Hook hookinfo; + + HookManagerInfo::VfnPtr::IfaceListIter iface_iter = std::find( + vfnptr_iter->ifaces.begin(), vfnptr_iter->ifaces.end(), adjustediface); + if (iface_iter == vfnptr_iter->ifaces.end()) + { + // Add a new one + HookManagerInfo::VfnPtr::Iface ifs; + ifs.ptr = adjustediface; + vfnptr_iter->ifaces.push_back(ifs); + + // Make iface_iter point to the new element + iface_iter = vfnptr_iter->ifaces.end(); + --iface_iter; + } + + // Add the hook + HookManagerInfo::VfnPtr::Iface::Hook hookinfo; hookinfo.handler = handler; hookinfo.plug = plug; hookinfo.paused = false; if (post) - ifsiter->hooks_post.push_back(hookinfo); + iface_iter->hooks_post.push_back(hookinfo); else - ifsiter->hooks_pre.push_back(hookinfo); + iface_iter->hooks_pre.push_back(hookinfo); // Now that it is done, check whether we have to update any callclasses for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter) { - if (cciter->iface == iface) + if (cciter->cc.ptr == iface) { - ApplyCallClassPatch(*cciter, tmp.vtbl_offs, tmp.vtbl_idx, ifsiter->orig_entry); + ApplyCallClassPatch(*cciter, tmp.vtbl_offs, tmp.vtbl_idx, vfnptr_iter->orig_entry); - // We can assume that there is no more callclass with the same iface + // We can assume that there is no more callclass for the same iface break; } } @@ -282,7 +260,18 @@ namespace SourceHook return true; } - bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) + bool CSourceHookImpl::RemoveHook(RemoveHookInfo info) + { + return RemoveHook(info.plug, info.iface, info.hookman, info.handler, info.post); + } + + bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) + { + return RemoveHook(plug, reinterpret_cast(reinterpret_cast(iface)+thisptr_offs), + myHookMan, handler, post); + } + + bool CSourceHookImpl::RemoveHook(Plugin plug, void *adjustediface, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) { HookManagerInfo tmp; if (myHookMan(HA_GetInfo, &tmp) != 0) @@ -290,196 +279,110 @@ namespace SourceHook // Find the hook manager and the hook HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(), - tmp.proto, tmp.vtbl_offs, tmp.vtbl_idx, tmp.thisptr_offs); + tmp.proto, tmp.vtbl_offs, tmp.vtbl_idx); if (hookman == m_HookMans.end()) return false; - for (std::list::iterator ifaceiter = hookman->ifaces.begin(); ifaceiter != hookman->ifaces.end(); ++ifaceiter) + void **cur_vtptr = *reinterpret_cast( + reinterpret_cast(adjustediface) + tmp.vtbl_offs); + void *cur_vfnptr = reinterpret_cast(cur_vtptr + tmp.vtbl_idx); + + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->vfnptrs.begin(); + vfnptr_iter != hookman->vfnptrs.end(); ++vfnptr_iter) { - if (ifaceiter->ptr == iface) + if (vfnptr_iter->vfnptr == cur_vfnptr) { - std::list &hooks = post ? ifaceiter->hooks_post : ifaceiter->hooks_pre; - bool erase; - for (std::list::iterator hookiter = hooks.begin(); - hookiter != hooks.end(); erase ? hookiter = hooks.erase(hookiter) : ++hookiter) + for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin(); + iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter) { - erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler); - if (erase) - hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object + std::list &hooks = + post ? iface_iter->hooks_post : iface_iter->hooks_pre; + + bool erase; + for (std::list::iterator hookiter = hooks.begin(); + hookiter != hooks.end(); erase ? hookiter = hooks.erase(hookiter) : ++hookiter) + { + erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler); + if (erase) + hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object + } + if (iface_iter->hooks_post.empty() && iface_iter->hooks_pre.empty()) + { + vfnptr_iter->ifaces.erase(iface_iter); + if (vfnptr_iter->ifaces.empty()) + { + // Deactivate the hook + *reinterpret_cast(vfnptr_iter->vfnptr) = vfnptr_iter->orig_entry; + + hookman->vfnptrs.erase(vfnptr_iter); + + if (hookman->vfnptrs.empty()) + { + // Unregister the hook manager + hookman->func(HA_Unregister, NULL); + } + } + } } - if (ifaceiter->hooks_post.empty() && ifaceiter->hooks_pre.empty()) - { - // Deactivate the hook - (*reinterpret_cast(reinterpret_cast(ifaceiter->ptr) + - hookman->vtbl_offs))[hookman->vtbl_idx]= ifaceiter->orig_entry; - - // Release the callclass - ReleaseCallClass(ifaceiter->callclass); - - // Remove the iface info - hookman->ifaces.erase(ifaceiter); - - if (hookman->ifaces.empty()) - hookman->func(HA_Unregister, NULL); - } - // :TODO: Better return value? Or none? return true; } } return false; } - void *CSourceHookImpl::GetCallClass(void *iface, size_t size) + GenericCallClass *CSourceHookImpl::GetCallClass(void *iface) { for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter) { - if (cciter->iface == iface) + if (cciter->cc.ptr == iface) { ++cciter->refcounter; - return cciter->ptr; + return &cciter->cc; } } - // The layout of callclasses is: - // Copy of the class; vtable entries pointing to gates - // Pointer to the corresponding CallClass object - // Copy of the class; vtable entries pointing to original functions - - CallClass tmp; - char *ptr = new char[size * 2 + sizeof(void*)]; - tmp.ptr = reinterpret_cast(ptr); - memcpy(reinterpret_cast(ptr), iface, size); - memcpy(reinterpret_cast(ptr + size + sizeof(void*)), iface, size); - tmp.iface = iface; - tmp.size = size; + CallClassInfo tmp; tmp.refcounter = 1; + tmp.cc.ptr = iface; - // Go through _all_ hooks and apply any needed patches for (HookManInfoList::iterator hookman = m_HookMans.begin(); hookman != m_HookMans.end(); ++hookman) - { - for (std::list::iterator ifaceiter = hookman->ifaces.begin(); ifaceiter != hookman->ifaces.end(); ++ifaceiter) - { - if (ifaceiter->ptr == iface) - { - if (!ApplyCallClassPatch(tmp, hookman->vtbl_offs, hookman->vtbl_idx, ifaceiter->orig_entry)) - { - FreeCallClass(tmp); - return NULL; - } - } - } - } + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->vfnptrs.begin(); + vfnptr_iter != hookman->vfnptrs.end(); ++vfnptr_iter) + for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin(); + iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter) + if (iface_iter->ptr == iface) + ApplyCallClassPatch(tmp, hookman->vtbl_offs, hookman->vtbl_idx, + vfnptr_iter->orig_entry); + m_CallClasses.push_back(tmp); - // The object has to be followed by the pointer to the vtable info object - *reinterpret_cast(ptr + size) = &m_CallClasses.back(); - return tmp.ptr; + return &m_CallClasses.back().cc; } - void CSourceHookImpl::ReleaseCallClass(void *ptr) + void CSourceHookImpl::ReleaseCallClass(GenericCallClass *ptr) { Impl_CallClassList::iterator iter = std::find(m_CallClasses.begin(), m_CallClasses.end(), ptr); if (iter == m_CallClasses.end()) return; --iter->refcounter; if (iter->refcounter < 1) - { - FreeCallClass(*iter); m_CallClasses.erase(iter); - } } - void CSourceHookImpl::FreeCallClass(CallClass &cc) + void CSourceHookImpl::ApplyCallClassPatch(CallClassInfo &cc, int vtbl_offs, int vtbl_idx, void *orig_entry) { - for (CallClass::VTableList::iterator vtbliter = cc.vtables.begin(); vtbliter != cc.vtables.end(); ++vtbliter) - { -#if SH_RUNTIME_CODEGEN == 1 - // Delete generated callgates - for (std::list::iterator cgiter = vtbliter->patches.begin(); cgiter != vtbliter->patches.end(); ++cgiter) - { - char *cgptr = reinterpret_cast(vtbliter->ptr)[*cgiter]; - delete [] cgptr; - } -#endif - delete [] reinterpret_cast(vtbliter->ptr); - } - delete [] reinterpret_cast(cc.ptr); + OrigFuncs &tmpvec = cc.cc.vt[vtbl_offs]; + if (tmpvec.size() <= (size_t)vtbl_idx) + tmpvec.resize(vtbl_idx+1); + tmpvec[vtbl_idx] = orig_entry; } - bool CSourceHookImpl::ApplyCallClassPatch(CallClass &cc, int vtbl_offs, int vtbl_idx, void *orig_entry) - { - char *ptr = reinterpret_cast(cc.ptr); - void *vtable = *reinterpret_cast(ptr + vtbl_offs); - - // Check whether we already know that vtable - CallClass::VTableList::iterator vtbliter = std::find(cc.vtables.begin(), - cc.vtables.end(), reinterpret_cast(vtable)); - int actvtablesize=MAX_VTABLE_LEN; - if (vtbliter == cc.vtables.end()) - { - CallClass::VTable newvtableinfo; - int pagesnum = (MAX_VTABLE_LEN % m_PageSize == 0) ? MAX_VTABLE_LEN / m_PageSize : MAX_VTABLE_LEN / m_PageSize + 1; - // Set all pages in the range to readwrite - // :TODO: Fix this! - char *pagebegin = reinterpret_cast(vtable) - (reinterpret_cast(vtable) % m_PageSize); - for (int ipage = 0; ipage < pagesnum; ++ipage) - { - if (!SetMemAccess(reinterpret_cast(pagebegin + ipage * m_PageSize), 1, - SH_MEM_READ | SH_MEM_WRITE)) - { - // We can't go here anymore - actvtablesize = static_cast((pagebegin + ipage * m_PageSize) - reinterpret_cast(vtable)); - break; - } - } - if (actvtablesize < 1) - { - // We can't access the vtable -> Quit - return false; - } - // Create a new vtable - newvtableinfo.ptr = reinterpret_cast(new char[actvtablesize]); - // Fill it with the information from the old vtable - memcpy(newvtableinfo.ptr, vtable, actvtablesize); - newvtableinfo.actsize = actvtablesize; - // Set the pointer in the object and add it to the list of already known vtables - *reinterpret_cast(ptr + vtbl_offs) = newvtableinfo.ptr; - cc.vtables.push_back(newvtableinfo); - - vtbliter = cc.vtables.end(); - --vtbliter; - // :TODO: When not codegen, patch the other vtable? - } - - // Check whether we already have this patch - if (std::find(vtbliter->patches.begin(), vtbliter->patches.end(), vtbl_idx) == vtbliter->patches.end()) - { - // No -> apply it - - // Get a call gate - void *callgate = NULL; -#if SH_RUNTIME_CODEGEN == 1 - unsigned char *cggen = new unsigned char[SH_CCC_CODESIZE]; - //SH_CCC_MakeGate(cc.iface, cc.ptr, cggen, orig_entry); - callgate = (void*)cggen; - SetMemAccess(callgate, SH_CCC_CODESIZE, SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC); -#else - // :TODO: -#error Not supported yet! -#endif - vtbliter->patches.push_back(vtbl_idx); - reinterpret_cast(vtbliter->ptr)[vtbl_idx] = callgate; - } - return true; - } - - CSourceHookImpl::HookManInfoList::iterator CSourceHookImpl::FindHookMan(HookManInfoList::iterator begin, - HookManInfoList::iterator end, const char *proto, int vtblofs, int vtblidx, int thisptrofs) + HookManInfoList::iterator end, const char *proto, int vtblofs, int vtblidx) { for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter) { - if (strcmp(hookmaniter->proto, proto) == 0 && hookmaniter->vtbl_offs == vtblofs && hookmaniter->vtbl_idx == vtblidx && - hookmaniter->thisptr_offs == thisptrofs) + if (strcmp(hookmaniter->proto, proto) == 0 && hookmaniter->vtbl_offs == vtblofs && + hookmaniter->vtbl_idx == vtblidx) break; } return hookmaniter; @@ -489,38 +392,42 @@ namespace SourceHook { // Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter) - for (std::list::iterator ifaceiter = hookmaniter->ifaces.begin(); - ifaceiter != hookmaniter->ifaces.end(); ++ifaceiter) - { - for (std::list::iterator hookiter = ifaceiter->hooks_pre.begin(); - hookiter != ifaceiter->hooks_pre.end(); ++hookiter) - if (plug == hookiter->plug) - hookiter->paused = true; + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->vfnptrs.begin(); + vfnptr_iter != hookmaniter->vfnptrs.end(); ++vfnptr_iter) + for (HookManagerInfo::VfnPtr::IfaceListIter ifaceiter = vfnptr_iter->ifaces.begin(); + ifaceiter != vfnptr_iter->ifaces.end(); ++ifaceiter) + { + for (std::list::iterator hookiter = ifaceiter->hooks_pre.begin(); + hookiter != ifaceiter->hooks_pre.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = true; - for (std::list::iterator hookiter = ifaceiter->hooks_post.begin(); - hookiter != ifaceiter->hooks_post.end(); ++hookiter) - if (plug == hookiter->plug) - hookiter->paused = true; - } + for (std::list::iterator hookiter = ifaceiter->hooks_post.begin(); + hookiter != ifaceiter->hooks_post.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = true; + } } void CSourceHookImpl::UnpausePlugin(Plugin plug) { - // Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to normal + // Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter) - for (std::list::iterator ifaceiter = hookmaniter->ifaces.begin(); - ifaceiter != hookmaniter->ifaces.end(); ++ifaceiter) - { - for (std::list::iterator hookiter = ifaceiter->hooks_pre.begin(); - hookiter != ifaceiter->hooks_pre.end(); ++hookiter) - if (plug == hookiter->plug) - hookiter->paused = false; + for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->vfnptrs.begin(); + vfnptr_iter != hookmaniter->vfnptrs.end(); ++vfnptr_iter) + for (HookManagerInfo::VfnPtr::IfaceListIter ifaceiter = vfnptr_iter->ifaces.begin(); + ifaceiter != vfnptr_iter->ifaces.end(); ++ifaceiter) + { + for (std::list::iterator hookiter = ifaceiter->hooks_pre.begin(); + hookiter != ifaceiter->hooks_pre.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = false; - for (std::list::iterator hookiter = ifaceiter->hooks_post.begin(); - hookiter != ifaceiter->hooks_post.end(); ++hookiter) - if (plug == hookiter->plug) - hookiter->paused = false; - } + for (std::list::iterator hookiter = ifaceiter->hooks_post.begin(); + hookiter != ifaceiter->hooks_post.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = false; + } } void CSourceHookImpl::SetRes(META_RES res) diff --git a/sourcehook/sourcehook.h b/sourcehook/sourcehook.h index b3953da..ecfedd6 100644 --- a/sourcehook/sourcehook.h +++ b/sourcehook/sourcehook.h @@ -1,16 +1,12 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2005 Metamod:Source Development Team +* By PM * No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko * ============================ */ /** - * @file sourcehook.h - * @brief Contains the public SourceHook API +* @file sourcehook.h +* @brief Contains the public SourceHook API */ #ifndef __SOURCEHOOK_H__ @@ -24,16 +20,16 @@ #define SH_GLOB_PLUGPTR g_PLID #endif +#define SH_ASSERT(x, info) if (!(x)) __asm { int 3 } + // System #define SH_SYS_WIN32 1 #define SH_SYS_LINUX 2 #ifdef _WIN32 # define SH_SYS SH_SYS_WIN32 -# define SH_ASSERT(x) if (!(x)) __asm { int 3 } #elif defined __linux__ # define SH_SYS SH_SYS_LINUX -# define SH_ASSERT(x) if (!(x)) asm("int $3"); #else # error Unsupported system #endif @@ -58,6 +54,8 @@ #include "sh_memfuncinfo.h" #include "sh_memory.h" #include +#include +#include #include // Good old metamod! @@ -77,6 +75,13 @@ namespace SourceHook { const int STRBUF_LEN=8192; // In bytes, for "vafmt" functions + /** + * @brief An empty class. No inheritance used. Used for original-function-call hacks + */ + class EmptyClass + { + }; + /** * @brief A plugin typedef * @@ -140,66 +145,61 @@ namespace SourceHook */ struct HookManagerInfo { - struct Iface + struct VfnPtr { - struct Hook + struct Iface { - ISHDelegate *handler; //!< Pointer to the handler - bool paused; //!< If true, the hook should not be executed - Plugin plug; //!< The owner plugin + struct Hook + { + ISHDelegate *handler; //!< Pointer to the handler + bool paused; //!< If true, the hook should not be executed + Plugin plug; //!< The owner plugin + }; + void *ptr; //!< Pointer to the interface instance + std::list hooks_pre; //!< A list of pre-hooks + std::list hooks_post; //!< A list of post-hooks + bool operator ==(void *other) const + { + return ptr == other; + } }; - void *callclass; //!< Stores a call class for this interface - void *ptr; //!< Pointer to the interface instance + + void *vfnptr; //!< Pointer to the function void *orig_entry; //!< The original vtable entry - std::list hooks_pre; //!< A list of pre-hooks - std::list hooks_post; //!< A list of post-hooks - bool operator ==(void *other) const + + typedef std::list IfaceList; + typedef IfaceList::iterator IfaceListIter; + IfaceList ifaces; + + bool operator ==(void *other) { - return ptr == other; + return vfnptr == other; } }; Plugin plug; //!< The owner plugin const char *proto; //!< The prototype of the function the hook manager is responsible for int vtbl_idx; //!< The vtable index int vtbl_offs; //!< The vtable offset - int thisptr_offs; //!< The this-pointer-adjuster HookManagerPubFunc func; //!< The interface to the hook manager - int hookfunc_vtbl_idx; //!< the vtable index of the hookfunc - int hookfunc_vtbl_offs; //!< the vtable offset of the hookfunc - void *hookfunc_inst; //!< Instance of the class the hookfunc is in + void *hookfunc_vfnptr; //!< Pointer to the hookfunc impl - std::list ifaces; //!< List of hooked interfaces + typedef std::list VfnPtrList; + typedef VfnPtrList::iterator VfnPtrListIter; + VfnPtrList vfnptrs; //!< List of hooked interfaces }; - /** - * @brief Structure describing a callclass - */ - struct CallClass + typedef std::vector OrigFuncs; + typedef std::map OrigVTables; + + template struct CallClass { - struct VTable - { - void *ptr; - int actsize; - std::list patches; //!< Already patched entries - bool operator ==(void *other) const - { - return ptr == other; - } - }; - void *iface; //!< The iface pointer this callclass belongs to - size_t size; //!< The size of the callclass - void *ptr; //!< The actual "object" - typedef std::list VTableList; - VTableList vtables; //!< Already known vtables - int refcounter; //!< How many times it was requested - - bool operator ==(void *other) const - { - return ptr == other; - } + B *ptr; + OrigVTables vt; }; + typedef CallClass GenericCallClass; + /** * @brief The main SourceHook interface */ @@ -218,7 +218,7 @@ namespace SourceHook * @param handler A pointer to a FastDelegate containing the hook handler * @param post Set to true if you want a post handler */ - virtual bool AddHook(Plugin plug, void *iface, int ifacesize, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; + virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; /** * @brief Removes a hook. @@ -231,7 +231,7 @@ namespace SourceHook * @param handler A pointer to a FastDelegate containing the hook handler * @param post Set to true if you want a post handler */ - virtual bool RemoveHook(Plugin plug, void *iface, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; + virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post) = 0; /** * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins @@ -246,14 +246,14 @@ namespace SourceHook * @param iface The interface pointer * @param size Size of the class */ - virtual void *GetCallClass(void *iface, size_t size) = 0; + virtual GenericCallClass *GetCallClass(void *iface) = 0; /** * @brief Release a callclass * * @param ptr Pointer to the callclass */ - virtual void ReleaseCallClass(void *ptr) = 0; + virtual void ReleaseCallClass(GenericCallClass *ptr) = 0; virtual void SetRes(META_RES res) = 0; //!< Sets the meta result virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the previously called handler @@ -288,11 +288,16 @@ namespace SourceHook /** * @brief Get/generate callclass for an interface pointer * -* @param ifacetype The type of the interface * @param ifaceptr The interface pointer */ -#define SH_GET_CALLCLASS(ifacetype, ifaceptr) reinterpret_cast(SH_GLOB_SHPTR->GetCallClass(ifaceptr, sizeof(ifacetype))) -#define SH_RELEASE_CALLCLASS(ptr) SH_GLOB_SHPTR->ReleaseCallClass(reinterpret_cast(ptr)) +template +inline SourceHook::CallClass *SH_GET_CALLCLASS(ifacetype *ptr) +{ + return reinterpret_cast*>( + SH_GLOB_SHPTR->GetCallClass(reinterpret_cast(ptr))); +} + +#define SH_RELEASE_CALLCLASS(ptr) SH_GLOB_SHPTR->ReleaseCallClass(reinterpret_cast(ptr)) #define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ SourceHook::SH_FHAdd##ifacetype##ifacefunc((void*)ifaceptr, post, handler) @@ -311,6 +316,18 @@ namespace SourceHook #define SH_NOATTRIB + +#if SH_COMP == SH_COMP_MSVC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr.orig_entry; +#elif SH_COMP == SH_COMP_GCC +# define SH_SETUP_MFP(mfp) \ + reinterpret_cast(&mfp)[0] = vfnptr.orig_entry; \ + reinterpret_cast(&mfp)[1] = 0; +#else +# error Not supported yet. +#endif + ////////////////////////////////////////////////////////////////////////// #define SH_FHCls(ift, iff, ov) FHCls_##ift##iff##ov @@ -324,13 +341,10 @@ namespace SourceHook GetFuncInfo(funcptr, mfi); \ param->vtbl_idx = mfi.vtblindex; \ param->vtbl_offs = mfi.vtbloffs; \ - param->thisptr_offs = mfi.thisptroffs; \ - if (param->thisptr_offs < 0) \ - return 2; /*No virtual inheritance supported*/ \ + \ GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ - param->hookfunc_vtbl_idx = mfi.vtblindex; \ - param->hookfunc_vtbl_offs = mfi.vtbloffs; \ - param->hookfunc_inst = (void*)&ms_Inst; \ + param->hookfunc_vfnptr = \ + reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]; \ return 0; \ } \ else if (action == HA_Register) \ @@ -357,7 +371,7 @@ namespace SourceHook static const char *ms_Proto; \ SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) -#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto) \ +#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \ }; \ const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \ SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ @@ -365,44 +379,67 @@ namespace SourceHook bool SH_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \ SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ { \ - return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, sizeof(ifacetype), \ + MemFuncInfo mfi; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ + return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ new CSHDelegate(handler), post); \ } \ bool SH_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ { \ + MemFuncInfo mfi; \ + GetFuncInfo(funcptr, mfi); \ + if (mfi.thisptroffs < 0) \ + return false; /* No virtual inheritance supported */ \ + \ CSHDelegate tmp(handler); \ - return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, \ + return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ } \ } -#define SH_SETUPCALLS(rettype) \ - /* 1) Find the iface ptr */ \ - /* 1.1) Adjust to original this pointer */ \ - void *origthis = this - ms_HI->thisptr_offs; \ - std::list::iterator ifaceiter = std::find(ms_HI->ifaces.begin(), \ - ms_HI->ifaces.end(), origthis); \ - SH_ASSERT(ifaceiter != ms_HI->ifaces.end()); \ - HookManagerInfo::Iface &ci = *ifaceiter; \ +#define SH_SETUPCALLS(rettype, paramtypes, params) \ + /* 1) Find the vfnptr */ \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \ + \ + HookManagerInfo::VfnPtrListIter vfptriter = std::find(ms_HI->vfnptrs.begin(), \ + ms_HI->vfnptrs.end(), ourvfnptr); \ + if (vfptriter == ms_HI->vfnptrs.end()) \ + { \ + /* Bleh? Should be impossible! */ \ + SH_ASSERT(0, "Called with vfnptr 0x%p which couldn't be found in the list"); \ + } \ + HookManagerInfo::VfnPtr &vfnptr = *vfptriter; \ + /* 2) Find the iface */ \ + HookManagerInfo::VfnPtr::IfaceListIter ifiter = std::find(vfnptr.ifaces.begin(), vfnptr.ifaces.end(), this); \ + if (ifiter == vfnptr.ifaces.end()) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + return (reinterpret_cast(this)->*mfp)params; \ + } \ + HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \ /* 2) Declare some vars and set it up */ \ - std::list &prelist = ci.hooks_pre; \ - std::list &postlist = ci.hooks_post; \ - rettype orig_ret; \ - rettype override_ret; \ - rettype plugin_ret; \ + std::list &prelist = ci.hooks_pre; \ + std::list &postlist = ci.hooks_post; \ + rettype orig_ret, override_ret, plugin_ret; \ META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \ META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \ META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \ status = MRES_IGNORED; \ - SH_GLOB_SHPTR->SetIfacePtr(ci.ptr); \ + SH_GLOB_SHPTR->SetIfacePtr(this); \ SH_GLOB_SHPTR->SetOrigRet(reinterpret_cast(&orig_ret)); \ SH_GLOB_SHPTR->SetOverrideRet(NULL); #define SH_CALL_HOOKS(post, params) \ prev_res = MRES_IGNORED; \ - for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ + for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ @@ -417,44 +454,64 @@ namespace SourceHook } \ } -#define SH_CALL_ORIG(ifacetype, ifacefunc, params) \ +#define SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params) \ if (status != MRES_SUPERCEDE) \ - orig_ret = reinterpret_cast(ci.callclass)->ifacefunc params; \ + { \ + rettype (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + orig_ret = (reinterpret_cast(ci.ptr)->*mfp)params; \ + } \ else \ orig_ret = override_ret; #define SH_RETURN() \ return status >= MRES_OVERRIDE ? override_ret : orig_ret; -#define SH_HANDLEFUNC(ifacetype, ifacefunc, params, rettype) \ - SH_SETUPCALLS(rettype) \ +#define SH_HANDLEFUNC(ifacetype, ifacefunc, paramtypes, params, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params) \ SH_CALL_HOOKS(pre, params) \ - SH_CALL_ORIG(ifacetype, ifacefunc, params) \ + SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params) \ SH_CALL_HOOKS(post, params) \ SH_RETURN() ////////////////////////////////////////////////////////////////////////// -#define SH_SETUPCALLS_void() \ - /* 1) Find the iface ptr */ \ - /* 1.1) Adjust to original this pointer */ \ - void *origthis = this - ms_HI->thisptr_offs; \ - std::list::iterator ifaceiter = std::find(ms_HI->ifaces.begin(), \ - ms_HI->ifaces.end(), origthis); \ - SH_ASSERT(ifaceiter != ms_HI->ifaces.end()); \ - HookManagerInfo::Iface &ci = *ifaceiter; \ +#define SH_SETUPCALLS_void(paramtypes, params) \ + /* 1) Find the vfnptr */ \ + void *ourvfnptr = reinterpret_cast( \ + *reinterpret_cast(reinterpret_cast(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \ + \ + HookManagerInfo::VfnPtrListIter vfptriter = std::find(ms_HI->vfnptrs.begin(), \ + ms_HI->vfnptrs.end(), ourvfnptr); \ + if (vfptriter == ms_HI->vfnptrs.end()) \ + { \ + /* Bleh? Should be impossible! */ \ + SH_ASSERT(0, "Called with vfnptr 0x%p which couldn't be found in the list"); \ + } \ + HookManagerInfo::VfnPtr &vfnptr = *vfptriter; \ + /* 2) Find the iface */ \ + HookManagerInfo::VfnPtr::IfaceListIter ifiter = std::find(vfnptr.ifaces.begin(), vfnptr.ifaces.end(), this); \ + if (ifiter == vfnptr.ifaces.end()) \ + { \ + /* The iface info was not found. Redirect the call to the original function. */ \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(this)->*mfp)params; \ + return; \ + } \ + HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \ /* 2) Declare some vars and set it up */ \ - std::list &prelist = ci.hooks_pre; \ - std::list &postlist = ci.hooks_post; \ + std::list &prelist = ci.hooks_pre; \ + std::list &postlist = ci.hooks_post; \ META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \ META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \ META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \ status = MRES_IGNORED; \ - SH_GLOB_SHPTR->SetIfacePtr(ci.ptr); \ + SH_GLOB_SHPTR->SetIfacePtr(this); \ SH_GLOB_SHPTR->SetOverrideRet(NULL); #define SH_CALL_HOOKS_void(post, params) \ prev_res = MRES_IGNORED; \ - for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ + for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ @@ -464,53 +521,59 @@ namespace SourceHook status = cur_res; \ } -#define SH_CALL_ORIG_void(ifacetype, ifacefunc, params) \ +#define SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params) \ if (status != MRES_SUPERCEDE) \ - reinterpret_cast(ci.callclass)->ifacefunc params; + { \ + void (EmptyClass::*mfp)paramtypes; \ + SH_SETUP_MFP(mfp); \ + (reinterpret_cast(ci.ptr)->*mfp)params; \ + } #define SH_RETURN_void() -#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, params) \ - SH_SETUPCALLS_void() \ +#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, paramtypes, params) \ + SH_SETUPCALLS_void(paramtypes, params) \ SH_CALL_HOOKS_void(pre, params) \ - SH_CALL_ORIG_void(ifacetype, ifacefunc, params) \ + SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params) \ SH_CALL_HOOKS_void(post, params) \ SH_RETURN_void() // Special vafmt handlers -#define SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, params_orig, params_plug, rettype) \ - SH_SETUPCALLS(rettype) \ +#define SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, paramtypes, params_orig, params_plug, rettype) \ + SH_SETUPCALLS(rettype, paramtypes, params_orig) \ SH_CALL_HOOKS(pre, params_plug) \ - SH_CALL_ORIG(ifacetype, ifacefunc, params_orig) \ + SH_CALL_ORIG(ifacetype, ifacefunc, rettype, paramtypes, params_orig) \ SH_CALL_HOOKS(post, params_plug) \ SH_RETURN() -#define SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, params_orig, params_plug) \ - SH_SETUPCALLS_void() \ +#define SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, paramtypes, params_orig, params_plug) \ + SH_SETUPCALLS_void(paramtypes, params_orig) \ SH_CALL_HOOKS_void(pre, params_plug) \ - SH_CALL_ORIG_void(ifacetype, ifacefunc, params_orig) \ + SH_CALL_ORIG_void(ifacetype, ifacefunc, paramtypes, params_orig) \ SH_CALL_HOOKS_void(post, params_plug) \ SH_RETURN_void() ////////////////////////////////////////////////////////////////////////// -// ********* +// ********* Support for 0 arguments ********* #define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate0 FD; \ virtual rettype Func() attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype ) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (), (), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype , \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK0_void(ifacetype, ifacefunc, attr, overload) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate0<> FD; \ virtual void Func() attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, ()); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr ) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (), ()); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr , \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -523,9 +586,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, ("%s", buf), (buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (...), ("%s", buf), (buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK0_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -538,26 +602,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, ("%s", buf), (buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (...), ("%s", buf), (buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 1 arguments ********* #define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate1 FD; \ virtual rettype Func(param1 p1) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1), (p1), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK1_void(ifacetype, ifacefunc, attr, overload, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate1 FD; \ virtual void Func(param1 p1) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1), (p1)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -570,9 +637,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, "%s", buf), (p1, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, ...), (p1, "%s", buf), (p1, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK1_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -585,26 +653,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, "%s", buf), (p1, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, ...), (p1, "%s", buf), (p1, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 2 arguments ********* #define SH_DECL_HOOK2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate2 FD; \ virtual rettype Func(param1 p1, param2 p2) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2), (p1, p2), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate2 FD; \ virtual void Func(param1 p1, param2 p2) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2), (p1, p2)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -617,9 +688,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, ...), (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK2_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -632,26 +704,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, "%s", buf), (p1, p2, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, ...), (p1, p2, "%s", buf), (p1, p2, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 3 arguments ********* #define SH_DECL_HOOK3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate3 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3), (p1, p2, p3), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate3 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3), (p1, p2, p3)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -664,9 +739,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK3_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -679,26 +755,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 4 arguments ********* #define SH_DECL_HOOK4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate4 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate4 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4), (p1, p2, p3, p4)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -711,9 +790,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK4_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -726,26 +806,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 5 arguments ********* #define SH_DECL_HOOK5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate5 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate5 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -758,9 +841,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK5_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -773,26 +857,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 6 arguments ********* #define SH_DECL_HOOK6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate6 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate6 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -805,9 +892,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK6_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -820,26 +908,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 7 arguments ********* #define SH_DECL_HOOK7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate7 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate7 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -852,9 +943,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK7_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -867,26 +959,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 8 arguments ********* #define SH_DECL_HOOK8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate8 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate8 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -899,9 +994,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK8_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -914,26 +1010,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 9 arguments ********* #define SH_DECL_HOOK9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate9 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate9 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -946,9 +1045,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK9_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -961,26 +1061,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 10 arguments ********* #define SH_DECL_HOOK10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate10 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate10 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -993,9 +1096,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK10_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1008,26 +1112,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 11 arguments ********* #define SH_DECL_HOOK11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate11 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate11 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1040,9 +1147,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK11_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1055,26 +1163,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 12 arguments ********* #define SH_DECL_HOOK12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate12 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate12 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1087,9 +1198,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK12_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1102,26 +1214,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 13 arguments ********* #define SH_DECL_HOOK13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate13 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate13 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1134,9 +1249,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK13_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1149,26 +1265,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 14 arguments ********* #define SH_DECL_HOOK14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate14 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate14 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1181,9 +1300,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK14_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1196,26 +1316,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 15 arguments ********* #define SH_DECL_HOOK15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate15 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate15 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1228,9 +1351,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK15_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1243,26 +1367,29 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -// ********* +// ********* Support for 16 arguments ********* #define SH_DECL_HOOK16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate16 FD; \ virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) attr \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16) + { SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ (&ifacetype::ifacefunc))) \ typedef fastdelegate::FastDelegate16 FD; \ virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) attr \ - { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16) + { SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16, \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1275,9 +1402,10 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ + SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) #define SH_DECL_HOOK16_void_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ @@ -1290,21 +1418,257 @@ namespace SourceHook va_start(ap, fmt); \ vsnprintf(buf, sizeof(buf), fmt, ap); \ va_end(ap); \ - SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ + SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|const char*|...") + SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|const char*|...", \ + (static_cast(&ifacetype::ifacefunc))) -/* -#define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload) \ - typedef fastdelegate::FastDelegate1 FD; \ - virtual rettype Func(param1 p1) \ - { SH_HANDLEFUNC(ifacetype, ifacefunc, (p1), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #rettype "|" #param1) - -*/ +////////////////////////////////////////////////////////////////////////// +// SH_CALL + + +#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \ +{ \ + MemFuncInfo mfi; \ + MFI_Impl::GetFuncInfo(m_MFP, mfi); \ + OrigVTables::const_iterator iter = m_CC->vt.find(mfi.vtbloffs); \ + if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->second.size() || iter->second[mfi.vtblindex] == NULL) \ + return (m_CC->ptr->*m_MFP)call; \ + \ + /* It's hooked. Call the original function. */ \ + union \ + { \ + RetType(EmptyClass::*mfpnew)prms; \ + void *addr; \ + } u; \ + u.addr = iter->second[mfi.vtblindex]; \ + \ + return (reinterpret_cast(m_CC->ptr)->*u.mfpnew)call; \ +} + + +namespace SourceHook +{ + template class ExecutableClass + { + CCType *m_CC; + MFPType m_MFP; + public: + ExecutableClass(CCType *cc, MFPType mfp) : m_CC(cc), m_MFP(mfp) + { + } + + // Support for 0 arguments + template<> RetType operator()() const + SH_MAKE_EXECUTABLECLASS_OB((), ()) + + // Support for 1 arguments + template RetType operator()(Param1 p1) const + SH_MAKE_EXECUTABLECLASS_OB((p1), (Param1)) + + // Support for 2 arguments + template RetType operator()(Param1 p1, Param2 p2) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2), (Param1Param2)) + + // Support for 3 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3), (Param1Param2Param3)) + + // Support for 4 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4), (Param1Param2Param3Param4)) + + // Support for 5 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5), (Param1Param2Param3Param4Param5)) + + // Support for 6 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6), (Param1Param2Param3Param4Param5Param6)) + + // Support for 7 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7), (Param1Param2Param3Param4Param5Param6Param7)) + + // Support for 8 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8), (Param1Param2Param3Param4Param5Param6Param7Param8)) + + // Support for 9 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9), (Param1Param2Param3Param4Param5Param6Param7Param8Param9)) + + // Support for 10 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10)) + + // Support for 11 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10p11), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10Param11)) + + // Support for 12 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10p11p12), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10Param11Param12)) + + // Support for 13 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10p11p12p13), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10Param11Param12Param13)) + + // Support for 14 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10p11p12p13p14), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10Param11Param12Param13Param14)) + + // Support for 15 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10p11p12p13p14p15), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10Param11Param12Param13Param14Param15)) + + // Support for 16 arguments + template RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13, Param14 p14, Param15 p15, Param16 p16) const + SH_MAKE_EXECUTABLECLASS_OB((p1p2p3p4p5p6p7p8p9p10p11p12p13p14p15p16), (Param1Param2Param3Param4Param5Param6Param7Param8Param9Param10Param11Param12Param13Param14Param15Param16)) + + }; +} + +// Support for 0 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)()> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)()) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)()>(ptr, mfp); +} + +// Support for 1 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1)>(ptr, mfp); +} + +// Support for 2 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2)>(ptr, mfp); +} + +// Support for 3 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3)>(ptr, mfp); +} + +// Support for 4 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4)>(ptr, mfp); +} + +// Support for 5 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5)>(ptr, mfp); +} + +// Support for 6 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6)>(ptr, mfp); +} + +// Support for 7 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7)>(ptr, mfp); +} + +// Support for 8 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)>(ptr, mfp); +} + +// Support for 9 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9)>(ptr, mfp); +} + +// Support for 10 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)>(ptr, mfp); +} + +// Support for 11 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11)>(ptr, mfp); +} + +// Support for 12 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12)>(ptr, mfp); +} + +// Support for 13 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13)>(ptr, mfp); +} + +// Support for 14 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14)>(ptr, mfp); +} + +// Support for 15 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)>(ptr, mfp); +} + +// Support for 16 arguments +template +SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)> +SH_CALL(SourceHook::CallClass *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)) +{ + return SourceHook::ExecutableClass, RetType, RetType (X::*)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16)>(ptr, mfp); +} + + +#undef SH_MAKE_EXECUTABLECLASS_BODY #endif // The pope is dead. -> :( diff --git a/sourcehook/sourcehook_impl.h b/sourcehook/sourcehook_impl.h index c90d2dc..e27a81c 100644 --- a/sourcehook/sourcehook_impl.h +++ b/sourcehook/sourcehook_impl.h @@ -28,14 +28,15 @@ namespace SourceHook */ struct RemoveHookInfo { - RemoveHookInfo(Plugin p, void *i, HookManagerPubFunc h, ISHDelegate *hd, bool ps) - : plug(p), iface(i), hpf(h), handler(hd), post(ps) + RemoveHookInfo(Plugin pplug, void *piface, HookManagerPubFunc phookman, + ISHDelegate *phandler, bool ppost) + : plug(pplug), iface(piface), hookman(phookman), handler(phandler), post(ppost) { } Plugin plug; void *iface; - HookManagerPubFunc hpf; + HookManagerPubFunc hookman; ISHDelegate *handler; bool post; }; @@ -45,27 +46,30 @@ namespace SourceHook */ typedef std::list HookManInfoList; - + struct CallClassInfo + { + GenericCallClass cc; + int refcounter; + bool operator==(void *other) + { + return cc.ptr == other; + } + }; /** - * @brief A list of Impl_CallClass structures + * @brief A list of CallClass structures */ - typedef std::list Impl_CallClassList; + typedef std::list Impl_CallClassList; Impl_CallClassList m_CallClasses; //!< A list of already generated callclasses HookManInfoList m_HookMans; //!< A list of hook managers - int m_PageSize; //!< Stores the system's page size - /** * @brief Finds a hook manager for a function based on a text-prototype, a vtable offset and a vtable index */ HookManInfoList::iterator FindHookMan(HookManInfoList::iterator begin, HookManInfoList::iterator end, - const char *proto, int vtblofs, int vtblidx, int thisptrofs); + const char *proto, int vtblofs, int vtblidx); - void FreeCallClass(CallClass &cc); - bool ApplyCallClassPatch(CallClass &cc, int vtbl_offs, int vtbl_idx, void *orig_entry); - - static const int MAX_VTABLE_LEN = 4096; //!< Maximal vtable length in bytes + void ApplyCallClassPatch(CallClassInfo &cc, int vtbl_offs, int vtbl_idx, void *orig_entry); META_RES m_Status, m_PrevRes, m_CurRes; const void *m_OrigRet; @@ -97,7 +101,7 @@ namespace SourceHook * @param handler A pointer to a FastDelegate containing the hook handler * @param post Set to true if you want a post handler */ - bool AddHook(Plugin plug, void *iface, int ifacesize, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post); + bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post); /** * @brief Removes a hook. @@ -106,12 +110,35 @@ namespace SourceHook * * @param plug The unique identifier of the plugin that calls this function * @param iface The interface pointer + * @param thisptr_offs This pointer adjuster + * @param myHookMan A hook manager function that should be capable of handling the function + * @param handler A pointer to a FastDelegate containing the hook handler + * @param post Set to true if you want a post handler + */ + bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post); + + /** + * @brief Removes a hook. + * + * @return True if the function succeeded, false otherwise + * + * @param plug The unique identifier of the plugin that calls this function + * @param iface Already adjusted interface pointer * @param myHookMan A hook manager function that should be capable of handling the function * @param handler A pointer to a FastDelegate containing the hook handler * @param post Set to true if you want a post handler */ bool RemoveHook(Plugin plug, void *iface, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post); + /** + * @brief Removes a hook. + * + * @ return True if the function succeeded, false otherwise + * + * @param info A RemoveHookInfo structure, describing the hook + */ + bool RemoveHook(RemoveHookInfo info); + /** * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins * @@ -138,14 +165,14 @@ namespace SourceHook * * @param iface The interface pointer */ - void *GetCallClass(void *iface, size_t size); + GenericCallClass *GetCallClass(void *iface); /** * @brief Release a callclass * * @param ptr Pointer to the callclass */ - virtual void ReleaseCallClass(void *ptr); + virtual void ReleaseCallClass(GenericCallClass *ptr); virtual void SetRes(META_RES res); //!< Sets the meta result virtual META_RES GetPrevRes(); //!< Gets the meta result of the previously called handler diff --git a/sourcehook/test/main.cpp b/sourcehook/test/main.cpp index 320275f..f9cc512 100644 --- a/sourcehook/test/main.cpp +++ b/sourcehook/test/main.cpp @@ -402,93 +402,93 @@ bool Test_F16_int_post_handler(int x) RETURN_META_VALUE(MRES_OVERRIDE, !META_RESULT_ORIG_RET(bool)); } -// I haven't checked the second F16 function yet - int main(int argc, char *argv[]) { // Get an instance and call the functions using the pointer // (otherwise the compiler optimizes away the vtable lookup) Test zLOL; + Test zLOL2; Test *zLOL_Ptr = &zLOL; + Test *zLOL2_Ptr = &zLOL2; g_SHPtr = &g_SHImpl; ////////////////////////////////////////////////////////////////////////// - Test *cc = SH_GET_CALLCLASS(Test, zLOL_Ptr); + SourceHook::CallClass *cc = SH_GET_CALLCLASS(zLOL_Ptr); printf("TEST1.1: Calling F299\n"); zLOL_Ptr->F299(); printf("TEST1.2: Calling F299 through cc\n"); - cc->F299(); + SH_CALL(cc, &Test::F299)(); printf("TEST1.3: Hooking it\n"); SH_ADD_HOOK_STATICFUNC(Test, F299, zLOL_Ptr, Test_F299_pre_handler, false); + zLOL2_Ptr->F299(); printf("TEST1.4: Calling F299\n"); zLOL_Ptr->F299(); printf("TEST1.5: Calling F299 through cc\n"); - cc->F299(); + SH_CALL(cc, &Test::F299)(); printf("TEST1.6: Adding one more pre and one post hook\n"); SH_ADD_HOOK_STATICFUNC(Test, F299, zLOL_Ptr, Test_F299_pre_handler2, false); SH_ADD_HOOK_STATICFUNC(Test, F299, zLOL_Ptr, Test_F299_post_handler, true); printf("TEST1.7: Calling F299\n"); zLOL_Ptr->F299(); printf("TEST1.8: Calling F299 through cc\n"); - cc->F299(); + SH_CALL(cc, &Test::F299)(); printf("TEST1.9: Removing pre hooks\n"); SH_REMOVE_HOOK_STATICFUNC(Test, F299, zLOL_Ptr, Test_F299_pre_handler, false); SH_REMOVE_HOOK_STATICFUNC(Test, F299, zLOL_Ptr, Test_F299_pre_handler2, false); printf("TEST1.10: Calling F299\n"); zLOL_Ptr->F299(); printf("TEST1.11: Calling F299 through cc\n"); - cc->F299(); + SH_CALL(cc, &Test::F299)(); printf("TEST1.12: Removing post hook\n"); SH_REMOVE_HOOK_STATICFUNC(Test, F299, zLOL_Ptr, Test_F299_post_handler, true); printf("TEST1.13: Calling F299\n"); zLOL_Ptr->F299(); printf("TEST1.14: Calling F299 through cc\n"); - cc->F299(); + SH_CALL(cc, &Test::F299)(); ////////////////////////////////////////////////////////////////////////// printf("\n\n*************************************************\n\n"); printf("TEST2.1: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.2: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); printf("TEST2.3: Hooking it\n"); SH_ADD_HOOK_STATICFUNC(Test, F16, zLOL_Ptr, Test_F16_int_pre_handler, false); printf("TEST2.4: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.5: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); printf("TEST2.6: Adding post hook\n"); SH_ADD_HOOK_STATICFUNC(Test, F16, zLOL_Ptr, Test_F16_int_post_handler, true); printf("TEST2.7: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.8: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); - printf("TEST2.9: Removing pre hook\n"); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); printf("TEST2.XX.1: Pausing the plugin\n"); g_SHImpl.PausePlugin(g_PLID); printf("TEST2.XX.2: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.XX.3: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); printf("TEST2.XX.4: Unpausing the plugin\n"); g_SHImpl.UnpausePlugin(g_PLID); printf("TEST2.XX.5: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.XX.6: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); printf("TEST2.9: Removing pre hook\n"); SH_REMOVE_HOOK_STATICFUNC(Test, F16, zLOL_Ptr, Test_F16_int_pre_handler, false); printf("TEST2.10: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.11: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); printf("TEST2.12: Removing post hook\n"); SH_REMOVE_HOOK_STATICFUNC(Test, F16, zLOL_Ptr, Test_F16_int_post_handler, true); printf("TEST2.10: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); printf("TEST2.11: Calling F16(155) through CC\n"); - printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("Returned: %d\n", SH_CALL(cc, static_cast(&Test::F16))(155) ? 1 : 0); SH_RELEASE_CALLCLASS(cc);