├── .gitignore
├── DX11-Base.sln
├── DX11-Base.vcxproj
├── DX11-Base.vcxproj.filters
├── DX11-Base.vcxproj.user
├── README.md
├── Source.cpp
├── dllmain.cpp
├── include
├── Engine.h
├── Menu.h
└── helper.h
├── libs
├── ImGui
│ ├── imconfig.h
│ ├── imgui.cpp
│ ├── imgui.h
│ ├── imgui_demo.cpp
│ ├── imgui_draw.cpp
│ ├── imgui_impl_dx11.cpp
│ ├── imgui_impl_dx11.h
│ ├── imgui_impl_win32.cpp
│ ├── imgui_impl_win32.h
│ ├── imgui_internal.h
│ ├── imgui_tables.cpp
│ ├── imgui_widgets.cpp
│ ├── imstb_rectpack.h
│ ├── imstb_textedit.h
│ └── imstb_truetype.h
└── MinHook
│ ├── MinHook.h
│ ├── buffer.c
│ ├── buffer.h
│ ├── framework.h
│ ├── hde32.c
│ ├── hde32.h
│ ├── hde64.c
│ ├── hde64.h
│ ├── hook.c
│ ├── hookmain.cpp
│ ├── hookmain.h
│ ├── minhook.def
│ ├── pstdint.h
│ ├── resource.h
│ ├── table32.h
│ ├── table64.h
│ ├── trampoline.c
│ └── trampoline.h
├── pch.cpp
├── pch.h
└── src
├── Engine.cpp
└── Menu.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # exclude binaries and debug output
2 | .vs/
3 | bin/
4 | debug/
5 | x64/
6 |
7 | # exclude personal settings
8 | *.sln
9 | *.vcxproj
10 | *.vcxproj.filters
11 | *.vcxproj.user
--------------------------------------------------------------------------------
/DX11-Base.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.32802.440
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DX11-Base", "DX11-Base.vcxproj", "{EB52DDF1-EFC4-4222-9D86-6918D4D891A5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Debug|x64.ActiveCfg = Debug|x64
17 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Debug|x64.Build.0 = Debug|x64
18 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Debug|x86.ActiveCfg = Debug|Win32
19 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Debug|x86.Build.0 = Debug|Win32
20 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Release|x64.ActiveCfg = Release|x64
21 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Release|x64.Build.0 = Release|x64
22 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Release|x86.ActiveCfg = Release|Win32
23 | {EB52DDF1-EFC4-4222-9D86-6918D4D891A5}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {B522717A-560B-4AB3-847D-7B56D37A9422}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/DX11-Base.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {eb52ddf1-efc4-4222-9d86-6918d4d891a5}
25 | DX11Base
26 | 10.0
27 |
28 |
29 |
30 | DynamicLibrary
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | DynamicLibrary
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | DynamicLibrary
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | DynamicLibrary
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 | $(SolutionDir)\bin
82 | $(ProjectName)d
83 |
84 |
85 | false
86 | $(SolutionDir)\bin
87 |
88 |
89 |
90 | Level3
91 | true
92 | WIN32;_DEBUG;DX11BASE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
93 | true
94 | Use
95 | pch.h
96 | stdcpplatest
97 | stdc17
98 |
99 |
100 | Windows
101 | true
102 | false
103 |
104 |
105 |
106 |
107 | Level3
108 | true
109 | true
110 | true
111 | WIN32;NDEBUG;DX11BASE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
112 | true
113 | Use
114 | pch.h
115 | stdcpplatest
116 | stdc17
117 |
118 |
119 | Windows
120 | true
121 | true
122 | true
123 | false
124 |
125 |
126 |
127 |
128 | Level3
129 | true
130 | _DEBUG;DX11BASE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
131 | true
132 | Use
133 | pch.h
134 | stdcpplatest
135 | stdc17
136 | $(SolutionDir)\include;$(SolutionDir);%(AdditionalIncludeDirectories)
137 |
138 |
139 | Windows
140 | true
141 | false
142 |
143 |
144 |
145 |
146 | Level3
147 | true
148 | true
149 | true
150 | NDEBUG;DX11BASE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
151 | true
152 | Use
153 | pch.h
154 | stdcpplatest
155 | stdc17
156 | $(SolutionDir)\include;$(SolutionDir);%(AdditionalIncludeDirectories)
157 |
158 |
159 | Windows
160 | true
161 | true
162 | true
163 | false
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | NotUsing
187 | NotUsing
188 |
189 |
190 | NotUsing
191 | NotUsing
192 |
193 |
194 | NotUsing
195 | NotUsing
196 |
197 |
198 | NotUsing
199 | NotUsing
200 |
201 |
202 | NotUsing
203 | NotUsing
204 |
205 |
206 | NotUsing
207 | NotUsing
208 |
209 |
210 | NotUsing
211 | NotUsing
212 |
213 |
214 | NotUsing
215 | NotUsing
216 | NotUsing
217 | NotUsing
218 |
219 |
220 | NotUsing
221 | NotUsing
222 | NotUsing
223 | NotUsing
224 |
225 |
226 | NotUsing
227 | NotUsing
228 | NotUsing
229 | NotUsing
230 |
231 |
232 | NotUsing
233 | NotUsing
234 | NotUsing
235 | NotUsing
236 |
237 |
238 | ../../pch.h
239 | ../../pch.h
240 | ../../pch.h
241 | ../../pch.h
242 |
243 |
244 | NotUsing
245 | NotUsing
246 | NotUsing
247 | NotUsing
248 |
249 |
250 | Create
251 | Create
252 | Create
253 | Create
254 |
255 |
256 |
257 | ../pch.h
258 | ../pch.h
259 | pch.h
260 | pch.h
261 |
262 |
263 | ../pch.h
264 | ../pch.h
265 | pch.h
266 | pch.h
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
--------------------------------------------------------------------------------
/DX11-Base.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {bd048e89-cc04-46ca-b539-1e22ffdd7ffc}
18 |
19 |
20 | {3a66d50b-1885-4c33-bc49-7bb2255e62fb}
21 |
22 |
23 | {4d1f2a92-a48e-45e5-a07c-42fa558f6919}
24 |
25 |
26 | {d55590e2-04e5-427a-a959-6dcc763f2f71}
27 |
28 |
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files\Class
38 |
39 |
40 | Header Files\Class
41 |
42 |
43 | Resource Files\MinHook
44 |
45 |
46 | Resource Files\MinHook
47 |
48 |
49 | Resource Files\MinHook
50 |
51 |
52 | Resource Files\MinHook
53 |
54 |
55 | Resource Files\MinHook
56 |
57 |
58 | Resource Files\MinHook
59 |
60 |
61 | Resource Files\MinHook
62 |
63 |
64 | Resource Files\MinHook
65 |
66 |
67 | Resource Files\MinHook
68 |
69 |
70 | Resource Files\MinHook
71 |
72 |
73 | Resource Files\MinHook
74 |
75 |
76 |
77 |
78 | Source Files
79 |
80 |
81 | Source Files
82 |
83 |
84 | Source Files\Class
85 |
86 |
87 | Source Files\Class
88 |
89 |
90 | Resource Files\MinHook
91 |
92 |
93 | Resource Files\MinHook
94 |
95 |
96 | Resource Files\MinHook
97 |
98 |
99 | Resource Files\MinHook
100 |
101 |
102 | Resource Files\MinHook
103 |
104 |
105 | Resource Files\MinHook
106 |
107 |
108 | Resource Files\ImGui
109 |
110 |
111 | Resource Files\ImGui
112 |
113 |
114 | Resource Files\ImGui
115 |
116 |
117 | Resource Files\ImGui
118 |
119 |
120 | Resource Files\ImGui
121 |
122 |
123 | Resource Files\ImGui
124 |
125 |
126 | Resource Files\ImGui
127 |
128 |
129 | Source Files
130 |
131 |
132 |
133 |
134 | Resource Files\MinHook
135 |
136 |
137 | Source Files
138 |
139 |
140 |
--------------------------------------------------------------------------------
/DX11-Base.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DX11-ImGui-Internal-Hook
2 | Complete DX11 Internal Hook w/ Dear ImGui
3 |
4 | 
5 |
6 | ## Usage Examples
7 | [Palworld Internal](https://github.com/NightFyre/Palworld-Internal)
8 | [Final Fantasy 7 Remake Internal](https://github.com/xCENTx/FF7RemakeInternal)
9 |
10 | ## External Library Credits
11 | [Dear ImGui](https://github.com/ocornut/imgui)
12 | [MinHook](https://github.com/TsudaKageyu/minhook)
--------------------------------------------------------------------------------
/Source.cpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | using namespace DX11Base;
6 |
7 | void ClientBGThread()
8 | {
9 | while (g_Running)
10 | {
11 | Menu::Loops();
12 |
13 | if (g_KillSwitch)
14 | {
15 | g_D3D11Window->UnhookD3D();
16 | g_Hooking->Shutdown();
17 | g_Engine.release(); // releases all created class instances
18 | g_Running = false;
19 | }
20 |
21 | std::this_thread::sleep_for(1ms);
22 | std::this_thread::yield();
23 | }
24 | }
25 |
26 | DWORD WINAPI MainThread_Initialize(LPVOID dwModule)
27 | {
28 | UNREFERENCED_PARAMETER(dwModule);
29 |
30 | g_Engine = std::make_unique();
31 | g_Console->InitializeConsole("DEBUG CONSOLE", true);
32 | g_Engine->Init();
33 | g_D3D11Window->HookD3D(); //
34 | g_Hooking->Initialize();
35 |
36 |
37 | // INITIALIZE BACKGROUND THREAD
38 | std::thread WCMUpdate(ClientBGThread); //
39 |
40 | // RENDER LOOP
41 | g_Running = true;
42 | static int LastTick = 0;
43 | while (g_Running)
44 | {
45 | if ((Engine::GamePadGetKeyState(XINPUT_GAMEPAD_RIGHT_THUMB | XINPUT_GAMEPAD_LEFT_THUMB) || Engine::GetKeyState(VK_INSERT, 0)) && ((GetTickCount64() - LastTick) > 500))
46 | {
47 | g_Engine->bShowMenu = !g_Engine->bShowMenu; // Main Menu Window
48 | g_Engine->bShowHud = !g_Engine->bShowMenu; // Render Window
49 | LastTick = GetTickCount64();
50 | }
51 |
52 | std::this_thread::sleep_for(1ms);
53 | std::this_thread::yield();
54 | }
55 |
56 | // EXIT
57 | WCMUpdate.join(); // Exit Loops Thread
58 | FreeLibraryAndExitThread(g_hModule, EXIT_SUCCESS); //
59 | return EXIT_SUCCESS;
60 | }
--------------------------------------------------------------------------------
/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwCallReason, LPVOID lpReserved)
6 | {
7 | UNREFERENCED_PARAMETER(lpReserved);
8 |
9 | if (dwCallReason == DLL_PROCESS_ATTACH)
10 | {
11 | DX11Base::g_hModule = hModule;
12 |
13 | DisableThreadLibraryCalls(hModule);
14 |
15 | HANDLE hThread = CreateThread(0, 0, MainThread_Initialize, DX11Base::g_hModule, 0, 0);
16 |
17 | if (hThread)
18 | CloseHandle(hThread);
19 | }
20 |
21 | return TRUE;
22 | }
--------------------------------------------------------------------------------
/include/Engine.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "helper.h"
3 |
4 | namespace DX11Base
5 | {
6 | class Engine
7 | {
8 | public:
9 |
10 | // PROCESS & WINDOW
11 | int mGamePID{ 0 };
12 | HMODULE pGameModule{ 0 };
13 | __int64 pGameBaseAddr{ 0 };
14 | HANDLE pGameHandle{ 0 };
15 | HWND pGameWindow{ 0 };
16 | int mGameWidth{ 0 };
17 | int mGameHeight{ 0 };
18 | ImVec2 mWindowSize{ 0.f , 0.f };
19 | LPCSTR pGameTitle{ 0 };
20 | LPCSTR pClassName{ 0 };
21 | LPCSTR pGamePath{ 0 };
22 |
23 | // MENU
24 | bool bShowMenu{ false };
25 | bool bShowHud{ false };
26 | bool bShowDemo{ false };
27 | bool bShowDemoWindow{ false };
28 | bool bShowStyleEditor{ false };
29 |
30 | public:
31 | void Init();
32 |
33 | public:
34 | static bool GetKeyState(WORD vKey, SHORT delta);
35 | static bool GamePadGetKeyState(WORD vButton);
36 |
37 | // constructor
38 | Engine();
39 | ~Engine();
40 | };
41 | inline std::unique_ptr g_Engine;
42 |
43 | class Console
44 | {
45 | public:
46 | enum EColors : int
47 | {
48 | EColor_dark_blue = 1,
49 | EColor_dark_green,
50 | EColor_dark_teal,
51 | EColor_dark_red,
52 | EColor_dark_pink,
53 | EColor_dark_yellow,
54 | EColor_dark_white,
55 | EColor_dark_gray,
56 | EColor_blue,
57 | EColor_green,
58 | EColor_teal,
59 | EColor_red,
60 | EColor_pink,
61 | EColor_yellow,
62 | EColor_white,
63 | EColor_DEFAULT = EColor_white
64 | };
65 |
66 | public:
67 | static FILE* pOutStream;
68 | static bool bInit;
69 | bool bShow{ false };
70 | bool bVerbose{ false };
71 |
72 | public:
73 | void InitializeConsole(const char* ConsoleName, bool bShowWindow = true);
74 | void cLog(const char* fmt, const EColors Color = EColor_DEFAULT, ...);
75 | void LogError(const char* fmt, ...);
76 | void DestroyConsole();
77 | void SetConsoleVisibility(bool bShow);
78 | HANDLE GetHandle();
79 | HWND GetWindowHandle();
80 |
81 | public:
82 | static void Log(const char* fmt, ...);
83 | static void Clear();
84 |
85 | public:
86 | explicit Console();
87 | Console(const char* title);
88 | Console(const char* title, bool bShow);
89 | ~Console();
90 |
91 | private:
92 | HANDLE pHandle{};
93 | HWND pHwnd{};
94 | };
95 | inline std::unique_ptr g_Console;
96 |
97 | class D3D11Window
98 | {
99 | public:
100 | enum DXGI : int
101 | {
102 | IDXGI_PRESENT = 8,
103 | IDXGI_DRAW_INDEXED = 12,
104 | IDXGI_RESIZE_BUFFERS = 13,
105 | };
106 |
107 | public:
108 | bool bInit{ false };
109 | bool bInitImGui{ false };
110 | WNDPROC m_OldWndProc{};
111 | ImGuiContext* pImGui;
112 | ImGuiViewport* pViewport;
113 |
114 | public:
115 | bool GetD3DContext();
116 | bool HookD3D();
117 | void UnhookD3D();
118 | bool InitWindow();
119 | bool DeleteWindow();
120 | bool InitImGui(IDXGISwapChain* swapChain);
121 | void Overlay(IDXGISwapChain* pSwapChain);
122 |
123 | public:
124 | explicit D3D11Window();
125 | ~D3D11Window() noexcept;
126 |
127 | private:
128 | typedef HRESULT(WINAPI* IDXGISwapChainPresent)(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
129 | typedef void(APIENTRY* ID3D11DeviceContextDrawIndexed)(ID3D11DeviceContext* pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation);
130 | typedef HRESULT(WINAPI* IDXGISwapChainResizeBuffers)(IDXGISwapChain* pSwapChain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
131 | IDXGISwapChainPresent IDXGISwapChain_Present_stub = 0;
132 | ID3D11DeviceContextDrawIndexed ID3D11DeviceContext_DrawIndexed_stub = 0;
133 | IDXGISwapChainResizeBuffers IDXGISwapChain_ResizeBuffers_stub = 0;
134 | WNDCLASSEX WindowClass;
135 | HWND WindowHwnd;
136 | ID3D11Device* m_Device{};
137 | ID3D11DeviceContext* m_DeviceContext{};
138 | ID3D11RenderTargetView* m_RenderTargetView{};
139 | IDXGISwapChain* m_pSwapChain{};
140 |
141 |
142 | private:
143 | static LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
144 | static HRESULT APIENTRY SwapChain_Present_hook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
145 | static void APIENTRY DeviceContext_DrawIndexed_hook(ID3D11DeviceContext* pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation);
146 | static HRESULT WINAPI SwapChain_ResizeBuffers_hook(IDXGISwapChain* pSwapChain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
147 | };
148 | inline std::unique_ptr g_D3D11Window;
149 |
150 | class Hooking
151 | {
152 | public:
153 | void Initialize();
154 | void Shutdown();
155 | static bool CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID* pOrig);
156 | static void EnableHook(LPVOID pTarget);
157 | static void EnableAllHooks();
158 | static void DisableHook(LPVOID pTarget);
159 | static void RemoveHook(LPVOID pTarget);
160 | static void DisableAllHooks();
161 | static void RemoveAllHooks();
162 |
163 |
164 | public:
165 | explicit Hooking();
166 | ~Hooking() noexcept;
167 | };
168 | inline std::unique_ptr g_Hooking;
169 | }
170 |
--------------------------------------------------------------------------------
/include/Menu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "helper.h"
3 | namespace DX11Base
4 | {
5 | class Menu
6 | {
7 | public:
8 | static void Draw();
9 | static void MainMenu();
10 | static void HUD();
11 | static void Loops();
12 |
13 | // constructor
14 | Menu() noexcept = default;
15 | ~Menu() noexcept = default;
16 | };
17 |
18 | class GUI
19 | {
20 | public:
21 | // WIDGETS
22 | static void TextCentered(const char* pText);
23 | static void TextCenteredf(const char* pText, ...);
24 |
25 | public:
26 | // CANVAS
27 | static void DrawText_(ImVec2 pos, ImColor color, const char* pText, float fontSize);
28 | static void DrawTextf(ImVec2 pos, ImColor color, const char* pText, float fontSize, ...);
29 | static void DrawTextCentered(ImVec2 pos, ImColor color, const char* pText, float fontsize);
30 | static void DrawTextCenteredf(ImVec2 pos, ImColor color, const char* pText, float fontsize, ...);
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/include/helper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define DEBUG 1
3 |
4 | #include "pch.h"
5 |
6 | extern DWORD WINAPI MainThread_Initialize(LPVOID dwModule);
7 |
8 | namespace DX11Base
9 | {
10 | using namespace std::chrono_literals;
11 | inline HMODULE g_hModule{};
12 | inline std::atomic_bool g_Running{};
13 | inline std::atomic_bool g_KillSwitch = FALSE;
14 |
15 | struct Vector2
16 | {
17 | float x, y;
18 | };
19 |
20 | struct Vector3
21 | {
22 | float x, y, z;
23 | };
24 |
25 | struct Vector4
26 | {
27 | float x, y, z, w;
28 | };
29 |
30 | struct DVector2
31 | {
32 | double x, y;
33 | };
34 |
35 | struct DVector3
36 | {
37 | double x, y, z;
38 | };
39 |
40 | struct DVector4
41 | {
42 | double x, y, z, w;
43 | };
44 | }
--------------------------------------------------------------------------------
/libs/ImGui/imconfig.h:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // DEAR IMGUI COMPILE-TIME OPTIONS
3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
5 | //-----------------------------------------------------------------------------
6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
8 | //-----------------------------------------------------------------------------
9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
12 | // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
13 | //-----------------------------------------------------------------------------
14 |
15 | #pragma once
16 |
17 | //---- Define assertion handler. Defaults to calling assert().
18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
21 |
22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
26 | //#define IMGUI_API __declspec( dllexport )
27 | //#define IMGUI_API __declspec( dllimport )
28 |
29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
31 | //#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
32 |
33 | //---- Disable all of Dear ImGui or don't implement standard windows/tools.
34 | // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
35 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
36 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
37 | //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
38 |
39 | //---- Don't implement some functions to reduce linkage requirements.
40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
41 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
42 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
43 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
44 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
45 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
46 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
47 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
48 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
49 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
50 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
51 |
52 | //---- Include imgui_user.h at the end of imgui.h as a convenience
53 | // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
54 | //#define IMGUI_INCLUDE_IMGUI_USER_H
55 | //#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
56 |
57 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
58 | //#define IMGUI_USE_BGRA_PACKED_COLOR
59 |
60 | //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
61 | //#define IMGUI_USE_WCHAR32
62 |
63 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
64 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
65 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
66 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
67 | //#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
68 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
69 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
70 | //#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
71 |
72 | //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
73 | // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
74 | //#define IMGUI_USE_STB_SPRINTF
75 |
76 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
77 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
78 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
79 | //#define IMGUI_ENABLE_FREETYPE
80 |
81 | //---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
82 | // Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
83 | // Only works in combination with IMGUI_ENABLE_FREETYPE.
84 | // (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
85 | //#define IMGUI_ENABLE_FREETYPE_LUNASVG
86 |
87 | //---- Use stb_truetype to build and rasterize the font atlas (default)
88 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
89 | //#define IMGUI_ENABLE_STB_TRUETYPE
90 |
91 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
92 | // This will be inlined as part of ImVec2 and ImVec4 class declarations.
93 | /*
94 | #define IM_VEC2_CLASS_EXTRA \
95 | constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
96 | operator MyVec2() const { return MyVec2(x,y); }
97 |
98 | #define IM_VEC4_CLASS_EXTRA \
99 | constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
100 | operator MyVec4() const { return MyVec4(x,y,z,w); }
101 | */
102 | //---- ...Or use Dear ImGui's own very basic math operators.
103 | //#define IMGUI_DEFINE_MATH_OPERATORS
104 |
105 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
106 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
107 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
108 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
109 | //#define ImDrawIdx unsigned int
110 |
111 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
112 | //struct ImDrawList;
113 | //struct ImDrawCmd;
114 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
115 | //#define ImDrawCallback MyImDrawCallback
116 |
117 | //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
118 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
119 | //#define IM_DEBUG_BREAK IM_ASSERT(0)
120 | //#define IM_DEBUG_BREAK __debugbreak()
121 |
122 | //---- Debug Tools: Enable slower asserts
123 | //#define IMGUI_DEBUG_PARANOID
124 |
125 | //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
126 | /*
127 | namespace ImGui
128 | {
129 | void MyFunction(const char* name, MyMatrix44* mtx);
130 | }
131 | */
132 |
--------------------------------------------------------------------------------
/libs/ImGui/imgui_impl_dx11.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer Backend for DirectX11
2 | // This needs to be used along with a Platform Backend (e.g. Win32)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
6 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
7 |
8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
10 | // Learn about Dear ImGui:
11 | // - FAQ https://dearimgui.com/faq
12 | // - Getting Started https://dearimgui.com/getting-started
13 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
14 | // - Introduction, links and more at the top of imgui.cpp
15 |
16 | #pragma once
17 | #include "imgui.h" // IMGUI_IMPL_API
18 | #ifndef IMGUI_DISABLE
19 |
20 | struct ID3D11Device;
21 | struct ID3D11DeviceContext;
22 |
23 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
24 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
25 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
26 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
27 |
28 | // Use if you want to reset your rendering device without losing Dear ImGui state.
29 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
30 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
31 |
32 | #endif // #ifndef IMGUI_DISABLE
33 |
--------------------------------------------------------------------------------
/libs/ImGui/imgui_impl_win32.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
3 |
4 | // Implemented features:
5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
6 | // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
7 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
10 |
11 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
12 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
13 | // Learn about Dear ImGui:
14 | // - FAQ https://dearimgui.com/faq
15 | // - Getting Started https://dearimgui.com/getting-started
16 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
17 | // - Introduction, links and more at the top of imgui.cpp
18 |
19 | #pragma once
20 | #include "imgui.h" // IMGUI_IMPL_API
21 | #ifndef IMGUI_DISABLE
22 |
23 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
24 | IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
25 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
26 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
27 |
28 | // Win32 message handler your application need to call.
29 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper.
30 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
31 | // - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
32 |
33 | #if 0
34 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
35 | #endif
36 |
37 | // DPI-related helpers (optional)
38 | // - Use to enable DPI awareness without having to create an application manifest.
39 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
40 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
41 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
42 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
43 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
44 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
45 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
46 |
47 | // Transparency related helpers (optional) [experimental]
48 | // - Use to enable alpha compositing transparency with the desktop.
49 | // - Use together with e.g. clearing your framebuffer with zero-alpha.
50 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
51 |
52 | #endif // #ifndef IMGUI_DISABLE
53 |
--------------------------------------------------------------------------------
/libs/ImGui/imstb_rectpack.h:
--------------------------------------------------------------------------------
1 | // [DEAR IMGUI]
2 | // This is a slightly modified version of stb_rect_pack.h 1.01.
3 | // Grep for [DEAR IMGUI] to find the changes.
4 | //
5 | // stb_rect_pack.h - v1.01 - public domain - rectangle packing
6 | // Sean Barrett 2014
7 | //
8 | // Useful for e.g. packing rectangular textures into an atlas.
9 | // Does not do rotation.
10 | //
11 | // Before #including,
12 | //
13 | // #define STB_RECT_PACK_IMPLEMENTATION
14 | //
15 | // in the file that you want to have the implementation.
16 | //
17 | // Not necessarily the awesomest packing method, but better than
18 | // the totally naive one in stb_truetype (which is primarily what
19 | // this is meant to replace).
20 | //
21 | // Has only had a few tests run, may have issues.
22 | //
23 | // More docs to come.
24 | //
25 | // No memory allocations; uses qsort() and assert() from stdlib.
26 | // Can override those by defining STBRP_SORT and STBRP_ASSERT.
27 | //
28 | // This library currently uses the Skyline Bottom-Left algorithm.
29 | //
30 | // Please note: better rectangle packers are welcome! Please
31 | // implement them to the same API, but with a different init
32 | // function.
33 | //
34 | // Credits
35 | //
36 | // Library
37 | // Sean Barrett
38 | // Minor features
39 | // Martins Mozeiko
40 | // github:IntellectualKitty
41 | //
42 | // Bugfixes / warning fixes
43 | // Jeremy Jaussaud
44 | // Fabian Giesen
45 | //
46 | // Version history:
47 | //
48 | // 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
49 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
50 | // 0.99 (2019-02-07) warning fixes
51 | // 0.11 (2017-03-03) return packing success/fail result
52 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings
53 | // 0.09 (2016-08-27) fix compiler warnings
54 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
55 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
56 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
57 | // 0.05: added STBRP_ASSERT to allow replacing assert
58 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support
59 | // 0.01: initial release
60 | //
61 | // LICENSE
62 | //
63 | // See end of file for license information.
64 |
65 | //////////////////////////////////////////////////////////////////////////////
66 | //
67 | // INCLUDE SECTION
68 | //
69 |
70 | #ifndef STB_INCLUDE_STB_RECT_PACK_H
71 | #define STB_INCLUDE_STB_RECT_PACK_H
72 |
73 | #define STB_RECT_PACK_VERSION 1
74 |
75 | #ifdef STBRP_STATIC
76 | #define STBRP_DEF static
77 | #else
78 | #define STBRP_DEF extern
79 | #endif
80 |
81 | #ifdef __cplusplus
82 | extern "C" {
83 | #endif
84 |
85 | typedef struct stbrp_context stbrp_context;
86 | typedef struct stbrp_node stbrp_node;
87 | typedef struct stbrp_rect stbrp_rect;
88 |
89 | typedef int stbrp_coord;
90 |
91 | #define STBRP__MAXVAL 0x7fffffff
92 | // Mostly for internal use, but this is the maximum supported coordinate value.
93 |
94 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
95 | // Assign packed locations to rectangles. The rectangles are of type
96 | // 'stbrp_rect' defined below, stored in the array 'rects', and there
97 | // are 'num_rects' many of them.
98 | //
99 | // Rectangles which are successfully packed have the 'was_packed' flag
100 | // set to a non-zero value and 'x' and 'y' store the minimum location
101 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left
102 | // if you imagine y increasing downwards). Rectangles which do not fit
103 | // have the 'was_packed' flag set to 0.
104 | //
105 | // You should not try to access the 'rects' array from another thread
106 | // while this function is running, as the function temporarily reorders
107 | // the array while it executes.
108 | //
109 | // To pack into another rectangle, you need to call stbrp_init_target
110 | // again. To continue packing into the same rectangle, you can call
111 | // this function again. Calling this multiple times with multiple rect
112 | // arrays will probably produce worse packing results than calling it
113 | // a single time with the full rectangle array, but the option is
114 | // available.
115 | //
116 | // The function returns 1 if all of the rectangles were successfully
117 | // packed and 0 otherwise.
118 |
119 | struct stbrp_rect
120 | {
121 | // reserved for your use:
122 | int id;
123 |
124 | // input:
125 | stbrp_coord w, h;
126 |
127 | // output:
128 | stbrp_coord x, y;
129 | int was_packed; // non-zero if valid packing
130 |
131 | }; // 16 bytes, nominally
132 |
133 |
134 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
135 | // Initialize a rectangle packer to:
136 | // pack a rectangle that is 'width' by 'height' in dimensions
137 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long
138 | //
139 | // You must call this function every time you start packing into a new target.
140 | //
141 | // There is no "shutdown" function. The 'nodes' memory must stay valid for
142 | // the following stbrp_pack_rects() call (or calls), but can be freed after
143 | // the call (or calls) finish.
144 | //
145 | // Note: to guarantee best results, either:
146 | // 1. make sure 'num_nodes' >= 'width'
147 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
148 | //
149 | // If you don't do either of the above things, widths will be quantized to multiples
150 | // of small integers to guarantee the algorithm doesn't run out of temporary storage.
151 | //
152 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm
153 | // may run out of temporary storage and be unable to pack some rectangles.
154 |
155 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
156 | // Optionally call this function after init but before doing any packing to
157 | // change the handling of the out-of-temp-memory scenario, described above.
158 | // If you call init again, this will be reset to the default (false).
159 |
160 |
161 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
162 | // Optionally select which packing heuristic the library should use. Different
163 | // heuristics will produce better/worse results for different data sets.
164 | // If you call init again, this will be reset to the default.
165 |
166 | enum
167 | {
168 | STBRP_HEURISTIC_Skyline_default=0,
169 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
170 | STBRP_HEURISTIC_Skyline_BF_sortHeight
171 | };
172 |
173 |
174 | //////////////////////////////////////////////////////////////////////////////
175 | //
176 | // the details of the following structures don't matter to you, but they must
177 | // be visible so you can handle the memory allocations for them
178 |
179 | struct stbrp_node
180 | {
181 | stbrp_coord x,y;
182 | stbrp_node *next;
183 | };
184 |
185 | struct stbrp_context
186 | {
187 | int width;
188 | int height;
189 | int align;
190 | int init_mode;
191 | int heuristic;
192 | int num_nodes;
193 | stbrp_node *active_head;
194 | stbrp_node *free_head;
195 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
196 | };
197 |
198 | #ifdef __cplusplus
199 | }
200 | #endif
201 |
202 | #endif
203 |
204 | //////////////////////////////////////////////////////////////////////////////
205 | //
206 | // IMPLEMENTATION SECTION
207 | //
208 |
209 | #ifdef STB_RECT_PACK_IMPLEMENTATION
210 | #ifndef STBRP_SORT
211 | #include
212 | #define STBRP_SORT qsort
213 | #endif
214 |
215 | #ifndef STBRP_ASSERT
216 | #include
217 | #define STBRP_ASSERT assert
218 | #endif
219 |
220 | #ifdef _MSC_VER
221 | #define STBRP__NOTUSED(v) (void)(v)
222 | #define STBRP__CDECL __cdecl
223 | #else
224 | #define STBRP__NOTUSED(v) (void)sizeof(v)
225 | #define STBRP__CDECL
226 | #endif
227 |
228 | enum
229 | {
230 | STBRP__INIT_skyline = 1
231 | };
232 |
233 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
234 | {
235 | switch (context->init_mode) {
236 | case STBRP__INIT_skyline:
237 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
238 | context->heuristic = heuristic;
239 | break;
240 | default:
241 | STBRP_ASSERT(0);
242 | }
243 | }
244 |
245 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
246 | {
247 | if (allow_out_of_mem)
248 | // if it's ok to run out of memory, then don't bother aligning them;
249 | // this gives better packing, but may fail due to OOM (even though
250 | // the rectangles easily fit). @TODO a smarter approach would be to only
251 | // quantize once we've hit OOM, then we could get rid of this parameter.
252 | context->align = 1;
253 | else {
254 | // if it's not ok to run out of memory, then quantize the widths
255 | // so that num_nodes is always enough nodes.
256 | //
257 | // I.e. num_nodes * align >= width
258 | // align >= width / num_nodes
259 | // align = ceil(width/num_nodes)
260 |
261 | context->align = (context->width + context->num_nodes-1) / context->num_nodes;
262 | }
263 | }
264 |
265 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
266 | {
267 | int i;
268 |
269 | for (i=0; i < num_nodes-1; ++i)
270 | nodes[i].next = &nodes[i+1];
271 | nodes[i].next = NULL;
272 | context->init_mode = STBRP__INIT_skyline;
273 | context->heuristic = STBRP_HEURISTIC_Skyline_default;
274 | context->free_head = &nodes[0];
275 | context->active_head = &context->extra[0];
276 | context->width = width;
277 | context->height = height;
278 | context->num_nodes = num_nodes;
279 | stbrp_setup_allow_out_of_mem(context, 0);
280 |
281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
282 | context->extra[0].x = 0;
283 | context->extra[0].y = 0;
284 | context->extra[0].next = &context->extra[1];
285 | context->extra[1].x = (stbrp_coord) width;
286 | context->extra[1].y = (1<<30);
287 | context->extra[1].next = NULL;
288 | }
289 |
290 | // find minimum y position if it starts at x1
291 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
292 | {
293 | stbrp_node *node = first;
294 | int x1 = x0 + width;
295 | int min_y, visited_width, waste_area;
296 |
297 | STBRP__NOTUSED(c);
298 |
299 | STBRP_ASSERT(first->x <= x0);
300 |
301 | #if 0
302 | // skip in case we're past the node
303 | while (node->next->x <= x0)
304 | ++node;
305 | #else
306 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
307 | #endif
308 |
309 | STBRP_ASSERT(node->x <= x0);
310 |
311 | min_y = 0;
312 | waste_area = 0;
313 | visited_width = 0;
314 | while (node->x < x1) {
315 | if (node->y > min_y) {
316 | // raise min_y higher.
317 | // we've accounted for all waste up to min_y,
318 | // but we'll now add more waste for everything we've visted
319 | waste_area += visited_width * (node->y - min_y);
320 | min_y = node->y;
321 | // the first time through, visited_width might be reduced
322 | if (node->x < x0)
323 | visited_width += node->next->x - x0;
324 | else
325 | visited_width += node->next->x - node->x;
326 | } else {
327 | // add waste area
328 | int under_width = node->next->x - node->x;
329 | if (under_width + visited_width > width)
330 | under_width = width - visited_width;
331 | waste_area += under_width * (min_y - node->y);
332 | visited_width += under_width;
333 | }
334 | node = node->next;
335 | }
336 |
337 | *pwaste = waste_area;
338 | return min_y;
339 | }
340 |
341 | typedef struct
342 | {
343 | int x,y;
344 | stbrp_node **prev_link;
345 | } stbrp__findresult;
346 |
347 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
348 | {
349 | int best_waste = (1<<30), best_x, best_y = (1 << 30);
350 | stbrp__findresult fr;
351 | stbrp_node **prev, *node, *tail, **best = NULL;
352 |
353 | // align to multiple of c->align
354 | width = (width + c->align - 1);
355 | width -= width % c->align;
356 | STBRP_ASSERT(width % c->align == 0);
357 |
358 | // if it can't possibly fit, bail immediately
359 | if (width > c->width || height > c->height) {
360 | fr.prev_link = NULL;
361 | fr.x = fr.y = 0;
362 | return fr;
363 | }
364 |
365 | node = c->active_head;
366 | prev = &c->active_head;
367 | while (node->x + width <= c->width) {
368 | int y,waste;
369 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
370 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
371 | // bottom left
372 | if (y < best_y) {
373 | best_y = y;
374 | best = prev;
375 | }
376 | } else {
377 | // best-fit
378 | if (y + height <= c->height) {
379 | // can only use it if it first vertically
380 | if (y < best_y || (y == best_y && waste < best_waste)) {
381 | best_y = y;
382 | best_waste = waste;
383 | best = prev;
384 | }
385 | }
386 | }
387 | prev = &node->next;
388 | node = node->next;
389 | }
390 |
391 | best_x = (best == NULL) ? 0 : (*best)->x;
392 |
393 | // if doing best-fit (BF), we also have to try aligning right edge to each node position
394 | //
395 | // e.g, if fitting
396 | //
397 | // ____________________
398 | // |____________________|
399 | //
400 | // into
401 | //
402 | // | |
403 | // | ____________|
404 | // |____________|
405 | //
406 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
407 | //
408 | // This makes BF take about 2x the time
409 |
410 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
411 | tail = c->active_head;
412 | node = c->active_head;
413 | prev = &c->active_head;
414 | // find first node that's admissible
415 | while (tail->x < width)
416 | tail = tail->next;
417 | while (tail) {
418 | int xpos = tail->x - width;
419 | int y,waste;
420 | STBRP_ASSERT(xpos >= 0);
421 | // find the left position that matches this
422 | while (node->next->x <= xpos) {
423 | prev = &node->next;
424 | node = node->next;
425 | }
426 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
427 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
428 | if (y + height <= c->height) {
429 | if (y <= best_y) {
430 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
431 | best_x = xpos;
432 | //STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
433 | best_y = y;
434 | best_waste = waste;
435 | best = prev;
436 | }
437 | }
438 | }
439 | tail = tail->next;
440 | }
441 | }
442 |
443 | fr.prev_link = best;
444 | fr.x = best_x;
445 | fr.y = best_y;
446 | return fr;
447 | }
448 |
449 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
450 | {
451 | // find best position according to heuristic
452 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
453 | stbrp_node *node, *cur;
454 |
455 | // bail if:
456 | // 1. it failed
457 | // 2. the best node doesn't fit (we don't always check this)
458 | // 3. we're out of memory
459 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
460 | res.prev_link = NULL;
461 | return res;
462 | }
463 |
464 | // on success, create new node
465 | node = context->free_head;
466 | node->x = (stbrp_coord) res.x;
467 | node->y = (stbrp_coord) (res.y + height);
468 |
469 | context->free_head = node->next;
470 |
471 | // insert the new node into the right starting point, and
472 | // let 'cur' point to the remaining nodes needing to be
473 | // stiched back in
474 |
475 | cur = *res.prev_link;
476 | if (cur->x < res.x) {
477 | // preserve the existing one, so start testing with the next one
478 | stbrp_node *next = cur->next;
479 | cur->next = node;
480 | cur = next;
481 | } else {
482 | *res.prev_link = node;
483 | }
484 |
485 | // from here, traverse cur and free the nodes, until we get to one
486 | // that shouldn't be freed
487 | while (cur->next && cur->next->x <= res.x + width) {
488 | stbrp_node *next = cur->next;
489 | // move the current node to the free list
490 | cur->next = context->free_head;
491 | context->free_head = cur;
492 | cur = next;
493 | }
494 |
495 | // stitch the list back in
496 | node->next = cur;
497 |
498 | if (cur->x < res.x + width)
499 | cur->x = (stbrp_coord) (res.x + width);
500 |
501 | #ifdef _DEBUG
502 | cur = context->active_head;
503 | while (cur->x < context->width) {
504 | STBRP_ASSERT(cur->x < cur->next->x);
505 | cur = cur->next;
506 | }
507 | STBRP_ASSERT(cur->next == NULL);
508 |
509 | {
510 | int count=0;
511 | cur = context->active_head;
512 | while (cur) {
513 | cur = cur->next;
514 | ++count;
515 | }
516 | cur = context->free_head;
517 | while (cur) {
518 | cur = cur->next;
519 | ++count;
520 | }
521 | STBRP_ASSERT(count == context->num_nodes+2);
522 | }
523 | #endif
524 |
525 | return res;
526 | }
527 |
528 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
529 | {
530 | const stbrp_rect *p = (const stbrp_rect *) a;
531 | const stbrp_rect *q = (const stbrp_rect *) b;
532 | if (p->h > q->h)
533 | return -1;
534 | if (p->h < q->h)
535 | return 1;
536 | return (p->w > q->w) ? -1 : (p->w < q->w);
537 | }
538 |
539 | static int STBRP__CDECL rect_original_order(const void *a, const void *b)
540 | {
541 | const stbrp_rect *p = (const stbrp_rect *) a;
542 | const stbrp_rect *q = (const stbrp_rect *) b;
543 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
544 | }
545 |
546 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
547 | {
548 | int i, all_rects_packed = 1;
549 |
550 | // we use the 'was_packed' field internally to allow sorting/unsorting
551 | for (i=0; i < num_rects; ++i) {
552 | rects[i].was_packed = i;
553 | }
554 |
555 | // sort according to heuristic
556 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
557 |
558 | for (i=0; i < num_rects; ++i) {
559 | if (rects[i].w == 0 || rects[i].h == 0) {
560 | rects[i].x = rects[i].y = 0; // empty rect needs no space
561 | } else {
562 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
563 | if (fr.prev_link) {
564 | rects[i].x = (stbrp_coord) fr.x;
565 | rects[i].y = (stbrp_coord) fr.y;
566 | } else {
567 | rects[i].x = rects[i].y = STBRP__MAXVAL;
568 | }
569 | }
570 | }
571 |
572 | // unsort
573 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
574 |
575 | // set was_packed flags and all_rects_packed status
576 | for (i=0; i < num_rects; ++i) {
577 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
578 | if (!rects[i].was_packed)
579 | all_rects_packed = 0;
580 | }
581 |
582 | // return the all_rects_packed status
583 | return all_rects_packed;
584 | }
585 | #endif
586 |
587 | /*
588 | ------------------------------------------------------------------------------
589 | This software is available under 2 licenses -- choose whichever you prefer.
590 | ------------------------------------------------------------------------------
591 | ALTERNATIVE A - MIT License
592 | Copyright (c) 2017 Sean Barrett
593 | Permission is hereby granted, free of charge, to any person obtaining a copy of
594 | this software and associated documentation files (the "Software"), to deal in
595 | the Software without restriction, including without limitation the rights to
596 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
597 | of the Software, and to permit persons to whom the Software is furnished to do
598 | so, subject to the following conditions:
599 | The above copyright notice and this permission notice shall be included in all
600 | copies or substantial portions of the Software.
601 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
602 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
603 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
604 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
605 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
606 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
607 | SOFTWARE.
608 | ------------------------------------------------------------------------------
609 | ALTERNATIVE B - Public Domain (www.unlicense.org)
610 | This is free and unencumbered software released into the public domain.
611 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
612 | software, either in source code form or as a compiled binary, for any purpose,
613 | commercial or non-commercial, and by any means.
614 | In jurisdictions that recognize copyright laws, the author or authors of this
615 | software dedicate any and all copyright interest in the software to the public
616 | domain. We make this dedication for the benefit of the public at large and to
617 | the detriment of our heirs and successors. We intend this dedication to be an
618 | overt act of relinquishment in perpetuity of all present and future rights to
619 | this software under copyright law.
620 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
621 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
622 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
623 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
624 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
625 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
626 | ------------------------------------------------------------------------------
627 | */
628 |
--------------------------------------------------------------------------------
/libs/MinHook/MinHook.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
32 | #error MinHook supports only x86 and x64 systems.
33 | #endif
34 |
35 | #include
36 |
37 | // MinHook Error Codes.
38 | typedef enum MH_STATUS
39 | {
40 | // Unknown error. Should not be returned.
41 | MH_UNKNOWN = -1,
42 |
43 | // Successful.
44 | MH_OK = 0,
45 |
46 | // MinHook is already initialized.
47 | MH_ERROR_ALREADY_INITIALIZED,
48 |
49 | // MinHook is not initialized yet, or already uninitialized.
50 | MH_ERROR_NOT_INITIALIZED,
51 |
52 | // The hook for the specified target function is already created.
53 | MH_ERROR_ALREADY_CREATED,
54 |
55 | // The hook for the specified target function is not created yet.
56 | MH_ERROR_NOT_CREATED,
57 |
58 | // The hook for the specified target function is already enabled.
59 | MH_ERROR_ENABLED,
60 |
61 | // The hook for the specified target function is not enabled yet, or already
62 | // disabled.
63 | MH_ERROR_DISABLED,
64 |
65 | // The specified pointer is invalid. It points the address of non-allocated
66 | // and/or non-executable region.
67 | MH_ERROR_NOT_EXECUTABLE,
68 |
69 | // The specified target function cannot be hooked.
70 | MH_ERROR_UNSUPPORTED_FUNCTION,
71 |
72 | // Failed to allocate memory.
73 | MH_ERROR_MEMORY_ALLOC,
74 |
75 | // Failed to change the memory protection.
76 | MH_ERROR_MEMORY_PROTECT,
77 |
78 | // The specified module is not loaded.
79 | MH_ERROR_MODULE_NOT_FOUND,
80 |
81 | // The specified function is not found.
82 | MH_ERROR_FUNCTION_NOT_FOUND
83 | }
84 | MH_STATUS;
85 |
86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
87 | // MH_QueueEnableHook or MH_QueueDisableHook.
88 | #define MH_ALL_HOOKS NULL
89 |
90 | #ifdef __cplusplus
91 | extern "C" {
92 | #endif
93 |
94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE
95 | // at the beginning of your program.
96 | MH_STATUS WINAPI MH_Initialize(VOID);
97 |
98 | // Uninitialize the MinHook library. You must call this function EXACTLY
99 | // ONCE at the end of your program.
100 | MH_STATUS WINAPI MH_Uninitialize(VOID);
101 |
102 | // Creates a Hook for the specified target function, in disabled state.
103 | // Parameters:
104 | // pTarget [in] A pointer to the target function, which will be
105 | // overridden by the detour function.
106 | // pDetour [in] A pointer to the detour function, which will override
107 | // the target function.
108 | // ppOriginal [out] A pointer to the trampoline function, which will be
109 | // used to call the original target function.
110 | // This parameter can be NULL.
111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID* ppOriginal);
112 |
113 | // Creates a Hook for the specified API function, in disabled state.
114 | // Parameters:
115 | // pszModule [in] A pointer to the loaded module name which contains the
116 | // target function.
117 | // pszTarget [in] A pointer to the target function name, which will be
118 | // overridden by the detour function.
119 | // pDetour [in] A pointer to the detour function, which will override
120 | // the target function.
121 | // ppOriginal [out] A pointer to the trampoline function, which will be
122 | // used to call the original target function.
123 | // This parameter can be NULL.
124 | MH_STATUS WINAPI MH_CreateHookApi(
125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal);
126 |
127 | // Creates a Hook for the specified API function, in disabled state.
128 | // Parameters:
129 | // pszModule [in] A pointer to the loaded module name which contains the
130 | // target function.
131 | // pszTarget [in] A pointer to the target function name, which will be
132 | // overridden by the detour function.
133 | // pDetour [in] A pointer to the detour function, which will override
134 | // the target function.
135 | // ppOriginal [out] A pointer to the trampoline function, which will be
136 | // used to call the original target function.
137 | // This parameter can be NULL.
138 | // ppTarget [out] A pointer to the target function, which will be used
139 | // with other functions.
140 | // This parameter can be NULL.
141 | MH_STATUS WINAPI MH_CreateHookApiEx(
142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal, LPVOID* ppTarget);
143 |
144 | // Removes an already created hook.
145 | // Parameters:
146 | // pTarget [in] A pointer to the target function.
147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
148 |
149 | // Enables an already created hook.
150 | // Parameters:
151 | // pTarget [in] A pointer to the target function.
152 | // If this parameter is MH_ALL_HOOKS, all created hooks are
153 | // enabled in one go.
154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
155 |
156 | // Disables an already created hook.
157 | // Parameters:
158 | // pTarget [in] A pointer to the target function.
159 | // If this parameter is MH_ALL_HOOKS, all created hooks are
160 | // disabled in one go.
161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
162 |
163 | // Queues to enable an already created hook.
164 | // Parameters:
165 | // pTarget [in] A pointer to the target function.
166 | // If this parameter is MH_ALL_HOOKS, all created hooks are
167 | // queued to be enabled.
168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
169 |
170 | // Queues to disable an already created hook.
171 | // Parameters:
172 | // pTarget [in] A pointer to the target function.
173 | // If this parameter is MH_ALL_HOOKS, all created hooks are
174 | // queued to be disabled.
175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
176 |
177 | // Applies all queued changes in one go.
178 | MH_STATUS WINAPI MH_ApplyQueued(VOID);
179 |
180 | // Translates the MH_STATUS to its name as a string.
181 | const char* WINAPI MH_StatusToString(MH_STATUS status);
182 |
183 | #ifdef __cplusplus
184 | }
185 | #endif
186 |
187 |
--------------------------------------------------------------------------------
/libs/MinHook/buffer.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NightFyre/DX11-ImGui-Internal-Hook/b44d74cbb20918c1b616190325ee49589b80cf36/libs/MinHook/buffer.c
--------------------------------------------------------------------------------
/libs/MinHook/buffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | // Size of each memory slot.
32 | #if defined(_M_X64) || defined(__x86_64__)
33 | #define MEMORY_SLOT_SIZE 64
34 | #else
35 | #define MEMORY_SLOT_SIZE 32
36 | #endif
37 |
38 | VOID InitializeBuffer(VOID);
39 | VOID UninitializeBuffer(VOID);
40 | LPVOID AllocateBuffer(LPVOID pOrigin);
41 | VOID FreeBuffer(LPVOID pBuffer);
42 | BOOL IsExecutableAddress(LPVOID pAddress);
43 |
--------------------------------------------------------------------------------
/libs/MinHook/framework.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
4 | // Windows Header Files
5 | #include
6 |
--------------------------------------------------------------------------------
/libs/MinHook/hde32.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 32 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #if defined(_M_IX86) || defined(__i386__)
9 |
10 | #include "hde32.h"
11 | #include "table32.h"
12 |
13 | unsigned int hde32_disasm(const void* code, hde32s* hs)
14 | {
15 | uint8_t x, c, * p = (uint8_t*)code, cflags, opcode, pref = 0;
16 | uint8_t* ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
17 |
18 | // Avoid using memset to reduce the footprint.
19 | #ifndef _MSC_VER
20 | memset((LPBYTE)hs, 0, sizeof(hde32s));
21 | #else
22 | __stosb((LPBYTE)hs, 0, sizeof(hde32s));
23 | #endif
24 |
25 | for (x = 16; x; x--)
26 | switch (c = *p++) {
27 | case 0xf3:
28 | hs->p_rep = c;
29 | pref |= PRE_F3;
30 | break;
31 | case 0xf2:
32 | hs->p_rep = c;
33 | pref |= PRE_F2;
34 | break;
35 | case 0xf0:
36 | hs->p_lock = c;
37 | pref |= PRE_LOCK;
38 | break;
39 | case 0x26: case 0x2e: case 0x36:
40 | case 0x3e: case 0x64: case 0x65:
41 | hs->p_seg = c;
42 | pref |= PRE_SEG;
43 | break;
44 | case 0x66:
45 | hs->p_66 = c;
46 | pref |= PRE_66;
47 | break;
48 | case 0x67:
49 | hs->p_67 = c;
50 | pref |= PRE_67;
51 | break;
52 | default:
53 | goto pref_done;
54 | }
55 | pref_done:
56 |
57 | hs->flags = (uint32_t)pref << 23;
58 |
59 | if (!pref)
60 | pref |= PRE_NONE;
61 |
62 | if ((hs->opcode = c) == 0x0f) {
63 | hs->opcode2 = c = *p++;
64 | ht += DELTA_OPCODES;
65 | }
66 | else if (c >= 0xa0 && c <= 0xa3) {
67 | if (pref & PRE_67)
68 | pref |= PRE_66;
69 | else
70 | pref &= ~PRE_66;
71 | }
72 |
73 | opcode = c;
74 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
75 |
76 | if (cflags == C_ERROR) {
77 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
78 | cflags = 0;
79 | if ((opcode & -3) == 0x24)
80 | cflags++;
81 | }
82 |
83 | x = 0;
84 | if (cflags & C_GROUP) {
85 | uint16_t t;
86 | t = *(uint16_t*)(ht + (cflags & 0x7f));
87 | cflags = (uint8_t)t;
88 | x = (uint8_t)(t >> 8);
89 | }
90 |
91 | if (hs->opcode2) {
92 | ht = hde32_table + DELTA_PREFIXES;
93 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
94 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
95 | }
96 |
97 | if (cflags & C_MODRM) {
98 | hs->flags |= F_MODRM;
99 | hs->modrm = c = *p++;
100 | hs->modrm_mod = m_mod = c >> 6;
101 | hs->modrm_rm = m_rm = c & 7;
102 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
103 |
104 | if (x && ((x << m_reg) & 0x80))
105 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
106 |
107 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
108 | uint8_t t = opcode - 0xd9;
109 | if (m_mod == 3) {
110 | ht = hde32_table + DELTA_FPU_MODRM + t * 8;
111 | t = ht[m_reg] << m_rm;
112 | }
113 | else {
114 | ht = hde32_table + DELTA_FPU_REG;
115 | t = ht[t] << m_reg;
116 | }
117 | if (t & 0x80)
118 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
119 | }
120 |
121 | if (pref & PRE_LOCK) {
122 | if (m_mod == 3) {
123 | hs->flags |= F_ERROR | F_ERROR_LOCK;
124 | }
125 | else {
126 | uint8_t* table_end, op = opcode;
127 | if (hs->opcode2) {
128 | ht = hde32_table + DELTA_OP2_LOCK_OK;
129 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
130 | }
131 | else {
132 | ht = hde32_table + DELTA_OP_LOCK_OK;
133 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
134 | op &= -2;
135 | }
136 | for (; ht != table_end; ht++)
137 | if (*ht++ == op) {
138 | if (!((*ht << m_reg) & 0x80))
139 | goto no_lock_error;
140 | else
141 | break;
142 | }
143 | hs->flags |= F_ERROR | F_ERROR_LOCK;
144 | no_lock_error:
145 | ;
146 | }
147 | }
148 |
149 | if (hs->opcode2) {
150 | switch (opcode) {
151 | case 0x20: case 0x22:
152 | m_mod = 3;
153 | if (m_reg > 4 || m_reg == 1)
154 | goto error_operand;
155 | else
156 | goto no_error_operand;
157 | case 0x21: case 0x23:
158 | m_mod = 3;
159 | if (m_reg == 4 || m_reg == 5)
160 | goto error_operand;
161 | else
162 | goto no_error_operand;
163 | }
164 | }
165 | else {
166 | switch (opcode) {
167 | case 0x8c:
168 | if (m_reg > 5)
169 | goto error_operand;
170 | else
171 | goto no_error_operand;
172 | case 0x8e:
173 | if (m_reg == 1 || m_reg > 5)
174 | goto error_operand;
175 | else
176 | goto no_error_operand;
177 | }
178 | }
179 |
180 | if (m_mod == 3) {
181 | uint8_t* table_end;
182 | if (hs->opcode2) {
183 | ht = hde32_table + DELTA_OP2_ONLY_MEM;
184 | table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
185 | }
186 | else {
187 | ht = hde32_table + DELTA_OP_ONLY_MEM;
188 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
189 | }
190 | for (; ht != table_end; ht += 2)
191 | if (*ht++ == opcode) {
192 | if (*ht++ & pref && !((*ht << m_reg) & 0x80))
193 | goto error_operand;
194 | else
195 | break;
196 | }
197 | goto no_error_operand;
198 | }
199 | else if (hs->opcode2) {
200 | switch (opcode) {
201 | case 0x50: case 0xd7: case 0xf7:
202 | if (pref & (PRE_NONE | PRE_66))
203 | goto error_operand;
204 | break;
205 | case 0xd6:
206 | if (pref & (PRE_F2 | PRE_F3))
207 | goto error_operand;
208 | break;
209 | case 0xc5:
210 | goto error_operand;
211 | }
212 | goto no_error_operand;
213 | }
214 | else
215 | goto no_error_operand;
216 |
217 | error_operand:
218 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
219 | no_error_operand:
220 |
221 | c = *p++;
222 | if (m_reg <= 1) {
223 | if (opcode == 0xf6)
224 | cflags |= C_IMM8;
225 | else if (opcode == 0xf7)
226 | cflags |= C_IMM_P66;
227 | }
228 |
229 | switch (m_mod) {
230 | case 0:
231 | if (pref & PRE_67) {
232 | if (m_rm == 6)
233 | disp_size = 2;
234 | }
235 | else
236 | if (m_rm == 5)
237 | disp_size = 4;
238 | break;
239 | case 1:
240 | disp_size = 1;
241 | break;
242 | case 2:
243 | disp_size = 2;
244 | if (!(pref & PRE_67))
245 | disp_size <<= 1;
246 | }
247 |
248 | if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
249 | hs->flags |= F_SIB;
250 | p++;
251 | hs->sib = c;
252 | hs->sib_scale = c >> 6;
253 | hs->sib_index = (c & 0x3f) >> 3;
254 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
255 | disp_size = 4;
256 | }
257 |
258 | p--;
259 | switch (disp_size) {
260 | case 1:
261 | hs->flags |= F_DISP8;
262 | hs->disp.disp8 = *p;
263 | break;
264 | case 2:
265 | hs->flags |= F_DISP16;
266 | hs->disp.disp16 = *(uint16_t*)p;
267 | break;
268 | case 4:
269 | hs->flags |= F_DISP32;
270 | hs->disp.disp32 = *(uint32_t*)p;
271 | }
272 | p += disp_size;
273 | }
274 | else if (pref & PRE_LOCK)
275 | hs->flags |= F_ERROR | F_ERROR_LOCK;
276 |
277 | if (cflags & C_IMM_P66) {
278 | if (cflags & C_REL32) {
279 | if (pref & PRE_66) {
280 | hs->flags |= F_IMM16 | F_RELATIVE;
281 | hs->imm.imm16 = *(uint16_t*)p;
282 | p += 2;
283 | goto disasm_done;
284 | }
285 | goto rel32_ok;
286 | }
287 | if (pref & PRE_66) {
288 | hs->flags |= F_IMM16;
289 | hs->imm.imm16 = *(uint16_t*)p;
290 | p += 2;
291 | }
292 | else {
293 | hs->flags |= F_IMM32;
294 | hs->imm.imm32 = *(uint32_t*)p;
295 | p += 4;
296 | }
297 | }
298 |
299 | if (cflags & C_IMM16) {
300 | if (hs->flags & F_IMM32) {
301 | hs->flags |= F_IMM16;
302 | hs->disp.disp16 = *(uint16_t*)p;
303 | }
304 | else if (hs->flags & F_IMM16) {
305 | hs->flags |= F_2IMM16;
306 | hs->disp.disp16 = *(uint16_t*)p;
307 | }
308 | else {
309 | hs->flags |= F_IMM16;
310 | hs->imm.imm16 = *(uint16_t*)p;
311 | }
312 | p += 2;
313 | }
314 | if (cflags & C_IMM8) {
315 | hs->flags |= F_IMM8;
316 | hs->imm.imm8 = *p++;
317 | }
318 |
319 | if (cflags & C_REL32) {
320 | rel32_ok:
321 | hs->flags |= F_IMM32 | F_RELATIVE;
322 | hs->imm.imm32 = *(uint32_t*)p;
323 | p += 4;
324 | }
325 | else if (cflags & C_REL8) {
326 | hs->flags |= F_IMM8 | F_RELATIVE;
327 | hs->imm.imm8 = *p++;
328 | }
329 |
330 | disasm_done:
331 |
332 | if ((hs->len = (uint8_t)(p - (uint8_t*)code)) > 15) {
333 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
334 | hs->len = 15;
335 | }
336 |
337 | return (unsigned int)hs->len;
338 | }
339 |
340 | #endif // defined(_M_IX86) || defined(__i386__)
341 |
--------------------------------------------------------------------------------
/libs/MinHook/hde32.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 32
3 | * Copyright (c) 2006-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | * hde32.h: C/C++ header file
7 | *
8 | */
9 |
10 | #ifndef _HDE32_H_
11 | #define _HDE32_H_
12 |
13 | /* stdint.h - C99 standard header
14 | * http://en.wikipedia.org/wiki/stdint.h
15 | *
16 | * if your compiler doesn't contain "stdint.h" header (for
17 | * example, Microsoft Visual C++), you can download file:
18 | * http://www.azillionmonkeys.com/qed/pstdint.h
19 | * and change next line to:
20 | * #include "pstdint.h"
21 | */
22 | #include "pstdint.h"
23 |
24 | #define F_MODRM 0x00000001
25 | #define F_SIB 0x00000002
26 | #define F_IMM8 0x00000004
27 | #define F_IMM16 0x00000008
28 | #define F_IMM32 0x00000010
29 | #define F_DISP8 0x00000020
30 | #define F_DISP16 0x00000040
31 | #define F_DISP32 0x00000080
32 | #define F_RELATIVE 0x00000100
33 | #define F_2IMM16 0x00000800
34 | #define F_ERROR 0x00001000
35 | #define F_ERROR_OPCODE 0x00002000
36 | #define F_ERROR_LENGTH 0x00004000
37 | #define F_ERROR_LOCK 0x00008000
38 | #define F_ERROR_OPERAND 0x00010000
39 | #define F_PREFIX_REPNZ 0x01000000
40 | #define F_PREFIX_REPX 0x02000000
41 | #define F_PREFIX_REP 0x03000000
42 | #define F_PREFIX_66 0x04000000
43 | #define F_PREFIX_67 0x08000000
44 | #define F_PREFIX_LOCK 0x10000000
45 | #define F_PREFIX_SEG 0x20000000
46 | #define F_PREFIX_ANY 0x3f000000
47 |
48 | #define PREFIX_SEGMENT_CS 0x2e
49 | #define PREFIX_SEGMENT_SS 0x36
50 | #define PREFIX_SEGMENT_DS 0x3e
51 | #define PREFIX_SEGMENT_ES 0x26
52 | #define PREFIX_SEGMENT_FS 0x64
53 | #define PREFIX_SEGMENT_GS 0x65
54 | #define PREFIX_LOCK 0xf0
55 | #define PREFIX_REPNZ 0xf2
56 | #define PREFIX_REPX 0xf3
57 | #define PREFIX_OPERAND_SIZE 0x66
58 | #define PREFIX_ADDRESS_SIZE 0x67
59 |
60 | #pragma pack(push,1)
61 |
62 | typedef struct {
63 | uint8_t len;
64 | uint8_t p_rep;
65 | uint8_t p_lock;
66 | uint8_t p_seg;
67 | uint8_t p_66;
68 | uint8_t p_67;
69 | uint8_t opcode;
70 | uint8_t opcode2;
71 | uint8_t modrm;
72 | uint8_t modrm_mod;
73 | uint8_t modrm_reg;
74 | uint8_t modrm_rm;
75 | uint8_t sib;
76 | uint8_t sib_scale;
77 | uint8_t sib_index;
78 | uint8_t sib_base;
79 | union {
80 | uint8_t imm8;
81 | uint16_t imm16;
82 | uint32_t imm32;
83 | } imm;
84 | union {
85 | uint8_t disp8;
86 | uint16_t disp16;
87 | uint32_t disp32;
88 | } disp;
89 | uint32_t flags;
90 | } hde32s;
91 |
92 | #pragma pack(pop)
93 |
94 | #ifdef __cplusplus
95 | extern "C" {
96 | #endif
97 |
98 | /* __cdecl */
99 | unsigned int hde32_disasm(const void* code, hde32s* hs);
100 |
101 | #ifdef __cplusplus
102 | }
103 | #endif
104 |
105 | #endif /* _HDE32_H_ */
106 |
--------------------------------------------------------------------------------
/libs/MinHook/hde64.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #if defined(_M_X64) || defined(__x86_64__)
9 |
10 | #include "hde64.h"
11 | #include "table64.h"
12 |
13 | unsigned int hde64_disasm(const void* code, hde64s* hs)
14 | {
15 | uint8_t x, c, * p = (uint8_t*)code, cflags, opcode, pref = 0;
16 | uint8_t* ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
17 | uint8_t op64 = 0;
18 |
19 | // Avoid using memset to reduce the footprint.
20 | #ifndef _MSC_VER
21 | memset((LPBYTE)hs, 0, sizeof(hde64s));
22 | #else
23 | __stosb((LPBYTE)hs, 0, sizeof(hde64s));
24 | #endif
25 |
26 | for (x = 16; x; x--)
27 | switch (c = *p++) {
28 | case 0xf3:
29 | hs->p_rep = c;
30 | pref |= PRE_F3;
31 | break;
32 | case 0xf2:
33 | hs->p_rep = c;
34 | pref |= PRE_F2;
35 | break;
36 | case 0xf0:
37 | hs->p_lock = c;
38 | pref |= PRE_LOCK;
39 | break;
40 | case 0x26: case 0x2e: case 0x36:
41 | case 0x3e: case 0x64: case 0x65:
42 | hs->p_seg = c;
43 | pref |= PRE_SEG;
44 | break;
45 | case 0x66:
46 | hs->p_66 = c;
47 | pref |= PRE_66;
48 | break;
49 | case 0x67:
50 | hs->p_67 = c;
51 | pref |= PRE_67;
52 | break;
53 | default:
54 | goto pref_done;
55 | }
56 | pref_done:
57 |
58 | hs->flags = (uint32_t)pref << 23;
59 |
60 | if (!pref)
61 | pref |= PRE_NONE;
62 |
63 | if ((c & 0xf0) == 0x40) {
64 | hs->flags |= F_PREFIX_REX;
65 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
66 | op64++;
67 | hs->rex_r = (c & 7) >> 2;
68 | hs->rex_x = (c & 3) >> 1;
69 | hs->rex_b = c & 1;
70 | if (((c = *p++) & 0xf0) == 0x40) {
71 | opcode = c;
72 | goto error_opcode;
73 | }
74 | }
75 |
76 | if ((hs->opcode = c) == 0x0f) {
77 | hs->opcode2 = c = *p++;
78 | ht += DELTA_OPCODES;
79 | }
80 | else if (c >= 0xa0 && c <= 0xa3) {
81 | op64++;
82 | if (pref & PRE_67)
83 | pref |= PRE_66;
84 | else
85 | pref &= ~PRE_66;
86 | }
87 |
88 | opcode = c;
89 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
90 |
91 | if (cflags == C_ERROR) {
92 | error_opcode:
93 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
94 | cflags = 0;
95 | if ((opcode & -3) == 0x24)
96 | cflags++;
97 | }
98 |
99 | x = 0;
100 | if (cflags & C_GROUP) {
101 | uint16_t t;
102 | t = *(uint16_t*)(ht + (cflags & 0x7f));
103 | cflags = (uint8_t)t;
104 | x = (uint8_t)(t >> 8);
105 | }
106 |
107 | if (hs->opcode2) {
108 | ht = hde64_table + DELTA_PREFIXES;
109 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
110 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
111 | }
112 |
113 | if (cflags & C_MODRM) {
114 | hs->flags |= F_MODRM;
115 | hs->modrm = c = *p++;
116 | hs->modrm_mod = m_mod = c >> 6;
117 | hs->modrm_rm = m_rm = c & 7;
118 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
119 |
120 | if (x && ((x << m_reg) & 0x80))
121 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
122 |
123 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
124 | uint8_t t = opcode - 0xd9;
125 | if (m_mod == 3) {
126 | ht = hde64_table + DELTA_FPU_MODRM + t * 8;
127 | t = ht[m_reg] << m_rm;
128 | }
129 | else {
130 | ht = hde64_table + DELTA_FPU_REG;
131 | t = ht[t] << m_reg;
132 | }
133 | if (t & 0x80)
134 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
135 | }
136 |
137 | if (pref & PRE_LOCK) {
138 | if (m_mod == 3) {
139 | hs->flags |= F_ERROR | F_ERROR_LOCK;
140 | }
141 | else {
142 | uint8_t* table_end, op = opcode;
143 | if (hs->opcode2) {
144 | ht = hde64_table + DELTA_OP2_LOCK_OK;
145 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
146 | }
147 | else {
148 | ht = hde64_table + DELTA_OP_LOCK_OK;
149 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
150 | op &= -2;
151 | }
152 | for (; ht != table_end; ht++)
153 | if (*ht++ == op) {
154 | if (!((*ht << m_reg) & 0x80))
155 | goto no_lock_error;
156 | else
157 | break;
158 | }
159 | hs->flags |= F_ERROR | F_ERROR_LOCK;
160 | no_lock_error:
161 | ;
162 | }
163 | }
164 |
165 | if (hs->opcode2) {
166 | switch (opcode) {
167 | case 0x20: case 0x22:
168 | m_mod = 3;
169 | if (m_reg > 4 || m_reg == 1)
170 | goto error_operand;
171 | else
172 | goto no_error_operand;
173 | case 0x21: case 0x23:
174 | m_mod = 3;
175 | if (m_reg == 4 || m_reg == 5)
176 | goto error_operand;
177 | else
178 | goto no_error_operand;
179 | }
180 | }
181 | else {
182 | switch (opcode) {
183 | case 0x8c:
184 | if (m_reg > 5)
185 | goto error_operand;
186 | else
187 | goto no_error_operand;
188 | case 0x8e:
189 | if (m_reg == 1 || m_reg > 5)
190 | goto error_operand;
191 | else
192 | goto no_error_operand;
193 | }
194 | }
195 |
196 | if (m_mod == 3) {
197 | uint8_t* table_end;
198 | if (hs->opcode2) {
199 | ht = hde64_table + DELTA_OP2_ONLY_MEM;
200 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
201 | }
202 | else {
203 | ht = hde64_table + DELTA_OP_ONLY_MEM;
204 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
205 | }
206 | for (; ht != table_end; ht += 2)
207 | if (*ht++ == opcode) {
208 | if (*ht++ & pref && !((*ht << m_reg) & 0x80))
209 | goto error_operand;
210 | else
211 | break;
212 | }
213 | goto no_error_operand;
214 | }
215 | else if (hs->opcode2) {
216 | switch (opcode) {
217 | case 0x50: case 0xd7: case 0xf7:
218 | if (pref & (PRE_NONE | PRE_66))
219 | goto error_operand;
220 | break;
221 | case 0xd6:
222 | if (pref & (PRE_F2 | PRE_F3))
223 | goto error_operand;
224 | break;
225 | case 0xc5:
226 | goto error_operand;
227 | }
228 | goto no_error_operand;
229 | }
230 | else
231 | goto no_error_operand;
232 |
233 | error_operand:
234 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
235 | no_error_operand:
236 |
237 | c = *p++;
238 | if (m_reg <= 1) {
239 | if (opcode == 0xf6)
240 | cflags |= C_IMM8;
241 | else if (opcode == 0xf7)
242 | cflags |= C_IMM_P66;
243 | }
244 |
245 | switch (m_mod) {
246 | case 0:
247 | if (pref & PRE_67) {
248 | if (m_rm == 6)
249 | disp_size = 2;
250 | }
251 | else
252 | if (m_rm == 5)
253 | disp_size = 4;
254 | break;
255 | case 1:
256 | disp_size = 1;
257 | break;
258 | case 2:
259 | disp_size = 2;
260 | if (!(pref & PRE_67))
261 | disp_size <<= 1;
262 | }
263 |
264 | if (m_mod != 3 && m_rm == 4) {
265 | hs->flags |= F_SIB;
266 | p++;
267 | hs->sib = c;
268 | hs->sib_scale = c >> 6;
269 | hs->sib_index = (c & 0x3f) >> 3;
270 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
271 | disp_size = 4;
272 | }
273 |
274 | p--;
275 | switch (disp_size) {
276 | case 1:
277 | hs->flags |= F_DISP8;
278 | hs->disp.disp8 = *p;
279 | break;
280 | case 2:
281 | hs->flags |= F_DISP16;
282 | hs->disp.disp16 = *(uint16_t*)p;
283 | break;
284 | case 4:
285 | hs->flags |= F_DISP32;
286 | hs->disp.disp32 = *(uint32_t*)p;
287 | }
288 | p += disp_size;
289 | }
290 | else if (pref & PRE_LOCK)
291 | hs->flags |= F_ERROR | F_ERROR_LOCK;
292 |
293 | if (cflags & C_IMM_P66) {
294 | if (cflags & C_REL32) {
295 | if (pref & PRE_66) {
296 | hs->flags |= F_IMM16 | F_RELATIVE;
297 | hs->imm.imm16 = *(uint16_t*)p;
298 | p += 2;
299 | goto disasm_done;
300 | }
301 | goto rel32_ok;
302 | }
303 | if (op64) {
304 | hs->flags |= F_IMM64;
305 | hs->imm.imm64 = *(uint64_t*)p;
306 | p += 8;
307 | }
308 | else if (!(pref & PRE_66)) {
309 | hs->flags |= F_IMM32;
310 | hs->imm.imm32 = *(uint32_t*)p;
311 | p += 4;
312 | }
313 | else
314 | goto imm16_ok;
315 | }
316 |
317 |
318 | if (cflags & C_IMM16) {
319 | imm16_ok:
320 | hs->flags |= F_IMM16;
321 | hs->imm.imm16 = *(uint16_t*)p;
322 | p += 2;
323 | }
324 | if (cflags & C_IMM8) {
325 | hs->flags |= F_IMM8;
326 | hs->imm.imm8 = *p++;
327 | }
328 |
329 | if (cflags & C_REL32) {
330 | rel32_ok:
331 | hs->flags |= F_IMM32 | F_RELATIVE;
332 | hs->imm.imm32 = *(uint32_t*)p;
333 | p += 4;
334 | }
335 | else if (cflags & C_REL8) {
336 | hs->flags |= F_IMM8 | F_RELATIVE;
337 | hs->imm.imm8 = *p++;
338 | }
339 |
340 | disasm_done:
341 |
342 | if ((hs->len = (uint8_t)(p - (uint8_t*)code)) > 15) {
343 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
344 | hs->len = 15;
345 | }
346 |
347 | return (unsigned int)hs->len;
348 | }
349 |
350 | #endif // defined(_M_X64) || defined(__x86_64__)
351 |
--------------------------------------------------------------------------------
/libs/MinHook/hde64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | * hde64.h: C/C++ header file
7 | *
8 | */
9 |
10 | #ifndef _HDE64_H_
11 | #define _HDE64_H_
12 |
13 | /* stdint.h - C99 standard header
14 | * http://en.wikipedia.org/wiki/stdint.h
15 | *
16 | * if your compiler doesn't contain "stdint.h" header (for
17 | * example, Microsoft Visual C++), you can download file:
18 | * http://www.azillionmonkeys.com/qed/pstdint.h
19 | * and change next line to:
20 | * #include "pstdint.h"
21 | */
22 | #include "pstdint.h"
23 |
24 | #define F_MODRM 0x00000001
25 | #define F_SIB 0x00000002
26 | #define F_IMM8 0x00000004
27 | #define F_IMM16 0x00000008
28 | #define F_IMM32 0x00000010
29 | #define F_IMM64 0x00000020
30 | #define F_DISP8 0x00000040
31 | #define F_DISP16 0x00000080
32 | #define F_DISP32 0x00000100
33 | #define F_RELATIVE 0x00000200
34 | #define F_ERROR 0x00001000
35 | #define F_ERROR_OPCODE 0x00002000
36 | #define F_ERROR_LENGTH 0x00004000
37 | #define F_ERROR_LOCK 0x00008000
38 | #define F_ERROR_OPERAND 0x00010000
39 | #define F_PREFIX_REPNZ 0x01000000
40 | #define F_PREFIX_REPX 0x02000000
41 | #define F_PREFIX_REP 0x03000000
42 | #define F_PREFIX_66 0x04000000
43 | #define F_PREFIX_67 0x08000000
44 | #define F_PREFIX_LOCK 0x10000000
45 | #define F_PREFIX_SEG 0x20000000
46 | #define F_PREFIX_REX 0x40000000
47 | #define F_PREFIX_ANY 0x7f000000
48 |
49 | #define PREFIX_SEGMENT_CS 0x2e
50 | #define PREFIX_SEGMENT_SS 0x36
51 | #define PREFIX_SEGMENT_DS 0x3e
52 | #define PREFIX_SEGMENT_ES 0x26
53 | #define PREFIX_SEGMENT_FS 0x64
54 | #define PREFIX_SEGMENT_GS 0x65
55 | #define PREFIX_LOCK 0xf0
56 | #define PREFIX_REPNZ 0xf2
57 | #define PREFIX_REPX 0xf3
58 | #define PREFIX_OPERAND_SIZE 0x66
59 | #define PREFIX_ADDRESS_SIZE 0x67
60 |
61 | #pragma pack(push,1)
62 |
63 | typedef struct {
64 | uint8_t len;
65 | uint8_t p_rep;
66 | uint8_t p_lock;
67 | uint8_t p_seg;
68 | uint8_t p_66;
69 | uint8_t p_67;
70 | uint8_t rex;
71 | uint8_t rex_w;
72 | uint8_t rex_r;
73 | uint8_t rex_x;
74 | uint8_t rex_b;
75 | uint8_t opcode;
76 | uint8_t opcode2;
77 | uint8_t modrm;
78 | uint8_t modrm_mod;
79 | uint8_t modrm_reg;
80 | uint8_t modrm_rm;
81 | uint8_t sib;
82 | uint8_t sib_scale;
83 | uint8_t sib_index;
84 | uint8_t sib_base;
85 | union {
86 | uint8_t imm8;
87 | uint16_t imm16;
88 | uint32_t imm32;
89 | uint64_t imm64;
90 | } imm;
91 | union {
92 | uint8_t disp8;
93 | uint16_t disp16;
94 | uint32_t disp32;
95 | } disp;
96 | uint32_t flags;
97 | } hde64s;
98 |
99 | #pragma pack(pop)
100 |
101 | #ifdef __cplusplus
102 | extern "C" {
103 | #endif
104 |
105 | /* __cdecl */
106 | unsigned int hde64_disasm(const void* code, hde64s* hs);
107 |
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /* _HDE64_H_ */
113 |
--------------------------------------------------------------------------------
/libs/MinHook/hook.c:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | #include "MinHook.h"
34 | #include "buffer.h"
35 | #include "trampoline.h"
36 |
37 | #ifndef ARRAYSIZE
38 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
39 | #endif
40 |
41 | // Initial capacity of the HOOK_ENTRY buffer.
42 | #define INITIAL_HOOK_CAPACITY 32
43 |
44 | // Initial capacity of the thread IDs buffer.
45 | #define INITIAL_THREAD_CAPACITY 128
46 |
47 | // Special hook position values.
48 | #define INVALID_HOOK_POS UINT_MAX
49 | #define ALL_HOOKS_POS UINT_MAX
50 |
51 | // Freeze() action argument defines.
52 | #define ACTION_DISABLE 0
53 | #define ACTION_ENABLE 1
54 | #define ACTION_APPLY_QUEUED 2
55 |
56 | // Thread access rights for suspending/resuming threads.
57 | #define THREAD_ACCESS \
58 | (THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT)
59 |
60 | // Hook information.
61 | typedef struct _HOOK_ENTRY
62 | {
63 | LPVOID pTarget; // Address of the target function.
64 | LPVOID pDetour; // Address of the detour or relay function.
65 | LPVOID pTrampoline; // Address of the trampoline function.
66 | UINT8 backup[8]; // Original prologue of the target function.
67 |
68 | UINT8 patchAbove : 1; // Uses the hot patch area.
69 | UINT8 isEnabled : 1; // Enabled.
70 | UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled.
71 |
72 | UINT nIP : 4; // Count of the instruction boundaries.
73 | UINT8 oldIPs[8]; // Instruction boundaries of the target function.
74 | UINT8 newIPs[8]; // Instruction boundaries of the trampoline function.
75 | } HOOK_ENTRY, * PHOOK_ENTRY;
76 |
77 | // Suspended threads for Freeze()/Unfreeze().
78 | typedef struct _FROZEN_THREADS
79 | {
80 | LPDWORD pItems; // Data heap
81 | UINT capacity; // Size of allocated data heap, items
82 | UINT size; // Actual number of data items
83 | } FROZEN_THREADS, * PFROZEN_THREADS;
84 |
85 | //-------------------------------------------------------------------------
86 | // Global Variables:
87 | //-------------------------------------------------------------------------
88 |
89 | // Spin lock flag for EnterSpinLock()/LeaveSpinLock().
90 | volatile LONG g_isLocked = FALSE;
91 |
92 | // Private heap handle. If not NULL, this library is initialized.
93 | HANDLE g_hHeap = NULL;
94 |
95 | // Hook entries.
96 | struct
97 | {
98 | PHOOK_ENTRY pItems; // Data heap
99 | UINT capacity; // Size of allocated data heap, items
100 | UINT size; // Actual number of data items
101 | } g_hooks;
102 |
103 | //-------------------------------------------------------------------------
104 | // Returns INVALID_HOOK_POS if not found.
105 | static UINT FindHookEntry(LPVOID pTarget)
106 | {
107 | UINT i;
108 | for (i = 0; i < g_hooks.size; ++i)
109 | {
110 | if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget)
111 | return i;
112 | }
113 |
114 | return INVALID_HOOK_POS;
115 | }
116 |
117 | //-------------------------------------------------------------------------
118 | static PHOOK_ENTRY AddHookEntry()
119 | {
120 | if (g_hooks.pItems == NULL)
121 | {
122 | g_hooks.capacity = INITIAL_HOOK_CAPACITY;
123 | g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc(
124 | g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY));
125 | if (g_hooks.pItems == NULL)
126 | return NULL;
127 | }
128 | else if (g_hooks.size >= g_hooks.capacity)
129 | {
130 | PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
131 | g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY));
132 | if (p == NULL)
133 | return NULL;
134 |
135 | g_hooks.capacity *= 2;
136 | g_hooks.pItems = p;
137 | }
138 |
139 | return &g_hooks.pItems[g_hooks.size++];
140 | }
141 |
142 | //-------------------------------------------------------------------------
143 | static void DeleteHookEntry(UINT pos)
144 | {
145 | if (pos < g_hooks.size - 1)
146 | g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1];
147 |
148 | g_hooks.size--;
149 |
150 | if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size)
151 | {
152 | PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
153 | g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY));
154 | if (p == NULL)
155 | return;
156 |
157 | g_hooks.capacity /= 2;
158 | g_hooks.pItems = p;
159 | }
160 | }
161 |
162 | //-------------------------------------------------------------------------
163 | static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
164 | {
165 | UINT i;
166 |
167 | if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL)))
168 | return (DWORD_PTR)pHook->pTarget;
169 |
170 | for (i = 0; i < pHook->nIP; ++i)
171 | {
172 | if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]))
173 | return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i];
174 | }
175 |
176 | #if defined(_M_X64) || defined(__x86_64__)
177 | // Check relay function.
178 | if (ip == (DWORD_PTR)pHook->pDetour)
179 | return (DWORD_PTR)pHook->pTarget;
180 | #endif
181 |
182 | return 0;
183 | }
184 |
185 | //-------------------------------------------------------------------------
186 | static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
187 | {
188 | UINT i;
189 | for (i = 0; i < pHook->nIP; ++i)
190 | {
191 | if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]))
192 | return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i];
193 | }
194 |
195 | return 0;
196 | }
197 |
198 | //-------------------------------------------------------------------------
199 | static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
200 | {
201 | // If the thread suspended in the overwritten area,
202 | // move IP to the proper address.
203 |
204 | CONTEXT c;
205 | #if defined(_M_X64) || defined(__x86_64__)
206 | DWORD64* pIP = &c.Rip;
207 | #else
208 | DWORD* pIP = &c.Eip;
209 | #endif
210 | UINT count;
211 |
212 | c.ContextFlags = CONTEXT_CONTROL;
213 | if (!GetThreadContext(hThread, &c))
214 | return;
215 |
216 | if (pos == ALL_HOOKS_POS)
217 | {
218 | pos = 0;
219 | count = g_hooks.size;
220 | }
221 | else
222 | {
223 | count = pos + 1;
224 | }
225 |
226 | for (; pos < count; ++pos)
227 | {
228 | PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
229 | BOOL enable;
230 | DWORD_PTR ip;
231 |
232 | switch (action)
233 | {
234 | case ACTION_DISABLE:
235 | enable = FALSE;
236 | break;
237 |
238 | case ACTION_ENABLE:
239 | enable = TRUE;
240 | break;
241 |
242 | default: // ACTION_APPLY_QUEUED
243 | enable = pHook->queueEnable;
244 | break;
245 | }
246 | if (pHook->isEnabled == enable)
247 | continue;
248 |
249 | if (enable)
250 | ip = FindNewIP(pHook, *pIP);
251 | else
252 | ip = FindOldIP(pHook, *pIP);
253 |
254 | if (ip != 0)
255 | {
256 | *pIP = ip;
257 | SetThreadContext(hThread, &c);
258 | }
259 | }
260 | }
261 |
262 | //-------------------------------------------------------------------------
263 | static VOID EnumerateThreads(PFROZEN_THREADS pThreads)
264 | {
265 | HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
266 | if (hSnapshot != INVALID_HANDLE_VALUE)
267 | {
268 | THREADENTRY32 te;
269 | te.dwSize = sizeof(THREADENTRY32);
270 | if (Thread32First(hSnapshot, &te))
271 | {
272 | do
273 | {
274 | if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD))
275 | && te.th32OwnerProcessID == GetCurrentProcessId()
276 | && te.th32ThreadID != GetCurrentThreadId())
277 | {
278 | if (pThreads->pItems == NULL)
279 | {
280 | pThreads->capacity = INITIAL_THREAD_CAPACITY;
281 | pThreads->pItems
282 | = (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD));
283 | if (pThreads->pItems == NULL)
284 | break;
285 | }
286 | else if (pThreads->size >= pThreads->capacity)
287 | {
288 | LPDWORD p = (LPDWORD)HeapReAlloc(
289 | g_hHeap, 0, pThreads->pItems, (pThreads->capacity * 2) * sizeof(DWORD));
290 | if (p == NULL)
291 | break;
292 |
293 | pThreads->capacity *= 2;
294 | pThreads->pItems = p;
295 | }
296 | pThreads->pItems[pThreads->size++] = te.th32ThreadID;
297 | }
298 |
299 | te.dwSize = sizeof(THREADENTRY32);
300 | } while (Thread32Next(hSnapshot, &te));
301 | }
302 | CloseHandle(hSnapshot);
303 | }
304 | }
305 |
306 | //-------------------------------------------------------------------------
307 | static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
308 | {
309 | pThreads->pItems = NULL;
310 | pThreads->capacity = 0;
311 | pThreads->size = 0;
312 | EnumerateThreads(pThreads);
313 |
314 | if (pThreads->pItems != NULL)
315 | {
316 | UINT i;
317 | for (i = 0; i < pThreads->size; ++i)
318 | {
319 | HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
320 | if (hThread != NULL)
321 | {
322 | SuspendThread(hThread);
323 | ProcessThreadIPs(hThread, pos, action);
324 | CloseHandle(hThread);
325 | }
326 | }
327 | }
328 | }
329 |
330 | //-------------------------------------------------------------------------
331 | static VOID Unfreeze(PFROZEN_THREADS pThreads)
332 | {
333 | if (pThreads->pItems != NULL)
334 | {
335 | UINT i;
336 | for (i = 0; i < pThreads->size; ++i)
337 | {
338 | HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
339 | if (hThread != NULL)
340 | {
341 | ResumeThread(hThread);
342 | CloseHandle(hThread);
343 | }
344 | }
345 |
346 | HeapFree(g_hHeap, 0, pThreads->pItems);
347 | }
348 | }
349 |
350 | //-------------------------------------------------------------------------
351 | static MH_STATUS EnableHookLL(UINT pos, BOOL enable)
352 | {
353 | PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
354 | DWORD oldProtect;
355 | SIZE_T patchSize = sizeof(JMP_REL);
356 | LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget;
357 |
358 | if (pHook->patchAbove)
359 | {
360 | pPatchTarget -= sizeof(JMP_REL);
361 | patchSize += sizeof(JMP_REL_SHORT);
362 | }
363 |
364 | if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
365 | return MH_ERROR_MEMORY_PROTECT;
366 |
367 | if (enable)
368 | {
369 | PJMP_REL pJmp = (PJMP_REL)pPatchTarget;
370 | pJmp->opcode = 0xE9;
371 | pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
372 |
373 | if (pHook->patchAbove)
374 | {
375 | PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
376 | pShortJmp->opcode = 0xEB;
377 | pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
378 | }
379 | }
380 | else
381 | {
382 | if (pHook->patchAbove)
383 | memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
384 | else
385 | memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL));
386 | }
387 |
388 | VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
389 |
390 | // Just-in-case measure.
391 | FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);
392 |
393 | pHook->isEnabled = enable;
394 | pHook->queueEnable = enable;
395 |
396 | return MH_OK;
397 | }
398 |
399 | //-------------------------------------------------------------------------
400 | static MH_STATUS EnableAllHooksLL(BOOL enable)
401 | {
402 | MH_STATUS status = MH_OK;
403 | UINT i, first = INVALID_HOOK_POS;
404 |
405 | for (i = 0; i < g_hooks.size; ++i)
406 | {
407 | if (g_hooks.pItems[i].isEnabled != enable)
408 | {
409 | first = i;
410 | break;
411 | }
412 | }
413 |
414 | if (first != INVALID_HOOK_POS)
415 | {
416 | FROZEN_THREADS threads;
417 | Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE);
418 |
419 | for (i = first; i < g_hooks.size; ++i)
420 | {
421 | if (g_hooks.pItems[i].isEnabled != enable)
422 | {
423 | status = EnableHookLL(i, enable);
424 | if (status != MH_OK)
425 | break;
426 | }
427 | }
428 |
429 | Unfreeze(&threads);
430 | }
431 |
432 | return status;
433 | }
434 |
435 | //-------------------------------------------------------------------------
436 | static VOID EnterSpinLock(VOID)
437 | {
438 | SIZE_T spinCount = 0;
439 |
440 | // Wait until the flag is FALSE.
441 | while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
442 | {
443 | // No need to generate a memory barrier here, since InterlockedCompareExchange()
444 | // generates a full memory barrier itself.
445 |
446 | // Prevent the loop from being too busy.
447 | if (spinCount < 32)
448 | Sleep(0);
449 | else
450 | Sleep(1);
451 |
452 | spinCount++;
453 | }
454 | }
455 |
456 | //-------------------------------------------------------------------------
457 | static VOID LeaveSpinLock(VOID)
458 | {
459 | // No need to generate a memory barrier here, since InterlockedExchange()
460 | // generates a full memory barrier itself.
461 |
462 | InterlockedExchange(&g_isLocked, FALSE);
463 | }
464 |
465 | //-------------------------------------------------------------------------
466 | MH_STATUS WINAPI MH_Initialize(VOID)
467 | {
468 | MH_STATUS status = MH_OK;
469 |
470 | EnterSpinLock();
471 |
472 | if (g_hHeap == NULL)
473 | {
474 | g_hHeap = HeapCreate(0, 0, 0);
475 | if (g_hHeap != NULL)
476 | {
477 | // Initialize the internal function buffer.
478 | InitializeBuffer();
479 | }
480 | else
481 | {
482 | status = MH_ERROR_MEMORY_ALLOC;
483 | }
484 | }
485 | else
486 | {
487 | status = MH_ERROR_ALREADY_INITIALIZED;
488 | }
489 |
490 | LeaveSpinLock();
491 |
492 | return status;
493 | }
494 |
495 | //-------------------------------------------------------------------------
496 | MH_STATUS WINAPI MH_Uninitialize(VOID)
497 | {
498 | MH_STATUS status = MH_OK;
499 |
500 | EnterSpinLock();
501 |
502 | if (g_hHeap != NULL)
503 | {
504 | status = EnableAllHooksLL(FALSE);
505 | if (status == MH_OK)
506 | {
507 | // Free the internal function buffer.
508 |
509 | // HeapFree is actually not required, but some tools detect a false
510 | // memory leak without HeapFree.
511 |
512 | UninitializeBuffer();
513 |
514 | HeapFree(g_hHeap, 0, g_hooks.pItems);
515 | HeapDestroy(g_hHeap);
516 |
517 | g_hHeap = NULL;
518 |
519 | g_hooks.pItems = NULL;
520 | g_hooks.capacity = 0;
521 | g_hooks.size = 0;
522 | }
523 | }
524 | else
525 | {
526 | status = MH_ERROR_NOT_INITIALIZED;
527 | }
528 |
529 | LeaveSpinLock();
530 |
531 | return status;
532 | }
533 |
534 | //-------------------------------------------------------------------------
535 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID* ppOriginal)
536 | {
537 | MH_STATUS status = MH_OK;
538 |
539 | EnterSpinLock();
540 |
541 | if (g_hHeap != NULL)
542 | {
543 | if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour))
544 | {
545 | UINT pos = FindHookEntry(pTarget);
546 | if (pos == INVALID_HOOK_POS)
547 | {
548 | LPVOID pBuffer = AllocateBuffer(pTarget);
549 | if (pBuffer != NULL)
550 | {
551 | TRAMPOLINE ct;
552 |
553 | ct.pTarget = pTarget;
554 | ct.pDetour = pDetour;
555 | ct.pTrampoline = pBuffer;
556 | if (CreateTrampolineFunction(&ct))
557 | {
558 | PHOOK_ENTRY pHook = AddHookEntry();
559 | if (pHook != NULL)
560 | {
561 | pHook->pTarget = ct.pTarget;
562 | #if defined(_M_X64) || defined(__x86_64__)
563 | pHook->pDetour = ct.pRelay;
564 | #else
565 | pHook->pDetour = ct.pDetour;
566 | #endif
567 | pHook->pTrampoline = ct.pTrampoline;
568 | pHook->patchAbove = ct.patchAbove;
569 | pHook->isEnabled = FALSE;
570 | pHook->queueEnable = FALSE;
571 | pHook->nIP = ct.nIP;
572 | memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
573 | memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));
574 |
575 | // Back up the target function.
576 |
577 | if (ct.patchAbove)
578 | {
579 | memcpy(
580 | pHook->backup,
581 | (LPBYTE)pTarget - sizeof(JMP_REL),
582 | sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
583 | }
584 | else
585 | {
586 | memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
587 | }
588 |
589 | if (ppOriginal != NULL)
590 | *ppOriginal = pHook->pTrampoline;
591 | }
592 | else
593 | {
594 | status = MH_ERROR_MEMORY_ALLOC;
595 | }
596 | }
597 | else
598 | {
599 | status = MH_ERROR_UNSUPPORTED_FUNCTION;
600 | }
601 |
602 | if (status != MH_OK)
603 | {
604 | FreeBuffer(pBuffer);
605 | }
606 | }
607 | else
608 | {
609 | status = MH_ERROR_MEMORY_ALLOC;
610 | }
611 | }
612 | else
613 | {
614 | status = MH_ERROR_ALREADY_CREATED;
615 | }
616 | }
617 | else
618 | {
619 | status = MH_ERROR_NOT_EXECUTABLE;
620 | }
621 | }
622 | else
623 | {
624 | status = MH_ERROR_NOT_INITIALIZED;
625 | }
626 |
627 | LeaveSpinLock();
628 |
629 | return status;
630 | }
631 |
632 | //-------------------------------------------------------------------------
633 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget)
634 | {
635 | MH_STATUS status = MH_OK;
636 |
637 | EnterSpinLock();
638 |
639 | if (g_hHeap != NULL)
640 | {
641 | UINT pos = FindHookEntry(pTarget);
642 | if (pos != INVALID_HOOK_POS)
643 | {
644 | if (g_hooks.pItems[pos].isEnabled)
645 | {
646 | FROZEN_THREADS threads;
647 | Freeze(&threads, pos, ACTION_DISABLE);
648 |
649 | status = EnableHookLL(pos, FALSE);
650 |
651 | Unfreeze(&threads);
652 | }
653 |
654 | if (status == MH_OK)
655 | {
656 | FreeBuffer(g_hooks.pItems[pos].pTrampoline);
657 | DeleteHookEntry(pos);
658 | }
659 | }
660 | else
661 | {
662 | status = MH_ERROR_NOT_CREATED;
663 | }
664 | }
665 | else
666 | {
667 | status = MH_ERROR_NOT_INITIALIZED;
668 | }
669 |
670 | LeaveSpinLock();
671 |
672 | return status;
673 | }
674 |
675 | //-------------------------------------------------------------------------
676 | static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable)
677 | {
678 | MH_STATUS status = MH_OK;
679 |
680 | EnterSpinLock();
681 |
682 | if (g_hHeap != NULL)
683 | {
684 | if (pTarget == MH_ALL_HOOKS)
685 | {
686 | status = EnableAllHooksLL(enable);
687 | }
688 | else
689 | {
690 | FROZEN_THREADS threads;
691 | UINT pos = FindHookEntry(pTarget);
692 | if (pos != INVALID_HOOK_POS)
693 | {
694 | if (g_hooks.pItems[pos].isEnabled != enable)
695 | {
696 | Freeze(&threads, pos, ACTION_ENABLE);
697 |
698 | status = EnableHookLL(pos, enable);
699 |
700 | Unfreeze(&threads);
701 | }
702 | else
703 | {
704 | status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED;
705 | }
706 | }
707 | else
708 | {
709 | status = MH_ERROR_NOT_CREATED;
710 | }
711 | }
712 | }
713 | else
714 | {
715 | status = MH_ERROR_NOT_INITIALIZED;
716 | }
717 |
718 | LeaveSpinLock();
719 |
720 | return status;
721 | }
722 |
723 | //-------------------------------------------------------------------------
724 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget)
725 | {
726 | return EnableHook(pTarget, TRUE);
727 | }
728 |
729 | //-------------------------------------------------------------------------
730 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget)
731 | {
732 | return EnableHook(pTarget, FALSE);
733 | }
734 |
735 | //-------------------------------------------------------------------------
736 | static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable)
737 | {
738 | MH_STATUS status = MH_OK;
739 |
740 | EnterSpinLock();
741 |
742 | if (g_hHeap != NULL)
743 | {
744 | if (pTarget == MH_ALL_HOOKS)
745 | {
746 | UINT i;
747 | for (i = 0; i < g_hooks.size; ++i)
748 | g_hooks.pItems[i].queueEnable = queueEnable;
749 | }
750 | else
751 | {
752 | UINT pos = FindHookEntry(pTarget);
753 | if (pos != INVALID_HOOK_POS)
754 | {
755 | g_hooks.pItems[pos].queueEnable = queueEnable;
756 | }
757 | else
758 | {
759 | status = MH_ERROR_NOT_CREATED;
760 | }
761 | }
762 | }
763 | else
764 | {
765 | status = MH_ERROR_NOT_INITIALIZED;
766 | }
767 |
768 | LeaveSpinLock();
769 |
770 | return status;
771 | }
772 |
773 | //-------------------------------------------------------------------------
774 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget)
775 | {
776 | return QueueHook(pTarget, TRUE);
777 | }
778 |
779 | //-------------------------------------------------------------------------
780 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget)
781 | {
782 | return QueueHook(pTarget, FALSE);
783 | }
784 |
785 | //-------------------------------------------------------------------------
786 | MH_STATUS WINAPI MH_ApplyQueued(VOID)
787 | {
788 | MH_STATUS status = MH_OK;
789 | UINT i, first = INVALID_HOOK_POS;
790 |
791 | EnterSpinLock();
792 |
793 | if (g_hHeap != NULL)
794 | {
795 | for (i = 0; i < g_hooks.size; ++i)
796 | {
797 | if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable)
798 | {
799 | first = i;
800 | break;
801 | }
802 | }
803 |
804 | if (first != INVALID_HOOK_POS)
805 | {
806 | FROZEN_THREADS threads;
807 | Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED);
808 |
809 | for (i = first; i < g_hooks.size; ++i)
810 | {
811 | PHOOK_ENTRY pHook = &g_hooks.pItems[i];
812 | if (pHook->isEnabled != pHook->queueEnable)
813 | {
814 | status = EnableHookLL(i, pHook->queueEnable);
815 | if (status != MH_OK)
816 | break;
817 | }
818 | }
819 |
820 | Unfreeze(&threads);
821 | }
822 | }
823 | else
824 | {
825 | status = MH_ERROR_NOT_INITIALIZED;
826 | }
827 |
828 | LeaveSpinLock();
829 |
830 | return status;
831 | }
832 |
833 | //-------------------------------------------------------------------------
834 | MH_STATUS WINAPI MH_CreateHookApiEx(
835 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour,
836 | LPVOID* ppOriginal, LPVOID* ppTarget)
837 | {
838 | HMODULE hModule;
839 | LPVOID pTarget;
840 |
841 | hModule = GetModuleHandleW(pszModule);
842 | if (hModule == NULL)
843 | return MH_ERROR_MODULE_NOT_FOUND;
844 |
845 | pTarget = (LPVOID)GetProcAddress(hModule, pszProcName);
846 | if (pTarget == NULL)
847 | return MH_ERROR_FUNCTION_NOT_FOUND;
848 |
849 | if (ppTarget != NULL)
850 | *ppTarget = pTarget;
851 |
852 | return MH_CreateHook(pTarget, pDetour, ppOriginal);
853 | }
854 |
855 | //-------------------------------------------------------------------------
856 | MH_STATUS WINAPI MH_CreateHookApi(
857 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal)
858 | {
859 | return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL);
860 | }
861 |
862 | //-------------------------------------------------------------------------
863 | const char* WINAPI MH_StatusToString(MH_STATUS status)
864 | {
865 | #define MH_ST2STR(x) \
866 | case x: \
867 | return #x;
868 |
869 | switch (status) {
870 | MH_ST2STR(MH_UNKNOWN)
871 | MH_ST2STR(MH_OK)
872 | MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED)
873 | MH_ST2STR(MH_ERROR_NOT_INITIALIZED)
874 | MH_ST2STR(MH_ERROR_ALREADY_CREATED)
875 | MH_ST2STR(MH_ERROR_NOT_CREATED)
876 | MH_ST2STR(MH_ERROR_ENABLED)
877 | MH_ST2STR(MH_ERROR_DISABLED)
878 | MH_ST2STR(MH_ERROR_NOT_EXECUTABLE)
879 | MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION)
880 | MH_ST2STR(MH_ERROR_MEMORY_ALLOC)
881 | MH_ST2STR(MH_ERROR_MEMORY_PROTECT)
882 | MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND)
883 | MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND)
884 | }
885 |
886 | #undef MH_ST2STR
887 |
888 | return "(unknown)";
889 | }
890 |
--------------------------------------------------------------------------------
/libs/MinHook/hookmain.cpp:
--------------------------------------------------------------------------------
1 | #include "../../pch.h"
2 | #include "hookmain.h"
3 | #include
4 | #include
5 |
6 | #if KIERO_INCLUDE_D3D9
7 | # include
8 | #endif
9 |
10 | #if KIERO_INCLUDE_D3D10
11 | # include
12 | # include
13 | # include
14 | #endif
15 |
16 | #if KIERO_INCLUDE_D3D11
17 | # include
18 | # include
19 | #endif
20 |
21 | #if KIERO_INCLUDE_D3D12
22 | # include
23 | # include
24 | #endif
25 |
26 | #if KIERO_INCLUDE_OPENGL
27 | # include
28 | #endif
29 |
30 | #if KIERO_INCLUDE_VULKAN
31 | # include
32 | #endif
33 |
34 | #if KIERO_USE_MINHOOK
35 | # include "MinHook.h"
36 | #endif
37 |
38 | #ifdef _UNICODE
39 | # define KIERO_TEXT(text) L##text
40 | #else
41 | # define KIERO_TEXT(text) text
42 | #endif
43 |
44 | #define KIERO_ARRAY_SIZE(arr) ((size_t)(sizeof(arr)/sizeof(arr[0])))
45 |
46 | static kiero::RenderType::Enum g_renderType = kiero::RenderType::None;
47 | static uint150_t* g_methodsTable = NULL;
48 |
49 | kiero::Status::Enum kiero::init(RenderType::Enum _renderType)
50 | {
51 | if (g_renderType != RenderType::None)
52 | {
53 | return Status::AlreadyInitializedError;
54 | }
55 |
56 | if (_renderType != RenderType::None)
57 | {
58 | if (_renderType >= RenderType::D3D9 && _renderType <= RenderType::D3D12)
59 | {
60 | WNDCLASSEX windowClass;
61 | windowClass.cbSize = sizeof(WNDCLASSEX);
62 | windowClass.style = CS_HREDRAW | CS_VREDRAW;
63 | windowClass.lpfnWndProc = DefWindowProc;
64 | windowClass.cbClsExtra = 0;
65 | windowClass.cbWndExtra = 0;
66 | windowClass.hInstance = GetModuleHandle(NULL);
67 | windowClass.hIcon = NULL;
68 | windowClass.hCursor = NULL;
69 | windowClass.hbrBackground = NULL;
70 | windowClass.lpszMenuName = NULL;
71 | windowClass.lpszClassName = KIERO_TEXT("Kiero");
72 | windowClass.hIconSm = NULL;
73 |
74 | ::RegisterClassEx(&windowClass);
75 |
76 | HWND window = ::CreateWindow(windowClass.lpszClassName, KIERO_TEXT("Kiero DirectX Window"), WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, windowClass.hInstance, NULL);
77 |
78 | if (_renderType == RenderType::D3D9)
79 | {
80 | #if KIERO_INCLUDE_D3D9
81 | HMODULE libD3D9;
82 | if ((libD3D9 = ::GetModuleHandle(KIERO_TEXT("d3d9.dll"))) == NULL)
83 | {
84 | ::DestroyWindow(window);
85 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
86 | return Status::ModuleNotFoundError;
87 | }
88 |
89 | void* Direct3DCreate9;
90 | if ((Direct3DCreate9 = ::GetProcAddress(libD3D9, "Direct3DCreate9")) == NULL)
91 | {
92 | ::DestroyWindow(window);
93 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
94 | return Status::UnknownError;
95 | }
96 |
97 | LPDIRECT3D9 direct3D9;
98 | if ((direct3D9 = ((LPDIRECT3D9(__stdcall*)(uint32_t))(Direct3DCreate9))(D3D_SDK_VERSION)) == NULL)
99 | {
100 | ::DestroyWindow(window);
101 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
102 | return Status::UnknownError;
103 | }
104 |
105 | D3DDISPLAYMODE displayMode;
106 | if (direct3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode) < 0)
107 | {
108 | ::DestroyWindow(window);
109 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
110 | return Status::UnknownError;
111 | }
112 |
113 | D3DPRESENT_PARAMETERS params;
114 | params.BackBufferWidth = 0;
115 | params.BackBufferHeight = 0;
116 | params.BackBufferFormat = displayMode.Format;
117 | params.BackBufferCount = 0;
118 | params.MultiSampleType = D3DMULTISAMPLE_NONE;
119 | params.MultiSampleQuality = NULL;
120 | params.SwapEffect = D3DSWAPEFFECT_DISCARD;
121 | params.hDeviceWindow = window;
122 | params.Windowed = 1;
123 | params.EnableAutoDepthStencil = 0;
124 | params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
125 | params.Flags = NULL;
126 | params.FullScreen_RefreshRateInHz = 0;
127 | params.PresentationInterval = 0;
128 |
129 | LPDIRECT3DDEVICE9 device;
130 | if (direct3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, ¶ms, &device) < 0)
131 | {
132 | direct3D9->Release();
133 | ::DestroyWindow(window);
134 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
135 | return Status::UnknownError;
136 | }
137 |
138 | g_methodsTable = (uint150_t*)::calloc(119, sizeof(uint150_t));
139 | ::memcpy(g_methodsTable, *(uint150_t**)device, 119 * sizeof(uint150_t));
140 |
141 | #if KIERO_USE_MINHOOK
142 | MH_Initialize();
143 | #endif
144 |
145 | direct3D9->Release();
146 | direct3D9 = NULL;
147 |
148 | device->Release();
149 | device = NULL;
150 |
151 | g_renderType = RenderType::D3D9;
152 |
153 | ::DestroyWindow(window);
154 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
155 |
156 | return Status::Success;
157 | #endif
158 | }
159 | else if (_renderType == RenderType::D3D10)
160 | {
161 | #if KIERO_INCLUDE_D3D10
162 | HMODULE libDXGI;
163 | HMODULE libD3D10;
164 | if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D10 = ::GetModuleHandle(KIERO_TEXT("d3d10.dll"))) == NULL)
165 | {
166 | ::DestroyWindow(window);
167 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
168 | return Status::ModuleNotFoundError;
169 | }
170 |
171 | void* CreateDXGIFactory;
172 | if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL)
173 | {
174 | ::DestroyWindow(window);
175 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
176 | return Status::UnknownError;
177 | }
178 |
179 | IDXGIFactory* factory;
180 | if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0)
181 | {
182 | ::DestroyWindow(window);
183 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
184 | return Status::UnknownError;
185 | }
186 |
187 | IDXGIAdapter* adapter;
188 | if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND)
189 | {
190 | ::DestroyWindow(window);
191 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
192 | return Status::UnknownError;
193 | }
194 |
195 | void* D3D10CreateDeviceAndSwapChain;
196 | if ((D3D10CreateDeviceAndSwapChain = ::GetProcAddress(libD3D10, "D3D10CreateDeviceAndSwapChain")) == NULL)
197 | {
198 | ::DestroyWindow(window);
199 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
200 | return Status::UnknownError;
201 | }
202 |
203 | DXGI_RATIONAL refreshRate;
204 | refreshRate.Numerator = 60;
205 | refreshRate.Denominator = 1;
206 |
207 | DXGI_MODE_DESC bufferDesc;
208 | bufferDesc.Width = 100;
209 | bufferDesc.Height = 100;
210 | bufferDesc.RefreshRate = refreshRate;
211 | bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
212 | bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
213 | bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
214 |
215 | DXGI_SAMPLE_DESC sampleDesc;
216 | sampleDesc.Count = 1;
217 | sampleDesc.Quality = 0;
218 |
219 | DXGI_SWAP_CHAIN_DESC swapChainDesc;
220 | swapChainDesc.BufferDesc = bufferDesc;
221 | swapChainDesc.SampleDesc = sampleDesc;
222 | swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
223 | swapChainDesc.BufferCount = 1;
224 | swapChainDesc.OutputWindow = window;
225 | swapChainDesc.Windowed = 1;
226 | swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
227 | swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
228 |
229 | IDXGISwapChain* swapChain;
230 | ID3D10Device* device;
231 |
232 | if (((long(__stdcall*)(
233 | IDXGIAdapter*,
234 | D3D10_DRIVER_TYPE,
235 | HMODULE,
236 | UINT,
237 | UINT,
238 | DXGI_SWAP_CHAIN_DESC*,
239 | IDXGISwapChain**,
240 | ID3D10Device**))(D3D10CreateDeviceAndSwapChain))(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &swapChainDesc, &swapChain, &device) < 0)
241 | {
242 | ::DestroyWindow(window);
243 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
244 | return Status::UnknownError;
245 | }
246 |
247 | g_methodsTable = (uint150_t*)::calloc(116, sizeof(uint150_t));
248 | ::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
249 | ::memcpy(g_methodsTable + 18, *(uint150_t**)device, 98 * sizeof(uint150_t));
250 |
251 | #if KIERO_USE_MINHOOK
252 | MH_Initialize();
253 | #endif
254 |
255 | swapChain->Release();
256 | swapChain = NULL;
257 |
258 | device->Release();
259 | device = NULL;
260 |
261 | ::DestroyWindow(window);
262 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
263 |
264 | g_renderType = RenderType::D3D10;
265 |
266 | return Status::Success;
267 | #endif
268 | }
269 | else if (_renderType == RenderType::D3D11)
270 | {
271 | #if KIERO_INCLUDE_D3D11
272 | HMODULE libD3D11;
273 | if ((libD3D11 = ::GetModuleHandle(KIERO_TEXT("d3d11.dll"))) == NULL)
274 | {
275 | ::DestroyWindow(window);
276 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
277 | return Status::ModuleNotFoundError;
278 | }
279 |
280 | void* D3D11CreateDeviceAndSwapChain;
281 | if ((D3D11CreateDeviceAndSwapChain = ::GetProcAddress(libD3D11, "D3D11CreateDeviceAndSwapChain")) == NULL)
282 | {
283 | ::DestroyWindow(window);
284 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
285 | return Status::UnknownError;
286 | }
287 |
288 | D3D_FEATURE_LEVEL featureLevel;
289 | const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0 };
290 |
291 | DXGI_RATIONAL refreshRate;
292 | refreshRate.Numerator = 60;
293 | refreshRate.Denominator = 1;
294 |
295 | DXGI_MODE_DESC bufferDesc;
296 | bufferDesc.Width = 100;
297 | bufferDesc.Height = 100;
298 | bufferDesc.RefreshRate = refreshRate;
299 | bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
300 | bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
301 | bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
302 |
303 | DXGI_SAMPLE_DESC sampleDesc;
304 | sampleDesc.Count = 1;
305 | sampleDesc.Quality = 0;
306 |
307 | DXGI_SWAP_CHAIN_DESC swapChainDesc;
308 | swapChainDesc.BufferDesc = bufferDesc;
309 | swapChainDesc.SampleDesc = sampleDesc;
310 | swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
311 | swapChainDesc.BufferCount = 1;
312 | swapChainDesc.OutputWindow = window;
313 | swapChainDesc.Windowed = 1;
314 | swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
315 | swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
316 |
317 | IDXGISwapChain* swapChain;
318 | ID3D11Device* device;
319 | ID3D11DeviceContext* context;
320 |
321 | if (((long(__stdcall*)(
322 | IDXGIAdapter*,
323 | D3D_DRIVER_TYPE,
324 | HMODULE,
325 | UINT,
326 | const D3D_FEATURE_LEVEL*,
327 | UINT,
328 | UINT,
329 | const DXGI_SWAP_CHAIN_DESC*,
330 | IDXGISwapChain**,
331 | ID3D11Device**,
332 | D3D_FEATURE_LEVEL*,
333 | ID3D11DeviceContext**))(D3D11CreateDeviceAndSwapChain))(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, &featureLevel, &context) < 0)
334 | {
335 | ::DestroyWindow(window);
336 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
337 | return Status::UnknownError;
338 | }
339 |
340 | g_methodsTable = (uint150_t*)::calloc(205, sizeof(uint150_t));
341 | ::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
342 | ::memcpy(g_methodsTable + 18, *(uint150_t**)device, 43 * sizeof(uint150_t));
343 | ::memcpy(g_methodsTable + 18 + 43, *(uint150_t**)context, 144 * sizeof(uint150_t));
344 |
345 | #if KIERO_USE_MINHOOK
346 | MH_Initialize();
347 | #endif
348 |
349 | swapChain->Release();
350 | swapChain = NULL;
351 |
352 | device->Release();
353 | device = NULL;
354 |
355 | context->Release();
356 | context = NULL;
357 |
358 | ::DestroyWindow(window);
359 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
360 |
361 | g_renderType = RenderType::D3D11;
362 |
363 | return Status::Success;
364 | #endif
365 | }
366 | else if (_renderType == RenderType::D3D12)
367 | {
368 | #if KIERO_INCLUDE_D3D12
369 | HMODULE libDXGI;
370 | HMODULE libD3D12;
371 | if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D12 = ::GetModuleHandle(KIERO_TEXT("d3d12.dll"))) == NULL)
372 | {
373 | ::DestroyWindow(window);
374 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
375 | return Status::ModuleNotFoundError;
376 | }
377 |
378 | void* CreateDXGIFactory;
379 | if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL)
380 | {
381 | ::DestroyWindow(window);
382 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
383 | return Status::UnknownError;
384 | }
385 |
386 | IDXGIFactory* factory;
387 | if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0)
388 | {
389 | ::DestroyWindow(window);
390 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
391 | return Status::UnknownError;
392 | }
393 |
394 | IDXGIAdapter* adapter;
395 | if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND)
396 | {
397 | ::DestroyWindow(window);
398 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
399 | return Status::UnknownError;
400 | }
401 |
402 | void* D3D12CreateDevice;
403 | if ((D3D12CreateDevice = ::GetProcAddress(libD3D12, "D3D12CreateDevice")) == NULL)
404 | {
405 | ::DestroyWindow(window);
406 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
407 | return Status::UnknownError;
408 | }
409 |
410 | ID3D12Device* device;
411 | if (((long(__stdcall*)(IUnknown*, D3D_FEATURE_LEVEL, const IID&, void**))(D3D12CreateDevice))(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&device) < 0)
412 | {
413 | ::DestroyWindow(window);
414 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
415 | return Status::UnknownError;
416 | }
417 |
418 | D3D12_COMMAND_QUEUE_DESC queueDesc;
419 | queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
420 | queueDesc.Priority = 0;
421 | queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
422 | queueDesc.NodeMask = 0;
423 |
424 | ID3D12CommandQueue* commandQueue;
425 | if (device->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue) < 0)
426 | {
427 | ::DestroyWindow(window);
428 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
429 | return Status::UnknownError;
430 | }
431 |
432 | ID3D12CommandAllocator* commandAllocator;
433 | if (device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&commandAllocator) < 0)
434 | {
435 | ::DestroyWindow(window);
436 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
437 | return Status::UnknownError;
438 | }
439 |
440 | ID3D12GraphicsCommandList* commandList;
441 | if (device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&commandList) < 0)
442 | {
443 | ::DestroyWindow(window);
444 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
445 | return Status::UnknownError;
446 | }
447 |
448 | DXGI_RATIONAL refreshRate;
449 | refreshRate.Numerator = 60;
450 | refreshRate.Denominator = 1;
451 |
452 | DXGI_MODE_DESC bufferDesc;
453 | bufferDesc.Width = 100;
454 | bufferDesc.Height = 100;
455 | bufferDesc.RefreshRate = refreshRate;
456 | bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
457 | bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
458 | bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
459 |
460 | DXGI_SAMPLE_DESC sampleDesc;
461 | sampleDesc.Count = 1;
462 | sampleDesc.Quality = 0;
463 |
464 | DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
465 | swapChainDesc.BufferDesc = bufferDesc;
466 | swapChainDesc.SampleDesc = sampleDesc;
467 | swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
468 | swapChainDesc.BufferCount = 2;
469 | swapChainDesc.OutputWindow = window;
470 | swapChainDesc.Windowed = 1;
471 | swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
472 | swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
473 |
474 | IDXGISwapChain* swapChain;
475 | if (factory->CreateSwapChain(commandQueue, &swapChainDesc, &swapChain) < 0)
476 | {
477 | ::DestroyWindow(window);
478 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
479 | return Status::UnknownError;
480 | }
481 |
482 | g_methodsTable = (uint150_t*)::calloc(150, sizeof(uint150_t));
483 | ::memcpy(g_methodsTable, *(uint150_t**)device, 44 * sizeof(uint150_t));
484 | ::memcpy(g_methodsTable + 44, *(uint150_t**)commandQueue, 19 * sizeof(uint150_t));
485 | ::memcpy(g_methodsTable + 44 + 19, *(uint150_t**)commandAllocator, 9 * sizeof(uint150_t));
486 | ::memcpy(g_methodsTable + 44 + 19 + 9, *(uint150_t**)commandList, 60 * sizeof(uint150_t));
487 | ::memcpy(g_methodsTable + 44 + 19 + 9 + 60, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
488 |
489 | #if KIERO_USE_MINHOOK
490 | MH_Initialize();
491 | #endif
492 |
493 | device->Release();
494 | device = NULL;
495 |
496 | commandQueue->Release();
497 | commandQueue = NULL;
498 |
499 | commandAllocator->Release();
500 | commandAllocator = NULL;
501 |
502 | commandList->Release();
503 | commandList = NULL;
504 |
505 | swapChain->Release();
506 | swapChain = NULL;
507 |
508 | ::DestroyWindow(window);
509 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
510 |
511 | g_renderType = RenderType::D3D12;
512 |
513 | return Status::Success;
514 | #endif
515 | }
516 |
517 | ::DestroyWindow(window);
518 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
519 |
520 | return Status::NotSupportedError;
521 | }
522 | else if (_renderType == RenderType::OpenGL)
523 | {
524 | #if KIERO_INCLUDE_OPENGL
525 | HMODULE libOpenGL32;
526 | if ((libOpenGL32 = ::GetModuleHandle(KIERO_TEXT("opengl32.dll"))) == NULL)
527 | {
528 | return Status::ModuleNotFoundError;
529 | }
530 |
531 | const char* const methodsNames[] = {
532 | "glAccum", "glAlphaFunc", "glAreTexturesResident", "glArrayElement", "glBegin", "glBindTexture", "glBitmap", "glBlendFunc", "glCallList", "glCallLists", "glClear", "glClearAccum",
533 | "glClearColor", "glClearDepth", "glClearIndex", "glClearStencil", "glClipPlane", "glColor3b", "glColor3bv", "glColor3d", "glColor3dv", "glColor3f", "glColor3fv", "glColor3i", "glColor3iv",
534 | "glColor3s", "glColor3sv", "glColor3ub", "glColor3ubv", "glColor3ui", "glColor3uiv", "glColor3us", "glColor3usv", "glColor4b", "glColor4bv", "glColor4d", "glColor4dv", "glColor4f",
535 | "glColor4fv", "glColor4i", "glColor4iv", "glColor4s", "glColor4sv", "glColor4ub", "glColor4ubv", "glColor4ui", "glColor4uiv", "glColor4us", "glColor4usv", "glColorMask", "glColorMaterial",
536 | "glColorPointer", "glCopyPixels", "glCopyTexImage1D", "glCopyTexImage2D", "glCopyTexSubImage1D", "glCopyTexSubImage2D", "glCullFaceglCullFace", "glDeleteLists", "glDeleteTextures",
537 | "glDepthFunc", "glDepthMask", "glDepthRange", "glDisable", "glDisableClientState", "glDrawArrays", "glDrawBuffer", "glDrawElements", "glDrawPixels", "glEdgeFlag", "glEdgeFlagPointer",
538 | "glEdgeFlagv", "glEnable", "glEnableClientState", "glEnd", "glEndList", "glEvalCoord1d", "glEvalCoord1dv", "glEvalCoord1f", "glEvalCoord1fv", "glEvalCoord2d", "glEvalCoord2dv",
539 | "glEvalCoord2f", "glEvalCoord2fv", "glEvalMesh1", "glEvalMesh2", "glEvalPoint1", "glEvalPoint2", "glFeedbackBuffer", "glFinish", "glFlush", "glFogf", "glFogfv", "glFogi", "glFogiv",
540 | "glFrontFace", "glFrustum", "glGenLists", "glGenTextures", "glGetBooleanv", "glGetClipPlane", "glGetDoublev", "glGetError", "glGetFloatv", "glGetIntegerv", "glGetLightfv", "glGetLightiv",
541 | "glGetMapdv", "glGetMapfv", "glGetMapiv", "glGetMaterialfv", "glGetMaterialiv", "glGetPixelMapfv", "glGetPixelMapuiv", "glGetPixelMapusv", "glGetPointerv", "glGetPolygonStipple",
542 | "glGetString", "glGetTexEnvfv", "glGetTexEnviv", "glGetTexGendv", "glGetTexGenfv", "glGetTexGeniv", "glGetTexImage", "glGetTexLevelParameterfv", "glGetTexLevelParameteriv",
543 | "glGetTexParameterfv", "glGetTexParameteriv", "glHint", "glIndexMask", "glIndexPointer", "glIndexd", "glIndexdv", "glIndexf", "glIndexfv", "glIndexi", "glIndexiv", "glIndexs", "glIndexsv",
544 | "glIndexub", "glIndexubv", "glInitNames", "glInterleavedArrays", "glIsEnabled", "glIsList", "glIsTexture", "glLightModelf", "glLightModelfv", "glLightModeli", "glLightModeliv", "glLightf",
545 | "glLightfv", "glLighti", "glLightiv", "glLineStipple", "glLineWidth", "glListBase", "glLoadIdentity", "glLoadMatrixd", "glLoadMatrixf", "glLoadName", "glLogicOp", "glMap1d", "glMap1f",
546 | "glMap2d", "glMap2f", "glMapGrid1d", "glMapGrid1f", "glMapGrid2d", "glMapGrid2f", "glMaterialf", "glMaterialfv", "glMateriali", "glMaterialiv", "glMatrixMode", "glMultMatrixd",
547 | "glMultMatrixf", "glNewList", "glNormal3b", "glNormal3bv", "glNormal3d", "glNormal3dv", "glNormal3f", "glNormal3fv", "glNormal3i", "glNormal3iv", "glNormal3s", "glNormal3sv",
548 | "glNormalPointer", "glOrtho", "glPassThrough", "glPixelMapfv", "glPixelMapuiv", "glPixelMapusv", "glPixelStoref", "glPixelStorei", "glPixelTransferf", "glPixelTransferi", "glPixelZoom",
549 | "glPointSize", "glPolygonMode", "glPolygonOffset", "glPolygonStipple", "glPopAttrib", "glPopClientAttrib", "glPopMatrix", "glPopName", "glPrioritizeTextures", "glPushAttrib",
550 | "glPushClientAttrib", "glPushMatrix", "glPushName", "glRasterPos2d", "glRasterPos2dv", "glRasterPos2f", "glRasterPos2fv", "glRasterPos2i", "glRasterPos2iv", "glRasterPos2s",
551 | "glRasterPos2sv", "glRasterPos3d", "glRasterPos3dv", "glRasterPos3f", "glRasterPos3fv", "glRasterPos3i", "glRasterPos3iv", "glRasterPos3s", "glRasterPos3sv", "glRasterPos4d",
552 | "glRasterPos4dv", "glRasterPos4f", "glRasterPos4fv", "glRasterPos4i", "glRasterPos4iv", "glRasterPos4s", "glRasterPos4sv", "glReadBuffer", "glReadPixels", "glRectd", "glRectdv", "glRectf",
553 | "glRectfv", "glRecti", "glRectiv", "glRects", "glRectsv", "glRenderMode", "glRotated", "glRotatef", "glScaled", "glScalef", "glScissor", "glSelectBuffer", "glShadeModel", "glStencilFunc",
554 | "glStencilMask", "glStencilOp", "glTexCoord1d", "glTexCoord1dv", "glTexCoord1f", "glTexCoord1fv", "glTexCoord1i", "glTexCoord1iv", "glTexCoord1s", "glTexCoord1sv", "glTexCoord2d",
555 | "glTexCoord2dv", "glTexCoord2f", "glTexCoord2fv", "glTexCoord2i", "glTexCoord2iv", "glTexCoord2s", "glTexCoord2sv", "glTexCoord3d", "glTexCoord3dv", "glTexCoord3f", "glTexCoord3fv",
556 | "glTexCoord3i", "glTexCoord3iv", "glTexCoord3s", "glTexCoord3sv", "glTexCoord4d", "glTexCoord4dv", "glTexCoord4f", "glTexCoord4fv", "glTexCoord4i", "glTexCoord4iv", "glTexCoord4s",
557 | "glTexCoord4sv", "glTexCoordPointer", "glTexEnvf", "glTexEnvfv", "glTexEnvi", "glTexEnviv", "glTexGend", "glTexGendv", "glTexGenf", "glTexGenfv", "glTexGeni", "glTexGeniv", "glTexImage1D",
558 | "glTexImage2D", "glTexParameterf", "glTexParameterfv", "glTexParameteri", "glTexParameteriv", "glTexSubImage1D", "glTexSubImage2D", "glTranslated", "glTranslatef", "glVertex2d",
559 | "glVertex2dv", "glVertex2f", "glVertex2fv", "glVertex2i", "glVertex2iv", "glVertex2s", "glVertex2sv", "glVertex3d", "glVertex3dv", "glVertex3f", "glVertex3fv", "glVertex3i", "glVertex3iv",
560 | "glVertex3s", "glVertex3sv", "glVertex4d", "glVertex4dv", "glVertex4f", "glVertex4fv", "glVertex4i", "glVertex4iv", "glVertex4s", "glVertex4sv", "glVertexPointer", "glViewport"
561 | };
562 |
563 | size_t size = KIERO_ARRAY_SIZE(methodsNames);
564 |
565 | g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t));
566 |
567 | for (int i = 0; i < size; i++)
568 | {
569 | g_methodsTable[i] = (uint150_t)::GetProcAddress(libOpenGL32, methodsNames[i]);
570 | }
571 |
572 | #if KIERO_USE_MINHOOK
573 | MH_Initialize();
574 | #endif
575 |
576 | g_renderType = RenderType::OpenGL;
577 |
578 | return Status::Success;
579 | #endif
580 | }
581 | else if (_renderType == RenderType::Vulkan)
582 | {
583 | #if KIERO_INCLUDE_VULKAN
584 | HMODULE libVulkan;
585 | if ((libVulkan = GetModuleHandle(KIERO_TEXT("vulcan-1.dll"))) == NULL)
586 | {
587 | return Status::ModuleNotFoundError;
588 | }
589 |
590 | const char* const methodsNames[] = {
591 | "vkCreateInstance", "vkDestroyInstance", "vkEnumeratePhysicalDevices", "vkGetPhysicalDeviceFeatures", "vkGetPhysicalDeviceFormatProperties", "vkGetPhysicalDeviceImageFormatProperties",
592 | "vkGetPhysicalDeviceProperties", "vkGetPhysicalDeviceQueueFamilyProperties", "vkGetPhysicalDeviceMemoryProperties", "vkGetInstanceProcAddr", "vkGetDeviceProcAddr", "vkCreateDevice",
593 | "vkDestroyDevice", "vkEnumerateInstanceExtensionProperties", "vkEnumerateDeviceExtensionProperties", "vkEnumerateDeviceLayerProperties", "vkGetDeviceQueue", "vkQueueSubmit", "vkQueueWaitIdle",
594 | "vkDeviceWaitIdle", "vkAllocateMemory", "vkFreeMemory", "vkMapMemory", "vkUnmapMemory", "vkFlushMappedMemoryRanges", "vkInvalidateMappedMemoryRanges", "vkGetDeviceMemoryCommitment",
595 | "vkBindBufferMemory", "vkBindImageMemory", "vkGetBufferMemoryRequirements", "vkGetImageMemoryRequirements", "vkGetImageSparseMemoryRequirements", "vkGetPhysicalDeviceSparseImageFormatProperties",
596 | "vkQueueBindSparse", "vkCreateFence", "vkDestroyFence", "vkResetFences", "vkGetFenceStatus", "vkWaitForFences", "vkCreateSemaphore", "vkDestroySemaphore", "vkCreateEvent", "vkDestroyEvent",
597 | "vkGetEventStatus", "vkSetEvent", "vkResetEvent", "vkCreateQueryPool", "vkDestroyQueryPool", "vkGetQueryPoolResults", "vkCreateBuffer", "vkDestroyBuffer", "vkCreateBufferView", "vkDestroyBufferView",
598 | "vkCreateImage", "vkDestroyImage", "vkGetImageSubresourceLayout", "vkCreateImageView", "vkDestroyImageView", "vkCreateShaderModule", "vkDestroyShaderModule", "vkCreatePipelineCache",
599 | "vkDestroyPipelineCache", "vkGetPipelineCacheData", "vkMergePipelineCaches", "vkCreateGraphicsPipelines", "vkCreateComputePipelines", "vkDestroyPipeline", "vkCreatePipelineLayout",
600 | "vkDestroyPipelineLayout", "vkCreateSampler", "vkDestroySampler", "vkCreateDescriptorSetLayout", "vkDestroyDescriptorSetLayout", "vkCreateDescriptorPool", "vkDestroyDescriptorPool",
601 | "vkResetDescriptorPool", "vkAllocateDescriptorSets", "vkFreeDescriptorSets", "vkUpdateDescriptorSets", "vkCreateFramebuffer", "vkDestroyFramebuffer", "vkCreateRenderPass", "vkDestroyRenderPass",
602 | "vkGetRenderAreaGranularity", "vkCreateCommandPool", "vkDestroyCommandPool", "vkResetCommandPool", "vkAllocateCommandBuffers", "vkFreeCommandBuffers", "vkBeginCommandBuffer", "vkEndCommandBuffer",
603 | "vkResetCommandBuffer", "vkCmdBindPipeline", "vkCmdSetViewport", "vkCmdSetScissor", "vkCmdSetLineWidth", "vkCmdSetDepthBias", "vkCmdSetBlendConstants", "vkCmdSetDepthBounds",
604 | "vkCmdSetStencilCompareMask", "vkCmdSetStencilWriteMask", "vkCmdSetStencilReference", "vkCmdBindDescriptorSets", "vkCmdBindIndexBuffer", "vkCmdBindVertexBuffers", "vkCmdDraw", "vkCmdDrawIndexed",
605 | "vkCmdDrawIndirect", "vkCmdDrawIndexedIndirect", "vkCmdDispatch", "vkCmdDispatchIndirect", "vkCmdCopyBuffer", "vkCmdCopyImage", "vkCmdBlitImage", "vkCmdCopyBufferToImage", "vkCmdCopyImageToBuffer",
606 | "vkCmdUpdateBuffer", "vkCmdFillBuffer", "vkCmdClearColorImage", "vkCmdClearDepthStencilImage", "vkCmdClearAttachments", "vkCmdResolveImage", "vkCmdSetEvent", "vkCmdResetEvent", "vkCmdWaitEvents",
607 | "vkCmdPipelineBarrier", "vkCmdBeginQuery", "vkCmdEndQuery", "vkCmdResetQueryPool", "vkCmdWriteTimestamp", "vkCmdCopyQueryPoolResults", "vkCmdPushConstants", "vkCmdBeginRenderPass", "vkCmdNextSubpass",
608 | "vkCmdEndRenderPass", "vkCmdExecuteCommands"
609 | };
610 |
611 | size_t size = KIERO_ARRAY_SIZE(methodsNames);
612 |
613 | g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t));
614 |
615 | for (int i = 0; i < size; i++)
616 | {
617 | g_methodsTable[i] = (uint150_t)::GetProcAddress(libVulkan, methodsNames[i]);
618 | }
619 |
620 | #if KIERO_USE_MINHOOK
621 | MH_Initialize();
622 | #endif
623 |
624 | g_renderType = RenderType::Vulkan;
625 |
626 | return Status::Success;
627 | #endif
628 | }
629 | else if (_renderType == RenderType::Auto)
630 | {
631 | RenderType::Enum type = RenderType::None;
632 |
633 | if (::GetModuleHandle(KIERO_TEXT("d3d9.dll")) != NULL)
634 | {
635 | type = RenderType::D3D9;
636 | }
637 | else if (::GetModuleHandle(KIERO_TEXT("d3d10.dll")) != NULL)
638 | {
639 | type = RenderType::D3D10;
640 | }
641 | else if (::GetModuleHandle(KIERO_TEXT("d3d11.dll")) != NULL)
642 | {
643 | type = RenderType::D3D11;
644 | }
645 | else if (::GetModuleHandle(KIERO_TEXT("d3d12.dll")) != NULL)
646 | {
647 | type = RenderType::D3D12;
648 | }
649 | else if (::GetModuleHandle(KIERO_TEXT("opengl32.dll")) != NULL)
650 | {
651 | type = RenderType::OpenGL;
652 | }
653 | else if (::GetModuleHandle(KIERO_TEXT("vulcan-1.dll")) != NULL)
654 | {
655 | type = RenderType::Vulkan;
656 | }
657 |
658 | return init(type);
659 | }
660 | }
661 |
662 | return Status::Success;
663 | }
664 |
665 | void kiero::shutdown()
666 | {
667 | if (g_renderType != RenderType::None)
668 | {
669 | #if KIERO_USE_MINHOOK
670 | MH_DisableHook(MH_ALL_HOOKS);
671 | #endif
672 |
673 | ::free(g_methodsTable);
674 | g_methodsTable = NULL;
675 | g_renderType = RenderType::None;
676 | }
677 | }
678 |
679 | kiero::Status::Enum kiero::bind(uint16_t _index, void** _original, void* _function)
680 | {
681 | // TODO: Need own detour function
682 |
683 | assert(_index >= 0 && _original != NULL && _function != NULL);
684 |
685 | if (g_renderType != RenderType::None)
686 | {
687 | #if KIERO_USE_MINHOOK
688 | void* target = (void*)g_methodsTable[_index];
689 | if (MH_CreateHook(target, _function, _original) != MH_OK || MH_EnableHook(target) != MH_OK)
690 | {
691 | return Status::UnknownError;
692 | }
693 | #endif
694 |
695 | return Status::Success;
696 | }
697 |
698 | return Status::NotInitializedError;
699 | }
700 |
701 | void kiero::unbind(uint16_t _index)
702 | {
703 | assert(_index >= 0);
704 |
705 | if (g_renderType != RenderType::None)
706 | {
707 | #if KIERO_USE_MINHOOK
708 | MH_DisableHook((void*)g_methodsTable[_index]);
709 | #endif
710 | }
711 | }
712 |
713 | kiero::RenderType::Enum kiero::getRenderType()
714 | {
715 | return g_renderType;
716 | }
717 |
718 | uint150_t* kiero::getMethodsTable()
719 | {
720 | return g_methodsTable;
721 | }
--------------------------------------------------------------------------------
/libs/MinHook/hookmain.h:
--------------------------------------------------------------------------------
1 | #ifndef __KIERO_H__
2 | #define __KIERO_H__
3 |
4 | #include
5 |
6 | #define KIERO_VERSION "1.2.6"
7 |
8 | #define KIERO_INCLUDE_D3D9 0 // 1 if you need D3D9 hook
9 | #define KIERO_INCLUDE_D3D10 0 // 1 if you need D3D10 hook
10 | #define KIERO_INCLUDE_D3D11 1 // 1 if you need D3D11 hook
11 | #define KIERO_INCLUDE_D3D12 0 // 1 if you need D3D12 hook
12 | #define KIERO_INCLUDE_OPENGL 0 // 1 if you need OpenGL hook
13 | #define KIERO_INCLUDE_VULKAN 0 // 1 if you need Vulkan hook
14 | #define KIERO_USE_MINHOOK 1 // 1 if you will use kiero::bind function
15 |
16 | #define KIERO_ARCH_X64 0
17 | #define KIERO_ARCH_X86 0
18 |
19 | #if defined(_M_X64)
20 | # undef KIERO_ARCH_X64
21 | # define KIERO_ARCH_X64 1
22 | #else
23 | # undef KIERO_ARCH_X86
24 | # define KIERO_ARCH_X86 1
25 | #endif
26 |
27 | #if KIERO_ARCH_X64
28 | typedef uint64_t uint150_t;
29 | #else
30 | typedef uint32_t uint150_t;
31 | #endif
32 |
33 | namespace kiero
34 | {
35 | struct Status
36 | {
37 | enum Enum
38 | {
39 | UnknownError = -1,
40 | NotSupportedError = -2,
41 | ModuleNotFoundError = -3,
42 |
43 | AlreadyInitializedError = -4,
44 | NotInitializedError = -5,
45 |
46 | Success = 0,
47 | };
48 | };
49 |
50 | struct RenderType
51 | {
52 | enum Enum
53 | {
54 | None,
55 |
56 | D3D9,
57 | D3D10,
58 | D3D11,
59 | D3D12,
60 |
61 | OpenGL,
62 | Vulkan,
63 |
64 | Auto
65 | };
66 | };
67 |
68 | Status::Enum init(RenderType::Enum renderType);
69 | void shutdown();
70 |
71 | Status::Enum bind(uint16_t index, void** original, void* function);
72 | void unbind(uint16_t index);
73 |
74 | RenderType::Enum getRenderType();
75 | uint150_t* getMethodsTable();
76 | }
77 |
78 | #endif // __KIERO_H__
--------------------------------------------------------------------------------
/libs/MinHook/minhook.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | MH_Initialize
3 | MH_Uninitialize
4 |
5 | MH_CreateHook
6 | MH_CreateHookApi
7 | MH_CreateHookApiEx
8 | MH_RemoveHook
9 | MH_EnableHook
10 | MH_DisableHook
11 | MH_QueueEnableHook
12 | MH_QueueDisableHook
13 | MH_ApplyQueued
14 | MH_StatusToString
15 |
--------------------------------------------------------------------------------
/libs/MinHook/pstdint.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #include
30 |
31 | // Integer types for HDE.
32 | typedef INT8 int8_t;
33 | typedef INT16 int16_t;
34 | typedef INT32 int32_t;
35 | typedef INT64 int64_t;
36 | typedef UINT8 uint8_t;
37 | typedef UINT16 uint16_t;
38 | typedef UINT32 uint32_t;
39 | typedef UINT64 uint64_t;
40 |
--------------------------------------------------------------------------------
/libs/MinHook/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by PCSX2 Internal Mod Menu_D3D11.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/libs/MinHook/table32.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 32 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #define C_NONE 0x00
9 | #define C_MODRM 0x01
10 | #define C_IMM8 0x02
11 | #define C_IMM16 0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8 0x20
14 | #define C_REL32 0x40
15 | #define C_GROUP 0x80
16 | #define C_ERROR 0xff
17 |
18 | #define PRE_ANY 0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2 0x02
21 | #define PRE_F3 0x04
22 | #define PRE_66 0x08
23 | #define PRE_67 0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG 0x40
26 | #define PRE_ALL 0xff
27 |
28 | #define DELTA_OPCODES 0x4a
29 | #define DELTA_FPU_REG 0xf1
30 | #define DELTA_FPU_MODRM 0xf8
31 | #define DELTA_PREFIXES 0x130
32 | #define DELTA_OP_LOCK_OK 0x1a1
33 | #define DELTA_OP2_LOCK_OK 0x1b9
34 | #define DELTA_OP_ONLY_MEM 0x1cb
35 | #define DELTA_OP2_ONLY_MEM 0x1da
36 |
37 | unsigned char hde32_table[] = {
38 | 0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,
39 | 0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f,
40 | 0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3,
41 | 0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa,
42 | 0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90,
43 | 0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f,
44 | 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d,
45 | 0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59,
46 | 0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,
47 | 0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0,
48 | 0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01,
49 | 0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11,
50 | 0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8,
51 | 0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca,
52 | 0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff,
53 | 0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03,
54 | 0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,
55 | 0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,
56 | 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
57 | 0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
58 | 0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f,
59 | 0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a,
60 | 0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,
61 | 0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a,
62 | 0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06,
63 | 0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06,
64 | 0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
65 | 0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08,
66 | 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,
67 | 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,
68 | 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,
69 | 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,
70 | 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,
71 | 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,
72 | 0xe7,0x08,0x00,0xf0,0x02,0x00
73 | };
74 |
--------------------------------------------------------------------------------
/libs/MinHook/table64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #define C_NONE 0x00
9 | #define C_MODRM 0x01
10 | #define C_IMM8 0x02
11 | #define C_IMM16 0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8 0x20
14 | #define C_REL32 0x40
15 | #define C_GROUP 0x80
16 | #define C_ERROR 0xff
17 |
18 | #define PRE_ANY 0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2 0x02
21 | #define PRE_F3 0x04
22 | #define PRE_66 0x08
23 | #define PRE_67 0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG 0x40
26 | #define PRE_ALL 0xff
27 |
28 | #define DELTA_OPCODES 0x4a
29 | #define DELTA_FPU_REG 0xfd
30 | #define DELTA_FPU_MODRM 0x104
31 | #define DELTA_PREFIXES 0x13c
32 | #define DELTA_OP_LOCK_OK 0x1ae
33 | #define DELTA_OP2_LOCK_OK 0x1c6
34 | #define DELTA_OP_ONLY_MEM 0x1d8
35 | #define DELTA_OP2_ONLY_MEM 0x1e7
36 |
37 | unsigned char hde64_table[] = {
38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
73 | 0x00,0xf0,0x02,0x00
74 | };
75 |
--------------------------------------------------------------------------------
/libs/MinHook/trampoline.c:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include
30 |
31 | #ifndef ARRAYSIZE
32 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
33 | #endif
34 |
35 | #if defined(_M_X64) || defined(__x86_64__)
36 | #include "hde64.h"
37 | typedef hde64s HDE;
38 | #define HDE_DISASM(code, hs) hde64_disasm(code, hs)
39 | #else
40 | #include "hde32.h"
41 | typedef hde32s HDE;
42 | #define HDE_DISASM(code, hs) hde32_disasm(code, hs)
43 | #endif
44 |
45 | #include "trampoline.h"
46 | #include "buffer.h"
47 |
48 | // Maximum size of a trampoline function.
49 | #if defined(_M_X64) || defined(__x86_64__)
50 | #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
51 | #else
52 | #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
53 | #endif
54 |
55 | //-------------------------------------------------------------------------
56 | static BOOL IsCodePadding(LPBYTE pInst, UINT size)
57 | {
58 | UINT i;
59 |
60 | if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
61 | return FALSE;
62 |
63 | for (i = 1; i < size; ++i)
64 | {
65 | if (pInst[i] != pInst[0])
66 | return FALSE;
67 | }
68 | return TRUE;
69 | }
70 |
71 | //-------------------------------------------------------------------------
72 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
73 | {
74 | #if defined(_M_X64) || defined(__x86_64__)
75 | CALL_ABS call = {
76 | 0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
77 | 0xEB, 0x08, // EB 08: JMP +10
78 | 0x0000000000000000ULL // Absolute destination address
79 | };
80 | JMP_ABS jmp = {
81 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
82 | 0x0000000000000000ULL // Absolute destination address
83 | };
84 | JCC_ABS jcc = {
85 | 0x70, 0x0E, // 7* 0E: J** +16
86 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
87 | 0x0000000000000000ULL // Absolute destination address
88 | };
89 | #else
90 | CALL_REL call = {
91 | 0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx
92 | 0x00000000 // Relative destination address
93 | };
94 | JMP_REL jmp = {
95 | 0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx
96 | 0x00000000 // Relative destination address
97 | };
98 | JCC_REL jcc = {
99 | 0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx
100 | 0x00000000 // Relative destination address
101 | };
102 | #endif
103 |
104 | UINT8 oldPos = 0;
105 | UINT8 newPos = 0;
106 | ULONG_PTR jmpDest = 0; // Destination address of an internal jump.
107 | BOOL finished = FALSE; // Is the function completed?
108 | #if defined(_M_X64) || defined(__x86_64__)
109 | UINT8 instBuf[16];
110 | #endif
111 |
112 | ct->patchAbove = FALSE;
113 | ct->nIP = 0;
114 |
115 | do
116 | {
117 | HDE hs;
118 | UINT copySize;
119 | LPVOID pCopySrc;
120 | ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos;
121 | ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
122 |
123 | copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
124 | if (hs.flags & F_ERROR)
125 | return FALSE;
126 |
127 | pCopySrc = (LPVOID)pOldInst;
128 | if (oldPos >= sizeof(JMP_REL))
129 | {
130 | // The trampoline function is long enough.
131 | // Complete the function with the jump to the target function.
132 | #if defined(_M_X64) || defined(__x86_64__)
133 | jmp.address = pOldInst;
134 | #else
135 | jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
136 | #endif
137 | pCopySrc = &jmp;
138 | copySize = sizeof(jmp);
139 |
140 | finished = TRUE;
141 | }
142 | #if defined(_M_X64) || defined(__x86_64__)
143 | else if ((hs.modrm & 0xC7) == 0x05)
144 | {
145 | // Instructions using RIP relative addressing. (ModR/M = 00???101B)
146 |
147 | // Modify the RIP relative address.
148 | PUINT32 pRelAddr;
149 |
150 | // Avoid using memcpy to reduce the footprint.
151 | #ifndef _MSC_VER
152 | memcpy(instBuf, (LPBYTE)pOldInst, copySize);
153 | #else
154 | __movsb(instBuf, (LPBYTE)pOldInst, copySize);
155 | #endif
156 | pCopySrc = instBuf;
157 |
158 | // Relative address is stored at (instruction length - immediate value length - 4).
159 | pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
160 | *pRelAddr
161 | = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
162 |
163 | // Complete the function if JMP (FF /4).
164 | if (hs.opcode == 0xFF && hs.modrm_reg == 4)
165 | finished = TRUE;
166 | }
167 | #endif
168 | else if (hs.opcode == 0xE8)
169 | {
170 | // Direct relative CALL
171 | ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
172 | #if defined(_M_X64) || defined(__x86_64__)
173 | call.address = dest;
174 | #else
175 | call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
176 | #endif
177 | pCopySrc = &call;
178 | copySize = sizeof(call);
179 | }
180 | else if ((hs.opcode & 0xFD) == 0xE9)
181 | {
182 | // Direct relative JMP (EB or E9)
183 | ULONG_PTR dest = pOldInst + hs.len;
184 |
185 | if (hs.opcode == 0xEB) // isShort jmp
186 | dest += (INT8)hs.imm.imm8;
187 | else
188 | dest += (INT32)hs.imm.imm32;
189 |
190 | // Simply copy an internal jump.
191 | if ((ULONG_PTR)ct->pTarget <= dest
192 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
193 | {
194 | if (jmpDest < dest)
195 | jmpDest = dest;
196 | }
197 | else
198 | {
199 | #if defined(_M_X64) || defined(__x86_64__)
200 | jmp.address = dest;
201 | #else
202 | jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
203 | #endif
204 | pCopySrc = &jmp;
205 | copySize = sizeof(jmp);
206 |
207 | // Exit the function If it is not in the branch
208 | finished = (pOldInst >= jmpDest);
209 | }
210 | }
211 | else if ((hs.opcode & 0xF0) == 0x70
212 | || (hs.opcode & 0xFC) == 0xE0
213 | || (hs.opcode2 & 0xF0) == 0x80)
214 | {
215 | // Direct relative Jcc
216 | ULONG_PTR dest = pOldInst + hs.len;
217 |
218 | if ((hs.opcode & 0xF0) == 0x70 // Jcc
219 | || (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ
220 | dest += (INT8)hs.imm.imm8;
221 | else
222 | dest += (INT32)hs.imm.imm32;
223 |
224 | // Simply copy an internal jump.
225 | if ((ULONG_PTR)ct->pTarget <= dest
226 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
227 | {
228 | if (jmpDest < dest)
229 | jmpDest = dest;
230 | }
231 | else if ((hs.opcode & 0xFC) == 0xE0)
232 | {
233 | // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
234 | return FALSE;
235 | }
236 | else
237 | {
238 | UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
239 | #if defined(_M_X64) || defined(__x86_64__)
240 | // Invert the condition in x64 mode to simplify the conditional jump logic.
241 | jcc.opcode = 0x71 ^ cond;
242 | jcc.address = dest;
243 | #else
244 | jcc.opcode1 = 0x80 | cond;
245 | jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
246 | #endif
247 | pCopySrc = &jcc;
248 | copySize = sizeof(jcc);
249 | }
250 | }
251 | else if ((hs.opcode & 0xFE) == 0xC2)
252 | {
253 | // RET (C2 or C3)
254 |
255 | // Complete the function if not in a branch.
256 | finished = (pOldInst >= jmpDest);
257 | }
258 |
259 | // Can't alter the instruction length in a branch.
260 | if (pOldInst < jmpDest && copySize != hs.len)
261 | return FALSE;
262 |
263 | // Trampoline function is too large.
264 | if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
265 | return FALSE;
266 |
267 | // Trampoline function has too many instructions.
268 | if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
269 | return FALSE;
270 |
271 | ct->oldIPs[ct->nIP] = oldPos;
272 | ct->newIPs[ct->nIP] = newPos;
273 | ct->nIP++;
274 |
275 | // Avoid using memcpy to reduce the footprint.
276 | #ifndef _MSC_VER
277 | memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
278 | #else
279 | __movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
280 | #endif
281 | newPos += copySize;
282 | oldPos += hs.len;
283 | } while (!finished);
284 |
285 | // Is there enough place for a long jump?
286 | if (oldPos < sizeof(JMP_REL)
287 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
288 | {
289 | // Is there enough place for a short jump?
290 | if (oldPos < sizeof(JMP_REL_SHORT)
291 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
292 | {
293 | return FALSE;
294 | }
295 |
296 | // Can we place the long jump above the function?
297 | if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
298 | return FALSE;
299 |
300 | if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
301 | return FALSE;
302 |
303 | ct->patchAbove = TRUE;
304 | }
305 |
306 | #if defined(_M_X64) || defined(__x86_64__)
307 | // Create a relay function.
308 | jmp.address = (ULONG_PTR)ct->pDetour;
309 |
310 | ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
311 | memcpy(ct->pRelay, &jmp, sizeof(jmp));
312 | #endif
313 |
314 | return TRUE;
315 | }
316 |
--------------------------------------------------------------------------------
/libs/MinHook/trampoline.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #pragma pack(push, 1)
32 |
33 | // Structs for writing x86/x64 instructions.
34 |
35 | // 8-bit relative jump.
36 | typedef struct _JMP_REL_SHORT
37 | {
38 | UINT8 opcode; // EB xx: JMP +2+xx
39 | UINT8 operand;
40 | } JMP_REL_SHORT, * PJMP_REL_SHORT;
41 |
42 | // 32-bit direct relative jump/call.
43 | typedef struct _JMP_REL
44 | {
45 | UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
46 | UINT32 operand; // Relative destination address
47 | } JMP_REL, * PJMP_REL, CALL_REL;
48 |
49 | // 64-bit indirect absolute jump.
50 | typedef struct _JMP_ABS
51 | {
52 | UINT8 opcode0; // FF25 00000000: JMP [+6]
53 | UINT8 opcode1;
54 | UINT32 dummy;
55 | UINT64 address; // Absolute destination address
56 | } JMP_ABS, * PJMP_ABS;
57 |
58 | // 64-bit indirect absolute call.
59 | typedef struct _CALL_ABS
60 | {
61 | UINT8 opcode0; // FF15 00000002: CALL [+6]
62 | UINT8 opcode1;
63 | UINT32 dummy0;
64 | UINT8 dummy1; // EB 08: JMP +10
65 | UINT8 dummy2;
66 | UINT64 address; // Absolute destination address
67 | } CALL_ABS;
68 |
69 | // 32-bit direct relative conditional jumps.
70 | typedef struct _JCC_REL
71 | {
72 | UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx
73 | UINT8 opcode1;
74 | UINT32 operand; // Relative destination address
75 | } JCC_REL;
76 |
77 | // 64bit indirect absolute conditional jumps that x64 lacks.
78 | typedef struct _JCC_ABS
79 | {
80 | UINT8 opcode; // 7* 0E: J** +16
81 | UINT8 dummy0;
82 | UINT8 dummy1; // FF25 00000000: JMP [+6]
83 | UINT8 dummy2;
84 | UINT32 dummy3;
85 | UINT64 address; // Absolute destination address
86 | } JCC_ABS;
87 |
88 | #pragma pack(pop)
89 |
90 | typedef struct _TRAMPOLINE
91 | {
92 | LPVOID pTarget; // [In] Address of the target function.
93 | LPVOID pDetour; // [In] Address of the detour function.
94 | LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function.
95 |
96 | #if defined(_M_X64) || defined(__x86_64__)
97 | LPVOID pRelay; // [Out] Address of the relay function.
98 | #endif
99 | BOOL patchAbove; // [Out] Should use the hot patch area?
100 | UINT nIP; // [Out] Number of the instruction boundaries.
101 | UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function.
102 | UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function.
103 | } TRAMPOLINE, * PTRAMPOLINE;
104 |
105 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct);
106 |
--------------------------------------------------------------------------------
/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp: source file corresponding to the pre-compiled header
2 |
3 | #include "pch.h"
4 |
5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
6 |
--------------------------------------------------------------------------------
/pch.h:
--------------------------------------------------------------------------------
1 | // pch.h: This is a precompiled header file.
2 | // Files listed below are compiled only once, improving build performance for future builds.
3 | // This also affects IntelliSense performance, including code completion and many code browsing features.
4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds.
5 | // Do not add files here that you will be updating frequently as this negates the performance advantage.
6 |
7 | #ifndef PCH_H
8 | #define PCH_H
9 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
10 |
11 | // STANDARD LIBRARIES
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | // DIRECTX
23 | #include
24 | #pragma comment(lib, "d3d11.lib")
25 |
26 | // GAMEPAD
27 | #include
28 | #pragma comment(lib, "XInput.lib")
29 |
30 | // INTERNET
31 | #include
32 | #pragma comment(lib, "ws2_32.lib")
33 | #pragma comment(lib, "wininet.lib")
34 |
35 | // MINHOOK
36 | #include "libs/MinHook/MinHook.h"
37 |
38 |
39 | // DEAR IMGUI
40 | #include "libs/ImGui/imgui.h"
41 | #include "libs/ImGui/imgui_internal.h"
42 | #include "libs/ImGui/imgui_Impl_dx11.h"
43 | #include "libs/ImGui/imgui_Impl_Win32.h"
44 |
45 | #endif //PCH_H
--------------------------------------------------------------------------------
/src/Engine.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
6 |
7 | namespace DX11Base
8 | {
9 | FILE* Console::pOutStream{ nullptr };
10 | bool Console::bInit{ false };
11 | static uint64_t* MethodsTable{ nullptr };
12 |
13 | //----------------------------------------------------------------------------------------------------
14 | // ENGINE
15 | //-----------------------------------------------------------------------------------
16 | #pragma region // ENGINE
17 |
18 | Engine::Engine()
19 | {
20 | g_Console = std::make_unique();
21 | g_D3D11Window = std::make_unique();
22 | g_Hooking = std::make_unique();
23 | }
24 |
25 | Engine::~Engine()
26 | {
27 | g_Hooking.release();
28 | g_D3D11Window.release();
29 | g_Console.release();
30 | }
31 |
32 | void Engine::Init()
33 | {
34 | mGamePID = GetCurrentProcessId();
35 | pGameHandle = GetCurrentProcess();
36 | pGameWindow = GetForegroundWindow();
37 | pGameModule = GetModuleHandle(0);
38 | pGameBaseAddr = reinterpret_cast<__int64>(pGameModule);
39 |
40 | RECT tempRECT;
41 | GetWindowRect(pGameWindow, &tempRECT);
42 | mGameWidth = tempRECT.right - tempRECT.left;
43 | mGameHeight = tempRECT.bottom - tempRECT.top;
44 |
45 | char tempTitle[MAX_PATH];
46 | GetWindowTextA(pGameWindow, tempTitle, sizeof(tempTitle));
47 | pGameTitle = tempTitle;
48 |
49 | char tempClassName[MAX_PATH];
50 | GetClassNameA(pGameWindow, tempClassName, sizeof(tempClassName));
51 | pClassName = tempClassName;
52 |
53 | char tempPath[MAX_PATH];
54 | GetModuleFileNameExA(pGameHandle, 0, tempPath, sizeof(tempPath));
55 | pGamePath = tempPath;
56 | }
57 |
58 | bool Engine::GetKeyState(WORD vKey, SHORT delta)
59 | {
60 | static int lastTick = 0;
61 |
62 | bool result = ((GetAsyncKeyState(vKey) & 0x8000) && (GetTickCount64() - lastTick) > delta);
63 |
64 | if (result)
65 | lastTick = GetTickCount64();
66 |
67 | return result;
68 | }
69 |
70 | bool Engine::GamePadGetKeyState(WORD vButton)
71 | {
72 | XINPUT_STATE state;
73 | ZeroMemory(&state, sizeof(XINPUT_STATE));
74 | DWORD result = XInputGetState(0, &state);
75 | if (result == ERROR_SUCCESS)
76 | {
77 | if ((state.Gamepad.wButtons & vButton) == vButton)
78 | return true;
79 | }
80 | return false;
81 | }
82 |
83 | #pragma endregion
84 |
85 |
86 | //----------------------------------------------------------------------------------------------------
87 | // CONSOLE
88 | //-----------------------------------------------------------------------------------
89 | #pragma region // CONSOLE
90 |
91 | Console::Console() { }
92 |
93 | Console::Console(const char* title) { InitializeConsole(title); }
94 |
95 | Console::Console(const char* title, bool bShow) { InitializeConsole(title, bShow); }
96 |
97 | Console::~Console() { DestroyConsole(); }
98 |
99 | HANDLE Console::GetHandle() { return this->pHandle; }
100 |
101 | HWND Console::GetWindowHandle() { return this->pHwnd; }
102 |
103 | void Console::Clear() { system("cls"); }
104 |
105 | // creates a console instance with input name
106 | void Console::InitializeConsole(const char* ConsoleName, bool bShowWindow)
107 | {
108 | if (Console::bInit)
109 | {
110 | LogError("[!] [Console::InitializeConsole] failed to initialize console .\n");
111 | return;
112 | }
113 |
114 | AllocConsole();
115 | pHandle = GetStdHandle(STD_OUTPUT_HANDLE);
116 | pHwnd = GetConsoleWindow();
117 | freopen_s(&pOutStream, "CONOUT$", "w", stdout);
118 |
119 | char titleBuff[256];
120 | sprintf_s(titleBuff, "[DX11Base] %s", ConsoleName);
121 | SetConsoleTitleA(titleBuff);
122 |
123 | Console::bInit = true;
124 | Console::bShow = bShowWindow;
125 |
126 | ShowWindow(this->pHwnd, Console::bShow ? SW_SHOW : SW_HIDE);
127 | }
128 |
129 | // raw print to console with desired color and formatting
130 | void Console::cLog(const char* fmt, EColors color, ...)
131 | {
132 | SetConsoleTextAttribute(pHandle, color);
133 | va_list arg;
134 | va_start(arg, color);
135 | vfprintf(pOutStream, fmt, arg);
136 | va_end(arg);
137 | SetConsoleTextAttribute(pHandle, EColor_DEFAULT);
138 | }
139 |
140 | void Console::LogError(const char* fmt, ...)
141 | {
142 | SetConsoleTextAttribute(pHandle, EColor_red);
143 | va_list arg;
144 | va_start(arg, fmt);
145 | vfprintf(pOutStream, fmt, arg);
146 | va_end(arg);
147 | SetConsoleTextAttribute(pHandle, EColor_DEFAULT);
148 | }
149 |
150 | //
151 | void Console::DestroyConsole()
152 | {
153 | fclose(pOutStream);
154 | DestroyWindow(pHwnd);
155 | FreeConsole();
156 | bInit = false;
157 | }
158 |
159 | //
160 | void Console::SetConsoleVisibility(bool bShow)
161 | {
162 | this->bShow = bShow;
163 | ShowWindow(pHwnd, bShow ? SW_SHOW : SW_HIDE);
164 | }
165 |
166 | //
167 | void Console::Log(const char* fmt, ...)
168 | {
169 | if (!pOutStream)
170 | return;
171 |
172 | va_list arg;
173 | va_start(arg, fmt);
174 | vfprintf(pOutStream, fmt, arg);
175 | va_end(arg);
176 | }
177 |
178 | #pragma endregion
179 |
180 |
181 | //----------------------------------------------------------------------------------------------------
182 | // D3DWINDOW
183 | //-----------------------------------------------------------------------------------
184 | #pragma region // D3DWINDOW
185 |
186 | D3D11Window::D3D11Window() {}
187 |
188 | D3D11Window::~D3D11Window() { bInit = false; }
189 |
190 | //-----------------------------------------------------------------------------------
191 | //
192 | LRESULT D3D11Window::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
193 | {
194 | if (g_Engine->bShowMenu)
195 | {
196 | ImGui_ImplWin32_WndProcHandler((HWND)g_D3D11Window->m_OldWndProc, msg, wParam, lParam);
197 | return true;
198 | }
199 | return CallWindowProc((WNDPROC)g_D3D11Window->m_OldWndProc, hWnd, msg, wParam, lParam);
200 | }
201 |
202 | //-----------------------------------------------------------------------------------
203 | //
204 | HRESULT APIENTRY D3D11Window::SwapChain_Present_hook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags)
205 | {
206 | g_D3D11Window->Overlay(pSwapChain);
207 |
208 | return g_D3D11Window->IDXGISwapChain_Present_stub(pSwapChain, SyncInterval, Flags);
209 | }
210 |
211 | //-----------------------------------------------------------------------------------
212 | //
213 | HRESULT APIENTRY D3D11Window::SwapChain_ResizeBuffers_hook(IDXGISwapChain* p, UINT bufferCount, UINT Width, UINT Height, DXGI_FORMAT fmt, UINT scFlags)
214 | {
215 | // Get new data & release render target
216 | g_D3D11Window->m_pSwapChain = p;
217 | g_D3D11Window->m_RenderTargetView->Release();
218 | g_D3D11Window->m_RenderTargetView = nullptr;
219 |
220 | // get fn result
221 | HRESULT result = g_D3D11Window->IDXGISwapChain_ResizeBuffers_stub(p, bufferCount, Width, Height, fmt, scFlags);
222 |
223 | // Get new render target
224 | ID3D11Texture2D* backBuffer;
225 | p->GetBuffer(0, __uuidof(ID3D11Texture2D*), (LPVOID*)&backBuffer);
226 | if (backBuffer)
227 | {
228 | g_D3D11Window->m_Device->CreateRenderTargetView(backBuffer, 0, &g_D3D11Window->m_RenderTargetView);
229 | backBuffer->Release();
230 | }
231 |
232 | // Reset ImGui
233 | if (g_D3D11Window->bInitImGui)
234 | {
235 | ImGuiIO& io = ImGui::GetIO();
236 | io.DisplaySize = ImVec2(static_cast(Width), static_cast(Height));
237 | }
238 |
239 | return result;
240 | }
241 |
242 | bool D3D11Window::HookD3D()
243 | {
244 | if (GetD3DContext())
245 | {
246 | Hooking::CreateHook((void*)MethodsTable[IDXGI_PRESENT], &SwapChain_Present_hook, (void**)&IDXGISwapChain_Present_stub);
247 | Hooking::CreateHook((void*)MethodsTable[IDXGI_RESIZE_BUFFERS], &SwapChain_ResizeBuffers_hook, (void**)&IDXGISwapChain_ResizeBuffers_stub);
248 | bInit = true;
249 | return true;
250 | }
251 | return false;
252 | }
253 |
254 | void D3D11Window::UnhookD3D()
255 | {
256 | SetWindowLongPtr(g_Engine->pGameWindow, GWLP_WNDPROC, (LONG_PTR)m_OldWndProc);
257 | Hooking::DisableHook((void*)MethodsTable[IDXGI_PRESENT]);
258 | Hooking::DisableHook((void*)MethodsTable[IDXGI_RESIZE_BUFFERS]);
259 | free(MethodsTable);
260 | }
261 |
262 | bool D3D11Window::GetD3DContext()
263 | {
264 | if (!InitWindow())
265 | return false;
266 |
267 | HMODULE D3D11Module = GetModuleHandleA("d3d11.dll");
268 |
269 | D3D_FEATURE_LEVEL FeatureLevel;
270 | const D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0 };
271 |
272 | DXGI_RATIONAL RefreshRate;
273 | RefreshRate.Numerator = 60;
274 | RefreshRate.Denominator = 1;
275 |
276 | DXGI_MODE_DESC BufferDesc;
277 | BufferDesc.Width = 100;
278 | BufferDesc.Height = 100;
279 | BufferDesc.RefreshRate = RefreshRate;
280 | BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
281 | BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
282 | BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
283 |
284 | DXGI_SAMPLE_DESC SampleDesc;
285 | SampleDesc.Count = 1;
286 | SampleDesc.Quality = 0;
287 |
288 | DXGI_SWAP_CHAIN_DESC SwapChainDesc;
289 | SwapChainDesc.BufferDesc = BufferDesc;
290 | SwapChainDesc.SampleDesc = SampleDesc;
291 | SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
292 | SwapChainDesc.BufferCount = 1;
293 | SwapChainDesc.OutputWindow = WindowHwnd;
294 | SwapChainDesc.Windowed = 1;
295 | SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
296 | SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
297 |
298 | IDXGISwapChain* SwapChain;
299 | ID3D11Device* Device;
300 | ID3D11DeviceContext* Context;
301 | if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, FeatureLevels, 1, D3D11_SDK_VERSION, &SwapChainDesc, &SwapChain, &Device, &FeatureLevel, &Context) < 0)
302 | {
303 | DeleteWindow();
304 | return false;
305 | }
306 |
307 | MethodsTable = (uint64_t*)::calloc(205, sizeof(uint64_t));
308 | memcpy(MethodsTable, *(uint64_t**)SwapChain, 18 * sizeof(uint64_t));
309 | memcpy(MethodsTable + 18, *(uint64_t**)Device, 43 * sizeof(uint64_t));
310 | memcpy(MethodsTable + 18 + 43, *(uint64_t**)Context, 144 * sizeof(uint64_t));
311 | Sleep(1000);
312 |
313 | // INIT NOTICE
314 | Beep(300, 300);
315 |
316 | SwapChain->Release();
317 | SwapChain = 0;
318 | Device->Release();
319 | Device = 0;
320 | Context->Release();
321 | Context = 0;
322 | DeleteWindow();
323 | return true;
324 | }
325 |
326 | bool D3D11Window::InitWindow()
327 | {
328 | WindowClass.cbSize = sizeof(WNDCLASSEX);
329 | WindowClass.style = CS_HREDRAW | CS_VREDRAW;
330 | WindowClass.lpfnWndProc = DefWindowProc;
331 | WindowClass.cbClsExtra = 0;
332 | WindowClass.cbWndExtra = 0;
333 | WindowClass.hInstance = GetModuleHandle(NULL);
334 | WindowClass.hIcon = NULL;
335 | WindowClass.hCursor = NULL;
336 | WindowClass.hbrBackground = NULL;
337 | WindowClass.lpszMenuName = NULL;
338 | WindowClass.lpszClassName = L"MJ";
339 | WindowClass.hIconSm = NULL;
340 | RegisterClassEx(&WindowClass);
341 | WindowHwnd = CreateWindow(WindowClass.lpszClassName, L"DX11 Window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, WindowClass.hInstance, NULL);
342 | if (WindowHwnd == NULL) {
343 | return FALSE;
344 | }
345 | return TRUE;
346 | }
347 |
348 | bool D3D11Window::DeleteWindow()
349 | {
350 | DestroyWindow(WindowHwnd);
351 | UnregisterClass(WindowClass.lpszClassName, WindowClass.hInstance);
352 | if (WindowHwnd != 0) {
353 | return FALSE;
354 | }
355 | return TRUE;
356 | }
357 |
358 | bool D3D11Window::InitImGui(IDXGISwapChain* swapChain)
359 | {
360 | if (SUCCEEDED(swapChain->GetDevice(__uuidof(ID3D11Device), (void**)&m_Device))) {
361 | ImGui::CreateContext();
362 | ImGuiIO& io = ImGui::GetIO(); (void)io;
363 | ImGui::GetIO().WantCaptureMouse || ImGui::GetIO().WantTextInput || ImGui::GetIO().WantCaptureKeyboard;
364 | io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
365 | io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
366 | io.IniFilename = 0;
367 | ImGui::StyleColorsDark();
368 | m_Device->GetImmediateContext(&m_DeviceContext);
369 |
370 | DXGI_SWAP_CHAIN_DESC Desc;
371 | swapChain->GetDesc(&Desc);
372 | g_Engine->pGameWindow = Desc.OutputWindow;
373 |
374 | ID3D11Texture2D* BackBuffer;
375 | swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&BackBuffer);
376 | m_Device->CreateRenderTargetView(BackBuffer, NULL, &m_RenderTargetView);
377 | BackBuffer->Release();
378 |
379 | ImGui_ImplWin32_Init(g_Engine->pGameWindow);
380 | ImGui_ImplDX11_Init(m_Device, m_DeviceContext);
381 | ImGui_ImplDX11_CreateDeviceObjects();
382 | ImGui::GetIO().ImeWindowHandle = g_Engine->pGameWindow;
383 | m_OldWndProc = (WNDPROC)SetWindowLongPtr(g_Engine->pGameWindow, GWLP_WNDPROC, (__int3264)(LONG_PTR)WndProc);
384 | bInitImGui = true;
385 | m_pSwapChain = swapChain;
386 | pImGui = GImGui;
387 | pViewport = pImGui->Viewports[0];
388 | return true;
389 | }
390 | bInitImGui = false;
391 | return false;
392 | }
393 |
394 | void D3D11Window::Overlay(IDXGISwapChain* pSwapChain)
395 | {
396 | if (!bInitImGui)
397 | InitImGui(pSwapChain);
398 |
399 | ImGui_ImplDX11_NewFrame();
400 | ImGui_ImplWin32_NewFrame();
401 | ImGui::NewFrame();
402 | ImGui::GetIO().MouseDrawCursor = g_Engine->bShowMenu;
403 |
404 | // Render Menu Loop
405 | Menu::Draw();
406 |
407 | ImGui::EndFrame();
408 | ImGui::Render();
409 | m_DeviceContext->OMSetRenderTargets(1, &m_RenderTargetView, NULL);
410 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
411 | }
412 |
413 | #pragma endregion
414 |
415 |
416 | //----------------------------------------------------------------------------------------------------
417 | // HOOKING
418 | //-----------------------------------------------------------------------------------
419 | #pragma region // HOOKING
420 |
421 | Hooking::Hooking()
422 | {
423 | MH_Initialize();
424 | }
425 |
426 | Hooking::~Hooking()
427 | {
428 | DisableAllHooks();
429 | RemoveAllHooks();
430 | MH_Uninitialize();
431 | }
432 |
433 | void Hooking::Initialize()
434 | {
435 | EnableAllHooks();
436 | }
437 |
438 | void Hooking::Shutdown()
439 | {
440 | RemoveAllHooks();
441 | }
442 |
443 | bool Hooking::CreateHook(LPVOID lpTarget, LPVOID pDetour, LPVOID* pOrig)
444 | {
445 | if (MH_CreateHook(lpTarget, pDetour, pOrig) != MH_OK || MH_EnableHook(lpTarget) != MH_OK)
446 | return false;
447 | return true;
448 | }
449 |
450 | void Hooking::EnableHook(LPVOID lpTarget) { MH_EnableHook(lpTarget); }
451 |
452 | void Hooking::DisableHook(LPVOID lpTarget) { MH_DisableHook(lpTarget); }
453 |
454 | void Hooking::RemoveHook(LPVOID lpTarget) { MH_RemoveHook(lpTarget); }
455 |
456 | void Hooking::EnableAllHooks() { MH_EnableHook(MH_ALL_HOOKS); }
457 |
458 | void Hooking::DisableAllHooks() { MH_DisableHook(MH_ALL_HOOKS); }
459 |
460 | void Hooking::RemoveAllHooks() { MH_RemoveHook(MH_ALL_HOOKS); }
461 |
462 | #pragma endregion
463 |
464 | }
--------------------------------------------------------------------------------
/src/Menu.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | namespace DX11Base
6 | {
7 | namespace Styles
8 | {
9 | void BaseStyle()
10 | {
11 | ImGuiStyle& style = ImGui::GetStyle();
12 | ImVec4* colors = ImGui::GetStyle().Colors;
13 |
14 | // STYLE PROPERTIES
15 | style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
16 |
17 | // Base ImGui Styling , Aplying a custyom style is left up to you.
18 | ImGui::StyleColorsDark();
19 |
20 | /// EXAMPLE COLOR
21 | //colors[ImGuiCol_FrameBg] = ImVec4(0, 0, 0, 0);
22 | }
23 |
24 | // Hides the Dear ImGui Navigation Interface ( Windowing Mode )
25 | // @TODO: Disable ImGui Navigation
26 | void SetNavigationMenuViewState(bool bShow)
27 | {
28 | ImVec4* colors = ImGui::GetStyle().Colors;
29 | switch (bShow)
30 | {
31 | case true:
32 | {
33 | // Show Navigation Panel | Default ImGui Dark Style
34 | // Perhaps just call BaseStyle() ?
35 | colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
36 | colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
37 | colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
38 | colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
39 | colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
40 | colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
41 | break;
42 | }
43 | case false:
44 | {
45 | // Hide Navigation Panel
46 | colors[ImGuiCol_Text] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
47 | colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
48 | colors[ImGuiCol_Border] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
49 | colors[ImGuiCol_NavHighlight] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
50 | colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
51 | colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
52 | break;
53 | }
54 | }
55 | }
56 | }
57 |
58 | namespace Tabs
59 | {
60 | void TABMain()
61 | {
62 | ImGui::Text("BASE MENU (PREVIEW)");
63 | ImGui::Text("BUILD VERSION: v1.0.1");
64 | ImGui::Text("BUILD DATE: 2/8/2024");
65 |
66 | ImGui::Spacing();
67 | ImGui::Separator();
68 | ImGui::Spacing();
69 |
70 | static int BytesPerLine{ 4 };
71 | static int BytesSpacing{ 2 };
72 | static unsigned int MemScanReadSize{ 0x1000 };
73 | static unsigned int MemScanStarAddress{ 0x0 };
74 | ImGui::InputInt("##MEMSCAN_START", (int*)&MemScanStarAddress, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
75 | ImGui::SameLine();
76 | ImGui::InputInt("##MEMSCAN_SIZE", (int*)&MemScanReadSize, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
77 | ImGui::BeginChild("MemoryScanner", ImVec2(ImGui::GetContentRegionAvail().x, 100.f), ImGuiChildFlags_Border);
78 | {
79 | int pad{ 0 };
80 | for (int i = 0; i < MemScanReadSize; i += BytesPerLine)
81 | {
82 | static unsigned long long base = reinterpret_cast(GetModuleHandle(0));
83 | if (!base)
84 | {
85 | ImGui::Text("Failed to get module base address.");
86 | break;
87 | }
88 |
89 | ImGui::Text("%p: ", base + i);
90 | ImGui::SameLine();
91 | for (int j = 0; j < BytesPerLine; j++)
92 | {
93 | unsigned long long addr = (base + i + j);
94 | if (addr > 0)
95 | ImGui::Text("0x%02X ", *(unsigned __int8*)addr);
96 | else
97 | ImGui::Text("?? ");
98 |
99 | ImGui::SameLine();
100 | }
101 | ImGui::NewLine();
102 | }
103 | }
104 | ImGui::EndChild();
105 | ImGui::Spacing();
106 | ImGui::Separator();
107 | ImGui::Spacing();
108 |
109 | if (ImGui::Button("UNHOOK DLL", ImVec2(ImGui::GetContentRegionAvail().x, 20))) {
110 | #if CONSOLE_OUTPUT
111 | g_Console->printdbg("\n\n[+] UNHOOK INITIALIZED\n\n", Console::Colors::red);
112 | #endif
113 | g_KillSwitch = TRUE;
114 | }
115 | }
116 | }
117 |
118 | //----------------------------------------------------------------------------------------------------
119 | // MENU
120 | //-----------------------------------------------------------------------------------
121 | void Menu::Draw()
122 | {
123 | if (g_Engine->bShowMenu)
124 | MainMenu();
125 |
126 | if (g_Engine->bShowHud && !g_Engine->bShowMenu)
127 | {
128 | Styles::SetNavigationMenuViewState(false);
129 | Menu::HUD();
130 | }
131 |
132 | if (g_Engine->bShowDemoWindow && g_Engine->bShowMenu)
133 | ImGui::ShowDemoWindow();
134 |
135 | if (g_Engine->bShowStyleEditor && g_Engine->bShowMenu)
136 | ImGui::ShowStyleEditor();
137 | }
138 |
139 | void Menu::MainMenu()
140 | {
141 | if (!g_Engine->bShowDemoWindow && !g_Engine->bShowStyleEditor)
142 | Styles::BaseStyle();
143 |
144 | if (!ImGui::Begin("(DX11) ImGui Internal Base", &g_Engine->bShowMenu, 96))
145 | {
146 | ImGui::End();
147 | return;
148 | }
149 |
150 | Tabs::TABMain();
151 |
152 | ImGui::End();
153 | }
154 |
155 | void Menu::HUD()
156 | {
157 | ImVec2 draw_size = g_D3D11Window->pViewport->WorkSize;
158 | ImVec2 draw_pos = g_D3D11Window->pViewport->WorkSize;
159 | ImGui::SetNextWindowPos(draw_pos);
160 | ImGui::SetNextWindowSize(draw_size);
161 | ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
162 | ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.00f, 0.00f, 0.00f, 0.00f));
163 | if (!ImGui::Begin("##HUDWINDOW", (bool*)true, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs))
164 | {
165 | ImGui::PopStyleColor();
166 | ImGui::PopStyleVar();
167 | ImGui::End();
168 | return;
169 | }
170 | ImGui::PopStyleColor();
171 | ImGui::PopStyleVar();
172 |
173 | ImDrawList* ImDraw = ImGui::GetWindowDrawList();
174 | auto center = ImVec2({ draw_size.x * .5f, draw_size.y * .5f });
175 | auto top_center = ImVec2({ draw_size.x * .5f, draw_size.y * 0.0f });
176 | ImDraw->AddText(top_center, ImColor(1.0f, 1.0f, 1.0f, 1.0f), "https://github.com/NightFyre/DX11-ImGui-Internal-Hook");
177 |
178 | ImGui::End();
179 | }
180 |
181 | void Menu::Loops()
182 | {
183 |
184 | }
185 |
186 | //----------------------------------------------------------------------------------------------------
187 | // GUI
188 | //-----------------------------------------------------------------------------------
189 |
190 | void GUI::TextCentered(const char* pText)
191 | {
192 | ImVec2 textSize = ImGui::CalcTextSize(pText);
193 | ImVec2 windowSize = ImGui::GetWindowSize();
194 | ImVec2 textPos = ImVec2((windowSize.x - textSize.x) * 0.5f, (windowSize.y - textSize.y) * 0.5f);
195 | ImGui::SetCursorPos(textPos);
196 | ImGui::Text("%s", pText);
197 | }
198 |
199 | // @ATTN: max buffer is 256chars
200 | void GUI::TextCenteredf(const char* pText, ...)
201 | {
202 | va_list args;
203 | va_start(args, pText);
204 | char buffer[256];
205 | vsnprintf(buffer, sizeof(buffer), pText, args);
206 | va_end(args);
207 |
208 | TextCentered(buffer);
209 | }
210 |
211 | void GUI::DrawText_(ImVec2 pos, ImColor color, const char* pText, float fontSize)
212 | {
213 | ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), fontSize, pos, color, pText, pText + strlen(pText), 800, 0);
214 | }
215 |
216 | // @ATTN: max buffer is 256chars
217 | void GUI::DrawTextf(ImVec2 pos, ImColor color, const char* pText, float fontSize, ...)
218 | {
219 | va_list args;
220 | va_start(args, fontSize);
221 | char buffer[256];
222 | vsnprintf(buffer, sizeof(buffer), pText, args);
223 | va_end(args);
224 |
225 | DrawText_(pos, color, buffer, fontSize);
226 | }
227 |
228 | void GUI::DrawTextCentered(ImVec2 pos, ImColor color, const char* pText, float fontSize)
229 | {
230 | float textSize = ImGui::CalcTextSize(pText).x;
231 | ImVec2 textPosition = ImVec2(pos.x - (textSize * 0.5f), pos.y);
232 | DrawText_(textPosition, color, pText, fontSize);
233 | }
234 |
235 | // @ATTN: max buffer is 256chars
236 | void GUI::DrawTextCenteredf(ImVec2 pos, ImColor color, const char* pText, float fontSize, ...)
237 | {
238 | va_list args;
239 | va_start(args, fontSize);
240 | char buffer[256];
241 | vsnprintf(buffer, sizeof(buffer), pText, args);
242 | va_end(args);
243 |
244 | DrawTextCentered(pos, color, pText, fontSize);
245 | }
246 | }
--------------------------------------------------------------------------------