1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-11-29 11:24:19 +01:00

Added support for functions returning references; added TestRefRet, fixed typos in sourcehook_impl.h

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40250
This commit is contained in:
Pavol Marko 2006-08-09 06:46:11 +00:00
parent 1f58fa8ed2
commit 6a15c59cce
7 changed files with 631 additions and 111 deletions

View File

@ -300,6 +300,49 @@ namespace SourceHook
typedef CallClass<void> GenericCallClass;
typedef CallClass<EmptyClass> ManualCallClass;
// 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!)
// - Today is an important day.
// I'm adding support for functions which return references.
// How it works:
// SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret,
// override ret) anymore; instead, it uses SourceHook::ReferenceCarrier<rettype>::type
// this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class
// which stores the reference as a pointer, and implements constructors, operator= and a conversion operator.
// special cases were needed for getoverrideret / getorigret; these are implemented through the
// SourceHook::MacroRefHelpers structs.
// Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file.
template <class T> struct ReferenceCarrier
{
typedef T type;
};
template <class T> struct ReferenceCarrier<T&>
{
class type
{
T *m_StoredRef;
public:
type() : m_StoredRef(NULL)
{
}
type(T& ref) : m_StoredRef(&ref)
{
}
T& operator= (T& ref)
{
m_StoredRef = &ref;
return ref;
}
operator T& () const
{
return *m_StoredRef;
}
};
};
/**
* @brief The main SourceHook interface
*/
@ -438,6 +481,35 @@ namespace SourceHook
//!<
};
// For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET:
// These have to be able to return references. If T is a reference, the pointers returned
// from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier<T>::type.
template <class T> struct MacroRefHelpers
{
inline static const T* GetOrigRet(ISourceHook *shptr)
{
return reinterpret_cast<const T*>(shptr->GetOrigRet());
}
inline static const T* GetOverrideRet(ISourceHook *shptr)
{
return reinterpret_cast<const T*>(shptr->GetOverrideRet());
}
};
template <class T> struct MacroRefHelpers<T&>
{
inline static T* GetOrigRet(ISourceHook *shptr)
{
T &ref = *reinterpret_cast<const ReferenceCarrier<T&>::type *>(shptr->GetOrigRet());
return &ref;
}
inline static T* GetOverrideRet(ISourceHook *shptr)
{
T &ref = *reinterpret_cast<const ReferenceCarrier<T&>::type *>(shptr->GetOverrideRet());
return &ref;
}
};
}
/************************************************************************/
@ -445,14 +517,18 @@ namespace SourceHook
/************************************************************************/
#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus()
#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes()
#define META_RESULT_ORIG_RET(type) *reinterpret_cast<const type*>(SH_GLOB_SHPTR->GetOrigRet())
#define META_RESULT_OVERRIDE_RET(type) *reinterpret_cast<const type*>(SH_GLOB_SHPTR->GetOverrideRet())
#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers<type>::GetOrigRet(SH_GLOB_SHPTR)
#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers<type>::GetOverrideRet(SH_GLOB_SHPTR)
#define META_IFACEPTR(type) reinterpret_cast<type*>(SH_GLOB_SHPTR->GetIfacePtr())
#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result)
#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0)
#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0)
// If a hook on a function which returns a reference does not want to specify a return value,
// it can use this macro.
// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!!
#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast<rettype>(*SH_GLOB_SHPTR); } while(0)
// only call these from the hook handlers directly!
// :TODO: enforce it ?
@ -477,7 +553,7 @@ namespace SourceHook
{ \
/* meh, set the override result here because we don't get a chance to return */ \
/* before continuing the hook loop through the recall */ \
SourceHook::SetOverrideResult(SH_GLOB_SHPTR, memfuncptr, value); \
SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \
} \
RETURN_META_VALUE(MRES_SUPERCEDE, \
(SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \
@ -808,11 +884,12 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
META_RES status = MRES_IGNORED; \
META_RES prev_res; \
META_RES cur_res; \
rettype orig_ret; \
rettype override_ret; \
rettype plugin_ret; \
typedef ReferenceCarrier<rettype>::type my_rettype; \
my_rettype orig_ret; \
my_rettype override_ret; \
my_rettype plugin_ret; \
void* ifptr; \
rettype *pOverrideRet = reinterpret_cast<rettype*>(SH_GLOB_SHPTR->SetupHookLoop( \
my_rettype *pOverrideRet = reinterpret_cast<my_rettype*>(SH_GLOB_SHPTR->SetupHookLoop( \
&status, &prev_res, &cur_res, &ifptr, &orig_ret, &override_ret));
#define SH_CALL_HOOKS(post, params) \
@ -945,6 +1022,11 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
//////////////////////////////////////////////////////////////////////////
// :FIXME:
// sizeof on references returns the size of the datatype, NOT the pointer size or something
// -> one should probably flag references in __SourceHook_ParamSizes_* !
// or simply assume that their size is sizeof(void*)=SH_PTRSIZE... could be doable through a simple template
// ********* Support for 0 arguments *********
#define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \
@ -5740,11 +5822,34 @@ namespace SourceHook
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
}
// SetOverrideResult used to be implemented like this:
// SetOverrideResult(shptr, memfuncptr, return);
// normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference
// (it thought it was ambigous - the ref and non-ref type)
// so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work
// new syntax: SetOverrideResult(memfuncptr)(shptr, return)
// This also allows us to create a special version for references which respects ReferenceCarrier.
template <class T> struct OverrideFunctor
{
void operator()(ISourceHook *shptr, T res)
{
*reinterpret_cast<T*>(shptr->GetOverrideRetPtr()) = res;
}
};
template <class T> struct OverrideFunctor<T&>
{
void operator()(ISourceHook *shptr, T &res)
{
// overrideretptr points to ReferenceCarrier<T&>
*reinterpret_cast<ReferenceCarrier<T&>::type *>(shptr->GetOverrideRetPtr()) = res;
}
};
template <class Iface, class RetType>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)())
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType>
@ -5754,9 +5859,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1>
@ -5766,9 +5871,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2>
@ -5778,9 +5883,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3>
@ -5790,9 +5895,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4>
@ -5802,9 +5907,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
@ -5814,9 +5919,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
@ -5826,9 +5931,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
@ -5838,9 +5943,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
@ -5850,9 +5955,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
@ -5862,9 +5967,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
@ -5874,9 +5979,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
@ -5886,9 +5991,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5898,9 +6003,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5910,9 +6015,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5922,9 +6027,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5934,9 +6039,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5946,9 +6051,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5958,9 +6063,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5970,9 +6075,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5982,9 +6087,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>

View File

@ -300,6 +300,49 @@ namespace SourceHook
typedef CallClass<void> GenericCallClass;
typedef CallClass<EmptyClass> ManualCallClass;
// 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!)
// - Today is an important day.
// I'm adding support for functions which return references.
// How it works:
// SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret,
// override ret) anymore; instead, it uses SourceHook::ReferenceCarrier<rettype>::type
// this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class
// which stores the reference as a pointer, and implements constructors, operator= and a conversion operator.
// special cases were needed for getoverrideret / getorigret; these are implemented through the
// SourceHook::MacroRefHelpers structs.
// Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file.
template <class T> struct ReferenceCarrier
{
typedef T type;
};
template <class T> struct ReferenceCarrier<T&>
{
class type
{
T *m_StoredRef;
public:
type() : m_StoredRef(NULL)
{
}
type(T& ref) : m_StoredRef(&ref)
{
}
T& operator= (T& ref)
{
m_StoredRef = &ref;
return ref;
}
operator T& () const
{
return *m_StoredRef;
}
};
};
/**
* @brief The main SourceHook interface
*/
@ -438,6 +481,35 @@ namespace SourceHook
//!<
};
// For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET:
// These have to be able to return references. If T is a reference, the pointers returned
// from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier<T>::type.
template <class T> struct MacroRefHelpers
{
inline static const T* GetOrigRet(ISourceHook *shptr)
{
return reinterpret_cast<const T*>(shptr->GetOrigRet());
}
inline static const T* GetOverrideRet(ISourceHook *shptr)
{
return reinterpret_cast<const T*>(shptr->GetOverrideRet());
}
};
template <class T> struct MacroRefHelpers<T&>
{
inline static T* GetOrigRet(ISourceHook *shptr)
{
T &ref = *reinterpret_cast<const ReferenceCarrier<T&>::type *>(shptr->GetOrigRet());
return &ref;
}
inline static T* GetOverrideRet(ISourceHook *shptr)
{
T &ref = *reinterpret_cast<const ReferenceCarrier<T&>::type *>(shptr->GetOverrideRet());
return &ref;
}
};
}
/************************************************************************/
@ -445,14 +517,18 @@ namespace SourceHook
/************************************************************************/
#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus()
#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes()
#define META_RESULT_ORIG_RET(type) *reinterpret_cast<const type*>(SH_GLOB_SHPTR->GetOrigRet())
#define META_RESULT_OVERRIDE_RET(type) *reinterpret_cast<const type*>(SH_GLOB_SHPTR->GetOverrideRet())
#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers<type>::GetOrigRet(SH_GLOB_SHPTR)
#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers<type>::GetOverrideRet(SH_GLOB_SHPTR)
#define META_IFACEPTR(type) reinterpret_cast<type*>(SH_GLOB_SHPTR->GetIfacePtr())
#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result)
#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0)
#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0)
// If a hook on a function which returns a reference does not want to specify a return value,
// it can use this macro.
// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!!
#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast<rettype>(*SH_GLOB_SHPTR); } while(0)
// only call these from the hook handlers directly!
// :TODO: enforce it ?
@ -477,7 +553,7 @@ namespace SourceHook
{ \
/* meh, set the override result here because we don't get a chance to return */ \
/* before continuing the hook loop through the recall */ \
SourceHook::SetOverrideResult(SH_GLOB_SHPTR, memfuncptr, value); \
SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \
} \
RETURN_META_VALUE(MRES_SUPERCEDE, \
(SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \
@ -808,11 +884,12 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
META_RES status = MRES_IGNORED; \
META_RES prev_res; \
META_RES cur_res; \
rettype orig_ret; \
rettype override_ret; \
rettype plugin_ret; \
typedef ReferenceCarrier<rettype>::type my_rettype; \
my_rettype orig_ret; \
my_rettype override_ret; \
my_rettype plugin_ret; \
void* ifptr; \
rettype *pOverrideRet = reinterpret_cast<rettype*>(SH_GLOB_SHPTR->SetupHookLoop( \
my_rettype *pOverrideRet = reinterpret_cast<my_rettype*>(SH_GLOB_SHPTR->SetupHookLoop( \
&status, &prev_res, &cur_res, &ifptr, &orig_ret, &override_ret));
#define SH_CALL_HOOKS(post, params) \
@ -945,6 +1022,11 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
//////////////////////////////////////////////////////////////////////////
// :FIXME:
// sizeof on references returns the size of the datatype, NOT the pointer size or something
// -> one should probably flag references in __SourceHook_ParamSizes_* !
// or simply assume that their size is sizeof(void*)=SH_PTRSIZE... could be doable through a simple template
@[$1,0,$a:
// ********* Support for $1 arguments *********
#define SH_DECL_HOOK$1(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \
@ -1246,11 +1328,34 @@ namespace SourceHook
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
}
// SetOverrideResult used to be implemented like this:
// SetOverrideResult(shptr, memfuncptr, return);
// normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference
// (it thought it was ambigous - the ref and non-ref type)
// so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work
// new syntax: SetOverrideResult(memfuncptr)(shptr, return)
// This also allows us to create a special version for references which respects ReferenceCarrier.
template <class T> struct OverrideFunctor
{
void operator()(ISourceHook *shptr, T res)
{
*reinterpret_cast<T*>(shptr->GetOverrideRetPtr()) = res;
}
};
template <class T> struct OverrideFunctor<T&>
{
void operator()(ISourceHook *shptr, T &res)
{
// overrideretptr points to ReferenceCarrier<T&>
*reinterpret_cast<ReferenceCarrier<T&>::type *>(shptr->GetOverrideRetPtr()) = res;
}
};
@[$1,0,$a:
template <class Iface, class RetType@[$2,1,$1:, class Param$2@]>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@]), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@]))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType@[$2,1,$1:, class Param$2@]>

