From 53b48bab947327e664a4e8acb12e5206406cfb87 Mon Sep 17 00:00:00 2001 From: Pavol Marko Date: Sun, 7 Oct 2007 23:00:38 +0000 Subject: [PATCH] Added SH_GET_ORIG_VFNPTR_ENTRY --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40471 --- sourcehook/generate/sourcehook.h | 24 ++++++++++++++++++++++++ sourcehook/generate/sourcehook.hxx | 24 ++++++++++++++++++++++++ sourcehook/sourcehook.cpp | 19 +++++++++++++++++++ sourcehook/sourcehook.h | 24 ++++++++++++++++++++++++ sourcehook/sourcehook_impl.h | 2 ++ sourcehook/test/test1.cpp | 6 ++++++ 6 files changed, 99 insertions(+) diff --git a/sourcehook/generate/sourcehook.h b/sourcehook/generate/sourcehook.h index 3645071..bdf1b29 100644 --- a/sourcehook/generate/sourcehook.h +++ b/sourcehook/generate/sourcehook.h @@ -391,6 +391,14 @@ namespace SourceHook */ virtual void ResetIgnoreHooks(void *vfnptr) = 0; + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; + ////////////////////////////////////////////////////////////////////////// // For hook managers @@ -466,6 +474,20 @@ namespace SourceHook return &ref; } }; + + template + void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) + { + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(pInstance, mfp, info); + + void *vfnptr = reinterpret_cast( + *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); + + void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); + + return origentry ? origentry : *reinterpret_cast(vfnptr); + } } /************************************************************************/ @@ -588,6 +610,8 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \ } while (0) +#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) + // New ADD / REMOVE macros. #define SH_STATIC(func) fastdelegate::MakeDelegate(func) #define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) diff --git a/sourcehook/generate/sourcehook.hxx b/sourcehook/generate/sourcehook.hxx index eb6117a..dad1ab9 100755 --- a/sourcehook/generate/sourcehook.hxx +++ b/sourcehook/generate/sourcehook.hxx @@ -391,6 +391,14 @@ namespace SourceHook */ virtual void ResetIgnoreHooks(void *vfnptr) = 0; + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; + ////////////////////////////////////////////////////////////////////////// // For hook managers @@ -466,6 +474,20 @@ namespace SourceHook return &ref; } }; + + template + void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) + { + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(pInstance, mfp, info); + + void *vfnptr = reinterpret_cast( + *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); + + void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); + + return origentry ? origentry : *reinterpret_cast(vfnptr); + } } /************************************************************************/ @@ -588,6 +610,8 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \ } while (0) +#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) + // New ADD / REMOVE macros. #define SH_STATIC(func) fastdelegate::MakeDelegate(func) #define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) diff --git a/sourcehook/sourcehook.cpp b/sourcehook/sourcehook.cpp index 568a019..9618fdc 100644 --- a/sourcehook/sourcehook.cpp +++ b/sourcehook/sourcehook.cpp @@ -733,6 +733,25 @@ namespace SourceHook m_ContextStack.pop(); } + void *CSourceHookImpl::GetOrigVfnPtrEntry(void *vfnptr) + { + for (CHookManContainerList::iterator hmcl_iter = m_HookManContainers.begin(); + hmcl_iter != m_HookManContainers.end(); ++hmcl_iter) + { + for (CHookManagerContainer::iterator hookmaniter = hmcl_iter->begin(); + hookmaniter != hmcl_iter->end(); ++hookmaniter) + { + for (List::iterator vfnptr_iter = hookmaniter->GetVfnPtrList().begin(); + vfnptr_iter != hookmaniter->GetVfnPtrList().end(); ++vfnptr_iter) + { + if (vfnptr_iter->GetPtr() == vfnptr) + return vfnptr_iter->GetOrigEntry(); + } + } + } + return NULL; + } + void CSourceHookImpl::DoRecall() { CHookContext newCtx; diff --git a/sourcehook/sourcehook.h b/sourcehook/sourcehook.h index 3645071..bdf1b29 100644 --- a/sourcehook/sourcehook.h +++ b/sourcehook/sourcehook.h @@ -391,6 +391,14 @@ namespace SourceHook */ virtual void ResetIgnoreHooks(void *vfnptr) = 0; + /** + * @brief Finds the original entry of a virtual function pointer + * + * @param vfnptr The virtual function pointer + * @return The original entry if the virtual function pointer has been patched; NULL otherwise. + */ + virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; + ////////////////////////////////////////////////////////////////////////// // For hook managers @@ -466,6 +474,20 @@ namespace SourceHook return &ref; } }; + + template + void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) + { + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(pInstance, mfp, info); + + void *vfnptr = reinterpret_cast( + *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); + + void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); + + return origentry ? origentry : *reinterpret_cast(vfnptr); + } } /************************************************************************/ @@ -588,6 +610,8 @@ SourceHook::CallClass *SH_GET_CALLCLASS(T *p) SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \ } while (0) +#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) + // New ADD / REMOVE macros. #define SH_STATIC(func) fastdelegate::MakeDelegate(func) #define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) diff --git a/sourcehook/sourcehook_impl.h b/sourcehook/sourcehook_impl.h index 8a0af2e..3797b28 100644 --- a/sourcehook/sourcehook_impl.h +++ b/sourcehook/sourcehook_impl.h @@ -314,6 +314,8 @@ namespace SourceHook void EndContext(IHookContext *pCtx); + void *GetOrigVfnPtrEntry(void *vfnptr); + /** * @brief Shut down the whole system, unregister all hook managers */ diff --git a/sourcehook/test/test1.cpp b/sourcehook/test/test1.cpp index 174e04f..5cf1978 100644 --- a/sourcehook/test/test1.cpp +++ b/sourcehook/test/test1.cpp @@ -419,6 +419,8 @@ bool TestBasic(std::string &error) Test test; Test *pTest = &test; + void *pOrigVfnPtrF1 = (*reinterpret_cast(pTest))[0]; + // 1) Get a call class and call the member through it and normally SourceHook::CallClass *cc = SH_GET_CALLCLASS(pTest); @@ -433,6 +435,8 @@ bool TestBasic(std::string &error) new State_F1_Called, NULL), "Part 1"); + CHECK_COND(SH_GET_ORIG_VFNPTR_ENTRY(pTest, &Test::F1) == pOrigVfnPtrF1, "Part S1"); + // 2) Request a call class again SourceHook::CallClass *cc2 = SH_GET_CALLCLASS(pTest); ADD_STATE(State_F1_CallClassGenerated); @@ -471,6 +475,8 @@ bool TestBasic(std::string &error) new State_F1_PreHandler_Called(&f1_handlers), NULL), "Part 3"); + CHECK_COND(SH_GET_ORIG_VFNPTR_ENTRY(pTest, &Test::F1) == pOrigVfnPtrF1, "Part S3"); + // 4) Rerequest the callclass SH_RELEASE_CALLCLASS(cc);