#pragma once #include "pch.h" #define CALL_ORIGIN(function, ...) \ HookManager::call(function, __func__, __VA_ARGS__) class HookManager { public: template static void install(Fn func, Fn handler) { enable(func, handler); holderMap[reinterpret_cast(handler)] = reinterpret_cast(func); } template [[nodiscard]] static Fn getOrigin(Fn handler, const char* callerName = nullptr) noexcept { if (holderMap.count(reinterpret_cast(handler)) == 0) { printf("Origin not found for handler: %s. Maybe racing bug.", callerName == nullptr ? "" : callerName); return nullptr; } return reinterpret_cast(holderMap[reinterpret_cast(handler)]); } template [[nodiscard]] static void detach(Fn handler) noexcept { disable(handler); holderMap.erase(reinterpret_cast(handler)); } template [[nodiscard]] static RType call(RType(*handler)(Params...), const char* callerName = nullptr, Params... params) { auto origin = getOrigin(handler, callerName); if (origin != nullptr) return origin(params...); return RType(); } static void detachAll() noexcept { for (const auto &[key, value] : holderMap) { disable(key); } holderMap.clear(); } private: inline static std::map holderMap{}; template static void disable(Fn handler) { Fn origin = getOrigin(handler); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)origin, handler); DetourTransactionCommit(); } template static void enable(Fn& func, Fn handler) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)func, handler); DetourTransactionCommit(); } };