template<typename T> struct to_dword { typedef dword type; }; template < typename RetType, kCallConv call_conv, typename Addr, typename... Args > inline RetType call(Addr addr, Args... args) { static_assert ( (call_conv == kStdcall) || (call_conv == kThiscall) || (call_conv == kFastcall) || (call_conv == kCdecl), "Unknown calling convention!" ); switch(call_conv) { case kStdcall: { typedef RetType (__stdcall *func)(typename to_dword<Args>::type...); return ((func) addr)((dword) args...); break; } case kThiscall: { typedef RetType (__thiscall *func)(typename to_dword<Args>::type...); return ((func) addr)((dword) args...); break; } case kFastcall: { typedef RetType (__fastcall *func)(typename to_dword<Args>::type...); return ((func) addr)((dword) args...); break; } case kCdecl: { typedef RetType (__cdecl *func)(typename to_dword<Args>::type...); return ((func) addr)((dword) args...); break; } default: { return RetType(); } } }
patching::call<HMODULE, patching::kCdecl>(0x887668, L"Hello", L"World");
MOV [DWORD ESP+4],60103086 MOV [DWORD ESP],60103092 MOV EAX,887668 CALL NEAR EAX