Implement portable Input hook system

This implementation is for portability, so its not module specific and can be used on all programs utilizing those API's
This commit is contained in:
Amos 2021-06-19 07:21:47 -07:00
parent 6700343e2e
commit 3577fe0b6c
3 changed files with 245 additions and 15 deletions

11
r5dev/include/input.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
/////////////////////////////////////////////////////////////////////////////
// Internals
void InstallIPHooks();
void RemoveIPHooks();
/////////////////////////////////////////////////////////////////////////////
// Globals
extern BOOL g_bBlockInput;
/////////////////////////////////////////////////////////////////////////////

View File

@ -6,6 +6,7 @@
#include <windows.h> #include <windows.h>
#include "id3dx.h" #include "id3dx.h"
#include "input.h"
#include "enums.h" #include "enums.h"
#include "detours.h" #include "detours.h"
#include "overlay.h" #include "overlay.h"
@ -25,11 +26,16 @@
typedef HRESULT(__stdcall* IDXGISwapChainPresent)(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags); typedef HRESULT(__stdcall* IDXGISwapChainPresent)(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags);
typedef HRESULT(__stdcall* IDXGIResizeBuffers) (IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags); typedef HRESULT(__stdcall* IDXGIResizeBuffers) (IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags);
///////////////////////////////////////////////////////////////////////////////////
typedef BOOL(WINAPI* IPostMessageA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
typedef BOOL(WINAPI* IPostMessageW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
extern BOOL g_bShowMenu = false; extern BOOL g_bShowMenu = false;
static BOOL g_bInitialized = false; static BOOL g_bInitialized = false;
static BOOL g_bPresentHooked = false; static BOOL g_bPresentHooked = false;
///////////////////////////////////////////////////////////////////////////////////
static WNDPROC g_oWndProc = NULL; static WNDPROC g_oWndProc = NULL;
static HWND g_hGameWindow = NULL; static HWND g_hGameWindow = NULL;
extern DWORD g_dThreadId = NULL; extern DWORD g_dThreadId = NULL;
@ -41,16 +47,14 @@ static IDXGIResizeBuffers g_oResizeBuffers = nullptr;
static ID3D11DeviceContext* g_pDeviceContext = nullptr; static ID3D11DeviceContext* g_pDeviceContext = nullptr;
static ID3D11Device* g_pDevice = nullptr; static ID3D11Device* g_pDevice = nullptr;
static ID3D11RenderTargetView* g_pRenderTargetView = nullptr; static ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
static IPostMessageA g_oPostMessageA = nullptr;
static IPostMessageW g_oPostMessageW = nullptr;
///////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Window // Window
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////
void Hook_SetCursorPosition(INT64 nFlag, LONG posX, LONG posY)
{
if (g_bShowMenu) { return; }
return SetCursorPosition(nFlag, posX, posY);
}
LRESULT CALLBACK DXGIMsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK DXGIMsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
@ -68,23 +72,82 @@ LRESULT CALLBACK hWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
g_bShowMenu = !g_bShowMenu; g_bShowMenu = !g_bShowMenu;
} }
} }
if (uMsg == WM_SIZE)
{
g_bShowMenu = false;
}
if (g_bShowMenu) if (g_bShowMenu)
{ {//////////////////////////////////////////////////////////////////////////////
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam); ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
return true; g_bBlockInput = true;
switch (uMsg)
{
case WM_LBUTTONDOWN:
return 1L;
case WM_LBUTTONUP:
return 1L;
case WM_RBUTTONDOWN:
return 1L;
case WM_RBUTTONUP:
return 1L;
case WM_MBUTTONDOWN:
return 1L;
case WM_MBUTTONUP:
return 1L;
case WM_KEYDOWN:
return 1L;
case WM_KEYUP:
return 1L;
case WM_MOUSEACTIVATE:
return 1L;
case WM_MOUSEHOVER:
return 1L;
case WM_MOUSEHWHEEL:
return 1L;
case WM_MOUSELEAVE:
return 1L;
case WM_MOUSEMOVE:
return 1L;
case WM_MOUSEWHEEL:
return 1L;
case WM_SETCURSOR:
return 1L;
default:
break;
}
}//////////////////////////////////////////////////////////////////////////////
else
{
g_bBlockInput = false;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
return CallWindowProc(g_oWndProc, hWnd, uMsg, wParam, lParam); return CallWindowProc(g_oWndProc, hWnd, uMsg, wParam, lParam);
} }
BOOL WINAPI HPostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (g_bBlockInput && Msg == WM_MOUSEMOVE)
{
return TRUE;
}
return g_oPostMessageA(hWnd, Msg, wParam, lParam);
}
BOOL WINAPI HPostMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (g_bBlockInput && Msg == WM_MOUSEMOVE)
{
return TRUE;
}
return g_oPostMessageW(hWnd, Msg, wParam, lParam);
}
///////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Present // Present
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////
HRESULT GetDeviceAndCtxFromSwapchain(IDXGISwapChain* pSwapChain, ID3D11Device** ppDevice, ID3D11DeviceContext** ppContext) HRESULT GetDeviceAndCtxFromSwapchain(IDXGISwapChain* pSwapChain, ID3D11Device** ppDevice, ID3D11DeviceContext** ppContext)
{ {
@ -178,9 +241,11 @@ void GetPresent()
g_bPresentHooked = true; g_bPresentHooked = true;
} }
///////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Init // Init
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////
void SetupImGui() void SetupImGui()
{ {
@ -314,30 +379,53 @@ HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT n
return g_fnIDXGISwapChainPresent(pSwapChain, nSyncInterval, nFlags); return g_fnIDXGISwapChainPresent(pSwapChain, nSyncInterval, nFlags);
} }
///////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Management // Management
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////
void InstallDXHooks() void InstallDXHooks()
{ {
g_oPostMessageA = (IPostMessageA)DetourFindFunction("user32.dll", "PostMessageA");
g_oPostMessageW = (IPostMessageW)DetourFindFunction("user32.dll", "PostMessageW");
///////////////////////////////////////////////////////////////////////////////
// Begin the detour transaction
DetourTransactionBegin(); DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread()); DetourUpdateThread(GetCurrentThread());
DetourAttach((LPVOID*)&SetCursorPosition, &Hook_SetCursorPosition); ///////////////////////////////////////////////////////////////////////////////
// Hook PostMessage
DetourAttach(&(LPVOID&)g_oPostMessageA, (PBYTE)HPostMessageA);
DetourAttach(&(LPVOID&)g_oPostMessageW, (PBYTE)HPostMessageW);
///////////////////////////////////////////////////////////////////////////////
// Hook SwapChain
DetourAttach(&(LPVOID&)g_fnIDXGISwapChainPresent, (PBYTE)Present); DetourAttach(&(LPVOID&)g_fnIDXGISwapChainPresent, (PBYTE)Present);
DetourAttach(&(LPVOID&)g_oResizeBuffers, (PBYTE)GetResizeBuffers); DetourAttach(&(LPVOID&)g_oResizeBuffers, (PBYTE)GetResizeBuffers);
///////////////////////////////////////////////////////////////////////////////
// Commit the transaction
DetourTransactionCommit(); DetourTransactionCommit();
} }
void RemoveDXHooks() void RemoveDXHooks()
{ {
///////////////////////////////////////////////////////////////////////////////
// Begin the detour transaction
DetourTransactionBegin(); DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread()); DetourUpdateThread(GetCurrentThread());
DetourDetach((LPVOID*)&SetCursorPosition, &Hook_SetCursorPosition); //////////////////////////////////////////////////////////////////////////////
// Unhook PostMessage
DetourAttach(&(LPVOID&)g_oPostMessageA, (PBYTE)HPostMessageA);
DetourAttach(&(LPVOID&)g_oPostMessageW, (PBYTE)HPostMessageW);
//////////////////////////////////////////////////////////////////////////////
// Unhook SwapChain
DetourDetach(&(LPVOID&)g_fnIDXGISwapChainPresent, (PBYTE)Present); DetourDetach(&(LPVOID&)g_fnIDXGISwapChainPresent, (PBYTE)Present);
DetourDetach(&(LPVOID&)g_oResizeBuffers, (PBYTE)GetResizeBuffers); DetourDetach(&(LPVOID&)g_oResizeBuffers, (PBYTE)GetResizeBuffers);
///////////////////////////////////////////////////////////////////////////////
// Commit the transaction
DetourTransactionCommit(); DetourTransactionCommit();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Shutdown ImGui
ImGui_ImplWin32_Shutdown(); ImGui_ImplWin32_Shutdown();
ImGui_ImplDX11_Shutdown(); ImGui_ImplDX11_Shutdown();
} }
@ -353,9 +441,11 @@ void PrintDXAddress()
std::cout << "+--------------------------------------------------------+" << std::endl; std::cout << "+--------------------------------------------------------+" << std::endl;
} }
///////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Main // Entry
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////
DWORD __stdcall DXSwapChainWorker(LPVOID) DWORD __stdcall DXSwapChainWorker(LPVOID)
{ {

129
r5dev/src/input.cpp Normal file
View File

@ -0,0 +1,129 @@
#include <windows.h>
#include <cassert>
#include <stdio.h>
#include "detours.h"
#include "input.h"
/*-----------------------------------------------------------------------------
* _input.cpp
*-----------------------------------------------------------------------------*/
///////////////////////////////////////////////////////////////////////////////
typedef BOOL(WINAPI* IGetCursorPos)(LPPOINT lpPoint);
typedef BOOL(WINAPI* ISetCursorPos)(int nX, int nY);
typedef BOOL(WINAPI* IClipCursor)(const RECT* lpRect);
typedef BOOL(WINAPI* IShowCursor)(BOOL bShow);
///////////////////////////////////////////////////////////////////////////////
static IGetCursorPos g_oGetCursorPos = nullptr;
static ISetCursorPos g_oSetCursorPos = nullptr;
static IClipCursor g_oClipCursor = nullptr;
static IShowCursor g_oShowCursor = nullptr;
///////////////////////////////////////////////////////////////////////////////
static POINT g_pLastCursorPos = { 0 };
extern BOOL g_bBlockInput = false;
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// Init
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
void SetupIPHooks()
{
g_oSetCursorPos = (ISetCursorPos)DetourFindFunction("user32.dll", "SetCursorPos");
g_oClipCursor = (IClipCursor )DetourFindFunction("user32.dll", "ClipCursor" );
g_oGetCursorPos = (IGetCursorPos)DetourFindFunction("user32.dll", "GetCursorPos");
g_oShowCursor = (IShowCursor )DetourFindFunction("user32.dll", "ShowCursor" );
}
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// Input
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI HGetCursorPos(LPPOINT lpPoint)
{
if (g_bBlockInput)
{
assert(lpPoint != nullptr);
*lpPoint = g_pLastCursorPos;
}
return g_oGetCursorPos(lpPoint);
}
BOOL WINAPI HSetCursorPos(int X, int Y)
{
g_pLastCursorPos.x = X;
g_pLastCursorPos.y = Y;
if (g_bBlockInput)
{
return TRUE;
}
return g_oSetCursorPos(X, Y);
}
BOOL WINAPI HClipCursor(const RECT* lpRect)
{
if (g_bBlockInput)
{
lpRect = nullptr;
}
return g_oClipCursor(lpRect);
}
BOOL WINAPI HShowCursor(BOOL bShow)
{
if (g_bBlockInput)
{
bShow = TRUE;
}
return g_oShowCursor(bShow);
}
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// Management
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
void InstallIPHooks()
{
SetupIPHooks();
///////////////////////////////////////////////////////////////////////////
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
///////////////////////////////////////////////////////////////////////////
DetourAttach(&(LPVOID&)g_oGetCursorPos, (PBYTE)HGetCursorPos);
DetourAttach(&(LPVOID&)g_oSetCursorPos, (PBYTE)HSetCursorPos);
DetourAttach(&(LPVOID&)g_oClipCursor, (PBYTE)HClipCursor);
DetourAttach(&(LPVOID&)g_oShowCursor, (PBYTE)HShowCursor);
///////////////////////////////////////////////////////////////////////////
DetourTransactionCommit();
}
void RemoveIPHooks()
{
///////////////////////////////////////////////////////////////////////////
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
///////////////////////////////////////////////////////////////////////////
DetourDetach(&(LPVOID&)g_oGetCursorPos, (PBYTE)HGetCursorPos);
DetourDetach(&(LPVOID&)g_oSetCursorPos, (PBYTE)HSetCursorPos);
DetourDetach(&(LPVOID&)g_oClipCursor, (PBYTE)HClipCursor);
DetourDetach(&(LPVOID&)g_oShowCursor, (PBYTE)HShowCursor);
///////////////////////////////////////////////////////////////////////////
DetourTransactionCommit();
}