Skip to content

Commit f279423

Browse files
authored
Merge pull request #187 from orange-cpp/feature/hooking
Feature/hooking
2 parents 7e55b1d + 0515236 commit f279423

12 files changed

Lines changed: 1329 additions & 12 deletions

File tree

CMakeLists.txt

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
cmake_minimum_required(VERSION 3.26)
2-
32
file(READ VERSION OMATH_VERSION)
43
project(omath VERSION ${OMATH_VERSION} LANGUAGES CXX)
54

@@ -31,9 +30,10 @@ option(OMATH_SUPRESS_SAFETY_CHECKS
3130
option(OMATH_ENABLE_COVERAGE "Enable coverage" OFF)
3231
option(OMATH_ENABLE_FORCE_INLINE
3332
"Will for compiler to make some functions to be force inlined no matter what" ON)
34-
3533
option(OMATH_ENABLE_LUA
3634
"omath bindings for lua" OFF)
35+
option(OMATH_ENABLE_HOOKING "omath will HooksManager that can hook DirectX automatically" OFF)
36+
3737
if(VCPKG_MANIFEST_FEATURES)
3838
foreach(omath_feature IN LISTS VCPKG_MANIFEST_FEATURES)
3939
if(omath_feature STREQUAL "imgui")
@@ -48,6 +48,8 @@ if(VCPKG_MANIFEST_FEATURES)
4848
set(OMATH_BUILD_EXAMPLES ON)
4949
elseif(omath_feature STREQUAL "lua")
5050
set(OMATH_ENABLE_LUA ON)
51+
elseif(omath_feature STREQUAL "hooking")
52+
set(OMATH_ENABLE_HOOKING ON)
5153
endif()
5254

5355
endforeach()
@@ -80,6 +82,10 @@ if(${PROJECT_IS_TOP_LEVEL})
8082
message(STATUS "[${PROJECT_NAME}]: Lua feature status ${OMATH_ENABLE_LUA}")
8183
endif()
8284

85+
if(OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
86+
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "" FORCE)
87+
endif()
88+
8389
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
8490
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
8591

@@ -100,6 +106,17 @@ if (OMATH_ENABLE_LUA)
100106
target_include_directories(${PROJECT_NAME} PRIVATE ${SOL2_INCLUDE_DIRS})
101107
endif ()
102108

109+
if (OMATH_ENABLE_HOOKING)
110+
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_HOOKING)
111+
112+
find_package(safetyhook CONFIG REQUIRED)
113+
target_link_libraries(${PROJECT_NAME} PRIVATE safetyhook::safetyhook)
114+
115+
if (WIN32)
116+
target_link_libraries(${PROJECT_NAME} PRIVATE d3d9 d3d11 d3d12 dxgi)
117+
endif ()
118+
endif ()
119+
103120
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
104121

105122
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_VERSION="${PROJECT_VERSION}")
@@ -147,10 +164,6 @@ set_target_properties(
147164
CXX_STANDARD 23
148165
CXX_STANDARD_REQUIRED ON)
149166

150-
if(OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
151-
set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY
152-
"MultiThreaded$<$<CONFIG:Debug>:Debug>")
153-
endif()
154167

155168
if(OMATH_USE_AVX2)
156169
if(MSVC)

