#pragma once namespace blackbone { template struct HookHandler : public DetourBase { using ReturnType = std::conditional_t, int, R>; using type = R( __cdecl* )(Args...); using hktype = R( __cdecl* )(Args&...); using hktypeC = R( C::* )(Args&...); // // Workaround for void return type // using typeR = ReturnType( __cdecl* )(Args...); using hktypeR = ReturnType( __cdecl* )(Args&...); using hktypeCR = ReturnType( C::* )(Args&...); static __declspec(noinline) ReturnType __cdecl Handler( Args... args ) { HookHandler* pInst = (HookHandler*)((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer; return pInst->HandlerP( std::forward( args )... ); } ReturnType HandlerP( Args&&... args ) { ReturnType val_new, val_original; DisableHook(); if (_order == CallOrder::HookFirst) { val_new = CallCallback( std::forward( args )... ); val_original = CallOriginal( std::forward( args )... ); } else if (_order == CallOrder::HookLast) { val_original = CallOriginal( std::forward( args )... ); val_new = CallCallback( std::forward( args )... ); } else { val_original = val_new = CallCallback( std::forward( args )... ); } if (this->_hooked) EnableHook(); return (_retType == ReturnMethod::UseOriginal ? val_original : val_new); } inline ReturnType CallOriginal( Args&&... args ) { return (reinterpret_cast(_callOriginal))(args...); } inline ReturnType CallCallback( Args&&... args ) { if (_callbackClass != nullptr) return (reinterpret_cast(_callbackClass)->*brutal_cast(_callback))(args...); else return (reinterpret_cast(_callback))(args...); } }; }