// hooks.cpp — vtable hook installation and teardown bookkeeping. #include "hl2h.h" #include #include namespace { struct Installed { void *iface; void **old_vt; }; std::mutex g_hook_mu; std::vector g_installed; } // namespace bool hooks_install_vtable(void *iface, size_t slots, const VtablePatch *patches, int count) { if (!iface || !patches || count <= 0) return false; void **old = *(void ***)iface; if (!old) return false; for (int i = 0; i < count; i++) { if (patches[i].slot < 0 || (size_t)patches[i].slot >= slots) { logf("hooks: slot %d out of range (table has %u)", patches[i].slot, (unsigned)slots); return false; } } void **clone = vtable_clone(iface, slots); if (!clone) return false; for (int i = 0; i < count; i++) { if (patches[i].original) *patches[i].original = old[patches[i].slot]; clone[patches[i].slot] = patches[i].replacement; } std::lock_guard lock(g_hook_mu); *(void ***)iface = clone; g_installed.push_back({iface, old}); return true; } void hooks_restore_all() { std::lock_guard lock(g_hook_mu); for (auto it = g_installed.rbegin(); it != g_installed.rend(); ++it) *(void ***)it->iface = it->old_vt; g_installed.clear(); } int hooks_installed_count() { std::lock_guard lock(g_hook_mu); return (int)g_installed.size(); }