Files
CoopAllTheThings/host/src/injection_panel.hpp
BlackMark e370c8dcc5 Phase 1a: input forwarding via DLL injection + XInput hook
The host can now inject coop_hook.dll into a running game and forward
controller state to it over shared memory, so the game reads the host's
(eventually the guest's) input and nothing else.

- hook/: coop_hook.dll. DllMain spawns a worker that opens the shared-memory
  channel (named by the game's pid) and installs SafetyHook inline hooks on
  XInputGetState/GetStateEx/GetCapabilities/SetState. Detours synthesize state
  from shared memory; unmanaged slots report disconnected, hiding physical pads.
- host/: process picker (Toolhelp32), CreateRemoteThread(LoadLibraryW) injector
  with an IsWow64Process2 bitness guard, IPC server publishing pads each frame,
  and an ImGui Injection panel wiring it together.
- tests/: hook_selftest exercises the IPC seqlock + hook detours in-process
  (no game/controller needed); passes.

Build: SafetyHook wired in (COOP_BUILD_HOOK=ON), Zydis via FetchContent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:21:20 +02:00

45 lines
861 B
C++

// ImGui panel that drives the input-forwarding pipeline: pick a target process,
// inject coop_hook.dll, and stream pad state to it over shared memory.
#pragma once
#include <array>
#include <string>
#include <vector>
#include "coop/protocol.hpp"
#include "imgui.h"
#include "inject/process_list.hpp"
#include "ipc/ipc_server.hpp"
namespace coop
{
class InjectionPanel
{
public:
InjectionPanel();
void draw();
// Forward the latest pad snapshot to the injected hook (if connected).
void publish(const std::array<PadInfo, kMaxPads>& pads)
{
server_.publish(pads);
}
private:
void refresh_processes();
void inject_selected();
std::vector<ProcessEntry> processes_;
char filter_[128] = {};
unsigned long selected_pid_ = 0;
std::wstring selected_name_;
IpcServer server_;
std::string status_;
ImVec4 status_color_;
};
} // namespace coop