Hook registry: list installed hooks + call counts in Injection panel
Add a process-wide hook registry (hook/src/hook_registry) that every hook module registers its hooks with and bumps a counter from each detour. The XInput, focus-spoof, and audio render-hooks now register their individual hooks (XInputGetState/Ex/Caps/SetState; GetForegroundWindow/GetActiveWindow/ GetFocus/WndProc guard; IMMDevice::Activate, IAudioClient::Initialize/ GetService, IAudioRenderClient::GetBuffer/ReleaseBuffer) and count calls. The worker publishes the table to the host each tick over a new HookStatus field (protocol v4 -> v5: HookEntry[] + count). The Injection panel shows it as a collapsible table grouped by subsystem with an installed flag and call count per hook; coop_audio_probe prints the same table headless. Verified against Phantom Brave: 13 hooks listed with live counts (focus APIs polled heavily, GetBuffer/ReleaseBuffer ticking with the audio render loop). All four tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <safetyhook.hpp>
|
||||
|
||||
#include "hook_registry.hpp"
|
||||
|
||||
namespace coop::hook
|
||||
{
|
||||
|
||||
@@ -18,6 +20,11 @@ bool g_unicode = true;
|
||||
std::vector<safetyhook::InlineHook> g_focus_hooks;
|
||||
IpcClient* g_focus_ipc = nullptr;
|
||||
|
||||
int g_id_foreground = -1;
|
||||
int g_id_active = -1;
|
||||
int g_id_focus = -1;
|
||||
int g_id_wndproc = -1;
|
||||
|
||||
struct EnumContext
|
||||
{
|
||||
DWORD pid;
|
||||
@@ -67,15 +74,19 @@ LRESULT CALLBACK subclass_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam
|
||||
if (LOWORD(wparam) == WA_INACTIVE)
|
||||
{
|
||||
wparam = MAKEWPARAM(WA_ACTIVE, HIWORD(wparam));
|
||||
hook_note_call(g_id_wndproc);
|
||||
}
|
||||
break;
|
||||
case WM_ACTIVATEAPP:
|
||||
wparam = TRUE; // app is "still active"
|
||||
hook_note_call(g_id_wndproc);
|
||||
break;
|
||||
case WM_NCACTIVATE:
|
||||
wparam = TRUE; // keep the active (non-greyed) appearance
|
||||
hook_note_call(g_id_wndproc);
|
||||
break;
|
||||
case WM_KILLFOCUS:
|
||||
hook_note_call(g_id_wndproc);
|
||||
return 0; // swallow: never tell the game it lost keyboard focus
|
||||
default:
|
||||
break;
|
||||
@@ -86,6 +97,7 @@ LRESULT CALLBACK subclass_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam
|
||||
|
||||
HWND WINAPI hk_GetForegroundWindow()
|
||||
{
|
||||
hook_note_call(g_id_foreground);
|
||||
if (g_focus_ipc != nullptr)
|
||||
{
|
||||
g_focus_ipc->note_focus_query(FocusApi_Foreground);
|
||||
@@ -95,6 +107,7 @@ HWND WINAPI hk_GetForegroundWindow()
|
||||
|
||||
HWND WINAPI hk_GetActiveWindow()
|
||||
{
|
||||
hook_note_call(g_id_active);
|
||||
if (g_focus_ipc != nullptr)
|
||||
{
|
||||
g_focus_ipc->note_focus_query(FocusApi_Active);
|
||||
@@ -104,6 +117,7 @@ HWND WINAPI hk_GetActiveWindow()
|
||||
|
||||
HWND WINAPI hk_GetFocus()
|
||||
{
|
||||
hook_note_call(g_id_focus);
|
||||
if (g_focus_ipc != nullptr)
|
||||
{
|
||||
g_focus_ipc->note_focus_query(FocusApi_Focus);
|
||||
@@ -111,11 +125,12 @@ HWND WINAPI hk_GetFocus()
|
||||
return g_game_hwnd;
|
||||
}
|
||||
|
||||
void hook_export(HMODULE module, const char* name, void* detour)
|
||||
void hook_export(HMODULE module, const char* name, void* detour, int registry_id)
|
||||
{
|
||||
if (void* target = reinterpret_cast<void*>(GetProcAddress(module, name)))
|
||||
{
|
||||
g_focus_hooks.emplace_back(safetyhook::create_inline(target, detour));
|
||||
hook_set_installed(registry_id, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +144,11 @@ bool install_focus_spoof(IpcClient& ipc)
|
||||
return true; // already active
|
||||
}
|
||||
|
||||
g_id_foreground = hook_register("GetForegroundWindow", HookSubsys_Focus);
|
||||
g_id_active = hook_register("GetActiveWindow", HookSubsys_Focus);
|
||||
g_id_focus = hook_register("GetFocus", HookSubsys_Focus);
|
||||
g_id_wndproc = hook_register("WndProc (deactivation guard)", HookSubsys_Focus);
|
||||
|
||||
HWND hwnd = find_main_window(GetCurrentProcessId());
|
||||
if (hwnd == nullptr)
|
||||
{
|
||||
@@ -144,12 +164,14 @@ bool install_focus_spoof(IpcClient& ipc)
|
||||
? SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&subclass_proc))
|
||||
: SetWindowLongPtrA(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&subclass_proc));
|
||||
g_orig_proc = reinterpret_cast<WNDPROC>(replaced);
|
||||
hook_set_installed(g_id_wndproc, true);
|
||||
|
||||
if (HMODULE user32 = GetModuleHandleW(L"user32.dll"))
|
||||
{
|
||||
hook_export(user32, "GetForegroundWindow", reinterpret_cast<void*>(&hk_GetForegroundWindow));
|
||||
hook_export(user32, "GetActiveWindow", reinterpret_cast<void*>(&hk_GetActiveWindow));
|
||||
hook_export(user32, "GetFocus", reinterpret_cast<void*>(&hk_GetFocus));
|
||||
hook_export(user32, "GetForegroundWindow", reinterpret_cast<void*>(&hk_GetForegroundWindow),
|
||||
g_id_foreground);
|
||||
hook_export(user32, "GetActiveWindow", reinterpret_cast<void*>(&hk_GetActiveWindow), g_id_active);
|
||||
hook_export(user32, "GetFocus", reinterpret_cast<void*>(&hk_GetFocus), g_id_focus);
|
||||
}
|
||||
|
||||
ipc.mark_focus_spoof(true, reinterpret_cast<std::uint64_t>(hwnd));
|
||||
@@ -204,6 +226,10 @@ void remove_focus_spoof()
|
||||
}
|
||||
}
|
||||
g_focus_hooks.clear();
|
||||
hook_set_installed(g_id_foreground, false);
|
||||
hook_set_installed(g_id_active, false);
|
||||
hook_set_installed(g_id_focus, false);
|
||||
hook_set_installed(g_id_wndproc, false);
|
||||
g_game_hwnd = nullptr;
|
||||
g_orig_proc = nullptr;
|
||||
g_focus_ipc = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user