From c1738ce42bc2a55a16a192ffeb6c77a0134fae09 Mon Sep 17 00:00:00 2001 From: aixxe Date: Fri, 23 Dec 2016 12:13:39 +0000 Subject: [PATCH] Replace IPanel::PaintTraverse hook with IEngineVGui::Paint. * Add example watermark text in bottom-right corner. Signed-off-by: aixxe --- include/cstrike/Interfaces/IEngineVGui.h | 26 ++++++++++++++++++ include/cstrike/cstrike.h | 1 + src/Basehook.cpp | 22 ++++++++++++--- src/Hooks/Hooks.h | 18 ++++++++----- src/Hooks/Paint.cpp | 34 ++++++++++++++++++++++++ src/Hooks/PaintTraverse.cpp | 11 -------- 6 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 include/cstrike/Interfaces/IEngineVGui.h create mode 100644 src/Hooks/Paint.cpp delete mode 100644 src/Hooks/PaintTraverse.cpp diff --git a/include/cstrike/Interfaces/IEngineVGui.h b/include/cstrike/Interfaces/IEngineVGui.h new file mode 100644 index 0000000..df1dcc0 --- /dev/null +++ b/include/cstrike/Interfaces/IEngineVGui.h @@ -0,0 +1,26 @@ +#pragma once + +enum VGuiPanel_t { + PANEL_ROOT = 0, + PANEL_GAMEUIDLL, + PANEL_CLIENTDLL, + PANEL_TOOLS, + PANEL_INGAMESCREENS, + PANEL_GAMEDLL, + PANEL_CLIENTDLL_TOOLS +}; + +enum PaintMode_t { + PAINT_UIPANELS = (1 << 0), + PAINT_INGAMEPANELS = (1 << 1), + PAINT_CURSOR = (1 << 2) +}; + +class IEngineVGui { + public: + virtual ~IEngineVGui(void) {}; + virtual VPANEL GetPanel(VGuiPanel_t type) = 0; + virtual bool IsGameUIVisible() = 0; +}; + +extern IEngineVGui* enginevgui; \ No newline at end of file diff --git a/include/cstrike/cstrike.h b/include/cstrike/cstrike.h index 3af392d..36ea3d8 100644 --- a/include/cstrike/cstrike.h +++ b/include/cstrike/cstrike.h @@ -31,6 +31,7 @@ #include "Interfaces/ICvar.h" #include "Interfaces/IPanel.h" #include "Interfaces/ISurface.h" +#include "Interfaces/IEngineVGui.h" #include "Interfaces/IVModelInfo.h" #include "Interfaces/ILauncherMgr.h" #include "Interfaces/IInputSystem.h" diff --git a/src/Basehook.cpp b/src/Basehook.cpp index 30638be..dd60df8 100644 --- a/src/Basehook.cpp +++ b/src/Basehook.cpp @@ -24,6 +24,7 @@ ICvar* cvar = nullptr; IPanel* panel = nullptr; ISurface* matsurface = nullptr; +IEngineVGui* enginevgui = nullptr; IVModelInfoClient* modelinfo = nullptr; ILauncherMgr* launchermgr = nullptr; IInputSystem* inputsystem = nullptr; @@ -41,9 +42,12 @@ CGlobalVarsBase* globalvars = nullptr; CRC32_ProcessBufferFn CRC32_ProcessBuffer = NULL; +StartDrawing_t StartDrawing = NULL; +FinishDrawing_t FinishDrawing = NULL; + std::unique_ptr sdl_hook; -std::unique_ptr panel_hook; std::unique_ptr clientdll_hook; +std::unique_ptr enginevgui_hook; std::unique_ptr modelrender_hook; std::unique_ptr inputinternal_hook; @@ -52,6 +56,7 @@ extern "C" void __attribute__((constructor)) css_basehook_open() { cvar = GetInterface("bin/libvstdlib.so", "VEngineCvar0"); panel = GetInterface("bin/vgui2.so", "VGUI_Panel0"); matsurface = GetInterface("bin/vguimatsurface.so", "VGUI_Surface0"); + enginevgui = GetInterface("bin/engine.so", "VEngineVGui0"); modelinfo = GetInterface("bin/engine.so", "VModelInfoClient0"); inputsystem = GetInterface("bin/inputsystem.so", "InputSystemVersion0"); inputinternal = GetInterface("bin/vgui2.so", "VGUI_InputInternal0"); @@ -73,9 +78,18 @@ extern "C" void __attribute__((constructor)) css_basehook_open() { clientdll_hook->HookFunction(reinterpret_cast(Hooks::CreateMove), 21); clientdll_hook->HookFunction(reinterpret_cast(Hooks::FrameStageNotify), 35); - // Hook 'PaintTraverse' from IPanel. - panel_hook = std::make_unique(panel); - panel_hook->HookFunction(reinterpret_cast(Hooks::PaintTraverse), 42); + // Scan for 'StartDrawing' and 'FinishDrawing' from CMatSystemSurface. + StartDrawing = reinterpret_cast( + FindPattern("bin/vguimatsurface.so", "\x55\x89\xE5\x53\x83\xEC\x74\x80\x3D\x00\x00\x00\x00\x00", "xxxxxxxxx????x") + ); + + FinishDrawing = reinterpret_cast( + FindPattern("bin/vguimatsurface.so", "\x55\x89\xE5\x53\x83\xEC\x24\xC7\x04\x00\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xA1", "xxxxxxxxx????xx????x") + ); + + // Hook 'Paint' from IEngineVGui. + enginevgui_hook = std::make_unique(enginevgui); + enginevgui_hook->HookFunction(reinterpret_cast(Hooks::Paint), 14); // Hook 'DrawModelExecute' from IVModelRender. modelrender_hook = std::make_unique(modelrender); diff --git a/src/Hooks/Hooks.h b/src/Hooks/Hooks.h index 36ffe5b..7dba594 100644 --- a/src/Hooks/Hooks.h +++ b/src/Hooks/Hooks.h @@ -3,20 +3,24 @@ #include "../Basehook.h" #include "../GUI/GUI.h" +// Extra functions neccessary for proper engine drawing. +typedef void (*StartDrawing_t) (ISurface*); +typedef void (*FinishDrawing_t) (ISurface*); + namespace Hooks { + // ILauncherMgr + void PumpWindowsMessageLoop(ILauncherMgr*); + void ShowPixels(ILauncherMgr*, CShowPixelsParams*); + // IBaseClientDLL void CreateMove(IBaseClientDLL*, int, float, bool); void FrameStageNotify(IBaseClientDLL*, ClientFrameStage_t); - // IPanel - void PaintTraverse(IPanel*, VPANEL, bool, bool); + // IEngineVGui + void Paint(IEngineVGui*, PaintMode_t); // IVModelRender void DrawModelExecute(IVModelRender*, DrawModelState_t const&, ModelRenderInfo_t const&, matrix3x4_t*); - - // ILauncherMgr - void PumpWindowsMessageLoop(ILauncherMgr*); - void ShowPixels(ILauncherMgr*, CShowPixelsParams*); // IInputInternal void SetKeyCodeState(IInputInternal*, KeyCode, bool); @@ -24,7 +28,7 @@ namespace Hooks { } extern std::unique_ptr sdl_hook; -extern std::unique_ptr panel_hook; extern std::unique_ptr clientdll_hook; +extern std::unique_ptr enginevgui_hook; extern std::unique_ptr modelrender_hook; extern std::unique_ptr inputinternal_hook; \ No newline at end of file diff --git a/src/Hooks/Paint.cpp b/src/Hooks/Paint.cpp new file mode 100644 index 0000000..cacb203 --- /dev/null +++ b/src/Hooks/Paint.cpp @@ -0,0 +1,34 @@ +#include "Hooks.h" + +extern StartDrawing_t StartDrawing; +extern FinishDrawing_t FinishDrawing; + +typedef void (*Paint_t) (IEngineVGui*, PaintMode_t); + +void Hooks::Paint(IEngineVGui* thisptr, PaintMode_t mode) { + // Get the original function and store it statically. + static Paint_t oPaint = enginevgui_hook->GetOriginalFunction(14); + + // Call original 'IEngineVGui::Paint'. + oPaint(thisptr, mode); + + if (mode & PaintMode_t::PAINT_UIPANELS) { + StartDrawing(matsurface); + + // Set watermark text. + const wchar_t* watermark = L"cstrike-basehook-linux"; + + // Set position of watermark text. (bottom-right) + int width = 0, height = 0, wide = 0, tall = 0; + engine->GetScreenSize(width, height); + matsurface->GetTextSize(37, watermark, wide, tall); + + // Do stuff here then call FinishDrawing. + matsurface->DrawSetTextColor(Color(150, 150, 255)); + matsurface->DrawSetTextPos((width - wide) - 15, (height - tall) - 15); + matsurface->DrawSetTextFont(37); + matsurface->DrawPrintText(L"cstrike-basehook-linux", 23); + + FinishDrawing(matsurface); + } +} \ No newline at end of file diff --git a/src/Hooks/PaintTraverse.cpp b/src/Hooks/PaintTraverse.cpp deleted file mode 100644 index 9eca49a..0000000 --- a/src/Hooks/PaintTraverse.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "Hooks.h" - -typedef void (*PaintTraverse_t) (IPanel*, VPANEL, bool, bool); - -void Hooks::PaintTraverse(IPanel* thisptr, VPANEL vpanel, bool force_repaint, bool allow_force) { - // Get the original function and store it statically. - static PaintTraverse_t oPaintTraverse = panel_hook->GetOriginalFunction(42); - - // Call original 'IPanel::PaintTraverse'. - oPaintTraverse(thisptr, vpanel, force_repaint, allow_force); -} \ No newline at end of file