summaryrefslogtreecommitdiffstats
path: root/src/hooks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/hooks.cpp')
-rw-r--r--src/hooks.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/hooks.cpp b/src/hooks.cpp
new file mode 100644
index 0000000..215ecfd
--- /dev/null
+++ b/src/hooks.cpp
@@ -0,0 +1,59 @@
1// hooks.cpp — vtable hook installation and teardown bookkeeping.
2#include "hl2h.h"
3
4#include <mutex>
5#include <vector>
6
7namespace {
8
9struct Installed {
10 void *iface;
11 void **old_vt;
12};
13
14std::mutex g_hook_mu;
15std::vector<Installed> g_installed;
16
17} // namespace
18
19bool hooks_install_vtable(void *iface, size_t slots, const VtablePatch *patches,
20 int count) {
21 if (!iface || !patches || count <= 0)
22 return false;
23 void **old = *(void ***)iface;
24 if (!old)
25 return false;
26 for (int i = 0; i < count; i++) {
27 if (patches[i].slot < 0 || (size_t)patches[i].slot >= slots) {
28 logf("hooks: slot %d out of range (table has %u)", patches[i].slot,
29 (unsigned)slots);
30 return false;
31 }
32 }
33
34 void **clone = vtable_clone(iface, slots);
35 if (!clone)
36 return false;
37 for (int i = 0; i < count; i++) {
38 if (patches[i].original)
39 *patches[i].original = old[patches[i].slot];
40 clone[patches[i].slot] = patches[i].replacement;
41 }
42
43 std::lock_guard<std::mutex> lock(g_hook_mu);
44 *(void ***)iface = clone;
45 g_installed.push_back({iface, old});
46 return true;
47}
48
49void hooks_restore_all() {
50 std::lock_guard<std::mutex> lock(g_hook_mu);
51 for (auto it = g_installed.rbegin(); it != g_installed.rend(); ++it)
52 *(void ***)it->iface = it->old_vt;
53 g_installed.clear();
54}
55
56int hooks_installed_count() {
57 std::lock_guard<std::mutex> lock(g_hook_mu);
58 return (int)g_installed.size();
59}