View File

@ -300,6 +300,49 @@ namespace SourceHook
typedef CallClass<void> GenericCallClass;
typedef CallClass<EmptyClass> ManualCallClass;
// 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!)
// - Today is an important day.
// I'm adding support for functions which return references.
// How it works:
// SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret,
// override ret) anymore; instead, it uses SourceHook::ReferenceCarrier<rettype>::type
// this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class
// which stores the reference as a pointer, and implements constructors, operator= and a conversion operator.
// special cases were needed for getoverrideret / getorigret; these are implemented through the
// SourceHook::MacroRefHelpers structs.
// Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file.
template <class T> struct ReferenceCarrier
{
typedef T type;
};
template <class T> struct ReferenceCarrier<T&>
{
class type
{
T *m_StoredRef;
public:
type() : m_StoredRef(NULL)
{
}
type(T& ref) : m_StoredRef(&ref)
{
}
T& operator= (T& ref)
{
m_StoredRef = &ref;
return ref;
}
operator T& () const
{
return *m_StoredRef;
}
};
};
/**
* @brief The main SourceHook interface
*/
@ -438,6 +481,35 @@ namespace SourceHook
//!<
};
// For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET:
// These have to be able to return references. If T is a reference, the pointers returned
// from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier<T>::type.
template <class T> struct MacroRefHelpers
{
inline static const T* GetOrigRet(ISourceHook *shptr)
{
return reinterpret_cast<const T*>(shptr->GetOrigRet());
}
inline static const T* GetOverrideRet(ISourceHook *shptr)
{
return reinterpret_cast<const T*>(shptr->GetOverrideRet());
}
};
template <class T> struct MacroRefHelpers<T&>
{
inline static T* GetOrigRet(ISourceHook *shptr)
{
T &ref = *reinterpret_cast<const ReferenceCarrier<T&>::type *>(shptr->GetOrigRet());
return &ref;
}
inline static T* GetOverrideRet(ISourceHook *shptr)
{
T &ref = *reinterpret_cast<const ReferenceCarrier<T&>::type *>(shptr->GetOverrideRet());
return &ref;
}
};
}
/************************************************************************/
@ -445,14 +517,18 @@ namespace SourceHook
/************************************************************************/
#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus()
#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes()
#define META_RESULT_ORIG_RET(type) *reinterpret_cast<const type*>(SH_GLOB_SHPTR->GetOrigRet())
#define META_RESULT_OVERRIDE_RET(type) *reinterpret_cast<const type*>(SH_GLOB_SHPTR->GetOverrideRet())
#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers<type>::GetOrigRet(SH_GLOB_SHPTR)
#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers<type>::GetOverrideRet(SH_GLOB_SHPTR)
#define META_IFACEPTR(type) reinterpret_cast<type*>(SH_GLOB_SHPTR->GetIfacePtr())
#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result)
#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0)
#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0)
// If a hook on a function which returns a reference does not want to specify a return value,
// it can use this macro.
// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!!
#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast<rettype>(*SH_GLOB_SHPTR); } while(0)
// only call these from the hook handlers directly!
// :TODO: enforce it ?
@ -477,7 +553,7 @@ namespace SourceHook
{ \
/* meh, set the override result here because we don't get a chance to return */ \
/* before continuing the hook loop through the recall */ \
SourceHook::SetOverrideResult(SH_GLOB_SHPTR, memfuncptr, value); \
SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \
} \
RETURN_META_VALUE(MRES_SUPERCEDE, \
(SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \
@ -808,11 +884,12 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
META_RES status = MRES_IGNORED; \
META_RES prev_res; \
META_RES cur_res; \
rettype orig_ret; \
rettype override_ret; \
rettype plugin_ret; \
typedef ReferenceCarrier<rettype>::type my_rettype; \
my_rettype orig_ret; \
my_rettype override_ret; \
my_rettype plugin_ret; \
void* ifptr; \
rettype *pOverrideRet = reinterpret_cast<rettype*>(SH_GLOB_SHPTR->SetupHookLoop( \
my_rettype *pOverrideRet = reinterpret_cast<my_rettype*>(SH_GLOB_SHPTR->SetupHookLoop( \
&status, &prev_res, &cur_res, &ifptr, &orig_ret, &override_ret));
#define SH_CALL_HOOKS(post, params) \
@ -945,6 +1022,11 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
//////////////////////////////////////////////////////////////////////////
// :FIXME:
// sizeof on references returns the size of the datatype, NOT the pointer size or something
// -> one should probably flag references in __SourceHook_ParamSizes_* !
// or simply assume that their size is sizeof(void*)=SH_PTRSIZE... could be doable through a simple template
// ********* Support for 0 arguments *********
#define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \
@ -5740,11 +5822,34 @@ namespace SourceHook
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
}
// SetOverrideResult used to be implemented like this:
// SetOverrideResult(shptr, memfuncptr, return);
// normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference
// (it thought it was ambigous - the ref and non-ref type)
// so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work
// new syntax: SetOverrideResult(memfuncptr)(shptr, return)
// This also allows us to create a special version for references which respects ReferenceCarrier.
template <class T> struct OverrideFunctor
{
void operator()(ISourceHook *shptr, T res)
{
*reinterpret_cast<T*>(shptr->GetOverrideRetPtr()) = res;
}
};
template <class T> struct OverrideFunctor<T&>
{
void operator()(ISourceHook *shptr, T &res)
{
// overrideretptr points to ReferenceCarrier<T&>
*reinterpret_cast<ReferenceCarrier<T&>::type *>(shptr->GetOverrideRetPtr()) = res;
}
};
template <class Iface, class RetType>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)())
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType>
@ -5754,9 +5859,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1>
@ -5766,9 +5871,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2>
@ -5778,9 +5883,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3>
@ -5790,9 +5895,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4>
@ -5802,9 +5907,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
@ -5814,9 +5919,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
@ -5826,9 +5931,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
@ -5838,9 +5943,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
@ -5850,9 +5955,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
@ -5862,9 +5967,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
@ -5874,9 +5979,9 @@ namespace SourceHook
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
@ -5886,9 +5991,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5898,9 +6003,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5910,9 +6015,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5922,9 +6027,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5934,9 +6039,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5946,9 +6051,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5958,9 +6063,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5970,9 +6075,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>
@ -5982,9 +6087,9 @@ namespace SourceHook
}
template <class Iface, 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>
void SetOverrideResult(ISourceHook *shptr, RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), const RetType res)
OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20))
{
*reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res;
return OverrideFunctor<RetType>();
}
template <class Iface, 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>

