#ifndef __MOCKCPP_API_HOOK_FUNCTOR_H__ #define __MOCKCPP_API_HOOK_FUNCTOR_H__ #include #include #include MOCKCPP_NS_START ///////////////////////////////////////////////////// template struct ApiHookFunctor { }; const std::string empty_caller(""); #define __MOCKCPP_C_API_HOOK_FUNCTOR_DEF(n, CallingConvention) \ template \ struct ApiHookFunctor \ { \ private: \ typedef R (CallingConvention *F) (DECL_ARGS(n)); \ \ static R CallingConvention hook(DECL_PARAMS_LIST(n)) \ { \ return GlobalMockObject::instance.invoke(apiAddress) \ (empty_caller, RefAny() DECL_REST_PARAMS(n)); \ } \ \ static bool appliedBy(F api) \ { return apiAddress == reinterpret_cast(api); } \ \ static void* getHook() \ { return reinterpret_cast(hook); } \ \ static void freeHook() \ { if(--refCount == 0) apiAddress = 0; } \ public: \ \ static void* getApiHook(F api) \ { \ if(!appliedBy(api)) return 0; \ ++refCount; \ return getHook(); \ } \ \ static void* applyApiHook(F api) \ { \ if(apiAddress != 0) return 0; \ apiAddress = reinterpret_cast(api); \ refCount = 1; \ return getHook(); \ } \ \ static bool freeApiHook(void* hook) \ { \ if(getHook() != hook) return false; \ freeHook(); \ return true; \ } \ private: \ static void* apiAddress; \ static unsigned int refCount; \ }; \ template \ void* ApiHookFunctor::apiAddress = 0; \ template \ unsigned int ApiHookFunctor::refCount = 0 /* For C++ method */ #define __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, CallingConvention, ConstConvention) \ template \ struct ApiHookFunctor \ { \ private: \ typedef ApiHookFunctor ThisType; \ typedef R (CallingConvention C::*F) (DECL_ARGS(n)) ConstConvention; \ \ R CallingConvention hook(DECL_PARAMS_LIST(n)) \ { \ C *This = reinterpret_cast(this); \ return GlobalMockObject::instance.invoke(apiAddress) \ (empty_caller, This DECL_REST_PARAMS(n)); \ } \ \ static bool appliedBy(F api) \ { return apiAddress == Details::methodToAddr(api); } \ \ static void* getHook() \ { return Details::methodToAddr(&ThisType::hook); } \ \ static void freeHook() \ { if(--refCount == 0) apiAddress = 0; } \ public: \ \ static void* getApiHook(F api) \ { \ if(!appliedBy(api)) return 0; \ ++refCount; \ return getHook(); \ } \ \ static void* applyApiHook(F api) \ { \ if(apiAddress != 0) return 0; \ apiAddress = Details::methodToAddr(api); \ refCount = 1; \ return getHook(); \ } \ \ static bool freeApiHook(void* hook) \ { \ if(getHook() != hook) return false; \ freeHook(); \ return true; \ } \ private: \ static void* apiAddress; \ static unsigned int refCount; \ }; \ template \ void* ApiHookFunctor::apiAddress = 0; \ template \ unsigned int ApiHookFunctor::refCount = 0 #ifdef WIN32 #if defined(_MSC_VER) && defined(BUILD_FOR_X86) #define MOCKCPP_API_HOOK_FUNCTOR_DEF(n) \ __MOCKCPP_C_API_HOOK_FUNCTOR_DEF(n, ); \ __MOCKCPP_C_API_HOOK_FUNCTOR_DEF(n, __stdcall); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, , ); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, , const); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, __stdcall, ); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, __stdcall, const) #else #define MOCKCPP_API_HOOK_FUNCTOR_DEF(n) \ __MOCKCPP_C_API_HOOK_FUNCTOR_DEF(n, ); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, , ); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, , const) #endif #else #define MOCKCPP_API_HOOK_FUNCTOR_DEF(n) \ __MOCKCPP_C_API_HOOK_FUNCTOR_DEF(n, ); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, , ); \ __MOCKCPP_CXX_API_HOOK_FUNCTOR_DEF(n, , const) #endif MOCKCPP_API_HOOK_FUNCTOR_DEF(0); MOCKCPP_API_HOOK_FUNCTOR_DEF(1); MOCKCPP_API_HOOK_FUNCTOR_DEF(2); MOCKCPP_API_HOOK_FUNCTOR_DEF(3); MOCKCPP_API_HOOK_FUNCTOR_DEF(4); MOCKCPP_API_HOOK_FUNCTOR_DEF(5); MOCKCPP_API_HOOK_FUNCTOR_DEF(6); MOCKCPP_API_HOOK_FUNCTOR_DEF(7); MOCKCPP_API_HOOK_FUNCTOR_DEF(8); MOCKCPP_API_HOOK_FUNCTOR_DEF(9); MOCKCPP_API_HOOK_FUNCTOR_DEF(10); MOCKCPP_API_HOOK_FUNCTOR_DEF(11); MOCKCPP_API_HOOK_FUNCTOR_DEF(12); MOCKCPP_NS_END #endif