/* ======== 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 m_HookMans; List 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 &GetIfaceList(); inline const List &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(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 &CVfnPtr::GetIfaceList() { return m_IfaceList; } inline const List &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(m_Ptr), SH_PTRSIZE)) { return Patch(m_OrigEntry); } else { return true; } } inline CIface *CVfnPtr::FindIface(void *iface) { List::iterator iter = m_IfaceList.find(iface); if (iter == m_IfaceList.end()) return NULL; else return &(*iter); } } } #endif