├── .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 | ![image](https://user-images.githubusercontent.com/80198020/173253818-fbe99e22-df23-4804-8401-72e37abc2a94.png) 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 | } --------------------------------------------------------------------------------