//------------------------------------------------------------------------- static MH_STATUS EnableAllHooksLL(BOOL enable) { UINT i; for (i = 0; i < g_hooks.size; ++i) { if (g_hooks.pItems[i].isEnabled != enable) { FROZEN_THREADS threads; Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE); __try { for (; i < g_hooks.size; ++i) { if (g_hooks.pItems[i].isEnabled != enable) { MH_STATUS status = EnableHookLL(i, enable); if (status != MH_OK) return status; } } } __finally { Unfreeze(&threads); } } }
//------------------------------------------------------------------------- static MH_STATUS EnableAllHooksLL(BOOL enable) { MH_STATUS status = MH_OK; UINT i, first = INVALID_HOOK_POS; for (i = 0; i < g_hooks.size; ++i) { if (g_hooks.pItems[i].isEnabled != enable) { first = i; break; } } if (first != INVALID_HOOK_POS) { FROZEN_THREADS threads; Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE); for (i = first; i < g_hooks.size; ++i) { if (g_hooks.pItems[i].isEnabled != enable) { status = EnableHookLL(i, enable); if (status != MH_OK) break; } } Unfreeze(&threads); } return status; }
//------------------------------------------------------------------------- static MH_STATUS EnableAllHooksLL(BOOL enable) { int i; for (i = 0; i < g_hooks.size; ++i) { if (g_hooks.items[i].isEnabled != enable) { Freeze(-1, 1); __try { for (; i < g_hooks.size; ++i) { if (g_hooks.items[i].isEnabled != enable) { MH_STATUS status = EnableHookLL(i, enable); if (status != MH_OK) return status; } } } __finally { Unfreeze(); } } }
MH_STATUS ApplyQueued() { CriticalSection::ScopedLock lock(*gCS); if (!gIsInitialized) { return MH_ERROR_NOT_INITIALIZED; } std::vector<uintptr_t> oldIPs; std::vector<uintptr_t> newIPs; for (size_t i = 0, count = gHooks.size(); i < count; ++i) { HOOK_ENTRY& hook = gHooks[i]; if (hook.isEnabled != hook.queueEnable) { if (hook.queueEnable) { oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end()); newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end()); } else { oldIPs.insert(oldIPs.end(), hook.newIPs.begin(), hook.newIPs.end()); newIPs.insert(newIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end()); } } } if (oldIPs.size() > 0) { ScopedThreadExclusive tex(oldIPs, newIPs); for (size_t i = 0, count = gHooks.size(); i < count; ++i) { HOOK_ENTRY& hook = gHooks[i]; if (hook.isEnabled != hook.queueEnable) { MH_STATUS status; if (hook.queueEnable) { status = EnableHookLL(&hook); } else { status = DisableHookLL(&hook); } if (status != MH_OK) { return status; } } } } return MH_OK; }
//------------------------------------------------------------------------- MH_STATUS WINAPI MH_ApplyQueued(VOID) { MH_STATUS status = MH_OK; UINT i, first = INVALID_HOOK_POS; EnterSpinLock(); if (g_hHeap != NULL) { for (i = 0; i < g_hooks.size; ++i) { if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable) { first = i; break; } } if (first != INVALID_HOOK_POS) { FROZEN_THREADS threads; Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED); for (i = first; i < g_hooks.size; ++i) { PHOOK_ENTRY pHook = &g_hooks.pItems[i]; if (pHook->isEnabled != pHook->queueEnable) { status = EnableHookLL(i, pHook->queueEnable); if (status != MH_OK) break; } } Unfreeze(&threads); } } else { status = MH_ERROR_NOT_INITIALIZED; } LeaveSpinLock(); return status; }
//------------------------------------------------------------------------- static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable) { MH_STATUS status = MH_OK; EnterSpinLock(); if (g_hHeap != NULL) { if (pTarget == MH_ALL_HOOKS) { status = EnableAllHooksLL(enable); } else { FROZEN_THREADS threads; UINT pos = FindHookEntry(pTarget); if (pos != INVALID_HOOK_POS) { if (g_hooks.pItems[pos].isEnabled != enable) { Freeze(&threads, pos, ACTION_ENABLE); status = EnableHookLL(pos, enable); Unfreeze(&threads); } else { status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED; } } else { status = MH_ERROR_NOT_CREATED; } } } else { status = MH_ERROR_NOT_INITIALIZED; } LeaveSpinLock(); return status; }
//------------------------------------------------------------------------- MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget) { MH_STATUS status = MH_OK; EnterSpinLock(); if (g_hHeap != NULL) { UINT pos = FindHookEntry(pTarget); if (pos != INVALID_HOOK_POS) { if (g_hooks.pItems[pos].isEnabled) { FROZEN_THREADS threads; Freeze(&threads, pos, ACTION_DISABLE); status = EnableHookLL(pos, FALSE); Unfreeze(&threads); } if (status == MH_OK) { FreeBuffer(g_hooks.pItems[pos].pTrampoline); DeleteHookEntry(pos); } } else { status = MH_ERROR_NOT_CREATED; } } else { status = MH_ERROR_NOT_INITIALIZED; } LeaveSpinLock(); return status; }
MH_STATUS EnableHook(void* pTarget) { CriticalSection::ScopedLock lock(*gCS); if (!gIsInitialized) { return MH_ERROR_NOT_INITIALIZED; } if (pTarget == MH_ALL_HOOKS) { return EnableAllHooksLL(); } HOOK_ENTRY *pHook = FindHook(pTarget); if (pHook == NULL) { return MH_ERROR_NOT_CREATED; } if (pHook->isEnabled) { return MH_ERROR_ENABLED; } // ターゲット関数の冒頭に、中継関数またはフック関数へのジャンプを書き込む { ScopedThreadExclusive tex(pHook->oldIPs, pHook->newIPs); MH_STATUS status = EnableHookLL(pHook); if (status != MH_OK) { return status; } } return MH_OK; }