mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2024-11-29 11:24:19 +01:00
118 lines
2.7 KiB
C
118 lines
2.7 KiB
C
|
/* ======== SourceHook ========
|
||
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||
|
* No warranties of any kind
|
||
|
*
|
||
|
* License: zlib/libpng
|
||
|
*
|
||
|
* Author(s): Pavol "PM OnoTo" Marko
|
||
|
* ============================
|
||
|
*/
|
||
|
|
||
|
#ifndef __SOURCEHOOK_IMPL_CVFNPTR_H__
|
||
|
#define __SOURCEHOOK_IMPL_CVFNPTR_H__
|
||
|
|
||
|
#include "sh_list.h"
|
||
|
#include "sh_memory.h"
|
||
|
|
||
|
namespace SourceHook
|
||
|
{
|
||
|
namespace Impl
|
||
|
{
|
||
|
class CVfnPtr
|
||
|
{
|
||
|
// *** Data ***
|
||
|
void *m_Ptr;
|
||
|
void *m_OrigEntry;
|
||
|
|
||
|
List<CHookManager*> m_HookMans;
|
||
|
List<CIface> m_IfaceList;
|
||
|
public:
|
||
|
// *** Descriptor ***
|
||
|
typedef void* Descriptor;
|
||
|
|
||
|
// *** Interface ***
|
||
|
inline CVfnPtr(void *ptr);
|
||
|
inline ~CVfnPtr();
|
||
|
inline bool operator==(const Descriptor &other);
|
||
|
inline void *GetPtr() const;
|
||
|
inline void *GetOrigEntry() const;
|
||
|
inline List<CIface> &GetIfaceList();
|
||
|
inline const List<CIface> &GetIfaceList() const;
|
||
|
inline CIface *FindIface(void *iface);
|
||
|
CIface &GetIface(void *iface);
|
||
|
bool Patch(void *newValue);
|
||
|
inline bool Revert();
|
||
|
|
||
|
void AddHookMan(CHookManager *pHookMan);
|
||
|
// If this returns false, it means that there is no hook manager left
|
||
|
// to use and that this vfnptr should be removed.
|
||
|
bool HookManRemoved(CHookManager *pHookMan);
|
||
|
};
|
||
|
|
||
|
// *** Implementation ***
|
||
|
inline CVfnPtr::CVfnPtr(void *ptr)
|
||
|
: m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(m_Ptr))
|
||
|
{
|
||
|
}
|
||
|
|
||
|
inline CVfnPtr::~CVfnPtr()
|
||
|
{
|
||
|
if (!m_HookMans.empty())
|
||
|
m_HookMans.front()->DecrRef(this);
|
||
|
}
|
||
|
|
||
|
inline bool CVfnPtr::operator==(const Descriptor &other)
|
||
|
{
|
||
|
return m_Ptr == other;
|
||
|
}
|
||
|
|
||
|
inline void *CVfnPtr::GetPtr() const
|
||
|
{
|
||
|
return m_Ptr;
|
||
|
}
|
||
|
|
||
|
inline void *CVfnPtr::GetOrigEntry() const
|
||
|
{
|
||
|
return m_OrigEntry;
|
||
|
}
|
||
|
|
||
|
inline List<CIface> &CVfnPtr::GetIfaceList()
|
||
|
{
|
||
|
return m_IfaceList;
|
||
|
}
|
||
|
|
||
|
inline const List<CIface> &CVfnPtr::GetIfaceList() const
|
||
|
{
|
||
|
return m_IfaceList;
|
||
|
}
|
||
|
|
||
|
inline bool CVfnPtr::Revert()
|
||
|
{
|
||
|
// Only patch the vfnptr back if the module is still in memory
|
||
|
// If it's not, do not remove stuff like we did before
|
||
|
// First off we did it wrong (shutdown the whole hookman, uh..) and secondly applications may be
|
||
|
// confused by RemoveHook returning false then (yeah, I know, I made this one up, no one checks for RemoveHook error)
|
||
|
if (ModuleInMemory(reinterpret_cast<char*>(m_Ptr), SH_PTRSIZE))
|
||
|
{
|
||
|
return Patch(m_OrigEntry);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline CIface *CVfnPtr::FindIface(void *iface)
|
||
|
{
|
||
|
List<CIface>::iterator iter = m_IfaceList.find(iface);
|
||
|
if (iter == m_IfaceList.end())
|
||
|
return NULL;
|
||
|
else
|
||
|
return &(*iter);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|