mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-12-07 02:18:30 +00:00
Hook->HookImpl, expose "public" hook template in PLUGIN_EXPOSE
This allows us to specify the SH pointer and the Plugin ID pointer in the template, so when the plugin uses Hook<> it doesn't have to touch g_PLID or g_SHPtr. Also added a little struct that wraps ISourceHook->xHookById methods.
This commit is contained in:
parent
e391dc5b14
commit
d96b3adb0a
@ -480,7 +480,9 @@ using namespace SourceMM;
|
|||||||
extern SourceHook::ISourceHook *g_SHPtr; \
|
extern SourceHook::ISourceHook *g_SHPtr; \
|
||||||
extern ISmmAPI *g_SMAPI; \
|
extern ISmmAPI *g_SMAPI; \
|
||||||
extern ISmmPlugin *g_PLAPI; \
|
extern ISmmPlugin *g_PLAPI; \
|
||||||
extern PluginId g_PLID;
|
extern PluginId g_PLID; \
|
||||||
|
template<typename Interface, auto Method, typename Result, typename... Args> \
|
||||||
|
struct Hook : public ::SourceHook::HookImpl<&g_SHPtr, &g_PLID, Interface, Method, Result, Args...> {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This should be the first line in your Load callback.
|
* @brief This should be the first line in your Load callback.
|
||||||
|
|||||||
@ -328,6 +328,8 @@ extern PluginId g_PLID;
|
|||||||
extern SourceHook::ISourceHook *g_SHPtr;
|
extern SourceHook::ISourceHook *g_SHPtr;
|
||||||
extern SourceMM::IMetamodSourceProvider *provider;
|
extern SourceMM::IMetamodSourceProvider *provider;
|
||||||
extern SourceMM::ISmmAPI *g_pMetamod;
|
extern SourceMM::ISmmAPI *g_pMetamod;
|
||||||
|
template<typename Interface, auto Method, typename Result, typename... Args> \
|
||||||
|
struct Hook : public ::SourceHook::HookImpl<&g_SHPtr, &g_PLID, Interface, Method, Result, Args...> {};
|
||||||
|
|
||||||
#endif //_INCLUDE_METAMOD_SOURCE_SUPPORT_H_
|
#endif //_INCLUDE_METAMOD_SOURCE_SUPPORT_H_
|
||||||
|
|
||||||
|
|||||||
@ -44,14 +44,14 @@ static SourceProvider g_SourceProvider;
|
|||||||
|
|
||||||
IMetamodSourceProvider* provider = &g_SourceProvider;
|
IMetamodSourceProvider* provider = &g_SourceProvider;
|
||||||
|
|
||||||
auto OnGameInit = SourceHook::Hook<&g_SHPtr, IServerGameDLL, &IServerGameDLL::GameInit, bool>::Make();
|
auto OnGameInit = Hook<IServerGameDLL, &IServerGameDLL::GameInit, bool>::Make();
|
||||||
auto OnLevelInit = SourceHook::Hook<&g_SHPtr, IServerGameDLL, &IServerGameDLL::LevelInit, bool, const char*, const char*, const char*, const char*, bool, bool>::Make();
|
auto OnLevelInit = Hook<IServerGameDLL, &IServerGameDLL::LevelInit, bool, const char*, const char*, const char*, const char*, bool, bool>::Make();
|
||||||
auto OnLevelShutdown = SourceHook::Hook<&g_SHPtr, IServerGameDLL, &IServerGameDLL::LevelShutdown, void>::Make();
|
auto OnLevelShutdown = Hook<IServerGameDLL, &IServerGameDLL::LevelShutdown, void>::Make();
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
auto OnClientCommand = SourceHook::Hook<&g_SHPtr, IServerGameClients, &IServerGameClients::ClientCommand, void, edict_t*, const CCommand&>::Make();
|
auto OnClientCommand = Hook<IServerGameClients, &IServerGameClients::ClientCommand, void, edict_t*, const CCommand&>::Make();
|
||||||
#else
|
#else
|
||||||
auto OnClientCommand = SourceHook::Hook<&g_SHPtr, IServerGameClients, &IServerGameClients::ClientCommand, void, edict_t*>::Make();
|
auto OnClientCommand = Hook<IServerGameClients, &IServerGameClients::ClientCommand, void, edict_t*>::Make();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
|
void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
|
||||||
@ -119,19 +119,19 @@ void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (gameclients) {
|
if (gameclients) {
|
||||||
OnClientCommand->Add(g_PLID, gameclients, false, SH_MEMBER(this, &SourceProvider::Hook_ClientCommand));
|
OnClientCommand->Add(gameclients, false, SH_MEMBER(this, &SourceProvider::Hook_ClientCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
OnGameInit->Add(g_PLID, server, false, SH_MEMBER(this, &SourceProvider::Hook_GameInit));
|
OnGameInit->Add(server, false, SH_MEMBER(this, &SourceProvider::Hook_GameInit));
|
||||||
OnLevelInit->Add(g_PLID, server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelInit));
|
OnLevelInit->Add(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelInit));
|
||||||
OnLevelShutdown->Add(g_PLID, server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown));
|
OnLevelShutdown->Add(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceProvider::Notify_DLLShutdown_Pre()
|
void SourceProvider::Notify_DLLShutdown_Pre()
|
||||||
{
|
{
|
||||||
OnGameInit->Remove(g_PLID, server, false, SH_MEMBER(this, &SourceProvider::Hook_GameInit));
|
OnGameInit->Remove(server, false, SH_MEMBER(this, &SourceProvider::Hook_GameInit));
|
||||||
OnLevelInit->Remove(g_PLID, server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelInit));
|
OnLevelInit->Remove(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelInit));
|
||||||
OnLevelShutdown->Remove(g_PLID, server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown));
|
OnLevelShutdown->Remove(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown));
|
||||||
|
|
||||||
m_ConVarAccessor.RemoveMetamodCommands();
|
m_ConVarAccessor.RemoveMetamodCommands();
|
||||||
|
|
||||||
|
|||||||
@ -723,6 +723,61 @@ namespace SourceHook
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to an active SourceHook
|
||||||
|
*/
|
||||||
|
struct HookInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HookInstance(ISourceHook** sh, int hookid)
|
||||||
|
: SH(sh)
|
||||||
|
, _hookid(hookid)
|
||||||
|
{}
|
||||||
|
protected:
|
||||||
|
// The global pointer to the SourceHook API
|
||||||
|
ISourceHook** SH;
|
||||||
|
|
||||||
|
// The ID of this specific hook
|
||||||
|
int _hookid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the hook was successfully placed.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Ok()
|
||||||
|
{
|
||||||
|
return _hookid != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pause the hook, preventing it from being called until unpaused.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Pause()
|
||||||
|
{
|
||||||
|
return (*SH)->PauseHookByID(_hookid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpause the hook if it is currently paused
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Unpause()
|
||||||
|
{
|
||||||
|
return (*SH)->UnpauseHookByID(_hookid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove the hook, permanently preventing it from being invoked.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Remove()
|
||||||
|
{
|
||||||
|
return (*SH)->RemoveHookByID(_hookid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A hook manager, used to hook instances of a specific interface.
|
* @brief A hook manager, used to hook instances of a specific interface.
|
||||||
@ -731,8 +786,8 @@ namespace SourceHook
|
|||||||
* and prototype in the template arguments. Any derived class of the interface
|
* and prototype in the template arguments. Any derived class of the interface
|
||||||
* can be hooked using this manager.
|
* can be hooked using this manager.
|
||||||
*/
|
*/
|
||||||
template<ISourceHook** SH, typename Interface, auto Method, typename Result, typename... Args>
|
template<ISourceHook** SH, Plugin* PL, typename Interface, auto Method, typename Result, typename... Args>
|
||||||
struct Hook
|
struct HookImpl
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief The type we expect the template arg "Method" to be.
|
* @brief The type we expect the template arg "Method" to be.
|
||||||
@ -750,15 +805,15 @@ namespace SourceHook
|
|||||||
|
|
||||||
// Singleton instance
|
// Singleton instance
|
||||||
// Initialized below!
|
// Initialized below!
|
||||||
static Hook Instance;
|
static HookImpl Instance;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Hook(Hook& other) = delete;
|
HookImpl(HookImpl& other) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Build the ProtoInfo for this hook
|
* @brief Build the ProtoInfo for this hook
|
||||||
*/
|
*/
|
||||||
constexpr Hook()
|
constexpr HookImpl()
|
||||||
{
|
{
|
||||||
// build protoinfo
|
// build protoinfo
|
||||||
Proto.numOfParams = sizeof...(Args);
|
Proto.numOfParams = sizeof...(Args);
|
||||||
@ -791,11 +846,11 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr Hook* Make()
|
static constexpr HookImpl* Make()
|
||||||
{
|
{
|
||||||
Hook::Instance = Hook();
|
HookImpl::Instance = HookImpl();
|
||||||
|
|
||||||
return &Hook::Instance;
|
return &HookImpl::Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public: // Public Interface
|
public: // Public Interface
|
||||||
@ -809,16 +864,18 @@ namespace SourceHook
|
|||||||
* @param handler the handler that will be called in place of the original method
|
* @param handler the handler that will be called in place of the original method
|
||||||
* @param mode the hook mode - Hook_Normal will only hook this instance, while others alter the global virtual table.
|
* @param mode the hook mode - Hook_Normal will only hook this instance, while others alter the global virtual table.
|
||||||
*/
|
*/
|
||||||
int Add(Plugin id, Interface* iface, bool post, Delegate handler, ::SourceHook::ISourceHook::AddHookMode mode = ISourceHook::AddHookMode::Hook_Normal)
|
HookInstance Add(Interface* iface, bool post, Delegate handler, ::SourceHook::ISourceHook::AddHookMode mode = ISourceHook::AddHookMode::Hook_Normal)
|
||||||
{
|
{
|
||||||
using namespace ::SourceHook;
|
using namespace ::SourceHook;
|
||||||
MemFuncInfo mfi = {true, -1, 0, 0};
|
MemFuncInfo mfi = {true, -1, 0, 0};
|
||||||
GetFuncInfo(Method, mfi);
|
GetFuncInfo(Method, mfi);
|
||||||
if (mfi.thisptroffs < 0 || !mfi.isVirtual)
|
if (mfi.thisptroffs < 0 || !mfi.isVirtual)
|
||||||
return false;
|
return HookInstance(SH, 0);
|
||||||
|
|
||||||
CMyDelegateImpl* delegate = new CMyDelegateImpl(handler);
|
CMyDelegateImpl* delegate = new CMyDelegateImpl(handler);
|
||||||
return (*SH)->AddHook(id, mode, iface, mfi.thisptroffs, Hook::HookManPubFunc, delegate, post);
|
int id = (*SH)->AddHook(*PL, mode, iface, mfi.thisptroffs, HookImpl::HookManPubFunc, delegate, post);
|
||||||
|
|
||||||
|
return HookInstance(SH, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -829,7 +886,7 @@ namespace SourceHook
|
|||||||
* @param post true if this was a post hook, false otherwise (pre-hook)
|
* @param post true if this was a post hook, false otherwise (pre-hook)
|
||||||
* @param handler the handler that will be removed from this hook.
|
* @param handler the handler that will be removed from this hook.
|
||||||
*/
|
*/
|
||||||
int Remove(Plugin id, Interface* iface, bool post, Delegate handler)
|
int Remove(Interface* iface, bool post, Delegate handler)
|
||||||
{
|
{
|
||||||
using namespace ::SourceHook;
|
using namespace ::SourceHook;
|
||||||
MemFuncInfo mfi = {true, -1, 0, 0};
|
MemFuncInfo mfi = {true, -1, 0, 0};
|
||||||
@ -837,7 +894,7 @@ namespace SourceHook
|
|||||||
|
|
||||||
// Temporary delegate for .IsEqual() comparison.
|
// Temporary delegate for .IsEqual() comparison.
|
||||||
CMyDelegateImpl temp(handler);
|
CMyDelegateImpl temp(handler);
|
||||||
return (*SH)->RemoveHook(id, iface, mfi.thisptroffs, Hook::HookManPubFunc, &temp, post);
|
return (*SH)->RemoveHook(*PL, iface, mfi.thisptroffs, HookImpl::HookManPubFunc, &temp, post);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -855,7 +912,7 @@ namespace SourceHook
|
|||||||
if (hi) {
|
if (hi) {
|
||||||
// Build a memberfuncinfo for our hook processor.
|
// Build a memberfuncinfo for our hook processor.
|
||||||
MemFuncInfo our_mfi = {true, -1, 0, 0};
|
MemFuncInfo our_mfi = {true, -1, 0, 0};
|
||||||
GetFuncInfo(&Hook::Func, our_mfi);
|
GetFuncInfo(&HookImpl::Func, our_mfi);
|
||||||
|
|
||||||
void* us = reinterpret_cast<void **>(reinterpret_cast<char *>(&Instance) + our_mfi.vtbloffs)[our_mfi.vtblindex];
|
void* us = reinterpret_cast<void **>(reinterpret_cast<char *>(&Instance) + our_mfi.vtbloffs)[our_mfi.vtblindex];
|
||||||
hi->SetInfo(SH_HOOKMAN_VERSION, Instance.MFI.vtbloffs, Instance.MFI.vtblindex, &Instance.Proto, us);
|
hi->SetInfo(SH_HOOKMAN_VERSION, Instance.MFI.vtbloffs, Instance.MFI.vtblindex, &Instance.Proto, us);
|
||||||
@ -908,6 +965,11 @@ namespace SourceHook
|
|||||||
Result
|
Result
|
||||||
>::type VoidSafeResult;
|
>::type VoidSafeResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A return type that is C++-reference-safe.
|
||||||
|
*
|
||||||
|
* Prevents us from doing silly things with byref-passed values.
|
||||||
|
*/
|
||||||
typedef typename ReferenceCarrier<VoidSafeResult>::type ResultType;
|
typedef typename ReferenceCarrier<VoidSafeResult>::type ResultType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -915,6 +977,9 @@ namespace SourceHook
|
|||||||
*/
|
*/
|
||||||
virtual Result Func(Args... args)
|
virtual Result Func(Args... args)
|
||||||
{
|
{
|
||||||
|
// Note to all ye who enter here:
|
||||||
|
// Do not, do NOT--DO NOT: touch "this" or any of our member variables.
|
||||||
|
// Hands off bucko. USE THE STATIC INSTANCE! (thisptr is undefined!!)
|
||||||
using namespace ::SourceHook;
|
using namespace ::SourceHook;
|
||||||
|
|
||||||
void *ourvfnptr = reinterpret_cast<void *>(
|
void *ourvfnptr = reinterpret_cast<void *>(
|
||||||
@ -994,8 +1059,8 @@ namespace SourceHook
|
|||||||
// You're probably wondering what the hell this does.
|
// You're probably wondering what the hell this does.
|
||||||
// https://stackoverflow.com/questions/11709859/how-to-have-static-data-members-in-a-header-only-library/11711082#11711082
|
// https://stackoverflow.com/questions/11709859/how-to-have-static-data-members-in-a-header-only-library/11711082#11711082
|
||||||
// Yes, I also happen to hate C++.
|
// Yes, I also happen to hate C++.
|
||||||
template<ISourceHook** SH, typename Interface, auto Method, typename Result, typename... Args>
|
template<ISourceHook** SH, Plugin* PL, typename Interface, auto Method, typename Result, typename... Args>
|
||||||
Hook<SH, Interface, Method, Result, Args...> Hook<SH, Interface, Method, Result, Args...>::Instance;
|
HookImpl<SH, PL, Interface, Method, Result, Args...> HookImpl<SH, PL, Interface, Method, Result, Args...>::Instance;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -723,6 +723,61 @@ namespace SourceHook
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to an active SourceHook
|
||||||
|
*/
|
||||||
|
struct HookInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HookInstance(ISourceHook** sh, int hookid)
|
||||||
|
: SH(sh)
|
||||||
|
, _hookid(hookid)
|
||||||
|
{}
|
||||||
|
protected:
|
||||||
|
// The global pointer to the SourceHook API
|
||||||
|
ISourceHook** SH;
|
||||||
|
|
||||||
|
// The ID of this specific hook
|
||||||
|
int _hookid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the hook was successfully placed.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Ok()
|
||||||
|
{
|
||||||
|
return _hookid != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pause the hook, preventing it from being called until unpaused.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Pause()
|
||||||
|
{
|
||||||
|
return (*SH)->PauseHookByID(_hookid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpause the hook if it is currently paused
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Unpause()
|
||||||
|
{
|
||||||
|
return (*SH)->UnpauseHookByID(_hookid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove the hook, permanently preventing it from being invoked.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool Remove()
|
||||||
|
{
|
||||||
|
return (*SH)->RemoveHookByID(_hookid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A hook manager, used to hook instances of a specific interface.
|
* @brief A hook manager, used to hook instances of a specific interface.
|
||||||
@ -731,8 +786,8 @@ namespace SourceHook
|
|||||||
* and prototype in the template arguments. Any derived class of the interface
|
* and prototype in the template arguments. Any derived class of the interface
|
||||||
* can be hooked using this manager.
|
* can be hooked using this manager.
|
||||||
*/
|
*/
|
||||||
template<ISourceHook** SH, typename Interface, auto Method, typename Result, typename... Args>
|
template<ISourceHook** SH, Plugin* PL, typename Interface, auto Method, typename Result, typename... Args>
|
||||||
struct Hook
|
struct HookImpl
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief The type we expect the template arg "Method" to be.
|
* @brief The type we expect the template arg "Method" to be.
|
||||||
@ -750,15 +805,15 @@ namespace SourceHook
|
|||||||
|
|
||||||
// Singleton instance
|
// Singleton instance
|
||||||
// Initialized below!
|
// Initialized below!
|
||||||
static Hook Instance;
|
static HookImpl Instance;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Hook(Hook& other) = delete;
|
HookImpl(HookImpl& other) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Build the ProtoInfo for this hook
|
* @brief Build the ProtoInfo for this hook
|
||||||
*/
|
*/
|
||||||
constexpr Hook()
|
constexpr HookImpl()
|
||||||
{
|
{
|
||||||
// build protoinfo
|
// build protoinfo
|
||||||
Proto.numOfParams = sizeof...(Args);
|
Proto.numOfParams = sizeof...(Args);
|
||||||
@ -791,11 +846,11 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr Hook* Make()
|
static constexpr HookImpl* Make()
|
||||||
{
|
{
|
||||||
Hook::Instance = Hook();
|
HookImpl::Instance = HookImpl();
|
||||||
|
|
||||||
return &Hook::Instance;
|
return &HookImpl::Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public: // Public Interface
|
public: // Public Interface
|
||||||
@ -809,16 +864,18 @@ namespace SourceHook
|
|||||||
* @param handler the handler that will be called in place of the original method
|
* @param handler the handler that will be called in place of the original method
|
||||||
* @param mode the hook mode - Hook_Normal will only hook this instance, while others alter the global virtual table.
|
* @param mode the hook mode - Hook_Normal will only hook this instance, while others alter the global virtual table.
|
||||||
*/
|
*/
|
||||||
int Add(Plugin id, Interface* iface, bool post, Delegate handler, ::SourceHook::ISourceHook::AddHookMode mode = ISourceHook::AddHookMode::Hook_Normal)
|
HookInstance Add(Interface* iface, bool post, Delegate handler, ::SourceHook::ISourceHook::AddHookMode mode = ISourceHook::AddHookMode::Hook_Normal)
|
||||||
{
|
{
|
||||||
using namespace ::SourceHook;
|
using namespace ::SourceHook;
|
||||||
MemFuncInfo mfi = {true, -1, 0, 0};
|
MemFuncInfo mfi = {true, -1, 0, 0};
|
||||||
GetFuncInfo(Method, mfi);
|
GetFuncInfo(Method, mfi);
|
||||||
if (mfi.thisptroffs < 0 || !mfi.isVirtual)
|
if (mfi.thisptroffs < 0 || !mfi.isVirtual)
|
||||||
return false;
|
return HookInstance(SH, 0);
|
||||||
|
|
||||||
CMyDelegateImpl* delegate = new CMyDelegateImpl(handler);
|
CMyDelegateImpl* delegate = new CMyDelegateImpl(handler);
|
||||||
return (*SH)->AddHook(id, mode, iface, mfi.thisptroffs, Hook::HookManPubFunc, delegate, post);
|
int id = (*SH)->AddHook(*PL, mode, iface, mfi.thisptroffs, HookImpl::HookManPubFunc, delegate, post);
|
||||||
|
|
||||||
|
return HookInstance(SH, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -829,7 +886,7 @@ namespace SourceHook
|
|||||||
* @param post true if this was a post hook, false otherwise (pre-hook)
|
* @param post true if this was a post hook, false otherwise (pre-hook)
|
||||||
* @param handler the handler that will be removed from this hook.
|
* @param handler the handler that will be removed from this hook.
|
||||||
*/
|
*/
|
||||||
int Remove(Plugin id, Interface* iface, bool post, Delegate handler)
|
int Remove(Interface* iface, bool post, Delegate handler)
|
||||||
{
|
{
|
||||||
using namespace ::SourceHook;
|
using namespace ::SourceHook;
|
||||||
MemFuncInfo mfi = {true, -1, 0, 0};
|
MemFuncInfo mfi = {true, -1, 0, 0};
|
||||||
@ -837,7 +894,7 @@ namespace SourceHook
|
|||||||
|
|
||||||
// Temporary delegate for .IsEqual() comparison.
|
// Temporary delegate for .IsEqual() comparison.
|
||||||
CMyDelegateImpl temp(handler);
|
CMyDelegateImpl temp(handler);
|
||||||
return (*SH)->RemoveHook(id, iface, mfi.thisptroffs, Hook::HookManPubFunc, &temp, post);
|
return (*SH)->RemoveHook(*PL, iface, mfi.thisptroffs, HookImpl::HookManPubFunc, &temp, post);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -855,7 +912,7 @@ namespace SourceHook
|
|||||||
if (hi) {
|
if (hi) {
|
||||||
// Build a memberfuncinfo for our hook processor.
|
// Build a memberfuncinfo for our hook processor.
|
||||||
MemFuncInfo our_mfi = {true, -1, 0, 0};
|
MemFuncInfo our_mfi = {true, -1, 0, 0};
|
||||||
GetFuncInfo(&Hook::Func, our_mfi);
|
GetFuncInfo(&HookImpl::Func, our_mfi);
|
||||||
|
|
||||||
void* us = reinterpret_cast<void **>(reinterpret_cast<char *>(&Instance) + our_mfi.vtbloffs)[our_mfi.vtblindex];
|
void* us = reinterpret_cast<void **>(reinterpret_cast<char *>(&Instance) + our_mfi.vtbloffs)[our_mfi.vtblindex];
|
||||||
hi->SetInfo(SH_HOOKMAN_VERSION, Instance.MFI.vtbloffs, Instance.MFI.vtblindex, &Instance.Proto, us);
|
hi->SetInfo(SH_HOOKMAN_VERSION, Instance.MFI.vtbloffs, Instance.MFI.vtblindex, &Instance.Proto, us);
|
||||||
@ -908,6 +965,11 @@ namespace SourceHook
|
|||||||
Result
|
Result
|
||||||
>::type VoidSafeResult;
|
>::type VoidSafeResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A return type that is C++-reference-safe.
|
||||||
|
*
|
||||||
|
* Prevents us from doing silly things with byref-passed values.
|
||||||
|
*/
|
||||||
typedef typename ReferenceCarrier<VoidSafeResult>::type ResultType;
|
typedef typename ReferenceCarrier<VoidSafeResult>::type ResultType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -915,6 +977,9 @@ namespace SourceHook
|
|||||||
*/
|
*/
|
||||||
virtual Result Func(Args... args)
|
virtual Result Func(Args... args)
|
||||||
{
|
{
|
||||||
|
// Note to all ye who enter here:
|
||||||
|
// Do not, do NOT--DO NOT: touch "this" or any of our member variables.
|
||||||
|
// Hands off bucko. USE THE STATIC INSTANCE! (thisptr is undefined!!)
|
||||||
using namespace ::SourceHook;
|
using namespace ::SourceHook;
|
||||||
|
|
||||||
void *ourvfnptr = reinterpret_cast<void *>(
|
void *ourvfnptr = reinterpret_cast<void *>(
|
||||||
@ -994,8 +1059,8 @@ namespace SourceHook
|
|||||||
// You're probably wondering what the hell this does.
|
// You're probably wondering what the hell this does.
|
||||||
// https://stackoverflow.com/questions/11709859/how-to-have-static-data-members-in-a-header-only-library/11711082#11711082
|
// https://stackoverflow.com/questions/11709859/how-to-have-static-data-members-in-a-header-only-library/11711082#11711082
|
||||||
// Yes, I also happen to hate C++.
|
// Yes, I also happen to hate C++.
|
||||||
template<ISourceHook** SH, typename Interface, auto Method, typename Result, typename... Args>
|
template<ISourceHook** SH, Plugin* PL, typename Interface, auto Method, typename Result, typename... Args>
|
||||||
Hook<SH, Interface, Method, Result, Args...> Hook<SH, Interface, Method, Result, Args...>::Instance;
|
HookImpl<SH, PL, Interface, Method, Result, Args...> HookImpl<SH, PL, Interface, Method, Result, Args...>::Instance;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user