| 77 | } |
| 78 | |
| 79 | static bool install_internal(const char *name, reshade::hook &hook, hook_method method) |
| 80 | { |
| 81 | // It does not make sense to install a hook which points to itself, so avoid that |
| 82 | if (hook.target == hook.replacement) |
| 83 | return false; |
| 84 | |
| 85 | #if RESHADE_VERBOSE_LOG |
| 86 | reshade::log::message(reshade::log::level::debug, "Installing hook for %s at %p with %p using method %d ...", name, hook.target, hook.replacement, static_cast<int>(method)); |
| 87 | #endif |
| 88 | auto status = reshade::hook::status::unknown; |
| 89 | |
| 90 | switch (method) |
| 91 | { |
| 92 | case hook_method::export_hook: |
| 93 | // Export functions are always called directly |
| 94 | status = reshade::hook::status::success; |
| 95 | break; |
| 96 | case hook_method::function_hook: |
| 97 | status = hook.install(); |
| 98 | break; |
| 99 | case hook_method::vtable_hook: |
| 100 | // Make virtual function table memory writable before modifying it |
| 101 | if (DWORD protection = PAGE_READWRITE; |
| 102 | VirtualProtect(hook.target, sizeof(reshade::hook::address), protection, &protection)) |
| 103 | { |
| 104 | // Replace entry in virtual function table with the replacement function |
| 105 | *reinterpret_cast<reshade::hook::address *>(hook.target) = hook.replacement; |
| 106 | |
| 107 | VirtualProtect(hook.target, sizeof(reshade::hook::address), protection, &protection); |
| 108 | |
| 109 | status = reshade::hook::status::success; |
| 110 | } |
| 111 | else |
| 112 | { |
| 113 | status = reshade::hook::status::memory_protection_failure; |
| 114 | } |
| 115 | break; |
| 116 | } |
| 117 | |
| 118 | if (status != reshade::hook::status::success) |
| 119 | { |
| 120 | reshade::log::message(reshade::log::level::error, "Failed to install hook for %s with status code %d!", name, static_cast<int>(status)); |
| 121 | return false; |
| 122 | } |
| 123 | |
| 124 | // Protect access to hook list with a mutex |
| 125 | { const std::unique_lock<std::shared_mutex> lock(s_hooks_mutex); |
| 126 | s_hooks.push_back({ hook, name, method }); |
| 127 | } |
| 128 | |
| 129 | #if RESHADE_VERBOSE_LOG |
| 130 | reshade::log::message(reshade::log::level::debug, "> Succeeded."); |
| 131 | #endif |
| 132 | |
| 133 | return true; |
| 134 | } |
| 135 | static bool install_internal(HMODULE target_module, HMODULE replacement_module, hook_method method) |
| 136 | { |
no test coverage detected