#pragma once #include #include #include namespace fxn { struct invoker_base { typedef void*(*get_native_handler_t)(std::uint64_t hash); static get_native_handler_t _get_native_handler; typedef void(*schedule_native_t)(fxn::NativeContext* context, bool wait); static schedule_native_t _schedule_native; typedef bool(*native_hook_t)(fxn::NativeContext* context, bool& call_original); typedef void(*register_native_hook_t)(std::uint64_t hash, native_hook_t hook); static register_native_hook_t _register_native_hook; static void initialize(std::string_view module_name); static void get_native_handler(std::uint64_t hash); static void schedule_native(fxn::NativeContext* context, bool wait); static void register_native_hook(std::uint64_t hash, native_hook_t hook); }; template struct invoker { using return_type = Ret; using native_hash = std::integral_constant; return_type operator()(Args... args); }; } #ifdef FXN_IMPORTS #include namespace fxn { inline invoker_base::get_native_handler_t invoker_base::_get_native_handler = nullptr; inline invoker_base::schedule_native_t invoker_base::_schedule_native = nullptr; inline invoker_base::register_native_hook_t invoker_base::_register_native_hook = nullptr; inline void invoker_base::initialize(std::string_view module_name) { HMODULE mod = GetModuleHandleA(module_name.data()); if (!mod) { exit(EXIT_FAILURE); } invoker_base::_get_native_handler = reinterpret_cast( GetProcAddress(mod, "fxn_native_invoker_get_handler") ); invoker_base::_schedule_native = reinterpret_cast( GetProcAddress(mod, "fxn_schedule_native") ); invoker_base::_register_native_hook = reinterpret_cast( GetProcAddress(mod, "fxn_register_native_hook") ); if (!invoker_base::_get_native_handler || !invoker_base::_schedule_native || !invoker_base::_register_native_hook) { exit(EXIT_FAILURE); } } inline void invoker_base::get_native_handler(std::uint64_t hash) { invoker_base::_get_native_handler(hash); } inline void invoker_base::schedule_native(fxn::NativeContext* context, bool wait) { invoker_base::_schedule_native(context, wait); } inline void invoker_base::register_native_hook(std::uint64_t hash, native_hook_t hook) { invoker_base::_register_native_hook(hash, hook); } template inline typename invoker::return_type invoker::operator()(Args... args) { fxn::NativeContext context(Hash); // Push arguments (context.PushArgument(args), ...); // Schedule native call invoker_base::schedule_native(&context, true); if constexpr (!std::is_same_v) { return context.GetResult(); } } } #endif