#pragma once #include "../utils/Result.hpp" #include "Handler.hpp" #include namespace geode::core { // The handle returned from adding a hook. It is used to remove a hook. struct HookHandle { void* handler; void* address; void* detour; void* trampoline; }; namespace impl { // a type alias for convenience and for clear type differentiation inside the source file using VectorPointer = std::vector*; GEODE_DLL void addHook( void* address, void* detour, VectorPointer* detourVectorAddress, void* generatedHandler, void** originalTrampolineAddress, void* generatedTrampoline ); GEODE_DLL void removeHook(HookHandle const& handle); } namespace hook { template class Conv, class Ret, class... Args> Result add(Ret (*address)(Args...)) { static std::vector* detourVector; static decltype(Detour) originalTrampoline; void* generatedHandler = (void*)handler; void* generatedTrampoline = (void*)trampoline; impl::addHook( (void*)address, (void*)Detour, (impl::VectorPointer*)&detourVector, (void*)generatedHandler, (void**)&originalTrampoline, (void*)generatedTrampoline ); return Ok({ (void*)generatedHandler, (void*)address, (void*)Detour, (void*)generatedTrampoline }); } inline Result<> remove(HookHandle const& handle) { impl::removeHook(handle); return Ok<>(); } } }