Forward mouse + keyboard to DirectInput and Raw Input games
The MKB subsystem covered message-loop (PostMessage) and polling (GetAsyncKeyState/GetKeyboardState/GetCursorPos) games. Add the two remaining read paths, both fed from the same synthesized state: - DirectInput: vtable-swap IDirectInputDevice8::GetDeviceState (a COM method -> vtable swap, not inline, per the x86 COM-prologue trap), reading the shared vtable from a kept-alive probe device (the game made its devices before we injected). Dispatch on cbData: 256 = keyboard BYTE[256] indexed by DIK scan-code (map VK->DIK via MapVirtualKey VK_TO_VSC); DIMOUSESTATE = mouse buttons + relative deltas from the forwarded cursor. - Raw Input: games get no WM_INPUT while unfocused, so mkb_pump synthesizes it (PostMessage WM_INPUT with lParam = one of our RAWINPUT slots) and the hooked GetRawInputData serves that slot back (RID_HEADER + RID_INPUT). Covers keys + buttons; relative raw-mouse movement isn't in the position-based MKB stream. Both detours use the DetourGate safe-unhook guard, and the mock_game_test storm exercises their install/remove. dinput_hook_test drives the real path end-to-end: forward a key + mouse button through the ring, then a real DI keyboard/mouse device's GetDeviceState returns them. The Raw Input round-trip is operator- validated against a real game (too brittle to assert in-process). vtable_hook.hpp factors the COM vtable-swap helper out for reuse. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,24 @@ target_link_libraries(hook_selftest PRIVATE
|
||||
|
||||
add_test(NAME hook_selftest COMMAND hook_selftest)
|
||||
|
||||
# In-process self-test for the DirectInput forwarding path: reuses mkb_hook.cpp, installs the MKB
|
||||
# hooks (which vtable-swap IDirectInputDevice8::GetDeviceState), forwards a synthetic key + mouse
|
||||
# button through the ring, then creates a real DI keyboard + mouse device and asserts GetDeviceState
|
||||
# returns the forwarded input. Skips cleanly if DirectInput can't acquire a device.
|
||||
add_executable(dinput_hook_test
|
||||
dinput_hook_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/hook/src/mkb_hook.cpp
|
||||
${CMAKE_SOURCE_DIR}/hook/src/hook_registry.cpp)
|
||||
target_include_directories(dinput_hook_test PRIVATE ${CMAKE_SOURCE_DIR}/hook/src)
|
||||
target_link_libraries(dinput_hook_test PRIVATE
|
||||
coop_common
|
||||
safetyhook::safetyhook
|
||||
user32
|
||||
dinput8
|
||||
dxguid
|
||||
ole32)
|
||||
add_test(NAME dinput_hook_test COMMAND dinput_hook_test)
|
||||
|
||||
# Unit test for the shared audio ring (lock-free SPSC push/pop, wrap-around,
|
||||
# format handshake, overrun policy). Header-only, no hook or audio device.
|
||||
add_executable(audio_ring_test audio_ring_test.cpp)
|
||||
@@ -242,6 +260,7 @@ add_test(NAME ui_fit_test COMMAND ui_fit_test)
|
||||
# test's "coop_tone.exe alongside me" lookup keeps working.
|
||||
coop_output_subdir(tests
|
||||
hook_selftest
|
||||
dinput_hook_test
|
||||
audio_ring_test
|
||||
mkb_ring_test
|
||||
mkb_map_test
|
||||
|
||||
Reference in New Issue
Block a user