Added manual callclasses

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40200
This commit is contained in:
Pavol Marko 2006-05-14 18:29:35 +00:00
parent 3e860a89cc
commit 2b3d8002f1
4 changed files with 2658 additions and 88 deletions

File diff suppressed because it is too large Load Diff

View File

@ -298,6 +298,7 @@ namespace SourceHook
};
typedef CallClass<void> GenericCallClass;
typedef CallClass<EmptyClass> ManualCallClass;
/**
* @brief The main SourceHook interface
@ -495,6 +496,13 @@ inline SourceHook::CallClass<ifacetype> *SH_GET_CALLCLASS_R(SourceHook::ISourceH
shptr->GetCallClass(reinterpret_cast<void*>(ptr), sizeof(ifacetype)));
}
template<class ifacetype>
inline SourceHook::CallClass<ifacetype> *SH_GET_MCALLCLASS_R(SourceHook::ISourceHook *shptr, ifacetype *ptr, int ifacesize)
{
return reinterpret_cast<SourceHook::CallClass<ifacetype>*>(
shptr->GetCallClass(reinterpret_cast<void*>(ptr), ifacesize));
}
template<class ifacetype>
inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::CallClass<ifacetype> *ptr)
{
@ -510,6 +518,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
} while (0)
#define SH_GET_CALLCLASS(ptr) SH_GET_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
#define SH_GET_MCALLCLASS(ptr, size) SH_GET_MCALLCLASS_R(SH_GLOB_SHPTR, reinterpret_cast<SourceHook::EmptyClass*>(ptr), size)
#define SH_RELEASE_CALLCLASS(ptr) SH_RELEASE_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \
@ -956,22 +965,24 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]@[$1!=0:, @]rettype> FD; \
virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \
{ SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \
typedef rettype(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \
SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
\
const int __SourceHook_ParamSizesM_##hookname[] = { 0@[$2,1,$1:, sizeof(param$2)@] }; \
::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(sizeof(rettype), \
$1, __SourceHook_ParamSizesM_##hookname);
$1, __SourceHook_ParamSizesM_##hookname); \
#define SH_DECL_MANUALHOOK$1_void(hookname, vtblidx, vtbloffs, thisptroffs@[$2,1,$1:, param$2@]) \
SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
typedef fastdelegate::FastDelegate$1<@[$2,1,$1|, :param$2@]> FD; \
virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \
{ SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \
typedef void(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \
SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \
\
const int __SourceHook_ParamSizesM_##hookname[] = { 0@[$2,1,$1:, sizeof(param$2)@] }; \
::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto(0, \
$1, __SourceHook_ParamSizesM_##hookname);
$1, __SourceHook_ParamSizesM_##hookname); \
@]
@ -1002,6 +1013,22 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
}
# define SH_MAKE_MEXECUTABLECLASS_OB(call, prms) \
{ \
using namespace ::SourceHook; \
char *adjustedthisptr = reinterpret_cast<char*>(m_CC->GetThisPtr()) + m_ThisPtrOffs; \
union \
{ \
RetType(EmptyClass::*mfpnew)prms; \
void *addr; \
} u; \
u.addr = m_CC->GetOrigFunc(m_ThisPtrOffs + m_VtblOffs, m_VtblIdx); \
if (!u.addr) \
u.addr = (*reinterpret_cast<void***>(adjustedthisptr + m_VtblOffs))[m_VtblIdx]; \
\
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
}
#elif SH_COMP == SH_COMP_GCC
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
@ -1029,6 +1056,26 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
return (reinterpret_cast<EmptyClass*>(m_CC->GetThisPtr())->*u.mfpnew)call; \
}
# define SH_MAKE_MEXECUTABLECLASS_OB(call, prms) \
{ \
using namespace ::SourceHook; \
char *thisptr = reinterpret_cast<char*>(m_CC->GetThisPtr()); \
union \
{ \
RetType(EmptyClass::*mfpnew)prms; \
struct { \
void *addr; \
intptr_t adjustor; \
} s; \
} u; \
u.s.addr = m_CC->GetOrigFunc(m_ThisPtrOffs + m_VtblOffs, m_VtblIdx); \
if (!u.s.addr) \
u.s.addr = (*reinterpret_cast<void***>(thisptr + m_ThisPtrOffs + m_VtblOffs))[m_VtblIdx]; \
\
u.s.adjustor = m_ThisPtrOffs; \
return (reinterpret_cast<EmptyClass*>(thisptr)->*u.mfpnew)call; \
}
#endif
namespace SourceHook
@ -1050,6 +1097,25 @@ namespace SourceHook
SH_MAKE_EXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@]))
@]
};
template <class RetType@[$2,1,$1:, class Param$2@]> class MExecutableClass$1
{
ManualCallClass *m_CC;
int m_ThisPtrOffs;
int m_VtblIdx;
int m_VtblOffs;
public:
MExecutableClass$1(ManualCallClass *cc, int vtbloffs, int vtblidx, int thisptroffs) : m_CC(cc),
m_ThisPtrOffs(thisptroffs), m_VtblIdx(vtblidx), m_VtblOffs(vtbloffs) { }
RetType operator()(@[$2,1,$1|, :Param$2 p$2@]) const
SH_MAKE_MEXECUTABLECLASS_OB((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@]))
@[$2,$1+1,$a:
template <@[$3,$1+1,$2|, :class Param$3@]> RetType operator()(@[$3,1,$2|, :Param$3 p$3@]) const
SH_MAKE_MEXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@]))
@]
};
@]
}
@ -1074,6 +1140,12 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :
return SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>(ptr, mfp);
}
template <class X, class RetType@[$2,1,$1:, class Param$2@]>
SourceHook::MExecutableClass$1<RetType@[$2,1,$1:, Param$2@]>
SH_MCALL2(SourceHook::ManualCallClass *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]), int vtblidx, int vtbloffs, int thisptroffs)
{
return SourceHook::MExecutableClass$1<RetType@[$2,1,$1:, Param$2@]>(ptr, vtbloffs, vtblidx, thisptroffs);
}
@]
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
@ -1094,11 +1166,14 @@ SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :
{
return SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>(ptr, mfp);
}
@]
#endif
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
#define SH_MCALL(ptr, mhookname) SH_MCALL2((ptr), SH_MFHCls(mhookname)::ECMFP(), SH_MFHCls(mhookname)::ms_MFI.vtblindex, \
SH_MFHCls(mhookname)::ms_MFI.vtbloffs, SH_MFHCls(mhookname)::ms_MFI.thisptroffs)
#undef SH_MAKE_EXECUTABLECLASS_OB

File diff suppressed because it is too large Load Diff

View File

@ -64,6 +64,11 @@ namespace
SH_DECL_MANUALHOOK0(TheWall_Func3, 2, 0, 0, short);
SH_DECL_MANUALHOOK1(TheWall_Func4, 3, 0, 0, short, int);
typedef void (SourceHook::EmptyClass::*MFP_Func1)();
typedef void (SourceHook::EmptyClass::*MFP_Func2)(int);
typedef short (SourceHook::EmptyClass::*MFP_Func3)();
typedef short (SourceHook::EmptyClass::*MFP_Func4)(int);
void Handler_Func1()
{
ADD_STATE(State_Func1H_Called(META_IFACEPTR(void)));
@ -101,6 +106,8 @@ bool TestManual(std::string &error)
TheWall inst;
TheWall *p = &inst;
SourceHook::ManualCallClass *cc = SH_GET_MCALLCLASS(p, sizeof(void*));
// 1)
// Call each function
p->Func1();
@ -117,8 +124,34 @@ bool TestManual(std::string &error)
new State_Return(4),
NULL), "Part 1");
// 1.1)
// Now call each function through the manual call class, using the hook decl and manually
SH_MCALL(cc, TheWall_Func1)();
SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)();
SH_MCALL(cc, TheWall_Func2)(200);
SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200);
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)()));
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)()));
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400)));
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400)));
CHECK_STATES((&g_States,
new State_Func1_Called(p),
new State_Func1_Called(p),
new State_Func2_Called(p, 200),
new State_Func2_Called(p, 200),
new State_Func3_Called(p),
new State_Return(3),
new State_Func3_Called(p),
new State_Return(3),
new State_Func4_Called(p, 400),
new State_Return(4),
new State_Func4_Called(p, 400),
new State_Return(4),
NULL), "Part 1.1");
// 2)
// Hook each function normally, call them, unhook them
// Hook each function normally, call them
SH_ADD_HOOK_STATICFUNC(TheWall, Func1, p, Handler_Func1, false);
SH_ADD_HOOK_STATICFUNC(TheWall, Func2, p, Handler_Func2, false);
SH_ADD_HOOK_STATICFUNC(TheWall, Func3, p, Handler_Func3, false);
@ -142,13 +175,41 @@ bool TestManual(std::string &error)
new State_Return(4),
NULL), "Part 2");
// Call them through the mcallclass
// 2.1)
// Now call each function through the manual call class, using the hook decl and manually
SH_MCALL(cc, TheWall_Func1)();
SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)();
SH_MCALL(cc, TheWall_Func2)(200);
SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200);
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)()));
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)()));
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400)));
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400)));
CHECK_STATES((&g_States,
new State_Func1_Called(p),
new State_Func1_Called(p),
new State_Func2_Called(p, 200),
new State_Func2_Called(p, 200),
new State_Func3_Called(p),
new State_Return(3),
new State_Func3_Called(p),
new State_Return(3),
new State_Func4_Called(p, 400),
new State_Return(4),
new State_Func4_Called(p, 400),
new State_Return(4),
NULL), "Part 2.1");
// Unhook them
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func1, p, Handler_Func1, false);
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func2, p, Handler_Func2, false);
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func3, p, Handler_Func3, false);
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func4, p, Handler_Func4, false);
// 3)
// Hook each function manually, call them, unhook them
// Hook each function manually, call them
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func1, p, Handler_Func1, false);
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func2, p, Handler_Func2, false);
@ -173,6 +234,36 @@ bool TestManual(std::string &error)
new State_Return(4),
NULL), "Part 3");
// Now through the mcallclass
// Call them through the mcallclass
// 3.1)
// Now call each function through the manual call class, using the hook decl and manually
SH_MCALL(cc, TheWall_Func1)();
SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)();
SH_MCALL(cc, TheWall_Func2)(200);
SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200);
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)()));
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)()));
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400)));
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400)));
CHECK_STATES((&g_States,
new State_Func1_Called(p),
new State_Func1_Called(p),
new State_Func2_Called(p, 200),
new State_Func2_Called(p, 200),
new State_Func3_Called(p),
new State_Return(3),
new State_Func3_Called(p),
new State_Return(3),
new State_Func4_Called(p, 400),
new State_Return(4),
new State_Func4_Called(p, 400),
new State_Return(4),
NULL), "Part 3.1");
// Unhook them
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func1, p, Handler_Func1, false);
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func2, p, Handler_Func2, false);
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func3, p, Handler_Func3, false);