diff --git a/sourcehook/generate/sourcehook.hxx b/sourcehook/generate/sourcehook.hxx index 6fe6bd0..95b0839 100755 --- a/sourcehook/generate/sourcehook.hxx +++ b/sourcehook/generate/sourcehook.hxx @@ -17,7 +17,7 @@ #endif #ifndef SH_GLOB_PLUGPTR -#define SH_GLOB_PLUGPTR g_Plug +#define SH_GLOB_PLUGPTR g_PLID #endif #define SH_ASSERT(x) if (!(x)) __asm { int 3 } @@ -79,7 +79,7 @@ namespace SourceHook * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it * and every plugin has a unique identifier, everything is ok. */ - typedef void* Plugin; + typedef int Plugin; enum HookManagerAction { @@ -141,6 +141,7 @@ namespace SourceHook struct Hook { ISHDelegate *handler; //!< Pointer to the handler + bool paused; //!< If true, the hook should not be executed Plugin plug; //!< The owner plugin }; void *callclass; //!< Stores a call class for this interface @@ -397,6 +398,7 @@ namespace SourceHook prev_res = MRES_IGNORED; \ for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ + if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ plugin_ret = reinterpret_cast*>(hiter->handler)->GetDeleg() params; \ prev_res = cur_res; \ @@ -448,6 +450,7 @@ namespace SourceHook prev_res = MRES_IGNORED; \ for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ + if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ reinterpret_cast*>(hiter->handler)->GetDeleg() params; \ prev_res = cur_res; \ diff --git a/sourcehook/sourcehook.cpp b/sourcehook/sourcehook.cpp index 8964b6e..7d467e2 100644 --- a/sourcehook/sourcehook.cpp +++ b/sourcehook/sourcehook.cpp @@ -87,6 +87,10 @@ namespace SourceHook // Iterate through their hooks // If a hook from an other plugin is found, return true // Return false otherwise +#define TMP_CHECK_LIST(name) \ + for (iter3 = iter2->name.begin(); iter3 != iter2->name.end(); ++iter3) \ + if (iter3->plug == plug) \ + return true; for (HookManInfoList::iterator iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) { @@ -95,15 +99,12 @@ namespace SourceHook for (std::list::iterator iter2 = iter->ifaces.begin(); iter2 != iter->ifaces.end(); ++iter2) { std::list::iterator iter3; - for (iter3 = iter2->hooks_pre.begin(); iter3 != iter2->hooks_pre.end(); ++iter3) - if (iter3->plug == plug) - return true; - for (iter3 = iter2->hooks_post.begin(); iter3 != iter2->hooks_post.end(); ++iter3) - if (iter3->plug == plug) - return true; + TMP_CHECK_LIST(hooks_pre); + TMP_CHECK_LIST(hooks_post); } } } +#undef TMP_CHECK_LIST return false; } @@ -255,6 +256,7 @@ namespace SourceHook HookManagerInfo::Iface::Hook hookinfo; hookinfo.handler = handler; hookinfo.plug = plug; + hookinfo.paused = false; if (post) ifsiter->hooks_post.push_back(hookinfo); else @@ -479,6 +481,43 @@ namespace SourceHook return hookmaniter; } + void CSourceHookImpl::PausePlugin(Plugin plug) + { + // Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused + for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter) + for (std::list::iterator ifaceiter = hookmaniter->ifaces.begin(); + ifaceiter != hookmaniter->ifaces.end(); ++ifaceiter) + { + for (std::list::iterator hookiter = ifaceiter->hooks_pre.begin(); + hookiter != ifaceiter->hooks_pre.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = true; + + for (std::list::iterator hookiter = ifaceiter->hooks_post.begin(); + hookiter != ifaceiter->hooks_post.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = true; + } + } + + void CSourceHookImpl::UnpausePlugin(Plugin plug) + { + // Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to normal + for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter) + for (std::list::iterator ifaceiter = hookmaniter->ifaces.begin(); + ifaceiter != hookmaniter->ifaces.end(); ++ifaceiter) + { + for (std::list::iterator hookiter = ifaceiter->hooks_pre.begin(); + hookiter != ifaceiter->hooks_pre.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = false; + + for (std::list::iterator hookiter = ifaceiter->hooks_post.begin(); + hookiter != ifaceiter->hooks_post.end(); ++hookiter) + if (plug == hookiter->plug) + hookiter->paused = false; + } + } void CSourceHookImpl::SetRes(META_RES res) { diff --git a/sourcehook/sourcehook.h b/sourcehook/sourcehook.h index 78f8dac..cc4e775 100644 --- a/sourcehook/sourcehook.h +++ b/sourcehook/sourcehook.h @@ -17,7 +17,7 @@ #endif #ifndef SH_GLOB_PLUGPTR -#define SH_GLOB_PLUGPTR g_Plug +#define SH_GLOB_PLUGPTR g_PLID #endif #define SH_ASSERT(x) if (!(x)) __asm { int 3 } @@ -79,7 +79,7 @@ namespace SourceHook * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it * and every plugin has a unique identifier, everything is ok. */ - typedef void* Plugin; + typedef int Plugin; enum HookManagerAction { @@ -141,6 +141,7 @@ namespace SourceHook struct Hook { ISHDelegate *handler; //!< Pointer to the handler + bool paused; //!< If true, the hook should not be executed Plugin plug; //!< The owner plugin }; void *callclass; //!< Stores a call class for this interface @@ -397,6 +398,7 @@ namespace SourceHook prev_res = MRES_IGNORED; \ for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ + if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ plugin_ret = reinterpret_cast*>(hiter->handler)->GetDeleg() params; \ prev_res = cur_res; \ @@ -448,6 +450,7 @@ namespace SourceHook prev_res = MRES_IGNORED; \ for (std::list::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \ { \ + if (hiter->paused) continue; \ cur_res = MRES_IGNORED; \ reinterpret_cast*>(hiter->handler)->GetDeleg() params; \ prev_res = cur_res; \ diff --git a/sourcehook/sourcehook_impl.h b/sourcehook/sourcehook_impl.h index b124de6..50441d6 100644 --- a/sourcehook/sourcehook_impl.h +++ b/sourcehook/sourcehook_impl.h @@ -117,6 +117,20 @@ namespace SourceHook */ bool IsPluginInUse(Plugin plug); + /** + * @brief Pauses all hooks of a plugin + * + * @param plug The unique identifier of the plugin + */ + void PausePlugin(Plugin plug); + + /** + * @brief Unpauses all hooks of a plugin + * + * @param plug The unique identifier of the plugin + */ + void UnpausePlugin(Plugin plug); + /** * @brief Return a pointer to a callclass. Generate a new one if required. * diff --git a/sourcehook/test/main.cpp b/sourcehook/test/main.cpp index b1581c1..320275f 100644 --- a/sourcehook/test/main.cpp +++ b/sourcehook/test/main.cpp @@ -359,7 +359,7 @@ public: }; // Sourcehook needs g_Plug and g_SHPtr, it will be customizable in the next release -void *g_Plug = (void*)1337; +int g_PLID = 1337; SourceHook::ISourceHook *g_SHPtr; SourceHook::CSourceHookImpl g_SHImpl; @@ -465,6 +465,19 @@ int main(int argc, char *argv[]) printf("TEST2.8: Calling F16(155) through CC\n"); printf("Returned: %d\n", cc->F16(155) ? 1 : 0); printf("TEST2.9: Removing pre hook\n"); + printf("TEST2.XX.1: Pausing the plugin\n"); + g_SHImpl.PausePlugin(g_PLID); + printf("TEST2.XX.2: Calling F16(155)\n"); + printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); + printf("TEST2.XX.3: Calling F16(155) through CC\n"); + printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("TEST2.XX.4: Unpausing the plugin\n"); + g_SHImpl.UnpausePlugin(g_PLID); + printf("TEST2.XX.5: Calling F16(155)\n"); + printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0); + printf("TEST2.XX.6: Calling F16(155) through CC\n"); + printf("Returned: %d\n", cc->F16(155) ? 1 : 0); + printf("TEST2.9: Removing pre hook\n"); SH_REMOVE_HOOK_STATICFUNC(Test, F16, zLOL_Ptr, Test_F16_int_pre_handler, false); printf("TEST2.10: Calling F16(155)\n"); printf("Returned: %d\n", zLOL_Ptr->F16(155) ? 1 : 0);