diff --git a/core/sourcehook/sourcehook.h b/core/sourcehook/sourcehook.h index 6c60cea3..b1843d20 100644 --- a/core/sourcehook/sourcehook.h +++ b/core/sourcehook/sourcehook.h @@ -184,6 +184,20 @@ namespace SourceHook */ struct PassInfo { + PassInfo() + : size(0) + , type(0) + , flags(0) + { + } + + PassInfo(size_t typeSize, int typeId, unsigned int typeFlags) + : size(typeSize) + , type(typeId) + , flags(typeFlags) + { + } + enum PassType { PassType_Unknown=0, /**< Unknown -- no extra info available */ @@ -217,6 +231,22 @@ namespace SourceHook struct V2Info { + V2Info() + : pNormalCtor(nullptr) + , pCopyCtor(nullptr) + , pDtor(nullptr) + , pAssignOperator(nullptr) + { + } + + V2Info(void *normalCtor, void *copyCtor, void *dtor, void *assignOperator) + : pNormalCtor(normalCtor) + , pCopyCtor(copyCtor) + , pDtor(dtor) + , pAssignOperator(assignOperator) + { + } + void *pNormalCtor; void *pCopyCtor; void *pDtor; @@ -252,6 +282,19 @@ namespace SourceHook const PassInfo::V2Info *paramsPassInfo2; }; + class IProtoInfo + { + public: + virtual ~IProtoInfo() = default; + virtual int GetNumOfParams() const = 0; + virtual const PassInfo &GetRetPassInfo() const = 0; + virtual const PassInfo *GetParamsPassInfo() const = 0; + virtual int GetConvention() const = 0; + virtual int GetVersion() const = 0; + virtual const PassInfo::V2Info &GetRetPassInfo2() const = 0; + virtual const PassInfo::V2Info *GetParamsPassInfo2() const = 0; + }; + struct IHookManagerInfo; /** @@ -409,6 +452,9 @@ namespace SourceHook { virtual void SetInfo(int hookman_version, int vtbloffs, int vtblidx, ProtoInfo *proto, void *hookfunc_vfnptr) = 0; + + virtual void SetInfo(int hookman_version, int vtbloffs, int vtblidx, + IProtoInfo *proto, void *hookfunc_vfnptr) = 0; }; // I'm adding support for functions which return references. @@ -5130,12 +5176,17 @@ class PassInfoInitializer InitializePassInfo(); } - const PassInfo *ParamsPassInfo() const + const PassInfo *GetParamsPassInfo() const { return params_; } - const size_t ParamsPassInfoSize() const + const PassInfo::V2Info *GetParamsPassInfoV2() const + { + return paramsV2_; + } + + const size_t GetParamsPassInfoSize() const { return sizeof...(ArgsType); } @@ -5155,6 +5206,32 @@ class PassInfoInitializer } PassInfo params_[sizeof...(ArgsType)]; + PassInfo::V2Info paramsV2_[sizeof...(ArgsType)]; +}; + +// For zero arguments +template<> +class PassInfoInitializer<> +{ +public: + constexpr PassInfoInitializer() + { + } + + const PassInfo *GetParamsPassInfo() const + { + return nullptr; + } + + const PassInfo::V2Info *GetParamsPassInfoV2() const + { + return nullptr; + } + + const size_t GetParamsPassInfoSize() const + { + return 0; + } }; template @@ -5181,7 +5258,7 @@ struct ReturnTypeInfo { static const size_t size() { - return 0; // why isn't it sizeof(void) like in TypeInfo? + return 0; } static const int type() @@ -5222,6 +5299,65 @@ class CHookManagerMemberFuncHandler : public IHookManagerMemberFunc HookManagerMemberFunc func_; }; +template +class CProtoInfo : public IProtoInfo +{ +public: + constexpr CProtoInfo() + : retPassInfo(ReturnTypeInfo::size(), + ReturnTypeInfo::type(), + ReturnTypeInfo::flags()) + { + } + + virtual ~CProtoInfo() override + { + } + + virtual int GetNumOfParams() const override + { + return paramsPassInfo.GetParamsPassInfoSize(); + } + + virtual const PassInfo &GetRetPassInfo() const override + { + return retPassInfo; + } + + virtual const PassInfo *GetParamsPassInfo() const override + { + return paramsPassInfo.GetParamsPassInfo(); + } + + virtual int GetConvention() const override + { + return 0; + } + + // version of the ProtoInfo structure. + virtual int GetVersion() const override + { + // 1 for Version2 + return 1; + } + + virtual const PassInfo::V2Info &GetRetPassInfo2() const override + { + return retPassInfo2; + } + + virtual const PassInfo::V2Info *GetParamsPassInfo2() const override + { + return paramsPassInfo.GetParamsPassInfoV2(); + } + +private: + int numOfParams; //!< number of parameters + PassInfo retPassInfo; //!< PassInfo for the return value. size=0 -> no retval + PassInfo::V2Info retPassInfo2; //!< Version2 only + PassInfoInitializer paramsPassInfo; //!< PassInfos for the parameters +}; + template class ManualHookHandler : public CHookManagerMemberFuncHandler> { @@ -5237,24 +5373,11 @@ class ManualHookHandler : public CHookManagerMemberFuncHandler(this, &ThisType::HookManPubFunc) - , thisPointerOffset_(0) - , vTableIndex_(0) - , vtableOffset_(0) , msMFI_{false, 0, 0, 0} , msHI_(nullptr) - , msProto_{sizeof...(Params), - {ReturnTypeInfo::size(), ReturnTypeInfo::type(), ReturnTypeInfo::flags()}, - paramInfosM_.ParamsPassInfo(), - 0, - __SH_EPI, - paramInfos2M_} { - for(PassInfo::V2Info& paramInfo : paramInfos2M_) - { - paramInfo = __SH_EPI; - } } virtual ~ManualHookHandler() @@ -5262,15 +5385,6 @@ class ManualHookHandler : public CHookManagerMemberFuncHandlerRemoveHookManager(g_PLID, this); @@ -5285,7 +5399,7 @@ class ManualHookHandler : public CHookManagerMemberFuncHandlerAddHook(g_PLID, mode, iface, thisPointerOffset_, this, tmp, post); + return g_SHPtr->AddHook(g_PLID, mode, iface, 0, this, tmp, post); } template @@ -5294,7 +5408,7 @@ class ManualHookHandler : public CHookManagerMemberFuncHandlerRemoveHook(g_PLID, iface, thisPointerOffset_, this, &tmp, post); + return g_SHPtr->RemoveHook(g_PLID, iface, 0, this, &tmp, post); } // For void return type only @@ -5557,16 +5671,10 @@ class ManualHookHandler : public CHookManagerMemberFuncHandler paramInfosM_; // ParamInfosM - PassInfo::V2Info paramInfos2M_[sizeof...(Params) + 1]; // ParamInfos2M - ProtoInfo msProto_; // ms_Proto + CProtoInfo msProto_; // ms_Proto }; } // SourceHook diff --git a/core/sourcehook/sourcehook_impl_chookmaninfo.cpp b/core/sourcehook/sourcehook_impl_chookmaninfo.cpp index 21e20429..bb497f72 100644 --- a/core/sourcehook/sourcehook_impl_chookmaninfo.cpp +++ b/core/sourcehook/sourcehook_impl_chookmaninfo.cpp @@ -37,6 +37,16 @@ namespace SourceHook m_HookfuncVfnptr = hookfunc_vfnptr; } + void CHookManager::SetInfo(int hookman_version, int vtbloffs, int vtblidx, + IProtoInfo *proto, void *hookfunc_vfnptr) + { + m_Version = hookman_version; + m_VtblOffs = vtbloffs; + m_VtblIdx = vtblidx; + m_Proto = proto; + m_HookfuncVfnptr = hookfunc_vfnptr; + } + void CHookManager::Register() { m_PubFunc(true, this); diff --git a/core/sourcehook/sourcehook_impl_chookmaninfo.h b/core/sourcehook/sourcehook_impl_chookmaninfo.h index afb0bd3c..5d757852 100644 --- a/core/sourcehook/sourcehook_impl_chookmaninfo.h +++ b/core/sourcehook/sourcehook_impl_chookmaninfo.h @@ -74,6 +74,9 @@ namespace SourceHook // *** IHookManagerInfo interface *** void SetInfo(int hookman_version, int vtbloffs, int vtblidx, ProtoInfo *proto, void *hookfunc_vfnptr); + + void SetInfo(int hookman_version, int vtbloffs, int vtblidx, + IProtoInfo *proto, void *hookfunc_vfnptr); }; class CHookManList : public List diff --git a/core/sourcehook/sourcehook_impl_cproto.cpp b/core/sourcehook/sourcehook_impl_cproto.cpp index ff8af288..33df809f 100644 --- a/core/sourcehook/sourcehook_impl_cproto.cpp +++ b/core/sourcehook/sourcehook_impl_cproto.cpp @@ -37,7 +37,6 @@ namespace SourceHook m_RetPassInfo.pDtor = NULL; m_RetPassInfo.pAssignOperator = NULL; - m_ParamsPassInfo.resize(pProto->numOfParams); for (int i = 1; i <= pProto->numOfParams; ++i) @@ -89,6 +88,48 @@ namespace SourceHook } } + void CProto::Fill(const IProtoInfo *pProto) + { + if (pProto == nullptr) + m_Version = -1; + + m_ParamsPassInfo.clear(); + + // Version 1 if 0 + // Version 2 if 1 + m_Version = pProto->GetVersion(); + m_Convention = pProto->GetConvention(); + m_NumOfParams = pProto->GetNumOfParams(); + + const PassInfo& retPassInfo = pProto->GetRetPassInfo(); + + m_RetPassInfo.size = retPassInfo.size; + m_RetPassInfo.type = retPassInfo.type; + m_RetPassInfo.flags = retPassInfo.flags; + + const PassInfo::V2Info& retPassInfo2 = pProto->GetRetPassInfo2(); + m_RetPassInfo.pNormalCtor = retPassInfo2.pNormalCtor; // should be nullptr for Version 1 + m_RetPassInfo.pCopyCtor = retPassInfo2.pCopyCtor; // should be nullptr for Version 1 + m_RetPassInfo.pDtor = retPassInfo2.pDtor; // should be nullptr for Version 1 + m_RetPassInfo.pAssignOperator = retPassInfo2.pAssignOperator; // should be nullptr for Version 1 + + m_ParamsPassInfo.resize(pProto->GetNumOfParams()); + + const PassInfo* paramsPassInfo = pProto->GetParamsPassInfo(); + const PassInfo::V2Info* paramsPassInfo2 = pProto->GetParamsPassInfo2(); + for (size_t i = 0; i != pProto->GetNumOfParams(); ++i) + { + m_ParamsPassInfo[i].size = paramsPassInfo[i].size; + m_ParamsPassInfo[i].type = paramsPassInfo[i].type; + m_ParamsPassInfo[i].flags = paramsPassInfo[i].flags; + + m_ParamsPassInfo[i].pNormalCtor = paramsPassInfo2[i].pNormalCtor; // should be nullptr for Version 1 + m_ParamsPassInfo[i].pCopyCtor = paramsPassInfo2[i].pCopyCtor; // should be nullptr for Version 1 + m_ParamsPassInfo[i].pDtor = paramsPassInfo2[i].pDtor; // should be nullptr for Version 1 + m_ParamsPassInfo[i].pAssignOperator = paramsPassInfo2[i].pAssignOperator; // should be nullptr for Version 1 + } + } + // Basic compat test // Other than this, we assume that the plugins know what they're doing bool CProto::operator == (const CProto &other) const diff --git a/core/sourcehook/sourcehook_impl_cproto.h b/core/sourcehook/sourcehook_impl_cproto.h index cb436f11..c209dba6 100644 --- a/core/sourcehook/sourcehook_impl_cproto.h +++ b/core/sourcehook/sourcehook_impl_cproto.h @@ -53,6 +53,8 @@ namespace SourceHook void Fill(const ProtoInfo *pProto); + void Fill(const IProtoInfo *pProto); + // For old sourcehook.h: flags 0 -> assume ByVal static unsigned int GetRealFlags(const PassInfo &info) { @@ -69,6 +71,11 @@ namespace SourceHook Fill(pProto); } + CProto(const IProtoInfo *pProto) + { + Fill(pProto); + } + CProto(const CProto &other) : m_Version(other.m_Version), m_NumOfParams(other.m_NumOfParams), m_RetPassInfo(other.m_RetPassInfo), m_ParamsPassInfo(other.m_ParamsPassInfo), m_Convention(other.m_Convention)