Skip to content

Commit

Permalink
Plugins: Add register_inline_hook/unregister_inline_hook
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Jul 5, 2024
1 parent a34f6de commit 3d6fb3b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
4 changes: 3 additions & 1 deletion include/uevr/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ SOFTWARE.
#define UEVR_OUT

#define UEVR_PLUGIN_VERSION_MAJOR 2
#define UEVR_PLUGIN_VERSION_MINOR 24
#define UEVR_PLUGIN_VERSION_MINOR 27
#define UEVR_PLUGIN_VERSION_PATCH 0

#define UEVR_RENDERER_D3D11 0
Expand Down Expand Up @@ -207,6 +207,8 @@ typedef struct {
bool (*is_drawing_ui)();
bool (*remove_callback)(void* cb);
unsigned int (*get_persistent_dir)(wchar_t* buffer, unsigned int buffer_size);
int (*register_inline_hook)(void* target, void* dst, void** original);
void (*unregister_inline_hook)(int hook_id);
} UEVR_PluginFunctions;

typedef struct {
Expand Down
26 changes: 25 additions & 1 deletion src/mods/PluginLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,27 @@ unsigned int get_persistent_dir(wchar_t* buffer, unsigned int buffer_size) {

return (unsigned int)size;
}

int register_inline_hook(void* target, void* dst, void** original) {
if (target == nullptr || dst == nullptr || original == nullptr) {
return -1;
}

auto hook = safetyhook::create_inline(target, dst);

if (!hook) {
spdlog::error("Failed to create inline hook at {:x}", (uintptr_t)target);
return -1;
}

*original = hook.original<void*>();

return PluginLoader::get()->add_inline_hook(std::move(hook));
}

void unregister_inline_hook(int id) {
PluginLoader::get()->remove_inline_hook(id);
}
}

namespace uevr {
Expand Down Expand Up @@ -162,7 +183,9 @@ UEVR_PluginFunctions g_plugin_functions {
uevr::log_info,
uevr::is_drawing_ui,
uevr::remove_callback,
uevr::get_persistent_dir
uevr::get_persistent_dir,
uevr::register_inline_hook,
uevr::unregister_inline_hook
};

#define GET_ENGINE_WORLD_RETNULL() \
Expand Down Expand Up @@ -1566,6 +1589,7 @@ void PluginLoader::attempt_unload_plugins() {
FreeLibrary(pair.second);
}

m_inline_hooks.clear();
m_plugins.clear();
}

Expand Down
40 changes: 40 additions & 0 deletions src/mods/PluginLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <Windows.h>

#include <safetyhook.hpp>

#include "Mod.hpp"
#include "uevr/API.h"

Expand Down Expand Up @@ -96,6 +98,30 @@ class PluginLoader : public Mod {
return true;
}

size_t add_inline_hook(safetyhook::InlineHook&& hook) {
std::scoped_lock lock{m_mux};

auto state = std::make_unique<InlineHookState>(std::move(hook));
m_inline_hooks[++m_inline_hook_idx] = std::move(state);

return m_inline_hook_idx;
}

void remove_inline_hook(size_t idx) {
std::scoped_lock lock{m_mux};

if (!m_inline_hooks.contains(idx)) {
return;
}

{
std::scoped_lock _{m_inline_hooks[idx]->mux};
m_inline_hooks[idx]->hook.reset();
}

m_inline_hooks.erase(idx);
}

private:
std::shared_mutex m_api_cb_mtx;
std::vector<PluginLoader::UEVR_OnPresentCb> m_on_present_cbs{};
Expand Down Expand Up @@ -145,4 +171,18 @@ class PluginLoader : public Mod {
std::map<std::string, HMODULE> m_plugins{};
std::map<std::string, std::string> m_plugin_load_errors{};
std::map<std::string, std::string> m_plugin_load_warnings{};

struct InlineHookState {
InlineHookState(safetyhook::InlineHook&& hook)
: hook{std::move(hook)}
{
}

safetyhook::InlineHook hook{};
std::mutex mux{};
};

//std::vector<InlineHookState> m_inline_hooks{};
std::unordered_map<size_t, std::unique_ptr<InlineHookState>> m_inline_hooks{};
size_t m_inline_hook_idx{0};
};

0 comments on commit 3d6fb3b

Please sign in to comment.