mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-02-26 19:54:14 +01:00
CHANGES!
sh_memory.h: Added ModuleInMemory; first checks /proc/self/maps OR /proc/curproc/map; if not available tries DS's sigsegv trapping method sh_tinyhash: Added simple erase function(s) test/Makefile: New makefile Changed internal interface: sourcehook.hxx now doesn't need to know about implementation details like vectors etc. --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40118
This commit is contained in:
parent
71d74c6722
commit
2790931701
@ -16,8 +16,8 @@
|
|||||||
#ifndef __SOURCEHOOK_H__
|
#ifndef __SOURCEHOOK_H__
|
||||||
#define __SOURCEHOOK_H__
|
#define __SOURCEHOOK_H__
|
||||||
|
|
||||||
#define SH_IFACE_VERSION 1
|
#define SH_IFACE_VERSION 2
|
||||||
#define SH_IMPL_VERSION 1
|
#define SH_IMPL_VERSION 2
|
||||||
|
|
||||||
#ifndef SH_GLOB_SHPTR
|
#ifndef SH_GLOB_SHPTR
|
||||||
#define SH_GLOB_SHPTR g_SHPtr
|
#define SH_GLOB_SHPTR g_SHPtr
|
||||||
@ -27,13 +27,21 @@
|
|||||||
#define SH_GLOB_PLUGPTR g_PLID
|
#define SH_GLOB_PLUGPTR g_PLID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SH_DEBUG
|
#ifdef SH_DEBUG
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# define SH_ASSERT__(x, info, file, line, func) \
|
|
||||||
((printf("SOURCEHOOK DEBUG ASSERTION FAILED:\n %s:%u(%s): %s\n", file, line, func, info), true) ? (abort(), 0) : 0)
|
# define SH_ASSERT(x, info) \
|
||||||
# define SH_ASSERT(x, info) if (!(x)) SH_ASSERT__(x, info, __FILE__, __LINE__, __FUNCTION__)
|
do { \
|
||||||
|
if (!(x)) \
|
||||||
|
{ \
|
||||||
|
printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \
|
||||||
|
printf info; \
|
||||||
|
putchar('\n'); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define SH_ASSERT(x, info)
|
# define SH_ASSERT(x, info)
|
||||||
#endif
|
#endif
|
||||||
@ -70,10 +78,6 @@
|
|||||||
|
|
||||||
#include "FastDelegate.h"
|
#include "FastDelegate.h"
|
||||||
#include "sh_memfuncinfo.h"
|
#include "sh_memfuncinfo.h"
|
||||||
#include "sh_memory.h"
|
|
||||||
#include "sh_list.h"
|
|
||||||
#include "sh_vector.h"
|
|
||||||
#include "sh_tinyhash.h"
|
|
||||||
|
|
||||||
// Good old metamod!
|
// Good old metamod!
|
||||||
|
|
||||||
@ -90,7 +94,10 @@ enum META_RES
|
|||||||
|
|
||||||
namespace SourceHook
|
namespace SourceHook
|
||||||
{
|
{
|
||||||
const int STRBUF_LEN=4096; // In bytes, for "vafmt" functions
|
/**
|
||||||
|
* @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers
|
||||||
|
*/
|
||||||
|
const int STRBUF_LEN=4096;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An empty class. No inheritance used. Used for original-function-call hacks
|
* @brief An empty class. No inheritance used. Used for original-function-call hacks
|
||||||
@ -111,29 +118,33 @@ namespace SourceHook
|
|||||||
/**
|
/**
|
||||||
* @brief A plugin typedef
|
* @brief A plugin typedef
|
||||||
*
|
*
|
||||||
* SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it
|
* SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every
|
||||||
* and every plugin has a unique identifier, everything is ok.
|
* plugin has a unique identifier, everything is ok.
|
||||||
|
* It should also be possible to set it to 0.
|
||||||
*/
|
*/
|
||||||
typedef int Plugin;
|
typedef int Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Specifies the actions for hook managers
|
||||||
|
*/
|
||||||
enum HookManagerAction
|
enum HookManagerAction
|
||||||
{
|
{
|
||||||
HA_GetInfo = 0, // -> Only store info
|
HA_GetInfo = 0, //!< Store info about the hook manager
|
||||||
HA_Register, // -> Save the pointer for future reference
|
HA_Register, //!< Save the IHookManagerInfo pointer for future reference
|
||||||
HA_Unregister // -> Clear the saved pointer
|
HA_Unregister //!< Clear the saved pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HookManagerInfo;
|
class IHookManagerInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to hook manager type
|
* @brief Pointer to hook manager interface function
|
||||||
*
|
*
|
||||||
* A "hook manager" is a the only thing that knows the actual protoype of the function at compile time.
|
* A "hook manager" is a the only thing that knows the actual protoype of the function at compile time.
|
||||||
*
|
*
|
||||||
* @param hi A pointer to a HookManagerInfo structure. The hook manager should fill it and store it for
|
* @param ha What the hook manager should do
|
||||||
* future reference (mainly if something should get hooked to its hookfunc)
|
* @param hi A pointer to IHookManagerInfo
|
||||||
*/
|
*/
|
||||||
typedef int (*HookManagerPubFunc)(HookManagerAction ha, HookManagerInfo *hi);
|
typedef int (*HookManagerPubFunc)(HookManagerAction ha, IHookManagerInfo *hi);
|
||||||
|
|
||||||
class ISHDelegate
|
class ISHDelegate
|
||||||
{
|
{
|
||||||
@ -170,65 +181,83 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct IHookList
|
||||||
* @brief This structure contains information about a hook manager (hook manager)
|
|
||||||
*/
|
|
||||||
struct HookManagerInfo
|
|
||||||
{
|
{
|
||||||
struct VfnPtr
|
struct IIter
|
||||||
{
|
{
|
||||||
struct Iface
|
virtual bool End() = 0;
|
||||||
{
|
virtual void Next() = 0;
|
||||||
struct Hook
|
virtual ISHDelegate *Handler() = 0;
|
||||||
{
|
virtual int ThisPtrOffs() = 0;
|
||||||
ISHDelegate *handler; //!< Pointer to the handler
|
|
||||||
bool paused; //!< If true, the hook should not be executed
|
|
||||||
Plugin plug; //!< The owner plugin
|
|
||||||
int thisptr_offs; //!< This pointer offset
|
|
||||||
};
|
};
|
||||||
void *ptr; //!< Pointer to the interface instance
|
virtual IIter *GetIter() = 0;
|
||||||
List<Hook> hooks_pre; //!< A list of pre-hooks
|
virtual void ReleaseIter(IIter *pIter) = 0;
|
||||||
List<Hook> hooks_post; //!< A list of post-hooks
|
};
|
||||||
bool operator ==(void *other) const
|
|
||||||
|
struct IIface
|
||||||
|
{
|
||||||
|
virtual void *GetPtr() = 0;
|
||||||
|
virtual IHookList *GetPreHooks() = 0;
|
||||||
|
virtual IHookList *GetPostHooks() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IVfnPtr
|
||||||
|
{
|
||||||
|
virtual void *GetVfnPtr() = 0;
|
||||||
|
virtual void *GetOrigEntry() = 0;
|
||||||
|
|
||||||
|
virtual IIface *FindIface(void *ptr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IHookManagerInfo
|
||||||
|
{
|
||||||
|
virtual IVfnPtr *FindVfnPtr(void *vfnptr) = 0;
|
||||||
|
|
||||||
|
virtual void SetInfo(int vtbloffs, int vtblidx, const char *proto) = 0;
|
||||||
|
virtual void SetHookfuncVfnptr(void *hookfunc_vfnptr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoHookIter
|
||||||
|
{
|
||||||
|
IHookList *m_pList;
|
||||||
|
IHookList::IIter *m_pIter;
|
||||||
|
public:
|
||||||
|
AutoHookIter(IHookList *pList)
|
||||||
|
: m_pList(pList), m_pIter(pList->GetIter())
|
||||||
{
|
{
|
||||||
return ptr == other;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
void *vfnptr; //!< Pointer to the function
|
~AutoHookIter()
|
||||||
void *orig_entry; //!< The original vtable entry
|
|
||||||
|
|
||||||
typedef List<Iface> IfaceList;
|
|
||||||
typedef IfaceList::iterator IfaceListIter;
|
|
||||||
IfaceList ifaces; //!< List of interface pointers
|
|
||||||
|
|
||||||
bool operator ==(void *other)
|
|
||||||
{
|
{
|
||||||
return vfnptr == other;
|
m_pList->ReleaseIter(m_pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool End()
|
||||||
|
{
|
||||||
|
return m_pIter->End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next()
|
||||||
|
{
|
||||||
|
m_pIter->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISHDelegate *Handler()
|
||||||
|
{
|
||||||
|
return m_pIter->Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThisPtrOffs()
|
||||||
|
{
|
||||||
|
return m_pIter->ThisPtrOffs();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
|
||||||
HookManagerPubFunc func; //!< The interface to the hook manager
|
|
||||||
|
|
||||||
void *hookfunc_vfnptr; //!< Pointer to the hookfunc impl
|
|
||||||
|
|
||||||
typedef List<VfnPtr> VfnPtrList;
|
|
||||||
typedef VfnPtrList::iterator VfnPtrListIter;
|
|
||||||
VfnPtrList vfnptrs; //!< List of hooked interfaces
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SourceHook::CVector<void*> OrigFuncs;
|
|
||||||
typedef SourceHook::THash<int, OrigFuncs> OrigVTables;
|
|
||||||
|
|
||||||
template<class B> struct CallClass
|
template<class B> struct CallClass
|
||||||
{
|
{
|
||||||
B *ptr; //!< Pointer to the actual object
|
virtual B *GetThisPtr() = 0;
|
||||||
size_t objsize; //!< Size of the instance
|
virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0;
|
||||||
OrigVTables vt; //!< Info about vtables & functions
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef CallClass<void> GenericCallClass;
|
typedef CallClass<void> GenericCallClass;
|
||||||
@ -239,8 +268,6 @@ namespace SourceHook
|
|||||||
class ISourceHook
|
class ISourceHook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ISourceHook()
|
|
||||||
{ }
|
|
||||||
/**
|
/**
|
||||||
* @brief Return interface version
|
* @brief Return interface version
|
||||||
*/
|
*/
|
||||||
@ -263,7 +290,8 @@ namespace SourceHook
|
|||||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||||
* @param post Set to true if you want a post handler
|
* @param post Set to true if you want a post handler
|
||||||
*/
|
*/
|
||||||
virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, 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.
|
* @brief Removes a hook.
|
||||||
@ -276,7 +304,8 @@ namespace SourceHook
|
|||||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||||
* @param post Set to true if you want a post handler
|
* @param post Set to true if you want a post handler
|
||||||
*/
|
*/
|
||||||
virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, 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
|
* @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins
|
||||||
@ -301,10 +330,13 @@ namespace SourceHook
|
|||||||
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
||||||
|
|
||||||
virtual void SetRes(META_RES res) = 0; //!< Sets the meta result
|
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
|
virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the
|
||||||
|
//!< previously calledhandler
|
||||||
virtual META_RES GetStatus() = 0; //!< Gets the highest meta result
|
virtual META_RES GetStatus() = 0; //!< Gets the highest meta result
|
||||||
virtual const void *GetOrigRet() = 0; //!< Gets the original result. If not in post function, undefined
|
virtual const void *GetOrigRet() = 0; //!< Gets the original result.
|
||||||
virtual const void *GetOverrideRet() = 0; //!< Gets the override result. If none is specified, NULL
|
//!< If not in post function, undefined
|
||||||
|
virtual const void *GetOverrideRet() = 0; //!< Gets the override result.
|
||||||
|
//!< If none is specified, NULL
|
||||||
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// For hook managers
|
// For hook managers
|
||||||
@ -375,10 +407,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
# define SH_SETUP_MFP(mfp) \
|
# define SH_SETUP_MFP(mfp) \
|
||||||
reinterpret_cast<void**>(&mfp)[0] = vfnptr.orig_entry;
|
reinterpret_cast<void**>(&mfp)[0] = vfnptr->GetOrigEntry();
|
||||||
#elif SH_COMP == SH_COMP_GCC
|
#elif SH_COMP == SH_COMP_GCC
|
||||||
# define SH_SETUP_MFP(mfp) \
|
# define SH_SETUP_MFP(mfp) \
|
||||||
reinterpret_cast<void**>(&mfp)[0] = vfnptr.orig_entry; \
|
reinterpret_cast<void**>(&mfp)[0] = vfnptr->GetOrigEntry(); \
|
||||||
reinterpret_cast<void**>(&mfp)[1] = 0;
|
reinterpret_cast<void**>(&mfp)[1] = 0;
|
||||||
#else
|
#else
|
||||||
# error Not supported yet.
|
# error Not supported yet.
|
||||||
@ -388,24 +420,27 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
||||||
|
|
||||||
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
||||||
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::HookManagerInfo *param) \
|
SH_FHCls(ifacetype,ifacefunc,overload)() \
|
||||||
|
{ \
|
||||||
|
GetFuncInfo(funcptr, ms_MFI); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \
|
||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
|
GetFuncInfo(funcptr, ms_MFI); \
|
||||||
/* Verify interface version */ \
|
/* Verify interface version */ \
|
||||||
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
if (action == ::SourceHook::HA_GetInfo) \
|
if (action == ::SourceHook::HA_GetInfo) \
|
||||||
{ \
|
{ \
|
||||||
param->proto = ms_Proto; \
|
param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, ms_Proto); \
|
||||||
MemFuncInfo mfi; \
|
|
||||||
GetFuncInfo(funcptr, mfi); \
|
|
||||||
param->vtbl_idx = mfi.vtblindex; \
|
|
||||||
param->vtbl_offs = mfi.vtbloffs; \
|
|
||||||
\
|
\
|
||||||
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
||||||
param->hookfunc_vfnptr = \
|
param->SetHookfuncVfnptr( \
|
||||||
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]; \
|
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
else if (action == ::SourceHook::HA_Register) \
|
else if (action == ::SourceHook::HA_Register) \
|
||||||
@ -429,15 +464,17 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
struct SH_FHCls(ifacetype,ifacefunc,overload) \
|
struct SH_FHCls(ifacetype,ifacefunc,overload) \
|
||||||
{ \
|
{ \
|
||||||
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
||||||
static ::SourceHook::HookManagerInfo *ms_HI; \
|
static ::SourceHook::MemFuncInfo ms_MFI; \
|
||||||
|
static ::SourceHook::IHookManagerInfo *ms_HI; \
|
||||||
static const char *ms_Proto; \
|
static const char *ms_Proto; \
|
||||||
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
||||||
|
|
||||||
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
||||||
}; \
|
}; \
|
||||||
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
||||||
::SourceHook::HookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \
|
||||||
|
::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
||||||
|
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
||||||
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
||||||
{ \
|
{ \
|
||||||
@ -469,28 +506,22 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
void *ourvfnptr = reinterpret_cast<void*>( \
|
void *ourvfnptr = reinterpret_cast<void*>( \
|
||||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
|
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \
|
||||||
|
IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \
|
||||||
|
SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \
|
||||||
\
|
\
|
||||||
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
|
/* ... and the iface */ \
|
||||||
if (vfptriter == ms_HI->vfnptrs.end()) \
|
IIface *ifinfo = vfnptr->FindIface(reinterpret_cast<void*>(this)); \
|
||||||
{ \
|
if (!ifinfo) \
|
||||||
/* 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 = vfnptr.ifaces.find(this); \
|
|
||||||
if (ifiter == vfnptr.ifaces.end()) \
|
|
||||||
{ \
|
{ \
|
||||||
/* The iface info was not found. Redirect the call to the original function. */ \
|
/* The iface info was not found. Redirect the call to the original function. */ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||||
} \
|
} \
|
||||||
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
|
|
||||||
/* 2) Declare some vars and set it up */ \
|
/* 2) Declare some vars and set it up */ \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
|
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
|
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||||
rettype orig_ret; \
|
rettype orig_ret; \
|
||||||
rettype override_ret; \
|
rettype override_ret; \
|
||||||
rettype plugin_ret; \
|
rettype plugin_ret; \
|
||||||
@ -504,12 +535,11 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#define SH_CALL_HOOKS(post, params) \
|
#define SH_CALL_HOOKS(post, params) \
|
||||||
prev_res = MRES_IGNORED; \
|
prev_res = MRES_IGNORED; \
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
|
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||||
{ \
|
{ \
|
||||||
if (hiter->paused) continue; \
|
|
||||||
cur_res = MRES_IGNORED; \
|
cur_res = MRES_IGNORED; \
|
||||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - hiter->thisptr_offs); \
|
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||||
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(hiter->handler)->GetDeleg() params; \
|
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||||
prev_res = cur_res; \
|
prev_res = cur_res; \
|
||||||
if (cur_res > status) \
|
if (cur_res > status) \
|
||||||
status = cur_res; \
|
status = cur_res; \
|
||||||
@ -525,7 +555,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
orig_ret = (reinterpret_cast<EmptyClass*>(ci.ptr)->*mfp)params; \
|
orig_ret = (reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)params; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
orig_ret = override_ret;
|
orig_ret = override_ret;
|
||||||
@ -542,21 +572,16 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define SH_SETUPCALLS_void(paramtypes, params) \
|
#define SH_SETUPCALLS_void(paramtypes, params) \
|
||||||
using namespace ::SourceHook; \
|
|
||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
|
using namespace ::SourceHook; \
|
||||||
void *ourvfnptr = reinterpret_cast<void*>( \
|
void *ourvfnptr = reinterpret_cast<void*>( \
|
||||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
|
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \
|
||||||
|
IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \
|
||||||
|
SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \
|
||||||
\
|
\
|
||||||
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
|
/* ... and the iface */ \
|
||||||
if (vfptriter == ms_HI->vfnptrs.end()) \
|
IIface *ifinfo = vfnptr->FindIface(reinterpret_cast<void*>(this)); \
|
||||||
{ \
|
if (!ifinfo) \
|
||||||
/* 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 = vfnptr.ifaces.find(this); \
|
|
||||||
if (ifiter == vfnptr.ifaces.end()) \
|
|
||||||
{ \
|
{ \
|
||||||
/* The iface info was not found. Redirect the call to the original function. */ \
|
/* The iface info was not found. Redirect the call to the original function. */ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
@ -564,25 +589,24 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
|
|
||||||
/* 2) Declare some vars and set it up */ \
|
/* 2) Declare some vars and set it up */ \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
|
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
|
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||||
status = MRES_IGNORED; \
|
status = MRES_IGNORED; \
|
||||||
SH_GLOB_SHPTR->SetOverrideRet(NULL);
|
SH_GLOB_SHPTR->SetOverrideRet(NULL); \
|
||||||
|
SH_GLOB_SHPTR->SetOrigRet(NULL);
|
||||||
|
|
||||||
#define SH_CALL_HOOKS_void(post, params) \
|
#define SH_CALL_HOOKS_void(post, params) \
|
||||||
prev_res = MRES_IGNORED; \
|
prev_res = MRES_IGNORED; \
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
|
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||||
{ \
|
{ \
|
||||||
if (hiter->paused) continue; \
|
|
||||||
cur_res = MRES_IGNORED; \
|
cur_res = MRES_IGNORED; \
|
||||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - hiter->thisptr_offs); \
|
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||||
reinterpret_cast<CSHDelegate<FD>*>(hiter->handler)->GetDeleg() params; \
|
reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||||
prev_res = cur_res; \
|
prev_res = cur_res; \
|
||||||
if (cur_res > status) \
|
if (cur_res > status) \
|
||||||
status = cur_res; \
|
status = cur_res; \
|
||||||
@ -593,7 +617,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
(reinterpret_cast<EmptyClass*>(ci.ptr)->*mfp)params; \
|
(reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)params; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SH_RETURN_void()
|
#define SH_RETURN_void()
|
||||||
@ -1490,6 +1514,210 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
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<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 17 arguments *********
|
||||||
|
#define SH_DECL_HOOK17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate17<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, rettype> 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, param17 p17) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), 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 "|" #param17, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate17<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17> 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, param17 p17) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, rettype> 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, param17 p17, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, 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 "|" #param17 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *> 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, param17 p17, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, 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 "|" #param17 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 18 arguments *********
|
||||||
|
#define SH_DECL_HOOK18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, rettype> 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, param17 p17, param18 p18) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), 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 "|" #param17 "|" #param18, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18> 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, param17 p17, param18 p18) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17 "|" #param18, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, rettype> 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, param17 p17, param18 p18, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, 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 "|" #param17 "|" #param18 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *> 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, param17 p17, param18 p18, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, 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 "|" #param17 "|" #param18 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 19 arguments *********
|
||||||
|
#define SH_DECL_HOOK19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, rettype> 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, param17 p17, param18 p18, param19 p19) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), 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 "|" #param17 "|" #param18 "|" #param19, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19> 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, param17 p17, param18 p18, param19 p19) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17 "|" #param18 "|" #param19, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, rettype> 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, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 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 "|" #param17 "|" #param18 "|" #param19 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *> 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, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 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 "|" #param17 "|" #param18 "|" #param19 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 20 arguments *********
|
||||||
|
#define SH_DECL_HOOK20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, rettype> 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, param17 p17, param18 p18, param19 p19, param20 p20) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), 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 "|" #param17 "|" #param18 "|" #param19 "|" #param20, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20> 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, param17 p17, param18 p18, param19 p19, param20 p20) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17 "|" #param18 "|" #param19 "|" #param20, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate21<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, rettype> 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, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, 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 "|" #param17 "|" #param18 "|" #param19 "|" #param20 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate21<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *> 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, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, 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 "|" #param17 "|" #param18 "|" #param19 "|" #param20 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -1497,14 +1725,16 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
|
|
||||||
|
// :TODO: TEST THIS ON MSVC
|
||||||
|
|
||||||
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(m_CC->ptr, m_MFP, mfi); \
|
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||||
OrigVTables::iterator iter = m_CC->vt.find(mfi.thisptroffs + mfi.vtbloffs); \
|
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||||
if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->val.size() || iter->val[mfi.vtblindex] == NULL) \
|
if (!origfunc) \
|
||||||
return (m_CC->ptr->*m_MFP)call; \
|
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||||
\
|
\
|
||||||
/* It's hooked. Call the original function. */ \
|
/* It's hooked. Call the original function. */ \
|
||||||
union \
|
union \
|
||||||
@ -1512,9 +1742,9 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
RetType(EmptyClass::*mfpnew)prms; \
|
RetType(EmptyClass::*mfpnew)prms; \
|
||||||
void *addr; \
|
void *addr; \
|
||||||
} u; \
|
} u; \
|
||||||
u.addr = iter->val[mfi.vtblindex]; \
|
u.addr = origfunc; \
|
||||||
\
|
\
|
||||||
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->ptr) + mfi.thisptroffs); \
|
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->GetThisPtr()) + mfi.thisptroffs); \
|
||||||
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1524,10 +1754,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(m_CC->ptr, m_MFP, mfi); \
|
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||||
OrigVTables::iterator iter = m_CC->vt.find(mfi.thisptroffs + mfi.vtbloffs); \
|
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||||
if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->val.size() || iter->val[mfi.vtblindex] == NULL) \
|
if (!origfunc) \
|
||||||
return (m_CC->ptr->*m_MFP)call; \
|
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||||
\
|
\
|
||||||
/* It's hooked. Call the original function. */ \
|
/* It's hooked. Call the original function. */ \
|
||||||
union \
|
union \
|
||||||
@ -1539,10 +1769,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
intptr_t adjustor; \
|
intptr_t adjustor; \
|
||||||
} s; \
|
} s; \
|
||||||
} u; \
|
} u; \
|
||||||
u.s.addr = iter->val[mfi.vtblindex]; \
|
u.s.addr = origfunc; \
|
||||||
u.s.adjustor = mfi.thisptroffs; \
|
u.s.adjustor = mfi.thisptroffs; \
|
||||||
\
|
\
|
||||||
return (reinterpret_cast<EmptyClass*>(m_CC->ptr)->*u.mfpnew)call; \
|
return (reinterpret_cast<EmptyClass*>(m_CC->GetThisPtr())->*u.mfpnew)call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1626,6 +1856,22 @@ namespace SourceHook
|
|||||||
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16> 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
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16> 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((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16))
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16))
|
||||||
|
|
||||||
|
// Support for 17 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17> 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, Param17 p17) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17))
|
||||||
|
|
||||||
|
// Support for 18 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18> 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, Param17 p17, Param18 p18) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18))
|
||||||
|
|
||||||
|
// Support for 19 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19> 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, Param17 p17, Param18 p18, Param19 p19) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19))
|
||||||
|
|
||||||
|
// Support for 20 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20> 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, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20))
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1888,6 +2134,66 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param
|
|||||||
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support for 17 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 18 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 19 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 20 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
|
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
|
||||||
// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it
|
// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it
|
||||||
@ -2147,12 +2453,72 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param
|
|||||||
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support for 17 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 18 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 19 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 20 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
||||||
|
|
||||||
#undef SH_MAKE_EXECUTABLECLASS_BODY
|
#undef SH_MAKE_EXECUTABLECLASS_OB
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// The pope is dead. -> :(
|
// The pope is dead. -> :(
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
#ifndef __SOURCEHOOK_H__
|
#ifndef __SOURCEHOOK_H__
|
||||||
#define __SOURCEHOOK_H__
|
#define __SOURCEHOOK_H__
|
||||||
|
|
||||||
#define SH_IFACE_VERSION 1
|
#define SH_IFACE_VERSION 2
|
||||||
#define SH_IMPL_VERSION 1
|
#define SH_IMPL_VERSION 2
|
||||||
|
|
||||||
#ifndef SH_GLOB_SHPTR
|
#ifndef SH_GLOB_SHPTR
|
||||||
#define SH_GLOB_SHPTR g_SHPtr
|
#define SH_GLOB_SHPTR g_SHPtr
|
||||||
@ -27,13 +27,21 @@
|
|||||||
#define SH_GLOB_PLUGPTR g_PLID
|
#define SH_GLOB_PLUGPTR g_PLID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SH_DEBUG
|
#ifdef SH_DEBUG
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# define SH_ASSERT__(x, info, file, line, func) \
|
|
||||||
((printf("SOURCEHOOK DEBUG ASSERTION FAILED:\n %s:%u(%s): %s\n", file, line, func, info), true) ? (abort(), 0) : 0)
|
# define SH_ASSERT(x, info) \
|
||||||
# define SH_ASSERT(x, info) if (!(x)) SH_ASSERT__(x, info, __FILE__, __LINE__, __FUNCTION__)
|
do { \
|
||||||
|
if (!(x)) \
|
||||||
|
{ \
|
||||||
|
printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \
|
||||||
|
printf info; \
|
||||||
|
putchar('\n'); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define SH_ASSERT(x, info)
|
# define SH_ASSERT(x, info)
|
||||||
#endif
|
#endif
|
||||||
@ -70,10 +78,6 @@
|
|||||||
|
|
||||||
#include "FastDelegate.h"
|
#include "FastDelegate.h"
|
||||||
#include "sh_memfuncinfo.h"
|
#include "sh_memfuncinfo.h"
|
||||||
#include "sh_memory.h"
|
|
||||||
#include "sh_list.h"
|
|
||||||
#include "sh_vector.h"
|
|
||||||
#include "sh_tinyhash.h"
|
|
||||||
|
|
||||||
// Good old metamod!
|
// Good old metamod!
|
||||||
|
|
||||||
@ -90,7 +94,10 @@ enum META_RES
|
|||||||
|
|
||||||
namespace SourceHook
|
namespace SourceHook
|
||||||
{
|
{
|
||||||
const int STRBUF_LEN=4096; // In bytes, for "vafmt" functions
|
/**
|
||||||
|
* @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers
|
||||||
|
*/
|
||||||
|
const int STRBUF_LEN=4096;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An empty class. No inheritance used. Used for original-function-call hacks
|
* @brief An empty class. No inheritance used. Used for original-function-call hacks
|
||||||
@ -111,29 +118,33 @@ namespace SourceHook
|
|||||||
/**
|
/**
|
||||||
* @brief A plugin typedef
|
* @brief A plugin typedef
|
||||||
*
|
*
|
||||||
* SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it
|
* SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every
|
||||||
* and every plugin has a unique identifier, everything is ok.
|
* plugin has a unique identifier, everything is ok.
|
||||||
|
* It should also be possible to set it to 0.
|
||||||
*/
|
*/
|
||||||
typedef int Plugin;
|
typedef int Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Specifies the actions for hook managers
|
||||||
|
*/
|
||||||
enum HookManagerAction
|
enum HookManagerAction
|
||||||
{
|
{
|
||||||
HA_GetInfo = 0, // -> Only store info
|
HA_GetInfo = 0, //!< Store info about the hook manager
|
||||||
HA_Register, // -> Save the pointer for future reference
|
HA_Register, //!< Save the IHookManagerInfo pointer for future reference
|
||||||
HA_Unregister // -> Clear the saved pointer
|
HA_Unregister //!< Clear the saved pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HookManagerInfo;
|
class IHookManagerInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to hook manager type
|
* @brief Pointer to hook manager interface function
|
||||||
*
|
*
|
||||||
* A "hook manager" is a the only thing that knows the actual protoype of the function at compile time.
|
* A "hook manager" is a the only thing that knows the actual protoype of the function at compile time.
|
||||||
*
|
*
|
||||||
* @param hi A pointer to a HookManagerInfo structure. The hook manager should fill it and store it for
|
* @param ha What the hook manager should do
|
||||||
* future reference (mainly if something should get hooked to its hookfunc)
|
* @param hi A pointer to IHookManagerInfo
|
||||||
*/
|
*/
|
||||||
typedef int (*HookManagerPubFunc)(HookManagerAction ha, HookManagerInfo *hi);
|
typedef int (*HookManagerPubFunc)(HookManagerAction ha, IHookManagerInfo *hi);
|
||||||
|
|
||||||
class ISHDelegate
|
class ISHDelegate
|
||||||
{
|
{
|
||||||
@ -170,65 +181,83 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct IHookList
|
||||||
* @brief This structure contains information about a hook manager (hook manager)
|
|
||||||
*/
|
|
||||||
struct HookManagerInfo
|
|
||||||
{
|
{
|
||||||
struct VfnPtr
|
struct IIter
|
||||||
{
|
{
|
||||||
struct Iface
|
virtual bool End() = 0;
|
||||||
{
|
virtual void Next() = 0;
|
||||||
struct Hook
|
virtual ISHDelegate *Handler() = 0;
|
||||||
{
|
virtual int ThisPtrOffs() = 0;
|
||||||
ISHDelegate *handler; //!< Pointer to the handler
|
|
||||||
bool paused; //!< If true, the hook should not be executed
|
|
||||||
Plugin plug; //!< The owner plugin
|
|
||||||
int thisptr_offs; //!< This pointer offset
|
|
||||||
};
|
};
|
||||||
void *ptr; //!< Pointer to the interface instance
|
virtual IIter *GetIter() = 0;
|
||||||
List<Hook> hooks_pre; //!< A list of pre-hooks
|
virtual void ReleaseIter(IIter *pIter) = 0;
|
||||||
List<Hook> hooks_post; //!< A list of post-hooks
|
};
|
||||||
bool operator ==(void *other) const
|
|
||||||
|
struct IIface
|
||||||
|
{
|
||||||
|
virtual void *GetPtr() = 0;
|
||||||
|
virtual IHookList *GetPreHooks() = 0;
|
||||||
|
virtual IHookList *GetPostHooks() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IVfnPtr
|
||||||
|
{
|
||||||
|
virtual void *GetVfnPtr() = 0;
|
||||||
|
virtual void *GetOrigEntry() = 0;
|
||||||
|
|
||||||
|
virtual IIface *FindIface(void *ptr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IHookManagerInfo
|
||||||
|
{
|
||||||
|
virtual IVfnPtr *FindVfnPtr(void *vfnptr) = 0;
|
||||||
|
|
||||||
|
virtual void SetInfo(int vtbloffs, int vtblidx, const char *proto) = 0;
|
||||||
|
virtual void SetHookfuncVfnptr(void *hookfunc_vfnptr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoHookIter
|
||||||
|
{
|
||||||
|
IHookList *m_pList;
|
||||||
|
IHookList::IIter *m_pIter;
|
||||||
|
public:
|
||||||
|
AutoHookIter(IHookList *pList)
|
||||||
|
: m_pList(pList), m_pIter(pList->GetIter())
|
||||||
{
|
{
|
||||||
return ptr == other;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
void *vfnptr; //!< Pointer to the function
|
~AutoHookIter()
|
||||||
void *orig_entry; //!< The original vtable entry
|
|
||||||
|
|
||||||
typedef List<Iface> IfaceList;
|
|
||||||
typedef IfaceList::iterator IfaceListIter;
|
|
||||||
IfaceList ifaces; //!< List of interface pointers
|
|
||||||
|
|
||||||
bool operator ==(void *other)
|
|
||||||
{
|
{
|
||||||
return vfnptr == other;
|
m_pList->ReleaseIter(m_pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool End()
|
||||||
|
{
|
||||||
|
return m_pIter->End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next()
|
||||||
|
{
|
||||||
|
m_pIter->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISHDelegate *Handler()
|
||||||
|
{
|
||||||
|
return m_pIter->Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThisPtrOffs()
|
||||||
|
{
|
||||||
|
return m_pIter->ThisPtrOffs();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
|
||||||
HookManagerPubFunc func; //!< The interface to the hook manager
|
|
||||||
|
|
||||||
void *hookfunc_vfnptr; //!< Pointer to the hookfunc impl
|
|
||||||
|
|
||||||
typedef List<VfnPtr> VfnPtrList;
|
|
||||||
typedef VfnPtrList::iterator VfnPtrListIter;
|
|
||||||
VfnPtrList vfnptrs; //!< List of hooked interfaces
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SourceHook::CVector<void*> OrigFuncs;
|
|
||||||
typedef SourceHook::THash<int, OrigFuncs> OrigVTables;
|
|
||||||
|
|
||||||
template<class B> struct CallClass
|
template<class B> struct CallClass
|
||||||
{
|
{
|
||||||
B *ptr; //!< Pointer to the actual object
|
virtual B *GetThisPtr() = 0;
|
||||||
size_t objsize; //!< Size of the instance
|
virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0;
|
||||||
OrigVTables vt; //!< Info about vtables & functions
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef CallClass<void> GenericCallClass;
|
typedef CallClass<void> GenericCallClass;
|
||||||
@ -239,8 +268,6 @@ namespace SourceHook
|
|||||||
class ISourceHook
|
class ISourceHook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ISourceHook()
|
|
||||||
{ }
|
|
||||||
/**
|
/**
|
||||||
* @brief Return interface version
|
* @brief Return interface version
|
||||||
*/
|
*/
|
||||||
@ -263,7 +290,8 @@ namespace SourceHook
|
|||||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||||
* @param post Set to true if you want a post handler
|
* @param post Set to true if you want a post handler
|
||||||
*/
|
*/
|
||||||
virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, 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.
|
* @brief Removes a hook.
|
||||||
@ -276,7 +304,8 @@ namespace SourceHook
|
|||||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||||
* @param post Set to true if you want a post handler
|
* @param post Set to true if you want a post handler
|
||||||
*/
|
*/
|
||||||
virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, 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
|
* @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins
|
||||||
@ -301,10 +330,13 @@ namespace SourceHook
|
|||||||
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
||||||
|
|
||||||
virtual void SetRes(META_RES res) = 0; //!< Sets the meta result
|
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
|
virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the
|
||||||
|
//!< previously calledhandler
|
||||||
virtual META_RES GetStatus() = 0; //!< Gets the highest meta result
|
virtual META_RES GetStatus() = 0; //!< Gets the highest meta result
|
||||||
virtual const void *GetOrigRet() = 0; //!< Gets the original result. If not in post function, undefined
|
virtual const void *GetOrigRet() = 0; //!< Gets the original result.
|
||||||
virtual const void *GetOverrideRet() = 0; //!< Gets the override result. If none is specified, NULL
|
//!< If not in post function, undefined
|
||||||
|
virtual const void *GetOverrideRet() = 0; //!< Gets the override result.
|
||||||
|
//!< If none is specified, NULL
|
||||||
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// For hook managers
|
// For hook managers
|
||||||
@ -375,10 +407,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
# define SH_SETUP_MFP(mfp) \
|
# define SH_SETUP_MFP(mfp) \
|
||||||
reinterpret_cast<void**>(&mfp)[0] = vfnptr.orig_entry;
|
reinterpret_cast<void**>(&mfp)[0] = vfnptr->GetOrigEntry();
|
||||||
#elif SH_COMP == SH_COMP_GCC
|
#elif SH_COMP == SH_COMP_GCC
|
||||||
# define SH_SETUP_MFP(mfp) \
|
# define SH_SETUP_MFP(mfp) \
|
||||||
reinterpret_cast<void**>(&mfp)[0] = vfnptr.orig_entry; \
|
reinterpret_cast<void**>(&mfp)[0] = vfnptr->GetOrigEntry(); \
|
||||||
reinterpret_cast<void**>(&mfp)[1] = 0;
|
reinterpret_cast<void**>(&mfp)[1] = 0;
|
||||||
#else
|
#else
|
||||||
# error Not supported yet.
|
# error Not supported yet.
|
||||||
@ -388,24 +420,27 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
||||||
|
|
||||||
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
||||||
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::HookManagerInfo *param) \
|
SH_FHCls(ifacetype,ifacefunc,overload)() \
|
||||||
|
{ \
|
||||||
|
GetFuncInfo(funcptr, ms_MFI); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \
|
||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
|
GetFuncInfo(funcptr, ms_MFI); \
|
||||||
/* Verify interface version */ \
|
/* Verify interface version */ \
|
||||||
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
if (action == ::SourceHook::HA_GetInfo) \
|
if (action == ::SourceHook::HA_GetInfo) \
|
||||||
{ \
|
{ \
|
||||||
param->proto = ms_Proto; \
|
param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, ms_Proto); \
|
||||||
MemFuncInfo mfi; \
|
|
||||||
GetFuncInfo(funcptr, mfi); \
|
|
||||||
param->vtbl_idx = mfi.vtblindex; \
|
|
||||||
param->vtbl_offs = mfi.vtbloffs; \
|
|
||||||
\
|
\
|
||||||
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
||||||
param->hookfunc_vfnptr = \
|
param->SetHookfuncVfnptr( \
|
||||||
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]; \
|
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
else if (action == ::SourceHook::HA_Register) \
|
else if (action == ::SourceHook::HA_Register) \
|
||||||
@ -429,15 +464,17 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
struct SH_FHCls(ifacetype,ifacefunc,overload) \
|
struct SH_FHCls(ifacetype,ifacefunc,overload) \
|
||||||
{ \
|
{ \
|
||||||
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
||||||
static ::SourceHook::HookManagerInfo *ms_HI; \
|
static ::SourceHook::MemFuncInfo ms_MFI; \
|
||||||
|
static ::SourceHook::IHookManagerInfo *ms_HI; \
|
||||||
static const char *ms_Proto; \
|
static const char *ms_Proto; \
|
||||||
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
||||||
|
|
||||||
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
||||||
}; \
|
}; \
|
||||||
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
||||||
::SourceHook::HookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \
|
||||||
|
::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
||||||
|
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
||||||
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
||||||
{ \
|
{ \
|
||||||
@ -469,28 +506,22 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
void *ourvfnptr = reinterpret_cast<void*>( \
|
void *ourvfnptr = reinterpret_cast<void*>( \
|
||||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
|
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \
|
||||||
|
IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \
|
||||||
|
SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \
|
||||||
\
|
\
|
||||||
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
|
/* ... and the iface */ \
|
||||||
if (vfptriter == ms_HI->vfnptrs.end()) \
|
IIface *ifinfo = vfnptr->FindIface(reinterpret_cast<void*>(this)); \
|
||||||
{ \
|
if (!ifinfo) \
|
||||||
/* 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 = vfnptr.ifaces.find(this); \
|
|
||||||
if (ifiter == vfnptr.ifaces.end()) \
|
|
||||||
{ \
|
{ \
|
||||||
/* The iface info was not found. Redirect the call to the original function. */ \
|
/* The iface info was not found. Redirect the call to the original function. */ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||||
} \
|
} \
|
||||||
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
|
|
||||||
/* 2) Declare some vars and set it up */ \
|
/* 2) Declare some vars and set it up */ \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
|
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
|
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||||
rettype orig_ret; \
|
rettype orig_ret; \
|
||||||
rettype override_ret; \
|
rettype override_ret; \
|
||||||
rettype plugin_ret; \
|
rettype plugin_ret; \
|
||||||
@ -504,12 +535,11 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#define SH_CALL_HOOKS(post, params) \
|
#define SH_CALL_HOOKS(post, params) \
|
||||||
prev_res = MRES_IGNORED; \
|
prev_res = MRES_IGNORED; \
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
|
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||||
{ \
|
{ \
|
||||||
if (hiter->paused) continue; \
|
|
||||||
cur_res = MRES_IGNORED; \
|
cur_res = MRES_IGNORED; \
|
||||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - hiter->thisptr_offs); \
|
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||||
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(hiter->handler)->GetDeleg() params; \
|
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||||
prev_res = cur_res; \
|
prev_res = cur_res; \
|
||||||
if (cur_res > status) \
|
if (cur_res > status) \
|
||||||
status = cur_res; \
|
status = cur_res; \
|
||||||
@ -525,7 +555,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
orig_ret = (reinterpret_cast<EmptyClass*>(ci.ptr)->*mfp)params; \
|
orig_ret = (reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)params; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
orig_ret = override_ret;
|
orig_ret = override_ret;
|
||||||
@ -542,21 +572,16 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define SH_SETUPCALLS_void(paramtypes, params) \
|
#define SH_SETUPCALLS_void(paramtypes, params) \
|
||||||
using namespace ::SourceHook; \
|
|
||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
|
using namespace ::SourceHook; \
|
||||||
void *ourvfnptr = reinterpret_cast<void*>( \
|
void *ourvfnptr = reinterpret_cast<void*>( \
|
||||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
|
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \
|
||||||
|
IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \
|
||||||
|
SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \
|
||||||
\
|
\
|
||||||
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
|
/* ... and the iface */ \
|
||||||
if (vfptriter == ms_HI->vfnptrs.end()) \
|
IIface *ifinfo = vfnptr->FindIface(reinterpret_cast<void*>(this)); \
|
||||||
{ \
|
if (!ifinfo) \
|
||||||
/* 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 = vfnptr.ifaces.find(this); \
|
|
||||||
if (ifiter == vfnptr.ifaces.end()) \
|
|
||||||
{ \
|
{ \
|
||||||
/* The iface info was not found. Redirect the call to the original function. */ \
|
/* The iface info was not found. Redirect the call to the original function. */ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
@ -564,25 +589,24 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
|
|
||||||
/* 2) Declare some vars and set it up */ \
|
/* 2) Declare some vars and set it up */ \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
|
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
|
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||||
status = MRES_IGNORED; \
|
status = MRES_IGNORED; \
|
||||||
SH_GLOB_SHPTR->SetOverrideRet(NULL);
|
SH_GLOB_SHPTR->SetOverrideRet(NULL); \
|
||||||
|
SH_GLOB_SHPTR->SetOrigRet(NULL);
|
||||||
|
|
||||||
#define SH_CALL_HOOKS_void(post, params) \
|
#define SH_CALL_HOOKS_void(post, params) \
|
||||||
prev_res = MRES_IGNORED; \
|
prev_res = MRES_IGNORED; \
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
|
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||||
{ \
|
{ \
|
||||||
if (hiter->paused) continue; \
|
|
||||||
cur_res = MRES_IGNORED; \
|
cur_res = MRES_IGNORED; \
|
||||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - hiter->thisptr_offs); \
|
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||||
reinterpret_cast<CSHDelegate<FD>*>(hiter->handler)->GetDeleg() params; \
|
reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||||
prev_res = cur_res; \
|
prev_res = cur_res; \
|
||||||
if (cur_res > status) \
|
if (cur_res > status) \
|
||||||
status = cur_res; \
|
status = cur_res; \
|
||||||
@ -593,7 +617,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
(reinterpret_cast<EmptyClass*>(ci.ptr)->*mfp)params; \
|
(reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)params; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SH_RETURN_void()
|
#define SH_RETURN_void()
|
||||||
@ -683,14 +707,16 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
|
|
||||||
|
// :TODO: TEST THIS ON MSVC
|
||||||
|
|
||||||
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(m_CC->ptr, m_MFP, mfi); \
|
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||||
OrigVTables::iterator iter = m_CC->vt.find(mfi.thisptroffs + mfi.vtbloffs); \
|
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||||
if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->val.size() || iter->val[mfi.vtblindex] == NULL) \
|
if (!origfunc) \
|
||||||
return (m_CC->ptr->*m_MFP)call; \
|
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||||
\
|
\
|
||||||
/* It's hooked. Call the original function. */ \
|
/* It's hooked. Call the original function. */ \
|
||||||
union \
|
union \
|
||||||
@ -698,9 +724,9 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
RetType(EmptyClass::*mfpnew)prms; \
|
RetType(EmptyClass::*mfpnew)prms; \
|
||||||
void *addr; \
|
void *addr; \
|
||||||
} u; \
|
} u; \
|
||||||
u.addr = iter->val[mfi.vtblindex]; \
|
u.addr = origfunc; \
|
||||||
\
|
\
|
||||||
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->ptr) + mfi.thisptroffs); \
|
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->GetThisPtr()) + mfi.thisptroffs); \
|
||||||
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,10 +736,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(m_CC->ptr, m_MFP, mfi); \
|
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||||
OrigVTables::iterator iter = m_CC->vt.find(mfi.thisptroffs + mfi.vtbloffs); \
|
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||||
if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->val.size() || iter->val[mfi.vtblindex] == NULL) \
|
if (!origfunc) \
|
||||||
return (m_CC->ptr->*m_MFP)call; \
|
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||||
\
|
\
|
||||||
/* It's hooked. Call the original function. */ \
|
/* It's hooked. Call the original function. */ \
|
||||||
union \
|
union \
|
||||||
@ -725,10 +751,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
intptr_t adjustor; \
|
intptr_t adjustor; \
|
||||||
} s; \
|
} s; \
|
||||||
} u; \
|
} u; \
|
||||||
u.s.addr = iter->val[mfi.vtblindex]; \
|
u.s.addr = origfunc; \
|
||||||
u.s.adjustor = mfi.thisptroffs; \
|
u.s.adjustor = mfi.thisptroffs; \
|
||||||
\
|
\
|
||||||
return (reinterpret_cast<EmptyClass*>(m_CC->ptr)->*u.mfpnew)call; \
|
return (reinterpret_cast<EmptyClass*>(m_CC->GetThisPtr())->*u.mfpnew)call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -800,7 +826,7 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@Param%%|, @@
|
|||||||
|
|
||||||
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
||||||
|
|
||||||
#undef SH_MAKE_EXECUTABLECLASS_BODY
|
#undef SH_MAKE_EXECUTABLECLASS_OB
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// The pope is dead. -> :(
|
// The pope is dead. -> :(
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
# define SH_MEM_EXEC 4
|
# define SH_MEM_EXEC 4
|
||||||
# elif /******/ defined __linux__
|
# elif /******/ defined __linux__
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <signal.h>
|
||||||
|
# include <setjmp.h>
|
||||||
// http://www.die.net/doc/linux/man/man2/mprotect.2.html
|
// http://www.die.net/doc/linux/man/man2/mprotect.2.html
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
# ifndef PAGESIZE
|
# ifndef PAGESIZE
|
||||||
@ -66,6 +69,118 @@ namespace SourceHook
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool g_BadReadCalled;
|
||||||
|
jmp_buf g_BadReadJmpBuf;
|
||||||
|
|
||||||
|
static void BadReadHandler(int sig)
|
||||||
|
{
|
||||||
|
if (g_BadReadCalled)
|
||||||
|
longjmp(g_BadReadJmpBuf, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether the specified memory region is (still) accessible
|
||||||
|
*
|
||||||
|
* @param addr The lower boundary
|
||||||
|
* @param len Length of the region to be checked
|
||||||
|
*/
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool ModuleInMemory(char *addr, size_t len)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
// On linux, first check /proc/self/maps
|
||||||
|
long lower = reinterpret_cast<long>(addr);
|
||||||
|
long upper = lower + len;
|
||||||
|
|
||||||
|
FILE *pF = fopen("/proc/self/maps", "r");
|
||||||
|
if (pF)
|
||||||
|
{
|
||||||
|
// Linux /proc/self/maps -> parse
|
||||||
|
// Format:
|
||||||
|
// lower upper prot stuff path
|
||||||
|
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
|
||||||
|
long rlower, rupper;
|
||||||
|
while (fscanf(pF, "%lx-%lx", &rlower, &rupper) != EOF)
|
||||||
|
{
|
||||||
|
// Check whether we're IN THERE!
|
||||||
|
if (lower >= rlower && upper <= rupper)
|
||||||
|
{
|
||||||
|
fclose(pF);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Read to end of line
|
||||||
|
int c;
|
||||||
|
while ((c = fgetc(pF)) != '\n')
|
||||||
|
{
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fclose(pF);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pF = fopen("/proc/curproc/map", "r");
|
||||||
|
if (pF)
|
||||||
|
{
|
||||||
|
// FreeBSD /proc/curproc/map -> parse
|
||||||
|
// 0x804800 0x805500 13 15 0xc6e18960 r-x 21 0x0 COW NC vnode
|
||||||
|
long rlower, rupper;
|
||||||
|
while (fscanf(pF, "0x%lx 0x%lx", &rlower, &rupper) != EOF)
|
||||||
|
{
|
||||||
|
// Check whether we're IN THERE!
|
||||||
|
if (lower >= rlower && upper <= rupper)
|
||||||
|
{
|
||||||
|
fclose(pF);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Read to end of line
|
||||||
|
int c;
|
||||||
|
while ((c = fgetc(pF)) != '\n')
|
||||||
|
{
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fclose(pF);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both of the above failed, try to actually read and trap sigsegv (implemented by Damaged Soul)
|
||||||
|
void(*prevHandler)(int sig);
|
||||||
|
g_BadReadCalled = true;
|
||||||
|
|
||||||
|
if (setjmp(g_BadReadJmpBuf))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
prevHandler = signal(SIGSEGV, BadReadHandler);
|
||||||
|
|
||||||
|
volatile const char *p = reinterpret_cast<const char*>(addr);
|
||||||
|
char dummy;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
dummy = p[i];
|
||||||
|
|
||||||
|
g_BadReadCalled = false;
|
||||||
|
|
||||||
|
signal(SIGSEGV, prevHandler);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
// On Win32, simply use IsBadReadPtr
|
||||||
|
return !IsBadReadPtr(addr, len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -234,6 +234,20 @@ namespace SourceHook
|
|||||||
{
|
{
|
||||||
return !( (*this) == where );
|
return !( (*this) == where );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void erase()
|
||||||
|
{
|
||||||
|
if (end || !hash || curbucket < 0 || curbucket >= static_cast<int>(hash->m_numBuckets))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove this element and move to the next one
|
||||||
|
iterator tmp = *this;
|
||||||
|
++tmp;
|
||||||
|
hash->m_Buckets[curbucket]->erase(iter);
|
||||||
|
*this = tmp;
|
||||||
|
|
||||||
|
// :TODO: Maybe refactor to a lower size if required
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
void _Inc()
|
void _Inc()
|
||||||
{
|
{
|
||||||
@ -428,6 +442,20 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator erase(iterator where)
|
||||||
|
{
|
||||||
|
where.erase();
|
||||||
|
return where;
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
void erase(const U & u)
|
||||||
|
{
|
||||||
|
iterator iter = find(u);
|
||||||
|
if (iter == end())
|
||||||
|
return;
|
||||||
|
iter.erase();
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
NodePtr *m_Buckets;
|
NodePtr *m_Buckets;
|
||||||
size_t m_numBuckets;
|
size_t m_numBuckets;
|
||||||
|
@ -17,8 +17,9 @@
|
|||||||
#if defined __GNUC__
|
#if defined __GNUC__
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sourcehook_impl.h"
|
#include "sourcehook_impl.h"
|
||||||
#include "sh_tinyhash.h"
|
#include "sh_memory.h"
|
||||||
|
|
||||||
namespace SourceHook
|
namespace SourceHook
|
||||||
{
|
{
|
||||||
@ -41,7 +42,6 @@ namespace SourceHook
|
|||||||
CSourceHookImpl::CSourceHookImpl()
|
CSourceHookImpl::CSourceHookImpl()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CSourceHookImpl::~CSourceHookImpl()
|
CSourceHookImpl::~CSourceHookImpl()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -63,23 +63,23 @@ namespace SourceHook
|
|||||||
// If a hook from an other plugin is found, return true
|
// If a hook from an other plugin is found, return true
|
||||||
// Return false otherwise
|
// Return false otherwise
|
||||||
#define TMP_CHECK_LIST(name) \
|
#define TMP_CHECK_LIST(name) \
|
||||||
for (hook_iter = iface_iter->name.begin(); hook_iter != iface_iter->name.end(); ++hook_iter) \
|
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||||
if (hook_iter->plug == plug) \
|
if (hook_iter->plug == plug) \
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
||||||
{
|
{
|
||||||
if (hmil_iter->plug != plug)
|
if (hmil_iter->m_Plug != plug)
|
||||||
continue;
|
continue;
|
||||||
for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->vfnptrs.begin();
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||||
vfnptr_iter != hmil_iter->vfnptrs.end(); ++vfnptr_iter)
|
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin();
|
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||||
iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter)
|
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||||
{
|
{
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hook_iter;
|
List<HookInfo>::iterator hook_iter;
|
||||||
TMP_CHECK_LIST(hooks_pre);
|
TMP_CHECK_LIST(m_PreHooks);
|
||||||
TMP_CHECK_LIST(hooks_post);
|
TMP_CHECK_LIST(m_PostHooks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,21 +94,22 @@ namespace SourceHook
|
|||||||
HookManInfoList::iterator hmil_iter;
|
HookManInfoList::iterator hmil_iter;
|
||||||
|
|
||||||
#define TMP_CHECK_LIST(name, ispost) \
|
#define TMP_CHECK_LIST(name, ispost) \
|
||||||
for (hook_iter = iface_iter->name.begin(); hook_iter != iface_iter->name.end(); ++hook_iter) \
|
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||||
if (hook_iter->plug == plug) \
|
if (hook_iter->plug == plug) \
|
||||||
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->ptr, \
|
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \
|
||||||
hook_iter->thisptr_offs, hmil_iter->func, hook_iter->handler, ispost))
|
hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost))
|
||||||
|
|
||||||
for (hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
for (hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->vfnptrs.begin();
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||||
vfnptr_iter != hmil_iter->vfnptrs.end(); ++vfnptr_iter)
|
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin();
|
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||||
iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter)
|
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||||
{
|
{
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hook_iter;
|
List<HookInfo>::iterator hook_iter;
|
||||||
TMP_CHECK_LIST(hooks_pre, false);
|
TMP_CHECK_LIST(m_PreHooks, false);
|
||||||
TMP_CHECK_LIST(hooks_post, true);
|
TMP_CHECK_LIST(m_PostHooks, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,9 +127,9 @@ namespace SourceHook
|
|||||||
for (hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end();
|
for (hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end();
|
||||||
erase ? hmil_iter=m_HookMans.erase(hmil_iter) : ++hmil_iter)
|
erase ? hmil_iter=m_HookMans.erase(hmil_iter) : ++hmil_iter)
|
||||||
{
|
{
|
||||||
if (hmil_iter->plug == plug)
|
if (hmil_iter->m_Plug == plug)
|
||||||
{
|
{
|
||||||
if (!hmil_iter->vfnptrs.empty())
|
if (!hmil_iter->m_VfnPtrs.empty())
|
||||||
{
|
{
|
||||||
// All hooks by this plugin are already removed
|
// All hooks by this plugin are already removed
|
||||||
// So if there is a vfnptr, it has to be used by an other plugin
|
// So if there is a vfnptr, it has to be used by an other plugin
|
||||||
@ -140,41 +141,41 @@ namespace SourceHook
|
|||||||
erase = false;
|
erase = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each hook manager:
|
// For each hook manager that is used in an other plugin:
|
||||||
for (hmil_iter = tmphookmans.begin(); hmil_iter != tmphookmans.end(); ++hmil_iter)
|
for (hmil_iter = tmphookmans.begin(); hmil_iter != tmphookmans.end(); ++hmil_iter)
|
||||||
{
|
{
|
||||||
// Find a suitable hook manager in an other plugin
|
// Find a suitable hook manager in an other plugin
|
||||||
HookManInfoList::iterator newHookMan = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
HookManInfoList::iterator newHookMan = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
||||||
hmil_iter->proto, hmil_iter->vtbl_offs, hmil_iter->vtbl_idx);
|
hmil_iter->m_Proto, hmil_iter->m_VtblOffs, hmil_iter->m_VtblIdx);
|
||||||
|
|
||||||
// This should _never_ happen.
|
// This should _never_ happen.
|
||||||
// If there is a hook from an other plugin, the plugin must have provided a hook manager as well.
|
// 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(),
|
SH_ASSERT(newHookMan != m_HookMans.end(),
|
||||||
"Could not find a suitable hook manager in an other plugin!");
|
("Could not find a suitable hook manager in an other plugin!"));
|
||||||
|
|
||||||
// AddHook should make sure that every plugin only has _one_ hook manager for _one_ proto/vi/vo
|
// 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!");
|
SH_ASSERT(newHookMan->m_Plug != plug, ("New hook manager from same plugin!"));
|
||||||
|
|
||||||
// The first hook manager should be always used - so the new hook manager has to be empty
|
// 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!");
|
SH_ASSERT(newHookMan->m_VfnPtrs.empty(), ("New hook manager not empty!"));
|
||||||
|
|
||||||
// Move the vfnptrs from the old hook manager to the new one
|
// Move the vfnptrs from the old hook manager to the new one
|
||||||
newHookMan->vfnptrs = hmil_iter->vfnptrs;
|
newHookMan->m_VfnPtrs = hmil_iter->m_VfnPtrs;
|
||||||
|
|
||||||
// Unregister the old one, register the new one
|
// Unregister the old one, register the new one
|
||||||
hmil_iter->func(HA_Unregister, NULL);
|
hmil_iter->m_Func(HA_Unregister, NULL);
|
||||||
newHookMan->func(HA_Register, &(*newHookMan));
|
newHookMan->m_Func(HA_Register, &(*newHookMan));
|
||||||
|
|
||||||
// zOMG BAIL, here is part of what you wanted:
|
// zOMG BAIL, here is part of what you wanted:
|
||||||
|
|
||||||
// Go through all vfnptrs in this hookman and patch them to point to the new manager's handler!
|
// Go through all vfnptrs in this hookman and patch them to point to the new manager's handler!
|
||||||
// or whatever
|
// or whatever
|
||||||
for (HookManagerInfo::VfnPtrListIter vfnptr_iter = newHookMan->vfnptrs.begin();
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = newHookMan->m_VfnPtrs.begin();
|
||||||
vfnptr_iter != newHookMan->vfnptrs.end(); ++vfnptr_iter)
|
vfnptr_iter != newHookMan->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
{
|
{
|
||||||
// And DEREFERENCE newHookMan->hookfunc_vfnptr!
|
// And DEREFERENCE newHookMan->m_HookfuncVfnptr!
|
||||||
// otherwise it will be executing the vtable... had to find out the hard way
|
// otherwise it will be executing the vtable... had to find out the hard way
|
||||||
*reinterpret_cast<void**>(vfnptr_iter->vfnptr) = *reinterpret_cast<void**>(newHookMan->hookfunc_vfnptr);
|
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = *reinterpret_cast<void**>(newHookMan->m_HookfuncVfnptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// That should fix it, bail!
|
// That should fix it, bail!
|
||||||
@ -185,20 +186,20 @@ namespace SourceHook
|
|||||||
{
|
{
|
||||||
List<RemoveHookInfo> hookstoremove;
|
List<RemoveHookInfo> hookstoremove;
|
||||||
#define TMP_CHECK_LIST(name, ispost) \
|
#define TMP_CHECK_LIST(name, ispost) \
|
||||||
for (hook_iter = iface_iter->name.begin(); hook_iter != iface_iter->name.end(); ++hook_iter) \
|
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||||
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->ptr, \
|
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \
|
||||||
hook_iter->thisptr_offs, hmil_iter->func, hook_iter->handler, ispost))
|
hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost))
|
||||||
for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->vfnptrs.begin();
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||||
vfnptr_iter != hmil_iter->vfnptrs.end(); ++vfnptr_iter)
|
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin();
|
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||||
iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter)
|
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||||
{
|
{
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hook_iter;
|
List<HookInfo>::iterator hook_iter;
|
||||||
TMP_CHECK_LIST(hooks_pre, false);
|
TMP_CHECK_LIST(m_PreHooks, false);
|
||||||
TMP_CHECK_LIST(hooks_post, true);
|
TMP_CHECK_LIST(m_PostHooks, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,87 +215,84 @@ namespace SourceHook
|
|||||||
{
|
{
|
||||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
||||||
// 1) Get info about the hook manager
|
// 1) Get info about the hook manager
|
||||||
HookManagerInfo tmp;
|
CHookManagerInfo tmp;
|
||||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||||
return false;
|
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
|
// 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 hkmi_iter;
|
HookManInfoList::iterator hkmi_iter;
|
||||||
for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter)
|
for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter)
|
||||||
{
|
{
|
||||||
if (hkmi_iter->plug == plug && strcmp(hkmi_iter->proto, tmp.proto) == 0 &&
|
if (hkmi_iter->m_Plug == plug && strcmp(hkmi_iter->m_Proto, tmp.m_Proto) == 0 &&
|
||||||
hkmi_iter->vtbl_offs == tmp.vtbl_offs && hkmi_iter->vtbl_idx == tmp.vtbl_idx)
|
hkmi_iter->m_VtblOffs == tmp.m_VtblOffs && hkmi_iter->m_VtblIdx == tmp.m_VtblIdx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (hkmi_iter == m_HookMans.end())
|
if (hkmi_iter == m_HookMans.end())
|
||||||
{
|
{
|
||||||
// No such hook manager from this plugin yet, add it!
|
// No such hook manager from this plugin yet, add it!
|
||||||
tmp.func = myHookMan;
|
tmp.m_Func = myHookMan;
|
||||||
tmp.plug = plug;
|
tmp.m_Plug = plug;
|
||||||
m_HookMans.push_back(tmp);
|
m_HookMans.push_back(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, search for a suitable hook manager (from the beginning)
|
// 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);
|
HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(), tmp.m_Proto,
|
||||||
SH_ASSERT(hookman != m_HookMans.end(), "No hookman found - but if there was none, we've just added one!");
|
tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||||
|
SH_ASSERT(hookman != m_HookMans.end(), ("No hookman found - but if there was none, we've just added one!"));
|
||||||
|
|
||||||
// Tell it to store the pointer if it's not already active
|
// Tell it to store the pointer if it's not already active
|
||||||
if (hookman->vfnptrs.empty())
|
if (hookman->m_VfnPtrs.empty())
|
||||||
hookman->func(HA_Register, &(*hookman));
|
hookman->m_Func(HA_Register, &(*hookman));
|
||||||
|
|
||||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||||
reinterpret_cast<char*>(adjustediface) + tmp.vtbl_offs);
|
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.vtbl_idx);
|
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||||
|
|
||||||
HookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->vfnptrs.find(cur_vfnptr);
|
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||||
|
|
||||||
if (vfnptr_iter == hookman->vfnptrs.end())
|
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||||
{
|
{
|
||||||
// Add a new one
|
// Add a new one
|
||||||
HookManagerInfo::VfnPtr vfp;
|
CVfnPtr vfp(cur_vfnptr);
|
||||||
vfp.vfnptr = cur_vfnptr;
|
|
||||||
vfp.orig_entry = *reinterpret_cast<void**>(cur_vfnptr);
|
|
||||||
|
|
||||||
// Alter vtable entry
|
// Alter vtable entry
|
||||||
if (!SetMemAccess(cur_vtptr, sizeof(void*) * (tmp.vtbl_idx + 1), SH_MEM_READ | SH_MEM_WRITE))
|
if (!SetMemAccess(cur_vtptr, sizeof(void*) * (tmp.m_VtblIdx + 1), SH_MEM_READ | SH_MEM_WRITE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*reinterpret_cast<void**>(cur_vfnptr) = *reinterpret_cast<void**>(hookman->hookfunc_vfnptr);
|
*reinterpret_cast<void**>(cur_vfnptr) = *reinterpret_cast<void**>(hookman->m_HookfuncVfnptr);
|
||||||
|
|
||||||
hookman->vfnptrs.push_back(vfp);
|
hookman->m_VfnPtrs.push_back(vfp);
|
||||||
|
|
||||||
// Make vfnptr_iter point to the new element
|
// Make vfnptr_iter point to the new element
|
||||||
vfnptr_iter = hookman->vfnptrs.end();
|
vfnptr_iter = hookman->m_VfnPtrs.end();
|
||||||
--vfnptr_iter;
|
--vfnptr_iter;
|
||||||
|
|
||||||
// Now that it is done, check whether we have to update any callclasses
|
// Now that it is done, check whether we have to update any callclasses
|
||||||
ApplyCallClassPatches(adjustediface, tmp.vtbl_offs, tmp.vtbl_idx, vfp.orig_entry);
|
ApplyCallClassPatches(adjustediface, tmp.m_VtblOffs, tmp.m_VtblIdx, vfp.m_OrigEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.find(adjustediface);
|
CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.find(adjustediface);
|
||||||
if (iface_iter == vfnptr_iter->ifaces.end())
|
if (iface_iter == vfnptr_iter->m_Ifaces.end())
|
||||||
{
|
{
|
||||||
// Add a new one
|
// Add a new one
|
||||||
HookManagerInfo::VfnPtr::Iface ifs;
|
vfnptr_iter->m_Ifaces.push_back(CIface(adjustediface));
|
||||||
ifs.ptr = adjustediface;
|
|
||||||
vfnptr_iter->ifaces.push_back(ifs);
|
|
||||||
|
|
||||||
// Make iface_iter point to the new element
|
// Make iface_iter point to the new element
|
||||||
iface_iter = vfnptr_iter->ifaces.end();
|
iface_iter = vfnptr_iter->m_Ifaces.end();
|
||||||
--iface_iter;
|
--iface_iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the hook
|
// Add the hook
|
||||||
HookManagerInfo::VfnPtr::Iface::Hook hookinfo;
|
HookInfo hookinfo;
|
||||||
hookinfo.handler = handler;
|
hookinfo.handler = handler;
|
||||||
hookinfo.plug = plug;
|
hookinfo.plug = plug;
|
||||||
hookinfo.paused = false;
|
hookinfo.paused = false;
|
||||||
hookinfo.thisptr_offs = thisptr_offs;
|
hookinfo.thisptr_offs = thisptr_offs;
|
||||||
if (post)
|
if (post)
|
||||||
iface_iter->hooks_post.push_back(hookinfo);
|
iface_iter->m_PostHooks.m_List.push_back(hookinfo);
|
||||||
else
|
else
|
||||||
iface_iter->hooks_pre.push_back(hookinfo);
|
iface_iter->m_PreHooks.m_List.push_back(hookinfo);
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -307,40 +305,42 @@ namespace SourceHook
|
|||||||
bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
||||||
{
|
{
|
||||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface)+thisptr_offs);
|
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface)+thisptr_offs);
|
||||||
HookManagerInfo tmp;
|
CHookManagerInfo tmp;
|
||||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Find the hook manager and the hook
|
// Find the hook manager and the hook
|
||||||
HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
||||||
tmp.proto, tmp.vtbl_offs, tmp.vtbl_idx);
|
tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||||
if (hookman == m_HookMans.end())
|
if (hookman == m_HookMans.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IsBadReadPtr(reinterpret_cast<char*>(adjustediface) + tmp.vtbl_offs, sizeof(char)))
|
if (!ModuleInMemory(reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs,
|
||||||
|
sizeof(void*) * (tmp.m_VtblIdx + 1)))
|
||||||
{
|
{
|
||||||
hookman->vfnptrs.clear();
|
// The module the vtable was in is already unloaded.
|
||||||
hookman->func(HA_Unregister, NULL);
|
hookman->m_VfnPtrs.clear();
|
||||||
|
hookman->m_Func(HA_Unregister, NULL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||||
reinterpret_cast<char*>(adjustediface) + tmp.vtbl_offs);
|
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.vtbl_idx);
|
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||||
|
|
||||||
HookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->vfnptrs.find(cur_vfnptr);
|
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||||
|
|
||||||
if (vfnptr_iter == hookman->vfnptrs.end())
|
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin();
|
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||||
iface_iter != vfnptr_iter->ifaces.end();)
|
iface_iter != vfnptr_iter->m_Ifaces.end();)
|
||||||
{
|
{
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &hooks =
|
List<HookInfo> &hooks =
|
||||||
post ? iface_iter->hooks_post : iface_iter->hooks_pre;
|
post ? iface_iter->m_PostHooks.m_List : iface_iter->m_PreHooks.m_List;
|
||||||
|
|
||||||
bool erase;
|
bool erase;
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hookiter = hooks.begin();
|
for (List<HookInfo>::iterator hookiter = hooks.begin();
|
||||||
hookiter != hooks.end(); erase ? hookiter = hooks.erase(hookiter) : ++hookiter)
|
hookiter != hooks.end(); erase ? hookiter = hooks.erase(hookiter) : ++hookiter)
|
||||||
{
|
{
|
||||||
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
|
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
|
||||||
@ -348,25 +348,27 @@ namespace SourceHook
|
|||||||
if (erase)
|
if (erase)
|
||||||
hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object
|
hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object
|
||||||
}
|
}
|
||||||
if (iface_iter->hooks_post.empty() && iface_iter->hooks_pre.empty())
|
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
|
||||||
{
|
{
|
||||||
iface_iter = vfnptr_iter->ifaces.erase(iface_iter);
|
// There are no hooks on this iface anymore...
|
||||||
if (vfnptr_iter->ifaces.empty())
|
|
||||||
{
|
|
||||||
// Deactivate the hook
|
|
||||||
*reinterpret_cast<void**>(vfnptr_iter->vfnptr) = vfnptr_iter->orig_entry;
|
|
||||||
|
|
||||||
hookman->vfnptrs.erase(vfnptr_iter);
|
iface_iter = vfnptr_iter->m_Ifaces.erase(iface_iter);
|
||||||
|
if (vfnptr_iter->m_Ifaces.empty())
|
||||||
|
{
|
||||||
|
// No ifaces at all -> Deactivate the hook
|
||||||
|
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = vfnptr_iter->m_OrigEntry;
|
||||||
|
|
||||||
|
hookman->m_VfnPtrs.erase(vfnptr_iter);
|
||||||
|
|
||||||
// Remove callclass patch
|
// Remove callclass patch
|
||||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||||
if (cciter->cc.ptr == adjustediface)
|
if (cciter->m_Ptr == adjustediface)
|
||||||
RemoveCallClassPatch(*cciter, tmp.vtbl_offs, tmp.vtbl_idx);
|
cciter->RemoveCallClassPatch(tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||||
|
|
||||||
if (hookman->vfnptrs.empty())
|
if (hookman->m_VfnPtrs.empty())
|
||||||
{
|
{
|
||||||
// Unregister the hook manager
|
// Unregister the hook manager
|
||||||
hookman->func(HA_Unregister, NULL);
|
hookman->m_Func(HA_Unregister, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't try to continue looping through ifaces
|
// Don't try to continue looping through ifaces
|
||||||
@ -384,22 +386,19 @@ namespace SourceHook
|
|||||||
{
|
{
|
||||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||||
{
|
{
|
||||||
if (cciter->cc.ptr == iface && cciter->cc.objsize == size)
|
if (cciter->m_Ptr == iface && cciter->m_ObjSize == size)
|
||||||
{
|
{
|
||||||
++cciter->refcounter;
|
++cciter->m_RefCounter;
|
||||||
return &cciter->cc;
|
return &(*cciter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CallClassInfo tmp;
|
// Make a new one
|
||||||
tmp.refcounter = 1;
|
|
||||||
tmp.cc.ptr = iface;
|
|
||||||
tmp.cc.objsize = size;
|
|
||||||
|
|
||||||
|
CCallClassImpl tmp(iface, size);
|
||||||
ApplyCallClassPatches(tmp);
|
ApplyCallClassPatches(tmp);
|
||||||
|
|
||||||
m_CallClasses.push_back(tmp);
|
m_CallClasses.push_back(tmp);
|
||||||
return &m_CallClasses.back().cc;
|
return &m_CallClasses.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSourceHookImpl::ReleaseCallClass(GenericCallClass *ptr)
|
void CSourceHookImpl::ReleaseCallClass(GenericCallClass *ptr)
|
||||||
@ -407,35 +406,27 @@ namespace SourceHook
|
|||||||
Impl_CallClassList::iterator iter = m_CallClasses.find(ptr);
|
Impl_CallClassList::iterator iter = m_CallClasses.find(ptr);
|
||||||
if (iter == m_CallClasses.end())
|
if (iter == m_CallClasses.end())
|
||||||
return;
|
return;
|
||||||
--iter->refcounter;
|
--iter->m_RefCounter;
|
||||||
if (iter->refcounter < 1)
|
if (iter->m_RefCounter < 1)
|
||||||
m_CallClasses.erase(iter);
|
m_CallClasses.erase(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSourceHookImpl::ApplyCallClassPatch(CallClassInfo &cc, int vtbl_offs, int vtbl_idx, void *orig_entry)
|
void CSourceHookImpl::ApplyCallClassPatches(CCallClassImpl &cc)
|
||||||
{
|
|
||||||
OrigFuncs &tmpvec = cc.cc.vt[vtbl_offs];
|
|
||||||
if (tmpvec.size() <= (size_t)vtbl_idx)
|
|
||||||
tmpvec.resize(vtbl_idx+1);
|
|
||||||
tmpvec[vtbl_idx] = orig_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSourceHookImpl::ApplyCallClassPatches(CallClassInfo &cc)
|
|
||||||
{
|
{
|
||||||
for (HookManInfoList::iterator hookman = m_HookMans.begin(); hookman != m_HookMans.end(); ++hookman)
|
for (HookManInfoList::iterator hookman = m_HookMans.begin(); hookman != m_HookMans.end(); ++hookman)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->vfnptrs.begin();
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.begin();
|
||||||
vfnptr_iter != hookman->vfnptrs.end(); ++vfnptr_iter)
|
vfnptr_iter != hookman->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
{
|
{
|
||||||
for (HookManagerInfo::VfnPtr::IfaceListIter iface_iter = vfnptr_iter->ifaces.begin();
|
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||||
iface_iter != vfnptr_iter->ifaces.end(); ++iface_iter)
|
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||||
{
|
{
|
||||||
if (iface_iter->ptr >= cc.cc.ptr &&
|
if (iface_iter->m_Ptr >= cc.m_Ptr &&
|
||||||
iface_iter->ptr < (reinterpret_cast<char*>(cc.cc.ptr) + cc.cc.objsize))
|
iface_iter->m_Ptr < (reinterpret_cast<char*>(cc.m_Ptr) + cc.m_ObjSize))
|
||||||
{
|
{
|
||||||
ApplyCallClassPatch(cc, static_cast<int>(reinterpret_cast<char*>(iface_iter->ptr) -
|
cc.ApplyCallClassPatch(static_cast<int>(reinterpret_cast<char*>(iface_iter->m_Ptr) -
|
||||||
reinterpret_cast<char*>(cc.cc.ptr)) + hookman->vtbl_offs,
|
reinterpret_cast<char*>(cc.m_Ptr)) + hookman->m_VtblOffs,
|
||||||
hookman->vtbl_idx, vfnptr_iter->orig_entry);
|
hookman->m_VtblIdx, vfnptr_iter->m_OrigEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,11 +438,11 @@ namespace SourceHook
|
|||||||
for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end();
|
for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end();
|
||||||
++cc_iter)
|
++cc_iter)
|
||||||
{
|
{
|
||||||
if (ifaceptr >= cc_iter->cc.ptr &&
|
if (ifaceptr >= cc_iter->m_Ptr &&
|
||||||
ifaceptr < (reinterpret_cast<char*>(cc_iter->cc.ptr) + cc_iter->cc.objsize))
|
ifaceptr < (reinterpret_cast<char*>(cc_iter->m_Ptr) + cc_iter->m_ObjSize))
|
||||||
{
|
{
|
||||||
ApplyCallClassPatch(*cc_iter, static_cast<int>(reinterpret_cast<char*>(ifaceptr) -
|
cc_iter->ApplyCallClassPatch(static_cast<int>(reinterpret_cast<char*>(ifaceptr) -
|
||||||
reinterpret_cast<char*>(cc_iter->cc.ptr)) + vtbl_offs, vtbl_idx, orig_entry);
|
reinterpret_cast<char*>(cc_iter->m_Ptr)) + vtbl_offs, vtbl_idx, orig_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -461,34 +452,10 @@ namespace SourceHook
|
|||||||
for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end();
|
for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end();
|
||||||
++cc_iter)
|
++cc_iter)
|
||||||
{
|
{
|
||||||
if (ifaceptr >= cc_iter->cc.ptr &&
|
if (ifaceptr >= cc_iter->m_Ptr &&
|
||||||
ifaceptr < (reinterpret_cast<char*>(cc_iter->cc.ptr) + cc_iter->cc.objsize))
|
ifaceptr < (reinterpret_cast<char*>(cc_iter->m_Ptr) + cc_iter->m_ObjSize))
|
||||||
{
|
{
|
||||||
RemoveCallClassPatch(*cc_iter, vtbl_offs, vtbl_idx);
|
cc_iter->RemoveCallClassPatch(vtbl_offs, vtbl_idx);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSourceHookImpl::RemoveCallClassPatch(CallClassInfo &cc, int vtbl_offs, int vtbl_idx)
|
|
||||||
{
|
|
||||||
OrigVTables::iterator iter = cc.cc.vt.find(vtbl_offs);
|
|
||||||
if (iter != cc.cc.vt.end())
|
|
||||||
{
|
|
||||||
if (iter->val.size() > (size_t)vtbl_idx)
|
|
||||||
{
|
|
||||||
iter->val[vtbl_idx] = 0;
|
|
||||||
// Free some memory if possible
|
|
||||||
// :TODO: add this back in!
|
|
||||||
/*
|
|
||||||
OrigFuncs::reverse_iterator riter;
|
|
||||||
for (riter = iter->second.rbegin(); riter != iter->second.rend(); ++riter)
|
|
||||||
{
|
|
||||||
if (*riter != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iter->second.resize(iter->second.size() - (riter - iter->second.rbegin()));
|
|
||||||
if (!iter->second.size())
|
|
||||||
cc.cc.vt.erase(iter);*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,53 +466,41 @@ namespace SourceHook
|
|||||||
HookManInfoList::iterator hookmaniter;
|
HookManInfoList::iterator hookmaniter;
|
||||||
for (hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
for (hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
||||||
{
|
{
|
||||||
if (strcmp(hookmaniter->proto, proto) == 0 && hookmaniter->vtbl_offs == vtblofs &&
|
if (strcmp(hookmaniter->m_Proto, proto) == 0 && hookmaniter->m_VtblOffs == vtblofs &&
|
||||||
hookmaniter->vtbl_idx == vtblidx)
|
hookmaniter->m_VtblIdx == vtblidx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return hookmaniter;
|
return hookmaniter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSourceHookImpl::PausePlugin(Plugin plug)
|
void CSourceHookImpl::SetPluginPaused(Plugin plug, bool paused)
|
||||||
{
|
{
|
||||||
// Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused
|
// 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 (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
||||||
for (HookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->vfnptrs.begin();
|
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->m_VfnPtrs.begin();
|
||||||
vfnptr_iter != hookmaniter->vfnptrs.end(); ++vfnptr_iter)
|
vfnptr_iter != hookmaniter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||||
for (HookManagerInfo::VfnPtr::IfaceListIter ifaceiter = vfnptr_iter->ifaces.begin();
|
for (CVfnPtr::IfaceListIter ifaceiter = vfnptr_iter->m_Ifaces.begin();
|
||||||
ifaceiter != vfnptr_iter->ifaces.end(); ++ifaceiter)
|
ifaceiter != vfnptr_iter->m_Ifaces.end(); ++ifaceiter)
|
||||||
{
|
{
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hookiter = ifaceiter->hooks_pre.begin();
|
for (List<HookInfo>::iterator hookiter = ifaceiter->m_PreHooks.m_List.begin();
|
||||||
hookiter != ifaceiter->hooks_pre.end(); ++hookiter)
|
hookiter != ifaceiter->m_PreHooks.m_List.end(); ++hookiter)
|
||||||
if (plug == hookiter->plug)
|
if (plug == hookiter->plug)
|
||||||
hookiter->paused = true;
|
hookiter->paused = paused;
|
||||||
|
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hookiter = ifaceiter->hooks_post.begin();
|
for (List<HookInfo>::iterator hookiter = ifaceiter->m_PostHooks.m_List.begin();
|
||||||
hookiter != ifaceiter->hooks_post.end(); ++hookiter)
|
hookiter != ifaceiter->m_PostHooks.m_List.end(); ++hookiter)
|
||||||
if (plug == hookiter->plug)
|
if (plug == hookiter->plug)
|
||||||
hookiter->paused = true;
|
hookiter->paused = paused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void CSourceHookImpl::PausePlugin(Plugin plug)
|
||||||
|
{
|
||||||
|
SetPluginPaused(plug, true);
|
||||||
|
}
|
||||||
|
|
||||||
void CSourceHookImpl::UnpausePlugin(Plugin plug)
|
void CSourceHookImpl::UnpausePlugin(Plugin plug)
|
||||||
{
|
{
|
||||||
// Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused
|
SetPluginPaused(plug, false);
|
||||||
for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
|
||||||
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 (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hookiter = ifaceiter->hooks_pre.begin();
|
|
||||||
hookiter != ifaceiter->hooks_pre.end(); ++hookiter)
|
|
||||||
if (plug == hookiter->plug)
|
|
||||||
hookiter->paused = false;
|
|
||||||
|
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::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)
|
void CSourceHookImpl::SetRes(META_RES res)
|
||||||
@ -608,38 +563,212 @@ namespace SourceHook
|
|||||||
return m_IfacePtr;
|
return m_IfacePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
////////////////////////////
|
||||||
bool g_BadReadCalled;
|
// CCallClassImpl
|
||||||
jmp_buf g_BadReadJmpBuf;
|
////////////////////////////
|
||||||
|
CSourceHookImpl::CCallClassImpl::CCallClassImpl(void *ptr, size_t size)
|
||||||
// Windows has an implementation for this already, but Linux does not :(
|
: m_Ptr(ptr), m_ObjSize(size), m_RefCounter(1)
|
||||||
bool IsBadReadPtr(const void *ptr, size_t len)
|
|
||||||
{
|
{
|
||||||
void(*prevHandler)(int sig);
|
|
||||||
g_BadReadCalled = true;
|
|
||||||
|
|
||||||
if (setjmp(g_BadReadJmpBuf))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
prevHandler = signal(SIGSEGV, BadReadHandler);
|
|
||||||
|
|
||||||
volatile const char *p = reinterpret_cast<const char*>(ptr);
|
|
||||||
char dummy;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++)
|
|
||||||
dummy = p[i];
|
|
||||||
|
|
||||||
g_BadReadCalled = false;
|
|
||||||
|
|
||||||
signal(SIGSEGV, prevHandler);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
CSourceHookImpl::CCallClassImpl::~CCallClassImpl()
|
||||||
void BadReadHandler(int sig)
|
|
||||||
{
|
{
|
||||||
if (g_BadReadCalled)
|
|
||||||
longjmp(g_BadReadJmpBuf, 1);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
void *CSourceHookImpl::CCallClassImpl::GetThisPtr()
|
||||||
|
{
|
||||||
|
return m_Ptr;
|
||||||
|
}
|
||||||
|
void *CSourceHookImpl::CCallClassImpl::GetOrigFunc(int vtbloffs, int vtblidx)
|
||||||
|
{
|
||||||
|
OrigVTables::iterator iter = m_VT.find(vtbloffs);
|
||||||
|
if (iter != m_VT.end() && iter->val.size() > (size_t)vtblidx)
|
||||||
|
{
|
||||||
|
return iter->val[vtblidx];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSourceHookImpl::CCallClassImpl::ApplyCallClassPatch(int vtbl_offs, int vtbl_idx, void *orig_entry)
|
||||||
|
{
|
||||||
|
OrigFuncs &tmpvec = m_VT[vtbl_offs];
|
||||||
|
if (tmpvec.size() <= (size_t)vtbl_idx)
|
||||||
|
tmpvec.resize(vtbl_idx+1);
|
||||||
|
tmpvec[vtbl_idx] = orig_entry;
|
||||||
|
}
|
||||||
|
void CSourceHookImpl::CCallClassImpl::RemoveCallClassPatch(int vtbl_offs, int vtbl_idx)
|
||||||
|
{
|
||||||
|
OrigVTables::iterator iter = m_VT.find(vtbl_offs);
|
||||||
|
if (iter != m_VT.end())
|
||||||
|
{
|
||||||
|
if (iter->val.size() > (size_t)vtbl_idx)
|
||||||
|
{
|
||||||
|
iter->val[vtbl_idx] = 0;
|
||||||
|
|
||||||
|
OrigFuncs &of = iter->val;
|
||||||
|
OrigFuncs::iterator lastused = of.end();
|
||||||
|
for (OrigFuncs::iterator viter = of.begin(); viter != of.end(); ++viter)
|
||||||
|
{
|
||||||
|
if (*viter)
|
||||||
|
lastused = viter;
|
||||||
|
}
|
||||||
|
if (lastused == of.end())
|
||||||
|
{
|
||||||
|
// No used element => Remove the whole vector
|
||||||
|
m_VT.erase(iter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
of.resize(lastused - of.begin() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// CHookManagerInfo
|
||||||
|
////////////////////////////
|
||||||
|
CSourceHookImpl::CHookManagerInfo::~CHookManagerInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IVfnPtr *CSourceHookImpl::CHookManagerInfo::FindVfnPtr(void *vfnptr)
|
||||||
|
{
|
||||||
|
VfnPtrListIter iter = m_VfnPtrs.find(vfnptr);
|
||||||
|
return iter == m_VfnPtrs.end() ? NULL : &(*iter);
|
||||||
|
}
|
||||||
|
void CSourceHookImpl::CHookManagerInfo::SetInfo(int vtbl_offs, int vtbl_idx, const char *proto)
|
||||||
|
{
|
||||||
|
m_VtblOffs = vtbl_offs;
|
||||||
|
m_VtblIdx = vtbl_idx;
|
||||||
|
m_Proto = proto;
|
||||||
|
}
|
||||||
|
void CSourceHookImpl::CHookManagerInfo::SetHookfuncVfnptr(void *hookfunc_vfnptr)
|
||||||
|
{
|
||||||
|
m_HookfuncVfnptr = hookfunc_vfnptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// CVfnPtr
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr) : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(ptr))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
CSourceHookImpl::CVfnPtr::~CVfnPtr()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CSourceHookImpl::CVfnPtr::GetVfnPtr()
|
||||||
|
{
|
||||||
|
return m_Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CSourceHookImpl::CVfnPtr::GetOrigEntry()
|
||||||
|
{
|
||||||
|
return m_OrigEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
IIface *CSourceHookImpl::CVfnPtr::FindIface(void *ptr)
|
||||||
|
{
|
||||||
|
IfaceListIter iter = m_Ifaces.find(ptr);
|
||||||
|
return iter == m_Ifaces.end() ? NULL : &(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// CIface
|
||||||
|
////////////////////////////
|
||||||
|
CSourceHookImpl::CIface::CIface(void *ptr) : m_Ptr(ptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
CSourceHookImpl::CIface::~CIface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CSourceHookImpl::CIface::GetPtr()
|
||||||
|
{
|
||||||
|
return m_Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IHookList *CSourceHookImpl::CIface::GetPreHooks()
|
||||||
|
{
|
||||||
|
return &m_PreHooks;
|
||||||
|
}
|
||||||
|
IHookList *CSourceHookImpl::CIface::GetPostHooks()
|
||||||
|
{
|
||||||
|
return &m_PostHooks;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// CHookList
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List), m_FreeIters(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
CSourceHookImpl::CHookList::~CHookList()
|
||||||
|
{
|
||||||
|
while (m_FreeIters)
|
||||||
|
{
|
||||||
|
CIter *iter = m_FreeIters->m_pNext;
|
||||||
|
delete m_FreeIters;
|
||||||
|
m_FreeIters = iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IHookList::IIter *CSourceHookImpl::CHookList::GetIter()
|
||||||
|
{
|
||||||
|
if (m_FreeIters)
|
||||||
|
{
|
||||||
|
CIter *ret = m_FreeIters;
|
||||||
|
m_FreeIters = ret->m_pNext;
|
||||||
|
ret->GoToBegin();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return new CIter(this);
|
||||||
|
}
|
||||||
|
void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter)
|
||||||
|
{
|
||||||
|
CIter *pIter2 = static_cast<CIter*>(pIter);
|
||||||
|
pIter2->m_pNext = m_FreeIters;
|
||||||
|
m_FreeIters = pIter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSourceHookImpl::CHookList::CIter::CIter(CHookList *pList) : m_pList(pList), m_pNext(NULL)
|
||||||
|
{
|
||||||
|
GoToBegin();
|
||||||
|
}
|
||||||
|
CSourceHookImpl::CHookList::CIter::~CIter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSourceHookImpl::CHookList::CIter::GoToBegin()
|
||||||
|
{
|
||||||
|
m_Iter = m_pList->m_List.begin();
|
||||||
|
SkipPaused();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSourceHookImpl::CHookList::CIter::End()
|
||||||
|
{
|
||||||
|
return m_Iter == m_pList->m_List.end();
|
||||||
|
}
|
||||||
|
void CSourceHookImpl::CHookList::CIter::Next()
|
||||||
|
{
|
||||||
|
++m_Iter;
|
||||||
|
SkipPaused();
|
||||||
|
}
|
||||||
|
void CSourceHookImpl::CHookList::CIter::SkipPaused()
|
||||||
|
{
|
||||||
|
while (m_Iter != m_pList->m_List.end() && m_Iter->paused)
|
||||||
|
++m_Iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISHDelegate *CSourceHookImpl::CHookList::CIter::Handler()
|
||||||
|
{
|
||||||
|
return m_Iter->handler;
|
||||||
|
}
|
||||||
|
int CSourceHookImpl::CHookList::CIter::ThisPtrOffs()
|
||||||
|
{
|
||||||
|
return m_Iter->thisptr_offs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
#ifndef __SOURCEHOOK_H__
|
#ifndef __SOURCEHOOK_H__
|
||||||
#define __SOURCEHOOK_H__
|
#define __SOURCEHOOK_H__
|
||||||
|
|
||||||
#define SH_IFACE_VERSION 1
|
#define SH_IFACE_VERSION 2
|
||||||
#define SH_IMPL_VERSION 1
|
#define SH_IMPL_VERSION 2
|
||||||
|
|
||||||
#ifndef SH_GLOB_SHPTR
|
#ifndef SH_GLOB_SHPTR
|
||||||
#define SH_GLOB_SHPTR g_SHPtr
|
#define SH_GLOB_SHPTR g_SHPtr
|
||||||
@ -27,13 +27,21 @@
|
|||||||
#define SH_GLOB_PLUGPTR g_PLID
|
#define SH_GLOB_PLUGPTR g_PLID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SH_DEBUG
|
#ifdef SH_DEBUG
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# define SH_ASSERT__(x, info, file, line, func) \
|
|
||||||
((printf("SOURCEHOOK DEBUG ASSERTION FAILED:\n %s:%u(%s): %s\n", file, line, func, info), true) ? (abort(), 0) : 0)
|
# define SH_ASSERT(x, info) \
|
||||||
# define SH_ASSERT(x, info) if (!(x)) SH_ASSERT__(x, info, __FILE__, __LINE__, __FUNCTION__)
|
do { \
|
||||||
|
if (!(x)) \
|
||||||
|
{ \
|
||||||
|
printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \
|
||||||
|
printf info; \
|
||||||
|
putchar('\n'); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define SH_ASSERT(x, info)
|
# define SH_ASSERT(x, info)
|
||||||
#endif
|
#endif
|
||||||
@ -70,10 +78,6 @@
|
|||||||
|
|
||||||
#include "FastDelegate.h"
|
#include "FastDelegate.h"
|
||||||
#include "sh_memfuncinfo.h"
|
#include "sh_memfuncinfo.h"
|
||||||
#include "sh_memory.h"
|
|
||||||
#include "sh_list.h"
|
|
||||||
#include "sh_vector.h"
|
|
||||||
#include "sh_tinyhash.h"
|
|
||||||
|
|
||||||
// Good old metamod!
|
// Good old metamod!
|
||||||
|
|
||||||
@ -90,7 +94,10 @@ enum META_RES
|
|||||||
|
|
||||||
namespace SourceHook
|
namespace SourceHook
|
||||||
{
|
{
|
||||||
const int STRBUF_LEN=4096; // In bytes, for "vafmt" functions
|
/**
|
||||||
|
* @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers
|
||||||
|
*/
|
||||||
|
const int STRBUF_LEN=4096;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An empty class. No inheritance used. Used for original-function-call hacks
|
* @brief An empty class. No inheritance used. Used for original-function-call hacks
|
||||||
@ -111,29 +118,33 @@ namespace SourceHook
|
|||||||
/**
|
/**
|
||||||
* @brief A plugin typedef
|
* @brief A plugin typedef
|
||||||
*
|
*
|
||||||
* SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it
|
* SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every
|
||||||
* and every plugin has a unique identifier, everything is ok.
|
* plugin has a unique identifier, everything is ok.
|
||||||
|
* It should also be possible to set it to 0.
|
||||||
*/
|
*/
|
||||||
typedef int Plugin;
|
typedef int Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Specifies the actions for hook managers
|
||||||
|
*/
|
||||||
enum HookManagerAction
|
enum HookManagerAction
|
||||||
{
|
{
|
||||||
HA_GetInfo = 0, // -> Only store info
|
HA_GetInfo = 0, //!< Store info about the hook manager
|
||||||
HA_Register, // -> Save the pointer for future reference
|
HA_Register, //!< Save the IHookManagerInfo pointer for future reference
|
||||||
HA_Unregister // -> Clear the saved pointer
|
HA_Unregister //!< Clear the saved pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HookManagerInfo;
|
class IHookManagerInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to hook manager type
|
* @brief Pointer to hook manager interface function
|
||||||
*
|
*
|
||||||
* A "hook manager" is a the only thing that knows the actual protoype of the function at compile time.
|
* A "hook manager" is a the only thing that knows the actual protoype of the function at compile time.
|
||||||
*
|
*
|
||||||
* @param hi A pointer to a HookManagerInfo structure. The hook manager should fill it and store it for
|
* @param ha What the hook manager should do
|
||||||
* future reference (mainly if something should get hooked to its hookfunc)
|
* @param hi A pointer to IHookManagerInfo
|
||||||
*/
|
*/
|
||||||
typedef int (*HookManagerPubFunc)(HookManagerAction ha, HookManagerInfo *hi);
|
typedef int (*HookManagerPubFunc)(HookManagerAction ha, IHookManagerInfo *hi);
|
||||||
|
|
||||||
class ISHDelegate
|
class ISHDelegate
|
||||||
{
|
{
|
||||||
@ -170,65 +181,83 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct IHookList
|
||||||
* @brief This structure contains information about a hook manager (hook manager)
|
|
||||||
*/
|
|
||||||
struct HookManagerInfo
|
|
||||||
{
|
{
|
||||||
struct VfnPtr
|
struct IIter
|
||||||
{
|
{
|
||||||
struct Iface
|
virtual bool End() = 0;
|
||||||
{
|
virtual void Next() = 0;
|
||||||
struct Hook
|
virtual ISHDelegate *Handler() = 0;
|
||||||
{
|
virtual int ThisPtrOffs() = 0;
|
||||||
ISHDelegate *handler; //!< Pointer to the handler
|
|
||||||
bool paused; //!< If true, the hook should not be executed
|
|
||||||
Plugin plug; //!< The owner plugin
|
|
||||||
int thisptr_offs; //!< This pointer offset
|
|
||||||
};
|
};
|
||||||
void *ptr; //!< Pointer to the interface instance
|
virtual IIter *GetIter() = 0;
|
||||||
List<Hook> hooks_pre; //!< A list of pre-hooks
|
virtual void ReleaseIter(IIter *pIter) = 0;
|
||||||
List<Hook> hooks_post; //!< A list of post-hooks
|
};
|
||||||
bool operator ==(void *other) const
|
|
||||||
|
struct IIface
|
||||||
|
{
|
||||||
|
virtual void *GetPtr() = 0;
|
||||||
|
virtual IHookList *GetPreHooks() = 0;
|
||||||
|
virtual IHookList *GetPostHooks() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IVfnPtr
|
||||||
|
{
|
||||||
|
virtual void *GetVfnPtr() = 0;
|
||||||
|
virtual void *GetOrigEntry() = 0;
|
||||||
|
|
||||||
|
virtual IIface *FindIface(void *ptr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IHookManagerInfo
|
||||||
|
{
|
||||||
|
virtual IVfnPtr *FindVfnPtr(void *vfnptr) = 0;
|
||||||
|
|
||||||
|
virtual void SetInfo(int vtbloffs, int vtblidx, const char *proto) = 0;
|
||||||
|
virtual void SetHookfuncVfnptr(void *hookfunc_vfnptr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoHookIter
|
||||||
|
{
|
||||||
|
IHookList *m_pList;
|
||||||
|
IHookList::IIter *m_pIter;
|
||||||
|
public:
|
||||||
|
AutoHookIter(IHookList *pList)
|
||||||
|
: m_pList(pList), m_pIter(pList->GetIter())
|
||||||
{
|
{
|
||||||
return ptr == other;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
void *vfnptr; //!< Pointer to the function
|
~AutoHookIter()
|
||||||
void *orig_entry; //!< The original vtable entry
|
|
||||||
|
|
||||||
typedef List<Iface> IfaceList;
|
|
||||||
typedef IfaceList::iterator IfaceListIter;
|
|
||||||
IfaceList ifaces; //!< List of interface pointers
|
|
||||||
|
|
||||||
bool operator ==(void *other)
|
|
||||||
{
|
{
|
||||||
return vfnptr == other;
|
m_pList->ReleaseIter(m_pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool End()
|
||||||
|
{
|
||||||
|
return m_pIter->End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next()
|
||||||
|
{
|
||||||
|
m_pIter->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISHDelegate *Handler()
|
||||||
|
{
|
||||||
|
return m_pIter->Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThisPtrOffs()
|
||||||
|
{
|
||||||
|
return m_pIter->ThisPtrOffs();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
|
||||||
HookManagerPubFunc func; //!< The interface to the hook manager
|
|
||||||
|
|
||||||
void *hookfunc_vfnptr; //!< Pointer to the hookfunc impl
|
|
||||||
|
|
||||||
typedef List<VfnPtr> VfnPtrList;
|
|
||||||
typedef VfnPtrList::iterator VfnPtrListIter;
|
|
||||||
VfnPtrList vfnptrs; //!< List of hooked interfaces
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SourceHook::CVector<void*> OrigFuncs;
|
|
||||||
typedef SourceHook::THash<int, OrigFuncs> OrigVTables;
|
|
||||||
|
|
||||||
template<class B> struct CallClass
|
template<class B> struct CallClass
|
||||||
{
|
{
|
||||||
B *ptr; //!< Pointer to the actual object
|
virtual B *GetThisPtr() = 0;
|
||||||
size_t objsize; //!< Size of the instance
|
virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0;
|
||||||
OrigVTables vt; //!< Info about vtables & functions
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef CallClass<void> GenericCallClass;
|
typedef CallClass<void> GenericCallClass;
|
||||||
@ -239,8 +268,6 @@ namespace SourceHook
|
|||||||
class ISourceHook
|
class ISourceHook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ISourceHook()
|
|
||||||
{ }
|
|
||||||
/**
|
/**
|
||||||
* @brief Return interface version
|
* @brief Return interface version
|
||||||
*/
|
*/
|
||||||
@ -263,7 +290,8 @@ namespace SourceHook
|
|||||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||||
* @param post Set to true if you want a post handler
|
* @param post Set to true if you want a post handler
|
||||||
*/
|
*/
|
||||||
virtual bool AddHook(Plugin plug, void *iface, int thisptr_offs, 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.
|
* @brief Removes a hook.
|
||||||
@ -276,7 +304,8 @@ namespace SourceHook
|
|||||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||||
* @param post Set to true if you want a post handler
|
* @param post Set to true if you want a post handler
|
||||||
*/
|
*/
|
||||||
virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, 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
|
* @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins
|
||||||
@ -301,10 +330,13 @@ namespace SourceHook
|
|||||||
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
||||||
|
|
||||||
virtual void SetRes(META_RES res) = 0; //!< Sets the meta result
|
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
|
virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the
|
||||||
|
//!< previously calledhandler
|
||||||
virtual META_RES GetStatus() = 0; //!< Gets the highest meta result
|
virtual META_RES GetStatus() = 0; //!< Gets the highest meta result
|
||||||
virtual const void *GetOrigRet() = 0; //!< Gets the original result. If not in post function, undefined
|
virtual const void *GetOrigRet() = 0; //!< Gets the original result.
|
||||||
virtual const void *GetOverrideRet() = 0; //!< Gets the override result. If none is specified, NULL
|
//!< If not in post function, undefined
|
||||||
|
virtual const void *GetOverrideRet() = 0; //!< Gets the override result.
|
||||||
|
//!< If none is specified, NULL
|
||||||
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// For hook managers
|
// For hook managers
|
||||||
@ -375,10 +407,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
# define SH_SETUP_MFP(mfp) \
|
# define SH_SETUP_MFP(mfp) \
|
||||||
reinterpret_cast<void**>(&mfp)[0] = vfnptr.orig_entry;
|
reinterpret_cast<void**>(&mfp)[0] = vfnptr->GetOrigEntry();
|
||||||
#elif SH_COMP == SH_COMP_GCC
|
#elif SH_COMP == SH_COMP_GCC
|
||||||
# define SH_SETUP_MFP(mfp) \
|
# define SH_SETUP_MFP(mfp) \
|
||||||
reinterpret_cast<void**>(&mfp)[0] = vfnptr.orig_entry; \
|
reinterpret_cast<void**>(&mfp)[0] = vfnptr->GetOrigEntry(); \
|
||||||
reinterpret_cast<void**>(&mfp)[1] = 0;
|
reinterpret_cast<void**>(&mfp)[1] = 0;
|
||||||
#else
|
#else
|
||||||
# error Not supported yet.
|
# error Not supported yet.
|
||||||
@ -388,24 +420,27 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov
|
||||||
|
|
||||||
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \
|
||||||
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::HookManagerInfo *param) \
|
SH_FHCls(ifacetype,ifacefunc,overload)() \
|
||||||
|
{ \
|
||||||
|
GetFuncInfo(funcptr, ms_MFI); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static int HookManPubFunc(::SourceHook::HookManagerAction action, ::SourceHook::IHookManagerInfo *param) \
|
||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
|
GetFuncInfo(funcptr, ms_MFI); \
|
||||||
/* Verify interface version */ \
|
/* Verify interface version */ \
|
||||||
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
if (action == ::SourceHook::HA_GetInfo) \
|
if (action == ::SourceHook::HA_GetInfo) \
|
||||||
{ \
|
{ \
|
||||||
param->proto = ms_Proto; \
|
param->SetInfo(ms_MFI.vtbloffs, ms_MFI.vtblindex, ms_Proto); \
|
||||||
MemFuncInfo mfi; \
|
|
||||||
GetFuncInfo(funcptr, mfi); \
|
|
||||||
param->vtbl_idx = mfi.vtblindex; \
|
|
||||||
param->vtbl_offs = mfi.vtbloffs; \
|
|
||||||
\
|
\
|
||||||
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \
|
||||||
param->hookfunc_vfnptr = \
|
param->SetHookfuncVfnptr( \
|
||||||
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]; \
|
reinterpret_cast<void**>(reinterpret_cast<char*>(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex]); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
else if (action == ::SourceHook::HA_Register) \
|
else if (action == ::SourceHook::HA_Register) \
|
||||||
@ -429,15 +464,17 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
struct SH_FHCls(ifacetype,ifacefunc,overload) \
|
struct SH_FHCls(ifacetype,ifacefunc,overload) \
|
||||||
{ \
|
{ \
|
||||||
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \
|
||||||
static ::SourceHook::HookManagerInfo *ms_HI; \
|
static ::SourceHook::MemFuncInfo ms_MFI; \
|
||||||
|
static ::SourceHook::IHookManagerInfo *ms_HI; \
|
||||||
static const char *ms_Proto; \
|
static const char *ms_Proto; \
|
||||||
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr)
|
||||||
|
|
||||||
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, proto, funcptr) \
|
||||||
}; \
|
}; \
|
||||||
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
||||||
::SourceHook::HookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \
|
||||||
|
::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
||||||
|
const char *SH_FHCls(ifacetype,ifacefunc,overload)::ms_Proto = proto; \
|
||||||
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
||||||
{ \
|
{ \
|
||||||
@ -469,28 +506,22 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
void *ourvfnptr = reinterpret_cast<void*>( \
|
void *ourvfnptr = reinterpret_cast<void*>( \
|
||||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
|
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \
|
||||||
|
IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \
|
||||||
|
SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \
|
||||||
\
|
\
|
||||||
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
|
/* ... and the iface */ \
|
||||||
if (vfptriter == ms_HI->vfnptrs.end()) \
|
IIface *ifinfo = vfnptr->FindIface(reinterpret_cast<void*>(this)); \
|
||||||
{ \
|
if (!ifinfo) \
|
||||||
/* 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 = vfnptr.ifaces.find(this); \
|
|
||||||
if (ifiter == vfnptr.ifaces.end()) \
|
|
||||||
{ \
|
{ \
|
||||||
/* The iface info was not found. Redirect the call to the original function. */ \
|
/* The iface info was not found. Redirect the call to the original function. */ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||||
} \
|
} \
|
||||||
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
|
|
||||||
/* 2) Declare some vars and set it up */ \
|
/* 2) Declare some vars and set it up */ \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
|
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
|
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||||
rettype orig_ret; \
|
rettype orig_ret; \
|
||||||
rettype override_ret; \
|
rettype override_ret; \
|
||||||
rettype plugin_ret; \
|
rettype plugin_ret; \
|
||||||
@ -504,12 +535,11 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#define SH_CALL_HOOKS(post, params) \
|
#define SH_CALL_HOOKS(post, params) \
|
||||||
prev_res = MRES_IGNORED; \
|
prev_res = MRES_IGNORED; \
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
|
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||||
{ \
|
{ \
|
||||||
if (hiter->paused) continue; \
|
|
||||||
cur_res = MRES_IGNORED; \
|
cur_res = MRES_IGNORED; \
|
||||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - hiter->thisptr_offs); \
|
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||||
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(hiter->handler)->GetDeleg() params; \
|
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||||
prev_res = cur_res; \
|
prev_res = cur_res; \
|
||||||
if (cur_res > status) \
|
if (cur_res > status) \
|
||||||
status = cur_res; \
|
status = cur_res; \
|
||||||
@ -525,7 +555,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
rettype (EmptyClass::*mfp)paramtypes; \
|
rettype (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
orig_ret = (reinterpret_cast<EmptyClass*>(ci.ptr)->*mfp)params; \
|
orig_ret = (reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)params; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
orig_ret = override_ret;
|
orig_ret = override_ret;
|
||||||
@ -542,21 +572,16 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define SH_SETUPCALLS_void(paramtypes, params) \
|
#define SH_SETUPCALLS_void(paramtypes, params) \
|
||||||
using namespace ::SourceHook; \
|
|
||||||
/* 1) Find the vfnptr */ \
|
/* 1) Find the vfnptr */ \
|
||||||
|
using namespace ::SourceHook; \
|
||||||
void *ourvfnptr = reinterpret_cast<void*>( \
|
void *ourvfnptr = reinterpret_cast<void*>( \
|
||||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
|
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \
|
||||||
|
IVfnPtr *vfnptr = ms_HI->FindVfnPtr(ourvfnptr); \
|
||||||
|
SH_ASSERT(vfnptr, ("Called with vfnptr 0x%p which couldn't be found in the list", ourvfnptr)); \
|
||||||
\
|
\
|
||||||
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
|
/* ... and the iface */ \
|
||||||
if (vfptriter == ms_HI->vfnptrs.end()) \
|
IIface *ifinfo = vfnptr->FindIface(reinterpret_cast<void*>(this)); \
|
||||||
{ \
|
if (!ifinfo) \
|
||||||
/* 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 = vfnptr.ifaces.find(this); \
|
|
||||||
if (ifiter == vfnptr.ifaces.end()) \
|
|
||||||
{ \
|
{ \
|
||||||
/* The iface info was not found. Redirect the call to the original function. */ \
|
/* The iface info was not found. Redirect the call to the original function. */ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
@ -564,25 +589,24 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
|
|
||||||
/* 2) Declare some vars and set it up */ \
|
/* 2) Declare some vars and set it up */ \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
|
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||||
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
|
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||||
status = MRES_IGNORED; \
|
status = MRES_IGNORED; \
|
||||||
SH_GLOB_SHPTR->SetOverrideRet(NULL);
|
SH_GLOB_SHPTR->SetOverrideRet(NULL); \
|
||||||
|
SH_GLOB_SHPTR->SetOrigRet(NULL);
|
||||||
|
|
||||||
#define SH_CALL_HOOKS_void(post, params) \
|
#define SH_CALL_HOOKS_void(post, params) \
|
||||||
prev_res = MRES_IGNORED; \
|
prev_res = MRES_IGNORED; \
|
||||||
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
|
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||||
{ \
|
{ \
|
||||||
if (hiter->paused) continue; \
|
|
||||||
cur_res = MRES_IGNORED; \
|
cur_res = MRES_IGNORED; \
|
||||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - hiter->thisptr_offs); \
|
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||||
reinterpret_cast<CSHDelegate<FD>*>(hiter->handler)->GetDeleg() params; \
|
reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||||
prev_res = cur_res; \
|
prev_res = cur_res; \
|
||||||
if (cur_res > status) \
|
if (cur_res > status) \
|
||||||
status = cur_res; \
|
status = cur_res; \
|
||||||
@ -593,7 +617,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
void (EmptyClass::*mfp)paramtypes; \
|
void (EmptyClass::*mfp)paramtypes; \
|
||||||
SH_SETUP_MFP(mfp); \
|
SH_SETUP_MFP(mfp); \
|
||||||
(reinterpret_cast<EmptyClass*>(ci.ptr)->*mfp)params; \
|
(reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)params; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SH_RETURN_void()
|
#define SH_RETURN_void()
|
||||||
@ -1490,6 +1514,210 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
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<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 17 arguments *********
|
||||||
|
#define SH_DECL_HOOK17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate17<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, rettype> 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, param17 p17) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), 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 "|" #param17, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate17<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17> 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, param17 p17) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, rettype> 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, param17 p17, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, 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 "|" #param17 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *> 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, param17 p17, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, 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 "|" #param17 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 18 arguments *********
|
||||||
|
#define SH_DECL_HOOK18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, rettype> 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, param17 p17, param18 p18) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), 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 "|" #param17 "|" #param18, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate18<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18> 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, param17 p17, param18 p18) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17 "|" #param18, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, rettype> 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, param17 p17, param18 p18, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, 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 "|" #param17 "|" #param18 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *> 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, param17 p17, param18 p18, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, 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 "|" #param17 "|" #param18 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 19 arguments *********
|
||||||
|
#define SH_DECL_HOOK19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, rettype> 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, param17 p17, param18 p18, param19 p19) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), 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 "|" #param17 "|" #param18 "|" #param19, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate19<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19> 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, param17 p17, param18 p18, param19 p19) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17 "|" #param18 "|" #param19, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, rettype> 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, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 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 "|" #param17 "|" #param18 "|" #param19 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *> 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, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 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 "|" #param17 "|" #param18 "|" #param19 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
// ********* Support for 20 arguments *********
|
||||||
|
#define SH_DECL_HOOK20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, rettype> 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, param17 p17, param18 p18, param19 p19, param20 p20) \
|
||||||
|
{ SH_HANDLEFUNC(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), 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 "|" #param17 "|" #param18 "|" #param19 "|" #param20, \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate20<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20> 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, param17 p17, param18 p18, param19 p19, param20 p20) \
|
||||||
|
{ SH_HANDLEFUNC_void(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, #attr "|" #param1 "|" #param2 "|" #param3 "|" #param4 "|" #param5 "|" #param6 "|" #param7 "|" #param8 "|" #param9 "|" #param10 "|" #param11 "|" #param12 "|" #param13 "|" #param14 "|" #param15 "|" #param16 "|" #param17 "|" #param18 "|" #param19 "|" #param20, \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate21<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, rettype> 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, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, 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 "|" #param17 "|" #param18 "|" #param19 "|" #param20 "|const char*|...", \
|
||||||
|
(static_cast<rettype (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
#define SH_DECL_HOOK20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr> \
|
||||||
|
(&ifacetype::ifacefunc))) \
|
||||||
|
typedef fastdelegate::FastDelegate21<param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *> 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, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \
|
||||||
|
{ \
|
||||||
|
char buf[::SourceHook::STRBUF_LEN]; \
|
||||||
|
va_list ap; \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
SH_HANDLEFUNC_void_vafmt(ifacetype, ifacefunc, (param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, 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 "|" #param17 "|" #param18 "|" #param19 "|" #param20 "|const char*|...", \
|
||||||
|
(static_cast<void (ifacetype::*)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...) attr>(&ifacetype::ifacefunc)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -1497,14 +1725,16 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
|
|
||||||
|
// :TODO: TEST THIS ON MSVC
|
||||||
|
|
||||||
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(m_CC->ptr, m_MFP, mfi); \
|
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||||
OrigVTables::iterator iter = m_CC->vt.find(mfi.thisptroffs + mfi.vtbloffs); \
|
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||||
if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->val.size() || iter->val[mfi.vtblindex] == NULL) \
|
if (!origfunc) \
|
||||||
return (m_CC->ptr->*m_MFP)call; \
|
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||||
\
|
\
|
||||||
/* It's hooked. Call the original function. */ \
|
/* It's hooked. Call the original function. */ \
|
||||||
union \
|
union \
|
||||||
@ -1512,9 +1742,9 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
RetType(EmptyClass::*mfpnew)prms; \
|
RetType(EmptyClass::*mfpnew)prms; \
|
||||||
void *addr; \
|
void *addr; \
|
||||||
} u; \
|
} u; \
|
||||||
u.addr = iter->val[mfi.vtblindex]; \
|
u.addr = origfunc; \
|
||||||
\
|
\
|
||||||
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->ptr) + mfi.thisptroffs); \
|
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->GetThisPtr()) + mfi.thisptroffs); \
|
||||||
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1524,10 +1754,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
{ \
|
{ \
|
||||||
using namespace ::SourceHook; \
|
using namespace ::SourceHook; \
|
||||||
MemFuncInfo mfi; \
|
MemFuncInfo mfi; \
|
||||||
GetFuncInfo(m_CC->ptr, m_MFP, mfi); \
|
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||||
OrigVTables::iterator iter = m_CC->vt.find(mfi.thisptroffs + mfi.vtbloffs); \
|
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||||
if (iter == m_CC->vt.end() || mfi.vtblindex >= (int)iter->val.size() || iter->val[mfi.vtblindex] == NULL) \
|
if (!origfunc) \
|
||||||
return (m_CC->ptr->*m_MFP)call; \
|
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||||
\
|
\
|
||||||
/* It's hooked. Call the original function. */ \
|
/* It's hooked. Call the original function. */ \
|
||||||
union \
|
union \
|
||||||
@ -1539,10 +1769,10 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
|||||||
intptr_t adjustor; \
|
intptr_t adjustor; \
|
||||||
} s; \
|
} s; \
|
||||||
} u; \
|
} u; \
|
||||||
u.s.addr = iter->val[mfi.vtblindex]; \
|
u.s.addr = origfunc; \
|
||||||
u.s.adjustor = mfi.thisptroffs; \
|
u.s.adjustor = mfi.thisptroffs; \
|
||||||
\
|
\
|
||||||
return (reinterpret_cast<EmptyClass*>(m_CC->ptr)->*u.mfpnew)call; \
|
return (reinterpret_cast<EmptyClass*>(m_CC->GetThisPtr())->*u.mfpnew)call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1626,6 +1856,22 @@ namespace SourceHook
|
|||||||
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16> 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
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16> 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((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16))
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16))
|
||||||
|
|
||||||
|
// Support for 17 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17> 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, Param17 p17) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17))
|
||||||
|
|
||||||
|
// Support for 18 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18> 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, Param17 p17, Param18 p18) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18))
|
||||||
|
|
||||||
|
// Support for 19 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19> 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, Param17 p17, Param18 p18, Param19 p19) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19))
|
||||||
|
|
||||||
|
// Support for 20 arguments
|
||||||
|
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20> 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, Param17 p17, Param18 p18, Param19 p19, Param20 p20) const
|
||||||
|
SH_MAKE_EXECUTABLECLASS_OB((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), (Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20))
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1888,6 +2134,66 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param
|
|||||||
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support for 17 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 18 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 19 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 20 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
|
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
|
||||||
// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it
|
// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it
|
||||||
@ -2147,12 +2453,72 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param
|
|||||||
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support for 17 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 18 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 19 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 20 arguments
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...))
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X, class Y, class MFP, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||||
|
SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>
|
||||||
|
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...)const)
|
||||||
|
{
|
||||||
|
return SourceHook::ExecutableClass<SourceHook::CallClass<Y>, RetType, MFP>(ptr, mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
||||||
|
|
||||||
#undef SH_MAKE_EXECUTABLECLASS_BODY
|
#undef SH_MAKE_EXECUTABLECLASS_OB
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// The pope is dead. -> :(
|
// The pope is dead. -> :(
|
||||||
|
@ -12,13 +12,12 @@
|
|||||||
#define __SOURCEHOOK_IMPL_H__
|
#define __SOURCEHOOK_IMPL_H__
|
||||||
|
|
||||||
#include "sourcehook.h"
|
#include "sourcehook.h"
|
||||||
|
#include "sh_list.h"
|
||||||
#ifdef __linux__
|
#include "sh_vector.h"
|
||||||
#include <signal.h>
|
#include "sh_tinyhash.h"
|
||||||
#include <setjmp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set this to 1 to enable runtime code generation (faster)
|
// Set this to 1 to enable runtime code generation (faster)
|
||||||
|
// (unused at the moment, but may come back, so I'm leaving it in here!)
|
||||||
#define SH_RUNTIME_CODEGEN 1
|
#define SH_RUNTIME_CODEGEN 1
|
||||||
|
|
||||||
namespace SourceHook
|
namespace SourceHook
|
||||||
@ -28,6 +27,7 @@ namespace SourceHook
|
|||||||
*/
|
*/
|
||||||
class CSourceHookImpl : public ISourceHook
|
class CSourceHookImpl : public ISourceHook
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief A hook can be removed if you have this information
|
* @brief A hook can be removed if you have this information
|
||||||
*/
|
*/
|
||||||
@ -48,24 +48,165 @@ namespace SourceHook
|
|||||||
bool post;
|
bool post;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct HookInfo
|
||||||
* @brief A list of HookManagerInfo structures
|
{
|
||||||
*/
|
ISHDelegate *handler; //!< Pointer to the handler
|
||||||
typedef List<HookManagerInfo> HookManInfoList;
|
bool paused; //!< If true, the hook should not be executed
|
||||||
|
Plugin plug; //!< The owner plugin
|
||||||
|
int thisptr_offs; //!< This pointer offset
|
||||||
|
};
|
||||||
|
|
||||||
struct CallClassInfo
|
class CHookList : public IHookList
|
||||||
{
|
{
|
||||||
GenericCallClass cc;
|
public:
|
||||||
int refcounter;
|
List<HookInfo> m_List;
|
||||||
bool operator==(void *other)
|
|
||||||
|
friend class CIter;
|
||||||
|
|
||||||
|
class CIter : public IHookList::IIter
|
||||||
{
|
{
|
||||||
return cc.ptr == other;
|
friend class CHookList;
|
||||||
|
|
||||||
|
CHookList *m_pList;
|
||||||
|
List<HookInfo>::iterator m_Iter;
|
||||||
|
|
||||||
|
void SkipPaused();
|
||||||
|
public:
|
||||||
|
CIter(CHookList *pList);
|
||||||
|
|
||||||
|
virtual ~CIter();
|
||||||
|
|
||||||
|
void GoToBegin();
|
||||||
|
|
||||||
|
bool End();
|
||||||
|
void Next();
|
||||||
|
ISHDelegate *Handler();
|
||||||
|
int ThisPtrOffs();
|
||||||
|
|
||||||
|
CIter *m_pNext; // When stored in m_FreeIters
|
||||||
|
};
|
||||||
|
|
||||||
|
CIter *m_FreeIters;
|
||||||
|
|
||||||
|
CHookList();
|
||||||
|
CHookList(const CHookList &other);
|
||||||
|
virtual ~CHookList();
|
||||||
|
|
||||||
|
void operator=(const CHookList &other);
|
||||||
|
|
||||||
|
IIter *GetIter();
|
||||||
|
void ReleaseIter(IIter *pIter);
|
||||||
|
};
|
||||||
|
|
||||||
|
// I know, data hiding... But I'm a lazy bastard!
|
||||||
|
|
||||||
|
class CIface : public IIface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void *m_Ptr;
|
||||||
|
CHookList m_PreHooks;
|
||||||
|
CHookList m_PostHooks;
|
||||||
|
public:
|
||||||
|
CIface(void *ptr);
|
||||||
|
virtual ~CIface();
|
||||||
|
|
||||||
|
void *GetPtr();
|
||||||
|
IHookList *GetPreHooks();
|
||||||
|
IHookList *GetPostHooks();
|
||||||
|
|
||||||
|
bool operator==(void *ptr)
|
||||||
|
{
|
||||||
|
return m_Ptr == ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CVfnPtr : public IVfnPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef List<CIface> IfaceList;
|
||||||
|
typedef IfaceList::iterator IfaceListIter;
|
||||||
|
|
||||||
|
void *m_Ptr;
|
||||||
|
void *m_OrigEntry;
|
||||||
|
|
||||||
|
IfaceList m_Ifaces;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CVfnPtr(void *ptr);
|
||||||
|
virtual ~CVfnPtr();
|
||||||
|
|
||||||
|
void *GetVfnPtr();
|
||||||
|
void *GetOrigEntry();
|
||||||
|
|
||||||
|
virtual IIface *FindIface(void *ptr);
|
||||||
|
|
||||||
|
bool operator==(void *ptr)
|
||||||
|
{
|
||||||
|
return m_Ptr == ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHookManagerInfo : public IHookManagerInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef List<CVfnPtr> VfnPtrList;
|
||||||
|
typedef VfnPtrList::iterator VfnPtrListIter;
|
||||||
|
|
||||||
|
Plugin m_Plug;
|
||||||
|
HookManagerPubFunc m_Func;
|
||||||
|
|
||||||
|
int m_VtblOffs;
|
||||||
|
int m_VtblIdx;
|
||||||
|
const char *m_Proto;
|
||||||
|
void *m_HookfuncVfnptr;
|
||||||
|
|
||||||
|
VfnPtrList m_VfnPtrs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~CHookManagerInfo();
|
||||||
|
|
||||||
|
IVfnPtr *FindVfnPtr(void *vfnptr);
|
||||||
|
|
||||||
|
void SetInfo(int vtbl_offs, int vtbl_idx, const char *proto);
|
||||||
|
void SetHookfuncVfnptr(void *hookfunc_vfnptr);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @brief A list of CHookManagerInfo classes
|
||||||
|
*/
|
||||||
|
typedef List<CHookManagerInfo> HookManInfoList;
|
||||||
|
|
||||||
|
class CCallClassImpl : public GenericCallClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef SourceHook::CVector<void*> OrigFuncs;
|
||||||
|
typedef SourceHook::THash<int, OrigFuncs> OrigVTables;
|
||||||
|
|
||||||
|
void *m_Ptr; //!< Pointer to the actual object
|
||||||
|
size_t m_ObjSize; //!< Size of the instance
|
||||||
|
OrigVTables m_VT; //!< Info about vtables & functions
|
||||||
|
|
||||||
|
int m_RefCounter;
|
||||||
|
|
||||||
|
CCallClassImpl(void *ptr, size_t size);
|
||||||
|
virtual ~CCallClassImpl();
|
||||||
|
|
||||||
|
bool operator==(void *other)
|
||||||
|
{
|
||||||
|
return m_Ptr == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *GetThisPtr();
|
||||||
|
void *GetOrigFunc(int vtbloffs, int vtblidx);
|
||||||
|
|
||||||
|
void ApplyCallClassPatch(int vtbl_offs, int vtbl_idx, void *orig_entry);
|
||||||
|
void RemoveCallClassPatch(int vtbl_offs, int vtbl_idx);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A list of CallClass structures
|
* @brief A list of CallClass structures
|
||||||
*/
|
*/
|
||||||
typedef List<CallClassInfo> Impl_CallClassList;
|
typedef List<CCallClassImpl> Impl_CallClassList;
|
||||||
|
|
||||||
Impl_CallClassList m_CallClasses; //!< A list of already generated callclasses
|
Impl_CallClassList m_CallClasses; //!< A list of already generated callclasses
|
||||||
HookManInfoList m_HookMans; //!< A list of hook managers
|
HookManInfoList m_HookMans; //!< A list of hook managers
|
||||||
@ -76,19 +217,19 @@ namespace SourceHook
|
|||||||
HookManInfoList::iterator FindHookMan(HookManInfoList::iterator begin, HookManInfoList::iterator end,
|
HookManInfoList::iterator FindHookMan(HookManInfoList::iterator begin, HookManInfoList::iterator end,
|
||||||
const char *proto, int vtblofs, int vtblidx);
|
const char *proto, int vtblofs, int vtblidx);
|
||||||
|
|
||||||
void ApplyCallClassPatch(CallClassInfo &cc, int vtbl_offs, int vtbl_idx, void *orig_entry);
|
void ApplyCallClassPatches(CCallClassImpl &cc);
|
||||||
void ApplyCallClassPatches(CallClassInfo &cc);
|
|
||||||
void ApplyCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx, void *orig_entry);
|
void ApplyCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx, void *orig_entry);
|
||||||
void RemoveCallClassPatch(CallClassInfo &cc, int vtbl_offs, int vtbl_idx);
|
|
||||||
void RemoveCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx);
|
void RemoveCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx);
|
||||||
|
|
||||||
|
void SetPluginPaused(Plugin plug, bool paused);
|
||||||
|
|
||||||
META_RES m_Status, m_PrevRes, m_CurRes;
|
META_RES m_Status, m_PrevRes, m_CurRes;
|
||||||
const void *m_OrigRet;
|
const void *m_OrigRet;
|
||||||
const void *m_OverrideRet;
|
const void *m_OverrideRet;
|
||||||
void *m_IfacePtr;
|
void *m_IfacePtr;
|
||||||
public:
|
public:
|
||||||
CSourceHookImpl();
|
CSourceHookImpl();
|
||||||
~CSourceHookImpl();
|
virtual ~CSourceHookImpl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the interface version
|
* @brief Returns the interface version
|
||||||
@ -199,19 +340,6 @@ namespace SourceHook
|
|||||||
virtual void SetOrigRet(const void *ptr); //!< Sets the original return pointer
|
virtual void SetOrigRet(const void *ptr); //!< Sets the original return pointer
|
||||||
virtual void SetOverrideRet(const void *ptr); //!< Sets the override result pointer
|
virtual void SetOverrideRet(const void *ptr); //!< Sets the override result pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
/**
|
|
||||||
* @brief Checks to see if a memory value can be read from a given pointer.
|
|
||||||
*
|
|
||||||
* @return True if the value can be read and false if it cannot.
|
|
||||||
*
|
|
||||||
* @param ptr The pointer to the memory value.
|
|
||||||
* @param len The length of the memory value to be read from the pointer.
|
|
||||||
*/
|
|
||||||
bool IsBadReadPtr(const void *ptr, size_t len);
|
|
||||||
void BadReadHandler(int sig);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#(C)2004-2005 SourceMM Development Team
|
#(C)2004-2005 SourceMM Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
# Makefile written by David "BAILOPAN" Anderson and Pavol Marko
|
||||||
|
|
||||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe
|
OPT_FLAGS = -O3 -funroll-loops -s -pipe
|
||||||
DEBUG_FLAGS = -g -ggdb3
|
DEBUG_FLAGS = -g -ggdb3
|
||||||
CPP = gcc
|
CPP = gcc
|
||||||
BINARY = sourcehook_test
|
|
||||||
|
|
||||||
OBJECTS = test1.cpp test2.cpp test3.cpp test4.cpp testbail.cpp testbail2.cpp testlist.cpp main.cpp sourcehook.cpp
|
|
||||||
|
|
||||||
LINK = -lstdc++
|
LINK = -lstdc++
|
||||||
|
|
||||||
INCLUDE = -I. -I..
|
INCLUDE = -I. -I..
|
||||||
|
MAX_PARAMS=20
|
||||||
|
|
||||||
|
BINARY = sourcehook_test
|
||||||
|
OBJECTS = main.cpp sourcehook.cpp $(shell ls -t test*.cpp)
|
||||||
|
HEADERS = ../sh_list.h ../sh_tinyhash.h ../sh_memory.h ../sh_string.h ../sh_vector.h ../sourcehook_impl.h ../FastDelegate.h ../sourcehook.h ../sh_memfuncinfo.h
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
ifeq "$(DEBUG)" "true"
|
||||||
BIN_DIR = Debug
|
BIN_DIR = Debug
|
||||||
@ -20,27 +20,41 @@ else
|
|||||||
CFLAGS = $(OPT_FLAGS)
|
CFLAGS = $(OPT_FLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# CFLAGS +=
|
CFLAGS += -Wall
|
||||||
|
# Also, enable SH_ASSERT
|
||||||
|
CFLAGS += -DSH_DEBUG
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||||
|
|
||||||
$(BIN_DIR)/%.o: %.cpp
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
$(BIN_DIR)/%.o: %.cpp $(HEADERS)
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
all:
|
../sourcehook.h: ../generate/sourcehook.hxx
|
||||||
mkdir -p $(BIN_DIR)
|
(cd ../generate; ./shworker.bin iter $(MAX_PARAMS) sourcehook.hxx sourcehook.h; cp sourcehook.h ..)
|
||||||
ln -sf ../sourcehook.cpp sourcehook.cpp
|
|
||||||
$(MAKE) sourcehook_test
|
|
||||||
rm -f $(BINARY)
|
|
||||||
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
|
|
||||||
|
|
||||||
sourcehook_test: $(OBJ_LINUX)
|
../sourcehook.hxx: ../generate/sh_memfuncinfo.hxx
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -o$(BIN_DIR)/$(BINARY)
|
(cd ../generate; ./shworker.bin iter $(MAX_PARAMS) sh_memfuncinfo.hxx sh_memfuncinfo.h; cp sh_memfuncino.h ..)
|
||||||
|
|
||||||
|
../FastDelegate.hxx: ../generate/FastDelegate.hxx
|
||||||
|
(cd ../generate; ./shworker.bin iter $(MAX_PARAMS) FastDelegate.hxx FastDelegate.h; cp FastDelegate.h ..)
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
$(MAKE) all DEBUG=true
|
$(MAKE) all DEBUG=true
|
||||||
|
|
||||||
default: all
|
all:
|
||||||
|
mkdir -p $(BIN_DIR)
|
||||||
|
ln -sf ../sourcehook.cpp sourcehook.cpp
|
||||||
|
$(MAKE) $(BINARY)
|
||||||
|
rm -f $(BINARY)
|
||||||
|
rm -f sourcehook.cpp
|
||||||
|
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
|
||||||
|
|
||||||
|
|
||||||
|
$(BINARY): $(OBJ_LINUX)
|
||||||
|
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -o$(BIN_DIR)/$(BINARY)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf Release/*.o
|
rm -rf Release/*.o
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "sourcehook_impl.h"
|
#include "sourcehook_impl.h"
|
||||||
#include "testevents.h"
|
#include "testevents.h"
|
||||||
|
|
||||||
|
#include "sh_memory.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
StateList g_States;
|
StateList g_States;
|
||||||
@ -12,6 +14,7 @@ namespace
|
|||||||
// Basic tests
|
// Basic tests
|
||||||
// Hooking and callclass
|
// Hooking and callclass
|
||||||
|
|
||||||
|
MAKE_STATE_1(State_ModuleInMemory, bool);
|
||||||
MAKE_STATE(State_F1_Called);
|
MAKE_STATE(State_F1_Called);
|
||||||
MAKE_STATE_1(State_F1_PreHandler_Called, void*);
|
MAKE_STATE_1(State_F1_PreHandler_Called, void*);
|
||||||
MAKE_STATE_1(State_F1_PostHandler_Called, void*);
|
MAKE_STATE_1(State_F1_PostHandler_Called, void*);
|
||||||
@ -385,6 +388,22 @@ namespace
|
|||||||
|
|
||||||
bool TestBasic(std::string &error)
|
bool TestBasic(std::string &error)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Simple test for ModuleInMemory:
|
||||||
|
// 1) &error should on the stack
|
||||||
|
// 2) 0 should not be mapped
|
||||||
|
// 3) &error to -1 should not be mapped
|
||||||
|
ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(reinterpret_cast<char*>(&error), sizeof(error))));
|
||||||
|
ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(0, 1)));
|
||||||
|
ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(reinterpret_cast<char*>(&error),
|
||||||
|
(reinterpret_cast<std::string*>(-1) - &error) - 1)));
|
||||||
|
|
||||||
|
CHECK_STATES((&g_States,
|
||||||
|
new State_ModuleInMemory(true),
|
||||||
|
new State_ModuleInMemory(false),
|
||||||
|
new State_ModuleInMemory(false),
|
||||||
|
NULL), "ModuleInMemory");
|
||||||
|
|
||||||
SourceHook::CSourceHookImpl g_SHImpl;
|
SourceHook::CSourceHookImpl g_SHImpl;
|
||||||
g_SHPtr = &g_SHImpl;
|
g_SHPtr = &g_SHImpl;
|
||||||
g_PLID = 1337;
|
g_PLID = 1337;
|
||||||
|
@ -31,6 +31,58 @@ namespace
|
|||||||
|
|
||||||
SH_DECL_HOOK0_void(IGaben, EatYams, SH_NOATTRIB, 0);
|
SH_DECL_HOOK0_void(IGaben, EatYams, SH_NOATTRIB, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
SHINT_MAKE_GENERICSTUFF_BEGIN(IGaben, EatYams, 0, (static_cast<void (IGaben::*)() SH_NOATTRIB>
|
||||||
|
(&IGaben::EatYams)))
|
||||||
|
typedef fastdelegate::FastDelegate0<> FD;
|
||||||
|
virtual void Func()
|
||||||
|
{
|
||||||
|
// SH_HANDLEFUNC_void(IGaben, EatYams, (), ());
|
||||||
|
|
||||||
|
SH_SETUPCALLS_void((), ())
|
||||||
|
SH_CALL_HOOKS_void(pre, ())
|
||||||
|
if (status != MRES_SUPERCEDE)
|
||||||
|
{
|
||||||
|
void (EmptyClass::*mfp)();
|
||||||
|
SH_SETUP_MFP(mfp);
|
||||||
|
(reinterpret_cast<EmptyClass*>(ifinfo->GetPtr())->*mfp)();
|
||||||
|
}
|
||||||
|
SH_CALL_HOOKS_void(post, ())
|
||||||
|
SH_RETURN_void()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SH_FHCls(IGaben,EatYams,0) SH_FHCls(IGaben,EatYams,0)::ms_Inst;
|
||||||
|
::SourceHook::MemFuncInfo SH_FHCls(IGaben,EatYams,0)::ms_MFI;
|
||||||
|
::SourceHook::IHookManagerInfo *SH_FHCls(IGaben,EatYams,0)::ms_HI;
|
||||||
|
const char *SH_FHCls(IGaben,EatYams,0)::ms_Proto = "SH_NOATTRIB";
|
||||||
|
bool __SourceHook_FHAddIGabenEatYams(void *iface, bool post,
|
||||||
|
SH_FHCls(IGaben,EatYams,0)::FD handler)
|
||||||
|
{
|
||||||
|
using namespace ::SourceHook;
|
||||||
|
MemFuncInfo mfi;
|
||||||
|
GetFuncInfo((static_cast<void (IGaben::*)() SH_NOATTRIB>(&IGaben::EatYams)), mfi);
|
||||||
|
if (mfi.thisptroffs < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs,
|
||||||
|
SH_FHCls(IGaben,EatYams,0)::HookManPubFunc,
|
||||||
|
new CSHDelegate<SH_FHCls(IGaben,EatYams,0)::FD>(handler), post);
|
||||||
|
}
|
||||||
|
bool __SourceHook_FHRemoveIGabenEatYams(void *iface, bool post,
|
||||||
|
SH_FHCls(IGaben,EatYams,0)::FD handler)
|
||||||
|
{
|
||||||
|
using namespace ::SourceHook;
|
||||||
|
MemFuncInfo mfi;
|
||||||
|
GetFuncInfo((static_cast<void (IGaben::*)() SH_NOATTRIB>(&IGaben::EatYams)), mfi);
|
||||||
|
if (mfi.thisptroffs < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CSHDelegate<SH_FHCls(IGaben,EatYams,0)::FD> tmp(handler);
|
||||||
|
return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs,
|
||||||
|
SH_FHCls(IGaben,EatYams,0)::HookManPubFunc, &tmp, post);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void EatYams0_Handler()
|
void EatYams0_Handler()
|
||||||
{
|
{
|
||||||
ADD_STATE(State_EatYams_Handler_Called);
|
ADD_STATE(State_EatYams_Handler_Called);
|
||||||
|
@ -148,6 +148,15 @@ namespace
|
|||||||
for (int i = 1; i <= mymax; ++i)
|
for (int i = 1; i <= mymax; ++i)
|
||||||
hash2[i] = i + 5000;
|
hash2[i] = i + 5000;
|
||||||
|
|
||||||
|
hash2.erase(mymax - 100);
|
||||||
|
CHECK_COND(hash2.find(mymax - 101) != hash2.end(), "Part 4.1");
|
||||||
|
CHECK_COND(hash2.find(mymax - 99) != hash2.end(), "Part 4.2");
|
||||||
|
CHECK_COND(hash2.find(mymax - 100) == hash2.end(), "Part 4.3");
|
||||||
|
hash2.erase(mymax - 99);
|
||||||
|
CHECK_COND(hash2.find(mymax - 101) != hash2.end(), "Part 4.4");
|
||||||
|
CHECK_COND(hash2.find(mymax - 99) == hash2.end(), "Part 4.5");
|
||||||
|
CHECK_COND(hash2.find(mymax - 100) == hash2.end(), "Part 4.6");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user