CMakePresets.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656
"hidden": true,
5757
"inherits": ["windows-base", "vcpkg-base"],
5858
"cacheVariables": {
59-
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
59+
"VCPKG_TARGET_TRIPLET": "x64-windows-static",
60+
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples;hooking",
61+
"OMATH_STATIC_MSVC_RUNTIME_LIBRARY": "ON"
6062
}
6163
},
6264
{
@@ -89,9 +91,10 @@
8991
"strategy": "external"
9092
},
9193
"cacheVariables": {
92-
"VCPKG_TARGET_TRIPLET": "x86-windows",
94+
"VCPKG_TARGET_TRIPLET": "x86-windows-static",
9395
"VCPKG_HOST_TRIPLET": "x64-windows",
94-
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
96+
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples",
97+
"OMATH_STATIC_MSVC_RUNTIME_LIBRARY": "ON"
9598
}
9699
},
97100
{
@@ -114,9 +117,10 @@
114117
"strategy": "external"
115118
},
116119
"cacheVariables": {
117-
"VCPKG_TARGET_TRIPLET": "arm64-windows",
118-
"VCPKG_HOST_TRIPLET": "arm64-windows",
119-
"VCPKG_MANIFEST_FEATURES": "tests;imgui;examples"
120+
"VCPKG_TARGET_TRIPLET": "arm64-windows-static",
121+
"VCPKG_HOST_TRIPLET": "arm64-windows-static",
122+
"VCPKG_MANIFEST_FEATURES": "tests;imgui;examples",
123+
"OMATH_STATIC_MSVC_RUNTIME_LIBRARY": "ON"
120124
}
121125
},
122126
{

examples/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ add_subdirectory(example_proj_mat_builder)
44
add_subdirectory(example_signature_scan)
55
add_subdirectory(example_hud)
66

7+
if(OMATH_ENABLE_HOOKING AND WIN32)
8+
# Requires imgui with dx9-binding, dx11-binding, dx12-binding, win32-binding.
9+
# Install via: vcpkg install imgui[dx9-binding,dx11-binding,dx12-binding,win32-binding]
10+
find_package(imgui CONFIG QUIET)
11+
if(imgui_FOUND)
12+
add_subdirectory(example_dx9_hook)
13+
add_subdirectory(example_dx11_hook)
14+
add_subdirectory(example_dx12_hook)
15+
else()
16+
message(STATUS "[omath] imgui not found — DX hook examples skipped")
17+
endif()
18+
endif()
19+
720
if(OMATH_ENABLE_VALGRIND)
821
omath_setup_valgrind(example_projection_matrix_builder)
922
omath_setup_valgrind(example_signature_scan)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
project(example_dx11_hook)
2+
3+
add_library(${PROJECT_NAME} SHARED dllmain.cpp)
4+
5+
set_target_properties(${PROJECT_NAME} PROPERTIES
6+
CXX_STANDARD 23
7+
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
8+
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
9+
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
10+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}")
11+
12+
find_package(imgui CONFIG REQUIRED)
13+
target_link_libraries(${PROJECT_NAME} PRIVATE omath::omath imgui::imgui d3d11 dxgi)
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include <Windows.h>
2+
#include <d3d11.h>
3+
#include <dxgi.h>
4+
#include <imgui.h>
5+
#include <imgui_impl_dx11.h>
6+
#include <imgui_impl_win32.h>
7+
8+
#include "omath/hooks/hooks_manager.hpp"
9+
10+
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM);
11+
12+
namespace
13+
{
14+
bool g_initialized = false;
15+
bool g_init_attempted = false;
16+
17+
ID3D11Device* g_device = nullptr;
18+
ID3D11DeviceContext* g_context = nullptr;
19+
ID3D11RenderTargetView* g_render_target_view = nullptr;
20+
21+
void create_render_target(IDXGISwapChain* swap_chain)
22+
{
23+
ID3D11Texture2D* back_buffer = nullptr;
24+
if (FAILED(swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer))))
25+
return;
26+
g_device->CreateRenderTargetView(back_buffer, nullptr, &g_render_target_view);
27+
back_buffer->Release();
28+
}
29+
30+
void init(IDXGISwapChain* swap_chain)
31+
{
32+
g_init_attempted = true;
33+
34+
if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&g_device))))
35+
return;
36+
37+
g_device->GetImmediateContext(&g_context);
38+
39+
DXGI_SWAP_CHAIN_DESC desc{};
40+
swap_chain->GetDesc(&desc);
41+
42+
create_render_target(swap_chain);
43+
44+
ImGui::CreateContext();
45+
ImGui::StyleColorsDark();
46+
ImGui::GetIO().IniFilename = nullptr;
47+
ImGui::GetIO().LogFilename = nullptr;
48+
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
49+
50+
ImGui_ImplWin32_Init(desc.OutputWindow);
51+
ImGui_ImplDX11_Init(g_device, g_context);
52+
53+
auto& mgr = omath::hooks::HooksManager::get();
54+
mgr.set_on_wnd_proc([](HWND h, UINT msg, WPARAM wp, LPARAM lp) -> std::optional<LRESULT> {
55+
if (ImGui_ImplWin32_WndProcHandler(h, msg, wp, lp))
56+
return 0;
57+
return std::nullopt;
58+
});
59+
mgr.hook_wnd_proc(desc.OutputWindow);
60+
61+
g_initialized = true;
62+
}
63+
64+
void on_present(IDXGISwapChain* swap_chain, UINT, UINT)
65+
{
66+
if (!g_initialized)
67+
{
68+
if (!g_init_attempted)
69+
init(swap_chain);
70+
return;
71+
}
72+
73+
if (!g_render_target_view)
74+
create_render_target(swap_chain);
75+
76+
g_context->OMSetRenderTargets(1, &g_render_target_view, nullptr);
77+
78+
ImGui_ImplDX11_NewFrame();
79+
ImGui_ImplWin32_NewFrame();
80+
ImGui::NewFrame();
81+
82+
ImGui::SetNextWindowSize({300.f, 80.f}, ImGuiCond_Once);
83+
ImGui::SetNextWindowPos({10.f, 10.f}, ImGuiCond_Once);
84+
ImGui::Begin("omath | DX11 hook");
85+
ImGui::Text("Hook active");
86+
ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate);
87+
ImGui::End();
88+
89+
ImGui::Render();
90+
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
91+
}
92+
93+
void on_resize_buffers(IDXGISwapChain*, UINT, UINT, UINT, DXGI_FORMAT, UINT)
94+
{
95+
if (g_render_target_view)
96+
{
97+
g_render_target_view->Release();
98+
g_render_target_view = nullptr;
99+
}
100+
}
101+
} // namespace
102+
103+
BOOL WINAPI DllMain(HINSTANCE h_instance, DWORD reason, LPVOID)
104+
{
105+
if (reason == DLL_PROCESS_ATTACH)
106+
{
107+
DisableThreadLibraryCalls(h_instance);
108+
CreateThread(nullptr, 0, [](LPVOID) -> DWORD
109+
{
110+
while (!GetModuleHandle("d3d11.dll"))
111+
Sleep(100);
112+
113+
auto& mgr = omath::hooks::HooksManager::get();
114+
mgr.set_on_present(on_present);
115+
mgr.set_on_resize_buffers(on_resize_buffers);
116+
mgr.hook_dx11();
117+
return 0;
118+
}, nullptr, 0, nullptr);
119+
}
120+
else if (reason == DLL_PROCESS_DETACH)
121+
{
122+
auto& mgr = omath::hooks::HooksManager::get();
123+
mgr.unhook_wnd_proc();
124+
mgr.unhook_dx11();
125+
126+
if (g_initialized)
127+
{
128+
ImGui_ImplDX11_Shutdown();
129+
ImGui_ImplWin32_Shutdown();
130+
ImGui::DestroyContext();
131+
}
132+
133+
if (g_render_target_view) { g_render_target_view->Release(); g_render_target_view = nullptr; }
134+
if (g_context) { g_context->Release(); g_context = nullptr; }
135+
if (g_device) { g_device->Release(); g_device = nullptr; }
136+
}
137+
return TRUE;
138+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
project(example_dx12_hook)
2+
3+
add_library(${PROJECT_NAME} MODULE dllmain.cpp)
4+
5+
set_target_properties(${PROJECT_NAME} PROPERTIES
6+
CXX_STANDARD 23
7+
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
8+
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
9+
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
10+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}")
11+
12+
find_package(imgui CONFIG REQUIRED)
13+
target_link_libraries(${PROJECT_NAME} PRIVATE omath::omath imgui::imgui d3d12 dxgi)

0 commit comments

Comments
 (0)