Skip to content

Commit

Permalink
Add new proto info
Browse files Browse the repository at this point in the history
  • Loading branch information
mixern6 committed Dec 4, 2023
1 parent 28cb3df commit 80d9750
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 36 deletions.
178 changes: 143 additions & 35 deletions core/sourcehook/sourcehook.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -252,6 +282,19 @@ namespace SourceHook
const PassInfo::V2Info *paramsPassInfo2;
};

class IProtoInfo
{
public:
virtual ~IProtoInfo() = default;
virtual size_t 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;

/**
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -5130,12 +5176,17 @@ class PassInfoInitializer
InitializePassInfo<sizeof...(ArgsType), 0, ArgsType...>();
}

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);
}
Expand All @@ -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 <typename T>
Expand All @@ -5181,7 +5258,7 @@ struct ReturnTypeInfo<void>
{
static const size_t size()
{
return 0; // why isn't it sizeof(void) like in TypeInfo<T>?
return 0;
}

static const int type()
Expand Down Expand Up @@ -5222,6 +5299,65 @@ class CHookManagerMemberFuncHandler : public IHookManagerMemberFunc
HookManagerMemberFunc func_;
};

template<typename ReturnType, class ... Params>
class CProtoInfo : public IProtoInfo
{
public:
constexpr CProtoInfo()
: retPassInfo(ReturnTypeInfo<ReturnType>::size(),
ReturnTypeInfo<ReturnType>::type(),
ReturnTypeInfo<ReturnType>::flags())
{
}

virtual ~CProtoInfo() override
{
}

virtual size_t 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<Params...> paramsPassInfo; //!< PassInfos for the parameters
};

template<typename ReturnType, class ... Params>
class ManualHookHandler : public CHookManagerMemberFuncHandler<ManualHookHandler<ReturnType, Params...>>
{
Expand All @@ -5237,40 +5373,18 @@ class ManualHookHandler : public CHookManagerMemberFuncHandler<ManualHookHandler
typedef ReturnType (T::*HookFunc)(Params...);
};

ManualHookHandler()
constexpr ManualHookHandler()
: CHookManagerMemberFuncHandler<ThisType>(this, &ThisType::HookManPubFunc)
, thisPointerOffset_(0)
, vTableIndex_(0)
, vtableOffset_(0)
, msMFI_{false, 0, 0, 0}
, msHI_(nullptr)
, msProto_{sizeof...(Params),
{ReturnTypeInfo<ReturnType>::size(), ReturnTypeInfo<ReturnType>::type(), ReturnTypeInfo<ReturnType>::flags()},
paramInfosM_.ParamsPassInfo(),
0,
__SH_EPI,
paramInfos2M_}
{
for(PassInfo::V2Info& paramInfo : paramInfos2M_)
{
paramInfo = __SH_EPI;
}
}

virtual ~ManualHookHandler()
{
//TODO apply RAII, cleanup all related hooks here
}

// TODO probably not needed for manual hooks
void Reconfigure()
{
msMFI_.isVirtual = true;
msMFI_.thisptroffs = thisPointerOffset_;
msMFI_.vtblindex = vTableIndex_;
msMFI_.vtbloffs = vtableOffset_;
}

void Reconfigure(int vtblindex, int vtbloffs = 0, int thisptroffs = 0)
{
g_SHPtr->RemoveHookManager(g_PLID, this);
Expand All @@ -5285,7 +5399,7 @@ class ManualHookHandler : public CHookManagerMemberFuncHandler<ManualHookHandler
typename ManualHookHandler::FD handler(callbackInstPtr, callbackFuncPtr);
typename ThisType::CMyDelegateImpl* tmp = new typename ThisType::CMyDelegateImpl(handler); // TODO use unique_ptr here

return g_SHPtr->AddHook(g_PLID, mode, iface, thisPointerOffset_, this, tmp, post);
return g_SHPtr->AddHook(g_PLID, mode, iface, 0, this, tmp, post);
}

template<typename T>
Expand All @@ -5294,7 +5408,7 @@ class ManualHookHandler : public CHookManagerMemberFuncHandler<ManualHookHandler
typename ManualHookHandler::FD handler(callbackInstPtr, callbackFuncPtr);
typename ThisType::CMyDelegateImpl tmp(handler);

return g_SHPtr->RemoveHook(g_PLID, iface, thisPointerOffset_, this, &tmp, post);
return g_SHPtr->RemoveHook(g_PLID, iface, 0, this, &tmp, post);
}

// For void return type only
Expand Down Expand Up @@ -5557,16 +5671,10 @@ class ManualHookHandler : public CHookManagerMemberFuncHandler<ManualHookHandler
}

private:
int thisPointerOffset_; // thisptroffs
int vTableIndex_; // vtblindex
int vtableOffset_; // vtbloffs

MemFuncInfo msMFI_; // ms_MFI
IHookManagerInfo *msHI_; // ms_HI

PassInfoInitializer<void, Params...> paramInfosM_; // ParamInfosM
PassInfo::V2Info paramInfos2M_[sizeof...(Params) + 1]; // ParamInfos2M
ProtoInfo msProto_; // ms_Proto
CProtoInfo<ReturnType, Params...> msProto_; // ms_Proto
};

} // SourceHook
Expand Down
10 changes: 10 additions & 0 deletions core/sourcehook/sourcehook_impl_chookmaninfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions core/sourcehook/sourcehook_impl_chookmaninfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CHookManager>
Expand Down
43 changes: 42 additions & 1 deletion core/sourcehook/sourcehook_impl_cproto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions core/sourcehook/sourcehook_impl_cproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down

0 comments on commit 80d9750

Please sign in to comment.