View File

@ -25,8 +25,8 @@ IMPLEMENTATION INFO
Protos ("Prototypes")
The purpose of protos is to provide the amount of type information about a function
which is required to be able to execute a function call without corrupting the stack.
Our protos do not fully do this, but they provide the size of the return value, the amount of
parameters, and the size of each parameter, which is enough for most situations,
Our protos do not fully do this, but they provide the size of the return value, the number of
parameters, and the size of each parameter, which is enough for most situations.
There are two version of protos:
OLD:

View File

@ -79,6 +79,7 @@ DO_TEST(Manual);
DO_TEST(Recall);
DO_TEST(Multi);
DO_TEST(Ref);
DO_TEST(RefRet);
int main(int argc, char *argv[])
{

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="test"
ProjectGUID="{456BBA64-FF14-4292-8443-3BA79E4D84CC}"
RootNamespace="test"
@ -427,6 +427,10 @@
RelativePath="..\testref.cpp"
>
</File>
<File
RelativePath=".\testrefret.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
@ -491,7 +495,7 @@
>
<Tool
Name="VCCustomBuildTool"
CommandLine="echo on&#x0D;&#x0A;pushd ..\..\generate&#x0D;&#x0A;shworker.exe iter sourcehook.hxx sourcehook.h&#x0D;&#x0A;copy sourcehook.h ..\sourcehook.h&#x0D;&#x0A;popd&#x0D;&#x0A;"
CommandLine="echo on&#x0D;&#x0A;pushd ..\..\generate&#x0D;&#x0A;shworker.exe iter sourcehook.hxx sourcehook.h 16&#x0D;&#x0A;copy sourcehook.h ..\sourcehook.h&#x0D;&#x0A;popd&#x0D;&#x0A;"
Outputs="..\..\sourcehook.h"
/>
</FileConfiguration>

View File

@ -0,0 +1,200 @@
#include "testevents.h"
#include "sourcehook_test.h"
// Tests support for functions which return references
namespace
{
StateList g_States;
SourceHook::ISourceHook *g_SHPtr;
SourceHook::Plugin g_PLID;
MAKE_STATE_1(State_Func1_Pre1, int*); // p1: the ref Func1_Pre1 is going to return
MAKE_STATE_3(State_Func1_Pre2, META_RES, int*, int*); // p1: current status
// p2: override ret
// p3: what this handler is going to supercede with
MAKE_STATE_1(State_Func1, int*); // p1: the ref Func1 is going to return
MAKE_STATE_2(State_Func1_Post1, int*, int*); // p1: orig_ret; p2: override_ret
MAKE_STATE_1(State_Func1_Post2, int*); // p1: what it's going to return
MAKE_STATE_1(State_Func1_Ret, int*); // p1: the ref it returned
MAKE_STATE_2(State_Func2_Pre1, int, const int*); // p1: func's p1; p2: what it's going to ret
MAKE_STATE_2(State_Func2, int, const int*); // p1: func's p1; p2: what it's going to ret
MAKE_STATE_3(State_Func2_Post1, int, const int*, const int*); // p1: func's p1; p2: orig ret; p3: override ret
MAKE_STATE_1(State_Func2_Ret, const int*); // p1: ret
int g_Var;
class Test
{
public:
int m_Var1;
int m_Var2;
Test() : m_Var1(87)
{
}
virtual int& Func1()
{
ADD_STATE(State_Func1(&m_Var1));
return m_Var1;
}
virtual const int& Func2(int p1)
{
ADD_STATE(State_Func2(p1, &m_Var2));
m_Var2 = p1;
return m_Var2;
}
};
class CHook
{
public:
int m_Var;
virtual int& Func1_Pre1()
{
ADD_STATE(State_Func1_Pre1(&m_Var));
RETURN_META_VALUE(MRES_OVERRIDE, m_Var);
}
virtual int &Func1_Pre2()
{
int &overrideret = META_RESULT_OVERRIDE_RET(int&);
overrideret = 1337;
ADD_STATE(State_Func1_Pre2(META_RESULT_STATUS, &overrideret, &g_Var));
RETURN_META_VALUE(MRES_SUPERCEDE, g_Var);
}
virtual int& Func1_Post1()
{
ADD_STATE(State_Func1_Post1(&META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&)));
RETURN_META_NOREF(MRES_IGNORED, int&);
}
virtual int& Func1_Post2()
{
ADD_STATE(State_Func1_Post2(&m_Var));
RETURN_META_VALUE(MRES_OVERRIDE, m_Var);
}
virtual const int& Func2_Pre1(int p1)
{
ADD_STATE(State_Func2_Pre1(p1, &m_Var));
RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, m_Var, static_cast<const int& (Test::*)(int)>(&Test::Func2), (1337));
}
virtual const int& Func2_Post1(int p1)
{
ADD_STATE(State_Func2_Post1(p1, &META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&)));
RETURN_META_NOREF(MRES_IGNORED, const int&);
}
};
SH_DECL_HOOK0(Test, Func1, SH_NOATTRIB, 0, int&);
SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, const int&, int);
}
bool TestRefRet(std::string &error)
{
GET_SHPTR(g_SHPtr);
g_PLID = 1;
Test test;
Test *pTest = &test;
CHook hook;
int &ret1 = pTest->Func1();
ADD_STATE(State_Func1_Ret(&ret1));
CHECK_STATES((&g_States,
new State_Func1(&test.m_Var1),
new State_Func1_Ret(&test.m_Var1),
NULL), "Part 1");
// Now add Func1_Pre1, which supercedes and returns hook.m_Var
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Pre1, false);
int &ret2 = pTest->Func1();
ADD_STATE(State_Func1_Ret(&ret2));
CHECK_STATES((&g_States,
new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var
new State_Func1(&test.m_Var1), // Function says that it's going to return test.m_Var1
new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned
NULL), "Part 2");
// Now add Func1_Post1, which only reports orig ret and override ret
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Post1, true);
int &ret3 = pTest->Func1();
ADD_STATE(State_Func1_Ret(&ret3));
CHECK_STATES((&g_States,
new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var
new State_Func1(&test.m_Var1), // Function says that it's going to return test.m_Var1
new State_Func1_Post1(&test.m_Var1, &hook.m_Var), // origret(=p1) is what it wanted to
// return, overrideret(=p2) is pre1's var
new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned
NULL), "Part 3");
// Now add Func1_Pre2, which supercedes and returns g_Var (it also sets the override ret from pre1 to 1337)
// and add Func1_Post2, which overrides and returns hook.m_Var again.
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Pre2, false);
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Post2, true);
int &ret4 = pTest->Func1();
ADD_STATE(State_Func1_Ret(&ret4));
CHECK_STATES((&g_States,
new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var
new State_Func1_Pre2(MRES_OVERRIDE, // current status
&hook.m_Var, // override ret (which it set to 1337)
&g_Var), // what it's going to ret, AND supercede with
new State_Func1_Post1(&g_Var, &g_Var), // origret(=p1) is what pre2 superceded with,
// so overrideret(=p2) has to be the same
new State_Func1_Post2(&hook.m_Var), // post2 is going to override with hook.m_Var again
new State_Func1_Ret(&hook.m_Var), // ==>>> hook.m_Var is returned
NULL), "Part 4");
CHECK_COND(hook.m_Var == 1337, "Part 4.1");
// Through a callclass
SourceHook::CallClass<Test> *cc1 = SH_GET_CALLCLASS(&test);
int &ret5 = SH_CALL(cc1, &Test::Func1)();
ADD_STATE(State_Func1_Ret(&ret5));
CHECK_STATES((&g_States,
new State_Func1(&test.m_Var1),
new State_Func1_Ret(&test.m_Var1),
NULL), "Part 5");
SH_RELEASE_CALLCLASS(cc1);
////////////////////////////////////////////////////////////////////////////////////////
// Func2 tests
const int &ret21 = pTest->Func2(500);
ADD_STATE(State_Func2_Ret(&ret21));
CHECK_STATES((&g_States,
new State_Func2(500, &test.m_Var2),
new State_Func2_Ret(&test.m_Var2),
NULL), "Part 6");
SH_ADD_HOOK_MEMFUNC(Test, Func2, &test, &hook, &CHook::Func2_Pre1, false);
SH_ADD_HOOK_MEMFUNC(Test, Func2, &test, &hook, &CHook::Func2_Post1, true);
const int &ret22 = pTest->Func2(500);
ADD_STATE(State_Func2_Ret(&ret22));
CHECK_STATES((&g_States,
new State_Func2_Pre1(500, &hook.m_Var), // p1 was 500; it's going to override with hook.m_Var; and also change p1 to 1337
new State_Func2(1337, &test.m_Var2), // p1 was 1337; it's going to ret test.m_Var2
new State_Func2_Post1(1337, // p1 was 1337
&test.m_Var2, // orig ret was test.m_Var2
&hook.m_Var), // override ret was hook.m_Var
new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var
NULL), "Part 7");
return true;
}