├── gasper-cpp.vcxproj.user
├── README.md
├── sdk
├── minecraft
│ ├── world
│ │ ├── world.h
│ │ └── world.cpp
│ ├── minecraft.h
│ ├── player
│ │ ├── player.h
│ │ └── player.cpp
│ └── minecraft.cpp
├── includes.h
├── libraries
│ ├── imgui
│ │ ├── imgui_impl_win32.h
│ │ ├── imgui_impl_opengl2.h
│ │ ├── imconfig.h
│ │ ├── imgui_impl_opengl2.cpp
│ │ ├── imgui_impl_win32.cpp
│ │ └── imstb_rectpack.h
│ └── xorstr.h
├── utils
│ └── utils.h
├── hook
│ ├── hde
│ │ ├── pstdint.h
│ │ ├── hde32.h
│ │ ├── hde64.h
│ │ ├── table32.h
│ │ ├── table64.h
│ │ ├── hde32.c
│ │ └── hde64.c
│ ├── buffer.h
│ ├── trampoline.h
│ ├── MinHook.h
│ ├── buffer.c
│ ├── trampoline.c
│ └── hook.c
└── wrapper
│ └── wrapper.h
├── entry
└── main.cpp
├── main
├── gasper.h
├── hooks
│ ├── swap_buffers.cpp
│ └── wndproc.cpp
└── gasper.cpp
├── gasper-cpp.vcxproj.filters
└── gasper-cpp.vcxproj
/gasper-cpp.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VincitSD
2 | Ghost client for Minecraft FORGE Client. Also official support Minecraft 1.6.4 - latest versions minecraft.
3 |
4 | # Compiling
5 | 1)Don't forget to link opengl32.dll or else it wont compile.
6 | 2)Don't forget to link OpenJDK 1.8 libraries and includes. I recommend to download AdoptOpenJDK.
7 |
8 | # Features
9 | * Aimbot
10 | * Menu
11 | * Dear ImGui
12 |
--------------------------------------------------------------------------------
/sdk/minecraft/world/world.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../minecraft.h"
4 | #include "../player/player.h"
5 |
6 | class c_world {
7 | private:
8 | jobject world_obj;
9 | public:
10 | c_world(jobject obj);
11 | ~c_world();
12 |
13 | const jobject get_object()
14 | {
15 | return world_obj;
16 | }
17 |
18 | std::vector> get_players();
19 | };
--------------------------------------------------------------------------------
/sdk/minecraft/minecraft.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../includes.h"
4 |
5 | namespace sdk {
6 | class c_minecraft {
7 | private:
8 | public:
9 |
10 | jobject get_minecraft();
11 |
12 | jobject get_player(jobject);
13 |
14 | jobject get_world(jobject mc);
15 |
16 | jobject get_current_screen(jobject mc);
17 |
18 | };
19 |
20 | extern std::unique_ptr instance;
21 | }
--------------------------------------------------------------------------------
/sdk/minecraft/player/player.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../minecraft.h"
4 |
5 | class c_player {
6 | private:
7 | jobject player_obj;
8 | public:
9 | c_player(jobject obj);
10 | ~c_player();
11 |
12 | float get_health();
13 | sdk::vec3d get_position();
14 | void set_yaw(float yaw);
15 | float get_yaw();
16 | void set_pitch(float pitch);
17 | float get_pitch();
18 | double get_distance_to(std::shared_ptr);
19 |
20 | const jobject get_object()
21 | {
22 | return player_obj;
23 | }
24 | };
--------------------------------------------------------------------------------
/sdk/includes.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Main includes for gasper-cpp, would be a pain to write this constantly wouldn't it?
5 |
6 | */
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | #include
19 | #include
20 |
21 | #include
22 |
23 | #ifndef M_PI
24 | #define M_PI 3.14159265358979323846
25 | #endif
26 |
27 | #include
28 |
29 | #include "hook/MinHook.h"
30 |
31 | #include "libraries/imgui/imgui.h"
32 | #include "libraries/imgui/imgui_impl_win32.h"
33 | #include "libraries/imgui/imgui_impl_opengl2.h"
34 | #include "libraries/imgui/imgui_internal.h"
35 |
36 | #include "libraries/xorstr.h"
37 | #include "wrapper/wrapper.h"
38 | #include "utils/utils.h"
--------------------------------------------------------------------------------
/sdk/libraries/imgui/imgui_impl_win32.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Binding for Windows (standard windows API for 32 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 imgui)
6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 |
10 | #pragma once
11 |
12 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
13 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
14 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
15 |
16 | // Handler for Win32 messages, update mouse/keyboard data.
17 | // You may or not need this for your implementation, but it can serve as reference for handling inputs.
18 | // Intentionally commented out to avoid dragging dependencies on types. You can COPY this line into your .cpp code instead.
19 | /*
20 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
21 | */
22 |
--------------------------------------------------------------------------------
/entry/main.cpp:
--------------------------------------------------------------------------------
1 | #include "../sdk/includes.h"
2 | #include "../main/gasper.h"
3 |
4 | void start_gasper_thread();
5 |
6 | /// Note: this DLL is manually mapped, there's literally NO reason to handle any other call than DLL_PROCESS_ATTACH
7 | /// thread calls are also non-existant, so no reason to use DisableThreadLibraryCalls
8 | int __stdcall DllMain(
9 | HINSTANCE hinstDLL,
10 | unsigned long fdwReason,
11 | void* lpvReserved
12 | ) {
13 |
14 | if (fdwReason != DLL_PROCESS_ATTACH)
15 | return false;
16 |
17 | /// Not necessary to handle the handle to the thread because, no second call I guess.
18 | wrapper::spawn_thread(reinterpret_cast(start_gasper_thread));
19 |
20 | return true;
21 | }
22 |
23 | void start_gasper_thread() {
24 |
25 | /// "Bro you know when the object is destroyed" true.
26 | gasper::instance = std::make_unique();
27 |
28 | /// Try to attach, if we fail the attach function will be sure to drop an error message
29 | if (!gasper::instance->attach())
30 | std::exit(0);
31 |
32 | /// Let's get this started
33 | gasper::instance->run();
34 |
35 | /// Wait a second actually
36 | std::this_thread::sleep_for(std::chrono::seconds(1));
37 |
38 | /// Ok now dispose of our shit
39 | gasper::instance->dispose();
40 | }
--------------------------------------------------------------------------------
/sdk/utils/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace sdk {
4 |
5 | /// Simple struct to store positions
6 | struct vec3d {
7 | double x, y, z;
8 | };
9 |
10 | using qword = unsigned long long;
11 | using t_createdvms = jint(__stdcall*)(JavaVM**, jsize, jsize*);
12 |
13 | /// NOTE: They're all inline LULW
14 | namespace util {
15 | inline float wrap_to_180(float value)
16 | {
17 | if (value >= 180.f)
18 | value -= 360.f;
19 | if (value < -180.f)
20 | value += 360.f;
21 | return value;
22 | }
23 |
24 | inline float radiants_to_deg(float x)
25 | {
26 | return x * 180.f / M_PI;
27 | }
28 |
29 | inline std::pair get_angles(sdk::vec3d pos, sdk::vec3d pos1)
30 | {
31 | double d_x = pos1.x - pos.x;
32 | double d_y = pos1.y - pos.y;
33 | double d_z = pos1.z - pos.z;
34 |
35 | double hypothenuse = sqrt(d_x * d_x + d_z * d_z);
36 | float yaw = radiants_to_deg(atan2(d_z, d_x)) - 90.f;
37 | float pitch = radiants_to_deg(-atan2(d_y, hypothenuse));
38 |
39 | return std::make_pair(yaw, pitch);
40 | }
41 |
42 | inline static double distance(double x, double y) {
43 | return sqrt(pow(x, 2) + pow(y, 2));
44 | }
45 |
46 | inline static double distance(double x1, double y1, double z1, double x2, double y2, double z2) {
47 | return distance(y1 - y2, distance(x1 - x2, z1 - z2));
48 | }
49 | }
50 | };
--------------------------------------------------------------------------------
/sdk/minecraft/world/world.cpp:
--------------------------------------------------------------------------------
1 | #include "world.h"
2 |
3 | #include "../../../main/gasper.h"
4 |
5 | c_world::c_world(jobject obj)
6 | {
7 | world_obj = obj;
8 | }
9 |
10 | c_world::~c_world()
11 | {
12 | gasper::instance->get_env()->DeleteLocalRef(world_obj);
13 | }
14 |
15 | std::vector> c_world::get_players()
16 | {
17 | jfieldID player_entities = gasper::instance->get_env()->GetFieldID(gasper::instance->get_env()->GetObjectClass(world_obj), xorstr_("field_73010_i"), xorstr_("Ljava/util/List;"));
18 | jclass list_cls = gasper::instance->get_env()->FindClass(xorstr_("java/util/List"));
19 | jmethodID to_array_md = gasper::instance->get_env()->GetMethodID(list_cls, xorstr_("toArray"), xorstr_("()[Ljava/lang/Object;"));
20 |
21 | gasper::instance->get_env()->DeleteLocalRef(list_cls);
22 |
23 | std::vector> res;
24 |
25 | jobject obj_player_entities = gasper::instance->get_env()->GetObjectField(world_obj, player_entities);
26 |
27 | if (!obj_player_entities)
28 | return res;
29 |
30 | jobjectArray array_player_list = reinterpret_cast(gasper::instance->get_env()->CallObjectMethod(obj_player_entities, to_array_md));
31 |
32 | if (!array_player_list)
33 | return res;
34 |
35 | size_t len = gasper::instance->get_env()->GetArrayLength(array_player_list);
36 |
37 | for (int i = 0; i < len; ++i)
38 | {
39 | jobject player = gasper::instance->get_env()->GetObjectArrayElement(array_player_list, i);
40 | res.push_back(std::make_shared(player));
41 | }
42 |
43 | gasper::instance->get_env()->DeleteLocalRef(obj_player_entities);
44 | gasper::instance->get_env()->DeleteLocalRef(array_player_list);
45 |
46 | return res;
47 | }
48 |
49 |
50 |
--------------------------------------------------------------------------------
/sdk/hook/hde/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 |
--------------------------------------------------------------------------------
/sdk/libraries/imgui/imgui_impl_opengl2.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer for OpenGL2 (legacy OpenGL, fixed pipeline)
2 | // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
6 |
7 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
8 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
9 | // https://github.com/ocornut/imgui
10 |
11 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
12 | // **Prefer using the code in imgui_impl_opengl3.cpp**
13 | // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
14 | // If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
15 | // complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
16 | // confuse your GPU driver.
17 | // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
18 |
19 | #pragma once
20 |
21 | IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
22 | IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
23 | IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
24 | IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
25 |
26 | // Called by Init/NewFrame/Shutdown
27 | IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
28 | IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
29 | IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
30 | IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
31 |
--------------------------------------------------------------------------------
/sdk/hook/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 |
--------------------------------------------------------------------------------
/main/gasper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../sdk/includes.h"
4 |
5 | namespace gasper {
6 | class c_gasper {
7 | private:
8 | JNIEnv* env;
9 | JavaVM* vm;
10 |
11 | jmethodID findclass_md;
12 | jobject classloader_obj;
13 | public:
14 | /// If we're still running
15 | bool b_running;
16 |
17 | /// If the menu is open
18 | bool b_open;
19 |
20 | /// Function to try and attach to the JVM
21 | bool attach();
22 |
23 | /// Run the cheat
24 | void run();
25 |
26 | /// Dispose of cheat
27 | void dispose();
28 |
29 | /// Get the launchwrapper for forge support
30 | void get_launchwrapper();
31 |
32 | /// Hook necessary functions
33 | void hook();
34 |
35 | const auto get_env() {
36 | return env;
37 | }
38 |
39 | const auto get_vm() {
40 | return vm;
41 | }
42 |
43 | /// Inline function to get class
44 | inline jclass find_class(const char* name) {
45 | jstring jname = get_env()->NewStringUTF(name);
46 |
47 | jclass cls = reinterpret_cast(get_env()->CallObjectMethod(classloader_obj, findclass_md, jname));
48 |
49 | get_env()->DeleteLocalRef(jname);
50 |
51 | wrapper::handle_issue(name, cls);
52 |
53 | return cls;
54 | }
55 | };
56 |
57 | namespace hooks {
58 | /// Function template of SwapBuffers
59 | using swap_buffers_fn = int(__stdcall*)(HDC);
60 |
61 | /// Store pointer to the original SwapBuffers function
62 | inline swap_buffers_fn oswap_buffers = nullptr;
63 |
64 | /// Simple glcontext wrapper to make life easy
65 | extern std::shared_ptr gl_context;
66 |
67 | /// The actual hook
68 | int __stdcall swap_buffers_hk(HDC);
69 |
70 | /// Original WndProc of the Window we're hooking
71 | inline WNDPROC original_wndproc = nullptr;
72 |
73 | /// Actual "hook", this really isn't a hook but it's whatever
74 | long __stdcall wndproc_hk(const HWND hwnd, unsigned int usermsg, uintptr_t wparam, long lparam);
75 | }
76 |
77 | extern std::unique_ptr instance;
78 | }
79 |
--------------------------------------------------------------------------------
/sdk/minecraft/minecraft.cpp:
--------------------------------------------------------------------------------
1 | #include "minecraft.h"
2 | #include "../../main/gasper.h"
3 |
4 | std::unique_ptr sdk::instance;
5 |
6 | jobject sdk::c_minecraft::get_minecraft()
7 | {
8 | jobject res;
9 | auto cls = gasper::instance->find_class(xorstr_("net.minecraft.client.Minecraft"));
10 | auto mc_fid = gasper::instance->get_env()->GetStaticFieldID(cls, xorstr_("field_71432_P"), xorstr_("Lnet/minecraft/client/Minecraft;"));
11 |
12 | res = gasper::instance->get_env()->GetStaticObjectField(cls, mc_fid);
13 |
14 | gasper::instance->get_env()->DeleteLocalRef(cls);
15 |
16 | return res;
17 | }
18 |
19 | jobject sdk::c_minecraft::get_player(jobject mc) {
20 | jobject res;
21 |
22 | auto cls = gasper::instance->find_class(xorstr_("net.minecraft.client.Minecraft"));
23 | auto player_fid = gasper::instance->get_env()->GetFieldID(cls, xorstr_("field_71439_g"), xorstr_("Lnet/minecraft/client/entity/EntityClientPlayerMP;"));
24 |
25 | res = gasper::instance->get_env()->GetObjectField(mc, player_fid);
26 |
27 | gasper::instance->get_env()->DeleteLocalRef(cls);
28 |
29 | return res;
30 | }
31 |
32 | jobject sdk::c_minecraft::get_world(jobject mc) {
33 | jobject res;
34 |
35 | auto cls = gasper::instance->find_class(xorstr_("net.minecraft.client.Minecraft"));
36 | auto world_fid = gasper::instance->get_env()->GetFieldID(cls, xorstr_("field_71441_e"), xorstr_("Lnet/minecraft/client/multiplayer/WorldClient;"));
37 |
38 | res = gasper::instance->get_env()->GetObjectField(mc, world_fid);
39 |
40 | gasper::instance->get_env()->DeleteLocalRef(cls);
41 |
42 | return res;
43 | }
44 |
45 | jobject sdk::c_minecraft::get_current_screen(jobject mc) {
46 | jobject res;
47 |
48 | auto cls = gasper::instance->find_class(xorstr_("net.minecraft.client.Minecraft"));
49 | auto current_screen_fid = gasper::instance->get_env()->GetFieldID(cls, xorstr_("field_71462_r"), xorstr_("Lnet/minecraft/client/gui/GuiScreen;"));
50 |
51 | res = gasper::instance->get_env()->GetObjectField(mc, current_screen_fid);
52 |
53 | gasper::instance->get_env()->DeleteLocalRef(cls);
54 |
55 | return res;
56 | }
--------------------------------------------------------------------------------
/main/hooks/swap_buffers.cpp:
--------------------------------------------------------------------------------
1 | #include "../gasper.h"
2 |
3 | /// Context
4 | std::shared_ptr gasper::hooks::gl_context = nullptr;
5 |
6 | /// Flag for initializing ImGui
7 | std::once_flag flag;
8 |
9 | /// Our le epic swap_buffers hook :)
10 | /// NOTE: This is "stream" proof, but flickers. You can fix this by modifying the buffer.
11 | int __stdcall gasper::hooks::swap_buffers_hk(HDC hdc) {
12 |
13 | /// Le retardation has arrived
14 | static auto mc_window = wrapper::find_window(xorstr_("Minecraft 1.7.10"));
15 | auto window_rect = wrapper::get_window_rect(xorstr_("Minecraft 1.7.10"));
16 |
17 | /// std::call_once because we're hip
18 | std::call_once(flag, [&]() {
19 | gl_context = wrapper::create_gl_context();
20 | ImGui::CreateContext();
21 | ImGui_ImplWin32_Init(mc_window);
22 | ImGui_ImplOpenGL2_Init();
23 | return gasper::hooks::oswap_buffers(hdc);
24 | });
25 |
26 | /// if for some reason our instance is nullptr'd or we aren't running anymore but this hook still is
27 | /// make sure to dip
28 | if (!gasper::instance || !gasper::instance->b_running)
29 | return gasper::hooks::oswap_buffers(hdc);
30 |
31 | /// Switch to our context
32 | wglMakeCurrent(gl_context->m_hdc_devicectx, gl_context->m_glrenderctx);
33 |
34 | /// If our menu is open why don't we draw
35 | /// NOTE: If it's according to phage, a 0fps dip when rendering the menu is too compromising
36 | /// which is frankly the funniest shit I've read in a while.
37 | if (gasper::instance->b_open)
38 | {
39 | ImGui_ImplOpenGL2_NewFrame();
40 | ImGui_ImplWin32_NewFrame();
41 | ImGui::NewFrame();
42 |
43 | ImGui::Begin(xorstr_("Gasper C++"), nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize);
44 |
45 | ImGui::Text(xorstr_("Hello, World!"));
46 |
47 | ImGui::End();
48 |
49 | ImGui::Render();
50 | glViewport(0, 0, window_rect.right, window_rect.top);
51 | ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
52 | }
53 |
54 | /// Switch back
55 | wglMakeCurrent(gl_context->m_hdc_devicectx, gl_context->m_oglrenderctx);
56 |
57 | /// Call original and dip
58 | return gasper::hooks::oswap_buffers(hdc);
59 | }
60 |
--------------------------------------------------------------------------------
/main/hooks/wndproc.cpp:
--------------------------------------------------------------------------------
1 | #include "../gasper.h"
2 |
3 | /// Stole this one off of the DirectX example.
4 | LRESULT imgui_wndproc(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
5 | {
6 | ImGuiIO& io = ImGui::GetIO();
7 | switch (msg) {
8 | case WM_LBUTTONDOWN:
9 | io.MouseDown[0] = true;
10 | return true;
11 | case WM_LBUTTONUP:
12 | io.MouseDown[0] = false;
13 | return true;
14 | case WM_RBUTTONDOWN:
15 | io.MouseDown[1] = true;
16 | return true;
17 | case WM_RBUTTONUP:
18 | io.MouseDown[1] = false;
19 | return true;
20 | case WM_MBUTTONDOWN:
21 | io.MouseDown[2] = true;
22 | return true;
23 | case WM_MBUTTONUP:
24 | io.MouseDown[2] = false;
25 | return true;
26 | case WM_XBUTTONDOWN:
27 | if ((GET_KEYSTATE_WPARAM(wParam) & MK_XBUTTON1) == MK_XBUTTON1)
28 | io.MouseDown[3] = true;
29 | else if ((GET_KEYSTATE_WPARAM(wParam) & MK_XBUTTON2) == MK_XBUTTON2)
30 | io.MouseDown[4] = true;
31 | return true;
32 | case WM_XBUTTONUP:
33 | if ((GET_KEYSTATE_WPARAM(wParam) & MK_XBUTTON1) == MK_XBUTTON1)
34 | io.MouseDown[3] = false;
35 | else if ((GET_KEYSTATE_WPARAM(wParam) & MK_XBUTTON2) == MK_XBUTTON2)
36 | io.MouseDown[4] = false;
37 | return true;
38 | case WM_MOUSEWHEEL:
39 | io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
40 | return true;
41 | case WM_MOUSEMOVE:
42 | io.MousePos.x = (signed short)(lParam);
43 | io.MousePos.y = (signed short)(lParam >> 16);
44 | return true;
45 | case WM_KEYDOWN:
46 | if (wParam < 256)
47 | io.KeysDown[wParam] = 1;
48 | return true;
49 | case WM_KEYUP:
50 | if (wParam < 256)
51 | io.KeysDown[wParam] = 0;
52 | return true;
53 | case WM_CHAR:
54 | if (wParam > 0 && wParam < 0x10000)
55 | io.AddInputCharacter((unsigned short)wParam);
56 | return true;
57 | }
58 | return 0;
59 | }
60 |
61 | long __stdcall gasper::hooks::wndproc_hk(const HWND hwnd, unsigned int usermsg, uintptr_t wparam, long lparam)
62 | {
63 | if (WM_KEYDOWN == usermsg)
64 | if (wparam == VK_UP)
65 | gasper::instance->b_open = !gasper::instance->b_open;
66 |
67 | if (gasper::instance->b_open && imgui_wndproc(hwnd, usermsg, wparam, lparam))
68 | return 1l;
69 |
70 | return CallWindowProcA(hooks::original_wndproc, hwnd, usermsg, wparam, lparam);
71 | }
72 |
--------------------------------------------------------------------------------
/gasper-cpp.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;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 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 |
--------------------------------------------------------------------------------
/sdk/hook/hde/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 |
--------------------------------------------------------------------------------
/sdk/hook/hde/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 |
--------------------------------------------------------------------------------
/sdk/minecraft/player/player.cpp:
--------------------------------------------------------------------------------
1 | #include "player.h"
2 |
3 | #include "../../../main/gasper.h"
4 |
5 | c_player::c_player(jobject obj)
6 | {
7 | player_obj = obj;
8 | }
9 |
10 | c_player::~c_player()
11 | {
12 | gasper::instance->get_env()->DeleteLocalRef(player_obj);
13 | }
14 |
15 | float c_player::get_health()
16 | {
17 | jmethodID get_health_mid = gasper::instance->get_env()->GetMethodID(gasper::instance->get_env()->GetObjectClass(player_obj), xorstr_("func_110143_aJ"), xorstr_("()F"));
18 |
19 | if (!get_health_mid)
20 | return 1337.f;
21 |
22 | return gasper::instance->get_env()->CallFloatMethod(player_obj, get_health_mid);
23 | }
24 |
25 | sdk::vec3d c_player::get_position()
26 | {
27 | auto player_class = gasper::instance->get_env()->GetObjectClass(player_obj);
28 |
29 | jfieldID pos_x_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70165_t"), xorstr_("D"));
30 | jfieldID pos_y_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70163_u"), xorstr_("D"));
31 | jfieldID pos_z_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70161_v"), xorstr_("D"));
32 |
33 | gasper::instance->get_env()->DeleteLocalRef(player_class);
34 |
35 | return sdk::vec3d{
36 | gasper::instance->get_env()->GetDoubleField(player_obj, pos_x_fid),
37 | gasper::instance->get_env()->GetDoubleField(player_obj, pos_y_fid),
38 | gasper::instance->get_env()->GetDoubleField(player_obj, pos_z_fid)
39 | };
40 | }
41 |
42 | void c_player::set_yaw(float yaw)
43 | {
44 | auto player_class = gasper::instance->get_env()->GetObjectClass(player_obj);
45 | jfieldID yaw_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70177_z"), xorstr_("F"));
46 |
47 | gasper::instance->get_env()->DeleteLocalRef(player_class);
48 |
49 | gasper::instance->get_env()->SetFloatField(player_obj, yaw_fid, yaw);
50 | }
51 |
52 | float c_player::get_yaw()
53 | {
54 | auto player_class = gasper::instance->get_env()->GetObjectClass(player_obj);
55 |
56 | jfieldID yaw_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70177_z"), xorstr_("F"));
57 |
58 | gasper::instance->get_env()->DeleteLocalRef(player_class);
59 |
60 | return gasper::instance->get_env()->GetFloatField(player_obj, yaw_fid);
61 | }
62 |
63 | void c_player::set_pitch(float pitch)
64 | {
65 | auto player_class = gasper::instance->get_env()->GetObjectClass(player_obj);
66 | jfieldID pitch_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70125_A"), xorstr_("F"));
67 |
68 | gasper::instance->get_env()->DeleteLocalRef(player_class);
69 |
70 | gasper::instance->get_env()->SetFloatField(player_obj, pitch_fid, pitch);
71 | }
72 |
73 | float c_player::get_pitch()
74 | {
75 | auto player_class = gasper::instance->get_env()->GetObjectClass(player_obj);
76 | jfieldID pitch_fid = gasper::instance->get_env()->GetFieldID(player_class, xorstr_("field_70125_A"), xorstr_("F"));
77 |
78 | gasper::instance->get_env()->DeleteLocalRef(player_class);
79 |
80 | return gasper::instance->get_env()->GetFloatField(player_obj, pitch_fid);
81 | }
82 |
83 | double c_player::get_distance_to(std::shared_ptr other)
84 | {
85 | auto pos = get_position();
86 | auto entity_pos = other->get_position();
87 | return sdk::util::distance(pos.x, pos.y, pos.z, entity_pos.x, entity_pos.y, entity_pos.z);
88 | }
89 |
--------------------------------------------------------------------------------
/sdk/hook/hde/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 |
--------------------------------------------------------------------------------
/sdk/hook/hde/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 |
--------------------------------------------------------------------------------
/sdk/wrapper/wrapper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /// Thought about wrapping certain WinAPI functions to keep syntax consistancy
4 | /// also handy when obfuscating these calls :)
5 | namespace wrapper {
6 |
7 | /// Simple wrapper for CreateThread
8 | inline HANDLE spawn_thread(LPTHREAD_START_ROUTINE routine) {
9 | return CreateThread(0, 0, routine, 0, 0, 0);
10 | }
11 |
12 | /// Simple wrapper to show MessageBox
13 | const inline void show_message(std::string msg) {
14 | MessageBoxA(nullptr, msg.c_str(), xorstr_("[dbg] gasper"), MB_OK);
15 | }
16 |
17 | /// Simple wrapper to handle issues
18 | const inline bool handle_issue(const char* name, void* ptr)
19 | {
20 | /// Constant formatting message
21 | const auto s_formatting = xorstr_("%s not intialized, value -> 0x%X");
22 |
23 | /// Value isn't initialized
24 | if (!ptr)
25 | {
26 | size_t len = std::snprintf(nullptr, 0, s_formatting, name, ptr) + 1; /// Had issues with terminator
27 |
28 | if (len <= 0)
29 | show_message(xorstr_("Issue formatting issue_handler wrapper::#handle_issue#26"));
30 |
31 | /// Allocate buffer with lenght of message
32 | std::unique_ptr buffer(new char[len]);
33 |
34 | /// Format the message to buffer
35 | std::snprintf(buffer.get(), len, s_formatting, name, ptr);
36 |
37 | /// Show the message
38 | show_message(std::string(buffer.get(), buffer.get() + len - 1));
39 |
40 | /// Show that an issue occured
41 | return true;
42 | }
43 |
44 | /// Everything gucci
45 | return false;
46 | }
47 |
48 | /// Wrapper to get address of module
49 | inline void* get_module_handle(const char* name) {
50 | auto h_module = GetModuleHandleA(name);
51 |
52 | if (handle_issue(name, h_module))
53 | std::exit(0);
54 |
55 | return h_module;
56 | }
57 |
58 | /// Wrapper to get window
59 | inline HWND find_window(const char* name)
60 | {
61 | auto res = FindWindowA(nullptr, name);
62 |
63 | if (handle_issue(name, res))
64 | std::exit(0);
65 |
66 | return res;
67 | }
68 |
69 | inline RECT get_window_rect(const char* name)
70 | {
71 | RECT res;
72 | GetWindowRect(find_window(name), &res);
73 |
74 | return res;
75 | }
76 |
77 | /// Wrapper to get procedure address
78 | inline void* get_proc_address(const char* name, void* handle)
79 | {
80 | auto p_procedure = GetProcAddress(reinterpret_cast(handle), name);
81 |
82 | if (handle_issue(name, p_procedure))
83 | std::exit(0);
84 |
85 | return p_procedure;
86 | }
87 |
88 | /// Wrapper for GetAynscKeyState
89 | inline short get_async_keystate(int key)
90 | {
91 | return GetAsyncKeyState(key);
92 | }
93 |
94 | /// Wrapper class for OpenGL context
95 | struct c_context {
96 | HDC m_hdc_devicectx;
97 | HGLRC m_glrenderctx;
98 | HGLRC m_oglrenderctx;
99 | };
100 |
101 | inline std::shared_ptr create_gl_context()
102 | {
103 | std::shared_ptr res = std::make_shared();
104 |
105 | PIXELFORMATDESCRIPTOR pfd =
106 | {
107 | sizeof(PIXELFORMATDESCRIPTOR),
108 | 1,
109 | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
110 | PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
111 | 32, // Colordepth of the framebuffer.
112 | 0, 0, 0, 0, 0, 0,
113 | 0,
114 | 0,
115 | 0,
116 | 0, 0, 0, 0,
117 | 24, // Number of bits for the depthbuffer
118 | 8, // Number of bits for the stencilbuffer
119 | 0, // Number of Aux buffers in the framebuffer.
120 | PFD_MAIN_PLANE,
121 | 0,
122 | 0, 0, 0
123 | };
124 |
125 | res->m_hdc_devicectx = GetDC(find_window(xorstr_("Minecraft 1.7.10")));
126 |
127 | int pixel_format = ChoosePixelFormat(res->m_hdc_devicectx, &pfd);
128 | SetPixelFormat(res->m_hdc_devicectx, pixel_format, &pfd);
129 |
130 | res->m_oglrenderctx = wglGetCurrentContext();
131 | res->m_glrenderctx = wglCreateContext(res->m_hdc_devicectx);
132 | return res;
133 | }
134 | }
--------------------------------------------------------------------------------
/sdk/hook/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 |
--------------------------------------------------------------------------------
/sdk/libraries/imgui/imconfig.h:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI
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/branch with your modifications to imconfig.h)
7 | // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
8 | // If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include
9 | // the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
10 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
11 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
12 | //-----------------------------------------------------------------------------
13 |
14 | #pragma once
15 |
16 | //---- Define assertion handler. Defaults to calling assert().
17 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
18 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
19 |
20 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
21 | // 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.
22 | //#define IMGUI_API __declspec( dllexport )
23 | //#define IMGUI_API __declspec( dllimport )
24 |
25 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
26 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
27 |
28 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
29 | // It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
30 | //#define IMGUI_DISABLE_DEMO_WINDOWS
31 | //#define IMGUI_DISABLE_METRICS_WINDOW
32 |
33 | //---- Don't implement some functions to reduce linkage requirements.
34 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
35 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
36 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
37 | //#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).
38 | //#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)
39 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
40 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite 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.
41 | //#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().
42 |
43 | //---- Include imgui_user.h at the end of imgui.h as a convenience
44 | //#define IMGUI_INCLUDE_IMGUI_USER_H
45 |
46 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
47 | //#define IMGUI_USE_BGRA_PACKED_COLOR
48 |
49 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
50 | // By default the embedded implementations are declared static and not available outside of imgui cpp files.
51 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
52 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
53 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
54 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
55 |
56 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
57 | // This will be inlined as part of ImVec2 and ImVec4 class declarations.
58 | /*
59 | #define IM_VEC2_CLASS_EXTRA \
60 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
61 | operator MyVec2() const { return MyVec2(x,y); }
62 |
63 | #define IM_VEC4_CLASS_EXTRA \
64 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
65 | operator MyVec4() const { return MyVec4(x,y,z,w); }
66 | */
67 |
68 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
69 | // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bit indices).
70 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
71 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
72 | //#define ImDrawIdx unsigned int
73 |
74 | //---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly)
75 | //struct ImDrawList;
76 | //struct ImDrawCmd;
77 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
78 | //#define ImDrawCallback MyImDrawCallback
79 |
80 | //---- Debug Tools: Macro to break in Debugger
81 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
82 | //#define IM_DEBUG_BREAK IM_ASSERT(0)
83 | //#define IM_DEBUG_BREAK __debugbreak()
84 |
85 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
86 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
87 | // This adds a small runtime cost which is why it is not enabled by default.
88 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
89 |
90 | //---- Debug Tools: Enable slower asserts
91 | //#define IMGUI_DEBUG_PARANOID
92 |
93 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
94 | /*
95 | namespace ImGui
96 | {
97 | void MyFunction(const char* name, const MyMatrix44& v);
98 | }
99 | */
100 |
--------------------------------------------------------------------------------
/main/gasper.cpp:
--------------------------------------------------------------------------------
1 | #include "gasper.h"
2 |
3 | #include "../sdk/minecraft/minecraft.h"
4 | #include "../sdk/minecraft/player/player.h"
5 | #include "../sdk/minecraft/world/world.h"
6 |
7 | /// Attach to the JVM
8 | bool gasper::c_gasper::attach()
9 | {
10 | auto jvm_dll = wrapper::get_module_handle(xorstr_("jvm.dll"));
11 |
12 | auto created_java_vms = reinterpret_cast(wrapper::get_proc_address(xorstr_("JNI_GetCreatedJavaVMs"), jvm_dll));
13 |
14 | auto ret = created_java_vms(&vm, 1, nullptr);
15 |
16 | if (ret != JNI_OK)
17 | return false;
18 |
19 | ret = get_vm()->AttachCurrentThread(reinterpret_cast(&env), nullptr);
20 |
21 | if (ret != JNI_OK)
22 | return false;
23 |
24 | /// Get the launchwrapper instance so that we can use findClass
25 | get_launchwrapper();
26 |
27 | /// Hook our shizzle
28 | hook();
29 |
30 | /// Now we can begin business
31 | b_running = true;
32 |
33 | return true;
34 | }
35 |
36 | void gasper::c_gasper::run()
37 | {
38 | /// Spawn an instance of our "SDK"
39 | sdk::instance = std::make_unique();
40 |
41 | /// We better be running
42 | while (b_running)
43 | {
44 | /// "Self-destruct" button
45 | if (wrapper::get_async_keystate(VK_HOME))
46 | b_running = false;
47 |
48 | /// Keep the time
49 | static sdk::qword time;
50 |
51 | /// Le epic flag for le epic modern C++
52 | static std::once_flag flag;
53 |
54 | /// Notify of injection (this is for testing)
55 | /// Note to self: release mode currently contains pretty much the same debug info as debug config
56 | /// so if you want to sell this piece of shit you better change that or else you'll get crackalacked in a minute
57 | std::call_once(flag, [&]() { wrapper::show_message(xorstr_("Injected.")); });
58 |
59 | /// Keep references simple so that we can easily dispose of them later (they're all localref btw)
60 | /// but they last for one cycle of this thread so we shouldn't worry about them being accidentally destroyed suddenly
61 | auto minecraft_inst = sdk::instance->get_minecraft();
62 |
63 | /// NOTE: the player and world class already dispose of the references themselves
64 | auto local = std::make_unique(sdk::instance->get_player(minecraft_inst));
65 | auto world = std::make_unique(sdk::instance->get_world(minecraft_inst));
66 |
67 | /// Returns true when the local player object and the world object aren't null
68 | const auto is_sane = [&]() {
69 | return (local->get_object() && world->get_object());
70 | };
71 |
72 | /// Get closest player to local player (distance wise)
73 | const auto get_closest_player = [&]() {
74 | /// If you still use some random number you're stupid
75 | double dist = (std::numeric_limits::max)();
76 | /// Target :O
77 | std::shared_ptr target = nullptr;
78 |
79 | /// Iterate over all player objects in the world
80 | /// note: c_world#get_players actually iterates the playerlist so if you want to iterate the entity list instead
81 | /// you should actually change the field
82 | for (const auto& player : world->get_players())
83 | {
84 | /// Compare the object to our local player to make sure we aren't going to be aiming at ourselves
85 | if (get_env()->IsSameObject(local->get_object(), player->get_object()))
86 | continue;
87 |
88 | /// Not ded?
89 | if (!player->get_health() > 0)
90 | continue;
91 |
92 | /// Basic stuff
93 | if (local->get_distance_to(player) <= dist)
94 | {
95 | dist = local->get_distance_to(player);
96 | target = player;
97 | }
98 | }
99 |
100 | return target;
101 | };
102 |
103 | /// Simple lambda function that returns true if time has been passed
104 | const auto has_passed = [&](float ms) {
105 | if (GetTickCount64() - time > ms)
106 | {
107 | time = GetTickCount64();
108 | return true;
109 | }
110 |
111 | return false;
112 | };
113 |
114 | /// We're ingame
115 | if (is_sane())
116 | {
117 | auto entity = get_closest_player();
118 |
119 | /// use 30ms, because the game runs on a 20 tick system, but we want to smooth it out, so run it a tad more
120 | if (entity && has_passed(30) )
121 | {
122 | auto angles = sdk::util::get_angles(local->get_position(), entity->get_position());
123 |
124 | auto difference = sdk::util::wrap_to_180(-(local->get_yaw() - angles.first));
125 |
126 | /// difference might be negative so yknow
127 | if (abs(difference) <= 30) {
128 | auto current_yaw = local->get_yaw();
129 | current_yaw += (difference / 20);
130 |
131 | local->set_yaw(current_yaw);
132 | }
133 | }
134 | }
135 |
136 | /// Delete the reference
137 | get_env()->DeleteLocalRef(minecraft_inst);
138 |
139 | /// Let's save the CPU some processing powerz
140 | std::this_thread::sleep_for(std::chrono::milliseconds(5));
141 | }
142 | }
143 |
144 | /// This is called when we're supposed to dispose of our mineman hackery
145 | void gasper::c_gasper::dispose()
146 | {
147 | get_env()->DeleteGlobalRef(classloader_obj);
148 | get_vm()->DetachCurrentThread();
149 |
150 | ImGui_ImplOpenGL2_Shutdown();
151 | wglDeleteContext(hooks::gl_context->m_glrenderctx);
152 | ImGui::DestroyContext();
153 | ImGui_ImplWin32_Shutdown();
154 |
155 | MH_DisableHook(MH_ALL_HOOKS);
156 | MH_Uninitialize();
157 |
158 | SetWindowLongPtrA(wrapper::find_window(xorstr_("Minecraft 1.7.10")), GWLP_WNDPROC, (LONG_PTR)hooks::original_wndproc);
159 |
160 | env = nullptr;
161 | hooks::gl_context = nullptr;
162 | vm = nullptr;
163 | }
164 |
165 | void gasper::c_gasper::get_launchwrapper()
166 | {
167 | jclass launchwrapper_cls = get_env()->FindClass(xorstr_("net/minecraft/launchwrapper/LaunchClassLoader"));
168 | jclass launch_cls = get_env()->FindClass(xorstr_("net/minecraft/launchwrapper/Launch"));
169 |
170 | if (wrapper::handle_issue(xorstr_("launchwrapper"), launchwrapper_cls) ||
171 | wrapper::handle_issue(xorstr_("launch_cls"), launch_cls))
172 | std::exit(0);
173 |
174 | auto classloader_fid = get_env()->GetStaticFieldID(launch_cls, xorstr_("classLoader"), xorstr_("Lnet/minecraft/launchwrapper/LaunchClassLoader;"));
175 |
176 | findclass_md = get_env()->GetMethodID(launchwrapper_cls, xorstr_("findClass"), xorstr_("(Ljava/lang/String;)Ljava/lang/Class;"));
177 | classloader_obj = get_env()->NewGlobalRef(get_env()->GetStaticObjectField(launch_cls, classloader_fid));
178 |
179 | get_env()->DeleteLocalRef(launchwrapper_cls);
180 | get_env()->DeleteLocalRef(launch_cls);
181 | }
182 |
183 | void gasper::c_gasper::hook()
184 | {
185 | MH_Initialize();
186 |
187 | auto swap_buffers_ptr = wrapper::get_proc_address(xorstr_("SwapBuffers"), wrapper::get_module_handle(xorstr_("Gdi32.dll")));
188 |
189 | MH_CreateHook(swap_buffers_ptr, hooks::swap_buffers_hk, reinterpret_cast(&hooks::oswap_buffers));
190 | MH_EnableHook(MH_ALL_HOOKS);
191 |
192 | /// Set the WndProc
193 | hooks::original_wndproc = reinterpret_cast(SetWindowLongPtrA(wrapper::find_window(xorstr_("Minecraft 1.7.10")), GWLP_WNDPROC, reinterpret_cast(hooks::wndproc_hk)));
194 | }
195 |
196 |
197 | std::unique_ptr gasper::instance;
--------------------------------------------------------------------------------
/sdk/hook/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 |
--------------------------------------------------------------------------------
/gasper-cpp.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 | {0F49A3C8-151C-466C-98E5-43E8EFC24D41}
24 | gaspercpp
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v142
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v142
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v142
45 | Unicode
46 |
47 |
48 | DynamicLibrary
49 | false
50 | v142
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 | C:\Program Files\Java\jdk1.8.0_231\include\win32;C:\Program Files\Java\jdk1.8.0_231\include;$(IncludePath)
84 | C:\Program Files\Java\jdk1.8.0_231\lib;$(LibraryPath)
85 |
86 |
87 |
88 | Level3
89 | true
90 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
91 | true
92 |
93 |
94 | Console
95 | true
96 |
97 |
98 |
99 |
100 | Level3
101 | true
102 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
103 | true
104 |
105 |
106 | Console
107 | true
108 |
109 |
110 |
111 |
112 | Level3
113 | true
114 | true
115 | true
116 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
117 | true
118 |
119 |
120 | Console
121 | true
122 | true
123 | true
124 |
125 |
126 |
127 |
128 | Level3
129 | true
130 | true
131 | true
132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
133 | true
134 | stdcpp17
135 |
136 |
137 | Console
138 | true
139 | true
140 | true
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/sdk/libraries/xorstr.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 - 2018 Justas Masiulis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef JM_XORSTR_HPP
18 | #define JM_XORSTR_HPP
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #define xorstr(str) \
26 | ::jm::make_xorstr( \
27 | []() { return str; }, \
28 | std::make_index_sequence{}, \
29 | std::make_index_sequence<::jm::detail::_buffer_size()>{})
30 | #define xorstr_(str) xorstr(str).crypt_get()
31 |
32 | #ifdef _MSC_VER
33 | #define XORSTR_FORCEINLINE __forceinline
34 | #else
35 | #define XORSTR_FORCEINLINE __attribute__((always_inline))
36 | #endif
37 |
38 | // you can define this macro to get possibly faster code on gcc/clang
39 | // at the expense of constants being put into data section.
40 | #if !defined(XORSTR_ALLOW_DATA)
41 | // MSVC - no volatile
42 | // GCC and clang - volatile everywhere
43 | #if defined(__clang__) || defined(__GNUC__)
44 | #define XORSTR_VOLATILE volatile
45 | #endif
46 |
47 | #endif
48 | #ifndef XORSTR_VOLATILE
49 | #define XORSTR_VOLATILE
50 | #endif
51 |
52 | namespace jm {
53 |
54 | namespace detail {
55 |
56 | template
57 | struct unsigned_;
58 |
59 | template<>
60 | struct unsigned_<1> {
61 | using type = std::uint8_t;
62 | };
63 | template<>
64 | struct unsigned_<2> {
65 | using type = std::uint16_t;
66 | };
67 | template<>
68 | struct unsigned_<4> {
69 | using type = std::uint32_t;
70 | };
71 |
72 | template
73 | struct pack_value_type {
74 | using type = decltype(C);
75 | };
76 |
77 | template
78 | constexpr std::size_t _buffer_size()
79 | {
80 | return ((Size / 16) + (Size % 16 != 0)) * 2;
81 | }
82 |
83 | template
84 | struct tstring_ {
85 | using value_type = typename pack_value_type::type;
86 | constexpr static std::size_t size = sizeof...(Cs);
87 | constexpr static value_type str[size] = { Cs... };
88 |
89 | constexpr static std::size_t buffer_size = _buffer_size();
90 | constexpr static std::size_t buffer_align =
91 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
92 | ((sizeof(str) > 16) ? 32 : 16);
93 | #else
94 | 16;
95 | #endif
96 | };
97 |
98 | template
99 | struct _ki {
100 | constexpr static std::size_t idx = I;
101 | constexpr static std::uint64_t key = K;
102 | };
103 |
104 | template
105 | constexpr std::uint32_t key4() noexcept
106 | {
107 | std::uint32_t value = Seed;
108 | for (char c : __TIME__)
109 | value = static_cast((value ^ c) * 16777619ull);
110 | return value;
111 | }
112 |
113 | template
114 | constexpr std::uint64_t key8()
115 | {
116 | constexpr auto first_part = key4<2166136261 + S>();
117 | constexpr auto second_part = key4();
118 | return (static_cast(first_part) << 32) | second_part;
119 | }
120 |
121 | // clang and gcc try really hard to place the constants in data
122 | // sections. to counter that there was a need to create an intermediate
123 | // constexpr string and then copy it into a non constexpr container with
124 | // volatile storage so that the constants would be placed directly into
125 | // code.
126 | template
127 | struct string_storage {
128 | std::uint64_t storage[T::buffer_size];
129 |
130 | XORSTR_FORCEINLINE constexpr string_storage() noexcept : storage{ Keys... }
131 | {
132 | using cast_type =
133 | typename unsigned_::type;
134 | constexpr auto value_size = sizeof(typename T::value_type);
135 | // puts the string into 64 bit integer blocks in a constexpr
136 | // fashion
137 | for (std::size_t i = 0; i < T::size; ++i)
138 | storage[i / (8 / value_size)] ^=
139 | (std::uint64_t{ static_cast(T::str[i]) }
140 | << ((i % (8 / value_size)) * 8 * value_size));
141 | }
142 | };
143 |
144 | } // namespace detail
145 |
146 | template
147 | class xor_string {
148 | alignas(T::buffer_align) std::uint64_t _storage[T::buffer_size];
149 |
150 | // _single functions needed because MSVC crashes without them
151 | XORSTR_FORCEINLINE void _crypt_256_single(const std::uint64_t* keys,
152 | std::uint64_t* storage) noexcept
153 |
154 | {
155 | _mm256_store_si256(
156 | reinterpret_cast<__m256i*>(storage),
157 | _mm256_xor_si256(
158 | _mm256_load_si256(reinterpret_cast(storage)),
159 | _mm256_load_si256(reinterpret_cast(keys))));
160 | }
161 |
162 | template
163 | XORSTR_FORCEINLINE void _crypt_256(const std::uint64_t* keys,
164 | std::index_sequence) noexcept
165 | {
166 | (_crypt_256_single(keys + Idxs * 4, _storage + Idxs * 4), ...);
167 | }
168 |
169 | XORSTR_FORCEINLINE void _crypt_128_single(const std::uint64_t* keys,
170 | std::uint64_t* storage) noexcept
171 | {
172 | _mm_store_si128(
173 | reinterpret_cast<__m128i*>(storage),
174 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(storage)),
175 | _mm_load_si128(reinterpret_cast(keys))));
176 | }
177 |
178 | template
179 | XORSTR_FORCEINLINE void _crypt_128(const std::uint64_t* keys,
180 | std::index_sequence) noexcept
181 | {
182 | (_crypt_128_single(keys + Idxs * 2, _storage + Idxs * 2), ...);
183 | }
184 |
185 | // loop generates vectorized code which places constants in data dir
186 | XORSTR_FORCEINLINE constexpr void _copy() noexcept
187 | {
188 | constexpr detail::string_storage storage;
189 | static_cast(std::initializer_list{
190 | (const_cast(_storage))[Keys::idx] =
191 | storage.storage[Keys::idx]... });
192 | }
193 |
194 | public:
195 | using value_type = typename T::value_type;
196 | using size_type = std::size_t;
197 | using pointer = value_type*;
198 | using const_pointer = const pointer;
199 |
200 | XORSTR_FORCEINLINE xor_string() noexcept { _copy(); }
201 |
202 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept
203 | {
204 | return T::size - 1;
205 | }
206 |
207 | XORSTR_FORCEINLINE void crypt() noexcept
208 | {
209 | alignas(T::buffer_align) std::uint64_t keys[T::buffer_size];
210 | static_cast(std::initializer_list{
211 | (const_cast(keys))[Keys::idx] =
212 | Keys::key... });
213 |
214 | _copy();
215 |
216 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
217 | _crypt_256(keys, std::make_index_sequence{});
218 | if constexpr (T::buffer_size % 4 != 0)
219 | _crypt_128(keys, std::index_sequence{});
220 | #else
221 | _crypt_128(keys, std::make_index_sequence{});
222 | #endif
223 | }
224 |
225 | XORSTR_FORCEINLINE const_pointer get() const noexcept
226 | {
227 | return reinterpret_cast(_storage);
228 | }
229 |
230 | XORSTR_FORCEINLINE const_pointer crypt_get() noexcept
231 | {
232 | crypt();
233 | return reinterpret_cast(_storage);
234 | }
235 | };
236 |
237 | template
238 | XORSTR_FORCEINLINE constexpr auto
239 | make_xorstr(Tstr str_lambda,
240 | std::index_sequence,
241 | std::index_sequence) noexcept
242 | {
243 | return xor_string,
244 | detail::_ki()>...>{};
245 | }
246 |
247 | } // namespace jm
248 |
249 | #endif // include guard
--------------------------------------------------------------------------------
/sdk/hook/hde/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 | } else if (c >= 0xa0 && c <= 0xa3) {
66 | if (pref & PRE_67)
67 | pref |= PRE_66;
68 | else
69 | pref &= ~PRE_66;
70 | }
71 |
72 | opcode = c;
73 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
74 |
75 | if (cflags == C_ERROR) {
76 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
77 | cflags = 0;
78 | if ((opcode & -3) == 0x24)
79 | cflags++;
80 | }
81 |
82 | x = 0;
83 | if (cflags & C_GROUP) {
84 | uint16_t t;
85 | t = *(uint16_t *)(ht + (cflags & 0x7f));
86 | cflags = (uint8_t)t;
87 | x = (uint8_t)(t >> 8);
88 | }
89 |
90 | if (hs->opcode2) {
91 | ht = hde32_table + DELTA_PREFIXES;
92 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
93 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
94 | }
95 |
96 | if (cflags & C_MODRM) {
97 | hs->flags |= F_MODRM;
98 | hs->modrm = c = *p++;
99 | hs->modrm_mod = m_mod = c >> 6;
100 | hs->modrm_rm = m_rm = c & 7;
101 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
102 |
103 | if (x && ((x << m_reg) & 0x80))
104 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
105 |
106 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
107 | uint8_t t = opcode - 0xd9;
108 | if (m_mod == 3) {
109 | ht = hde32_table + DELTA_FPU_MODRM + t*8;
110 | t = ht[m_reg] << m_rm;
111 | } else {
112 | ht = hde32_table + DELTA_FPU_REG;
113 | t = ht[t] << m_reg;
114 | }
115 | if (t & 0x80)
116 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
117 | }
118 |
119 | if (pref & PRE_LOCK) {
120 | if (m_mod == 3) {
121 | hs->flags |= F_ERROR | F_ERROR_LOCK;
122 | } else {
123 | uint8_t *table_end, op = opcode;
124 | if (hs->opcode2) {
125 | ht = hde32_table + DELTA_OP2_LOCK_OK;
126 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
127 | } else {
128 | ht = hde32_table + DELTA_OP_LOCK_OK;
129 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
130 | op &= -2;
131 | }
132 | for (; ht != table_end; ht++)
133 | if (*ht++ == op) {
134 | if (!((*ht << m_reg) & 0x80))
135 | goto no_lock_error;
136 | else
137 | break;
138 | }
139 | hs->flags |= F_ERROR | F_ERROR_LOCK;
140 | no_lock_error:
141 | ;
142 | }
143 | }
144 |
145 | if (hs->opcode2) {
146 | switch (opcode) {
147 | case 0x20: case 0x22:
148 | m_mod = 3;
149 | if (m_reg > 4 || m_reg == 1)
150 | goto error_operand;
151 | else
152 | goto no_error_operand;
153 | case 0x21: case 0x23:
154 | m_mod = 3;
155 | if (m_reg == 4 || m_reg == 5)
156 | goto error_operand;
157 | else
158 | goto no_error_operand;
159 | }
160 | } else {
161 | switch (opcode) {
162 | case 0x8c:
163 | if (m_reg > 5)
164 | goto error_operand;
165 | else
166 | goto no_error_operand;
167 | case 0x8e:
168 | if (m_reg == 1 || m_reg > 5)
169 | goto error_operand;
170 | else
171 | goto no_error_operand;
172 | }
173 | }
174 |
175 | if (m_mod == 3) {
176 | uint8_t *table_end;
177 | if (hs->opcode2) {
178 | ht = hde32_table + DELTA_OP2_ONLY_MEM;
179 | table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
180 | } else {
181 | ht = hde32_table + DELTA_OP_ONLY_MEM;
182 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
183 | }
184 | for (; ht != table_end; ht += 2)
185 | if (*ht++ == opcode) {
186 | if (*ht++ & pref && !((*ht << m_reg) & 0x80))
187 | goto error_operand;
188 | else
189 | break;
190 | }
191 | goto no_error_operand;
192 | } else if (hs->opcode2) {
193 | switch (opcode) {
194 | case 0x50: case 0xd7: case 0xf7:
195 | if (pref & (PRE_NONE | PRE_66))
196 | goto error_operand;
197 | break;
198 | case 0xd6:
199 | if (pref & (PRE_F2 | PRE_F3))
200 | goto error_operand;
201 | break;
202 | case 0xc5:
203 | goto error_operand;
204 | }
205 | goto no_error_operand;
206 | } else
207 | goto no_error_operand;
208 |
209 | error_operand:
210 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
211 | no_error_operand:
212 |
213 | c = *p++;
214 | if (m_reg <= 1) {
215 | if (opcode == 0xf6)
216 | cflags |= C_IMM8;
217 | else if (opcode == 0xf7)
218 | cflags |= C_IMM_P66;
219 | }
220 |
221 | switch (m_mod) {
222 | case 0:
223 | if (pref & PRE_67) {
224 | if (m_rm == 6)
225 | disp_size = 2;
226 | } else
227 | if (m_rm == 5)
228 | disp_size = 4;
229 | break;
230 | case 1:
231 | disp_size = 1;
232 | break;
233 | case 2:
234 | disp_size = 2;
235 | if (!(pref & PRE_67))
236 | disp_size <<= 1;
237 | }
238 |
239 | if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
240 | hs->flags |= F_SIB;
241 | p++;
242 | hs->sib = c;
243 | hs->sib_scale = c >> 6;
244 | hs->sib_index = (c & 0x3f) >> 3;
245 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
246 | disp_size = 4;
247 | }
248 |
249 | p--;
250 | switch (disp_size) {
251 | case 1:
252 | hs->flags |= F_DISP8;
253 | hs->disp.disp8 = *p;
254 | break;
255 | case 2:
256 | hs->flags |= F_DISP16;
257 | hs->disp.disp16 = *(uint16_t *)p;
258 | break;
259 | case 4:
260 | hs->flags |= F_DISP32;
261 | hs->disp.disp32 = *(uint32_t *)p;
262 | }
263 | p += disp_size;
264 | } else if (pref & PRE_LOCK)
265 | hs->flags |= F_ERROR | F_ERROR_LOCK;
266 |
267 | if (cflags & C_IMM_P66) {
268 | if (cflags & C_REL32) {
269 | if (pref & PRE_66) {
270 | hs->flags |= F_IMM16 | F_RELATIVE;
271 | hs->imm.imm16 = *(uint16_t *)p;
272 | p += 2;
273 | goto disasm_done;
274 | }
275 | goto rel32_ok;
276 | }
277 | if (pref & PRE_66) {
278 | hs->flags |= F_IMM16;
279 | hs->imm.imm16 = *(uint16_t *)p;
280 | p += 2;
281 | } else {
282 | hs->flags |= F_IMM32;
283 | hs->imm.imm32 = *(uint32_t *)p;
284 | p += 4;
285 | }
286 | }
287 |
288 | if (cflags & C_IMM16) {
289 | if (hs->flags & F_IMM32) {
290 | hs->flags |= F_IMM16;
291 | hs->disp.disp16 = *(uint16_t *)p;
292 | } else if (hs->flags & F_IMM16) {
293 | hs->flags |= F_2IMM16;
294 | hs->disp.disp16 = *(uint16_t *)p;
295 | } else {
296 | hs->flags |= F_IMM16;
297 | hs->imm.imm16 = *(uint16_t *)p;
298 | }
299 | p += 2;
300 | }
301 | if (cflags & C_IMM8) {
302 | hs->flags |= F_IMM8;
303 | hs->imm.imm8 = *p++;
304 | }
305 |
306 | if (cflags & C_REL32) {
307 | rel32_ok:
308 | hs->flags |= F_IMM32 | F_RELATIVE;
309 | hs->imm.imm32 = *(uint32_t *)p;
310 | p += 4;
311 | } else if (cflags & C_REL8) {
312 | hs->flags |= F_IMM8 | F_RELATIVE;
313 | hs->imm.imm8 = *p++;
314 | }
315 |
316 | disasm_done:
317 |
318 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
319 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
320 | hs->len = 15;
321 | }
322 |
323 | return (unsigned int)hs->len;
324 | }
325 |
326 | #endif // defined(_M_IX86) || defined(__i386__)
327 |
--------------------------------------------------------------------------------
/sdk/hook/hde/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 | } else if (c >= 0xa0 && c <= 0xa3) {
80 | op64++;
81 | if (pref & PRE_67)
82 | pref |= PRE_66;
83 | else
84 | pref &= ~PRE_66;
85 | }
86 |
87 | opcode = c;
88 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
89 |
90 | if (cflags == C_ERROR) {
91 | error_opcode:
92 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
93 | cflags = 0;
94 | if ((opcode & -3) == 0x24)
95 | cflags++;
96 | }
97 |
98 | x = 0;
99 | if (cflags & C_GROUP) {
100 | uint16_t t;
101 | t = *(uint16_t *)(ht + (cflags & 0x7f));
102 | cflags = (uint8_t)t;
103 | x = (uint8_t)(t >> 8);
104 | }
105 |
106 | if (hs->opcode2) {
107 | ht = hde64_table + DELTA_PREFIXES;
108 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
109 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
110 | }
111 |
112 | if (cflags & C_MODRM) {
113 | hs->flags |= F_MODRM;
114 | hs->modrm = c = *p++;
115 | hs->modrm_mod = m_mod = c >> 6;
116 | hs->modrm_rm = m_rm = c & 7;
117 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
118 |
119 | if (x && ((x << m_reg) & 0x80))
120 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
121 |
122 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
123 | uint8_t t = opcode - 0xd9;
124 | if (m_mod == 3) {
125 | ht = hde64_table + DELTA_FPU_MODRM + t*8;
126 | t = ht[m_reg] << m_rm;
127 | } else {
128 | ht = hde64_table + DELTA_FPU_REG;
129 | t = ht[t] << m_reg;
130 | }
131 | if (t & 0x80)
132 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
133 | }
134 |
135 | if (pref & PRE_LOCK) {
136 | if (m_mod == 3) {
137 | hs->flags |= F_ERROR | F_ERROR_LOCK;
138 | } else {
139 | uint8_t *table_end, op = opcode;
140 | if (hs->opcode2) {
141 | ht = hde64_table + DELTA_OP2_LOCK_OK;
142 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
143 | } else {
144 | ht = hde64_table + DELTA_OP_LOCK_OK;
145 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
146 | op &= -2;
147 | }
148 | for (; ht != table_end; ht++)
149 | if (*ht++ == op) {
150 | if (!((*ht << m_reg) & 0x80))
151 | goto no_lock_error;
152 | else
153 | break;
154 | }
155 | hs->flags |= F_ERROR | F_ERROR_LOCK;
156 | no_lock_error:
157 | ;
158 | }
159 | }
160 |
161 | if (hs->opcode2) {
162 | switch (opcode) {
163 | case 0x20: case 0x22:
164 | m_mod = 3;
165 | if (m_reg > 4 || m_reg == 1)
166 | goto error_operand;
167 | else
168 | goto no_error_operand;
169 | case 0x21: case 0x23:
170 | m_mod = 3;
171 | if (m_reg == 4 || m_reg == 5)
172 | goto error_operand;
173 | else
174 | goto no_error_operand;
175 | }
176 | } else {
177 | switch (opcode) {
178 | case 0x8c:
179 | if (m_reg > 5)
180 | goto error_operand;
181 | else
182 | goto no_error_operand;
183 | case 0x8e:
184 | if (m_reg == 1 || m_reg > 5)
185 | goto error_operand;
186 | else
187 | goto no_error_operand;
188 | }
189 | }
190 |
191 | if (m_mod == 3) {
192 | uint8_t *table_end;
193 | if (hs->opcode2) {
194 | ht = hde64_table + DELTA_OP2_ONLY_MEM;
195 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
196 | } else {
197 | ht = hde64_table + DELTA_OP_ONLY_MEM;
198 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
199 | }
200 | for (; ht != table_end; ht += 2)
201 | if (*ht++ == opcode) {
202 | if (*ht++ & pref && !((*ht << m_reg) & 0x80))
203 | goto error_operand;
204 | else
205 | break;
206 | }
207 | goto no_error_operand;
208 | } else if (hs->opcode2) {
209 | switch (opcode) {
210 | case 0x50: case 0xd7: case 0xf7:
211 | if (pref & (PRE_NONE | PRE_66))
212 | goto error_operand;
213 | break;
214 | case 0xd6:
215 | if (pref & (PRE_F2 | PRE_F3))
216 | goto error_operand;
217 | break;
218 | case 0xc5:
219 | goto error_operand;
220 | }
221 | goto no_error_operand;
222 | } else
223 | goto no_error_operand;
224 |
225 | error_operand:
226 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
227 | no_error_operand:
228 |
229 | c = *p++;
230 | if (m_reg <= 1) {
231 | if (opcode == 0xf6)
232 | cflags |= C_IMM8;
233 | else if (opcode == 0xf7)
234 | cflags |= C_IMM_P66;
235 | }
236 |
237 | switch (m_mod) {
238 | case 0:
239 | if (pref & PRE_67) {
240 | if (m_rm == 6)
241 | disp_size = 2;
242 | } else
243 | if (m_rm == 5)
244 | disp_size = 4;
245 | break;
246 | case 1:
247 | disp_size = 1;
248 | break;
249 | case 2:
250 | disp_size = 2;
251 | if (!(pref & PRE_67))
252 | disp_size <<= 1;
253 | }
254 |
255 | if (m_mod != 3 && m_rm == 4) {
256 | hs->flags |= F_SIB;
257 | p++;
258 | hs->sib = c;
259 | hs->sib_scale = c >> 6;
260 | hs->sib_index = (c & 0x3f) >> 3;
261 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
262 | disp_size = 4;
263 | }
264 |
265 | p--;
266 | switch (disp_size) {
267 | case 1:
268 | hs->flags |= F_DISP8;
269 | hs->disp.disp8 = *p;
270 | break;
271 | case 2:
272 | hs->flags |= F_DISP16;
273 | hs->disp.disp16 = *(uint16_t *)p;
274 | break;
275 | case 4:
276 | hs->flags |= F_DISP32;
277 | hs->disp.disp32 = *(uint32_t *)p;
278 | }
279 | p += disp_size;
280 | } else if (pref & PRE_LOCK)
281 | hs->flags |= F_ERROR | F_ERROR_LOCK;
282 |
283 | if (cflags & C_IMM_P66) {
284 | if (cflags & C_REL32) {
285 | if (pref & PRE_66) {
286 | hs->flags |= F_IMM16 | F_RELATIVE;
287 | hs->imm.imm16 = *(uint16_t *)p;
288 | p += 2;
289 | goto disasm_done;
290 | }
291 | goto rel32_ok;
292 | }
293 | if (op64) {
294 | hs->flags |= F_IMM64;
295 | hs->imm.imm64 = *(uint64_t *)p;
296 | p += 8;
297 | } else if (!(pref & PRE_66)) {
298 | hs->flags |= F_IMM32;
299 | hs->imm.imm32 = *(uint32_t *)p;
300 | p += 4;
301 | } else
302 | goto imm16_ok;
303 | }
304 |
305 |
306 | if (cflags & C_IMM16) {
307 | imm16_ok:
308 | hs->flags |= F_IMM16;
309 | hs->imm.imm16 = *(uint16_t *)p;
310 | p += 2;
311 | }
312 | if (cflags & C_IMM8) {
313 | hs->flags |= F_IMM8;
314 | hs->imm.imm8 = *p++;
315 | }
316 |
317 | if (cflags & C_REL32) {
318 | rel32_ok:
319 | hs->flags |= F_IMM32 | F_RELATIVE;
320 | hs->imm.imm32 = *(uint32_t *)p;
321 | p += 4;
322 | } else if (cflags & C_REL8) {
323 | hs->flags |= F_IMM8 | F_RELATIVE;
324 | hs->imm.imm8 = *p++;
325 | }
326 |
327 | disasm_done:
328 |
329 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
330 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
331 | hs->len = 15;
332 | }
333 |
334 | return (unsigned int)hs->len;
335 | }
336 |
337 | #endif // defined(_M_X64) || defined(__x86_64__)
338 |
--------------------------------------------------------------------------------
/sdk/hook/buffer.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 "buffer.h"
31 |
32 | // Size of each memory block. (= page size of VirtualAlloc)
33 | #define MEMORY_BLOCK_SIZE 0x1000
34 |
35 | // Max range for seeking a memory block. (= 1024MB)
36 | #define MAX_MEMORY_RANGE 0x40000000
37 |
38 | // Memory protection flags to check the executable address.
39 | #define PAGE_EXECUTE_FLAGS \
40 | (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
41 |
42 | // Memory slot.
43 | typedef struct _MEMORY_SLOT
44 | {
45 | union
46 | {
47 | struct _MEMORY_SLOT *pNext;
48 | UINT8 buffer[MEMORY_SLOT_SIZE];
49 | };
50 | } MEMORY_SLOT, *PMEMORY_SLOT;
51 |
52 | // Memory block info. Placed at the head of each block.
53 | typedef struct _MEMORY_BLOCK
54 | {
55 | struct _MEMORY_BLOCK *pNext;
56 | PMEMORY_SLOT pFree; // First element of the free slot list.
57 | UINT usedCount;
58 | } MEMORY_BLOCK, *PMEMORY_BLOCK;
59 |
60 | //-------------------------------------------------------------------------
61 | // Global Variables:
62 | //-------------------------------------------------------------------------
63 |
64 | // First element of the memory block list.
65 | PMEMORY_BLOCK g_pMemoryBlocks;
66 |
67 | //-------------------------------------------------------------------------
68 | VOID InitializeBuffer(VOID)
69 | {
70 | // Nothing to do for now.
71 | }
72 |
73 | //-------------------------------------------------------------------------
74 | VOID UninitializeBuffer(VOID)
75 | {
76 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
77 | g_pMemoryBlocks = NULL;
78 |
79 | while (pBlock)
80 | {
81 | PMEMORY_BLOCK pNext = pBlock->pNext;
82 | VirtualFree(pBlock, 0, MEM_RELEASE);
83 | pBlock = pNext;
84 | }
85 | }
86 |
87 | //-------------------------------------------------------------------------
88 | #if defined(_M_X64) || defined(__x86_64__)
89 | static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
90 | {
91 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
92 |
93 | // Round down to the allocation granularity.
94 | tryAddr -= tryAddr % dwAllocationGranularity;
95 |
96 | // Start from the previous allocation granularity multiply.
97 | tryAddr -= dwAllocationGranularity;
98 |
99 | while (tryAddr >= (ULONG_PTR)pMinAddr)
100 | {
101 | MEMORY_BASIC_INFORMATION mbi;
102 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
103 | break;
104 |
105 | if (mbi.State == MEM_FREE)
106 | return (LPVOID)tryAddr;
107 |
108 | if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
109 | break;
110 |
111 | tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
112 | }
113 |
114 | return NULL;
115 | }
116 | #endif
117 |
118 | //-------------------------------------------------------------------------
119 | #if defined(_M_X64) || defined(__x86_64__)
120 | static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
121 | {
122 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
123 |
124 | // Round down to the allocation granularity.
125 | tryAddr -= tryAddr % dwAllocationGranularity;
126 |
127 | // Start from the next allocation granularity multiply.
128 | tryAddr += dwAllocationGranularity;
129 |
130 | while (tryAddr <= (ULONG_PTR)pMaxAddr)
131 | {
132 | MEMORY_BASIC_INFORMATION mbi;
133 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
134 | break;
135 |
136 | if (mbi.State == MEM_FREE)
137 | return (LPVOID)tryAddr;
138 |
139 | tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
140 |
141 | // Round up to the next allocation granularity.
142 | tryAddr += dwAllocationGranularity - 1;
143 | tryAddr -= tryAddr % dwAllocationGranularity;
144 | }
145 |
146 | return NULL;
147 | }
148 | #endif
149 |
150 | //-------------------------------------------------------------------------
151 | static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
152 | {
153 | PMEMORY_BLOCK pBlock;
154 | #if defined(_M_X64) || defined(__x86_64__)
155 | ULONG_PTR minAddr;
156 | ULONG_PTR maxAddr;
157 |
158 | SYSTEM_INFO si;
159 | GetSystemInfo(&si);
160 | minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
161 | maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
162 |
163 | // pOrigin ± 512MB
164 | if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
165 | minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
166 |
167 | if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
168 | maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
169 |
170 | // Make room for MEMORY_BLOCK_SIZE bytes.
171 | maxAddr -= MEMORY_BLOCK_SIZE - 1;
172 | #endif
173 |
174 | // Look the registered blocks for a reachable one.
175 | for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
176 | {
177 | #if defined(_M_X64) || defined(__x86_64__)
178 | // Ignore the blocks too far.
179 | if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
180 | continue;
181 | #endif
182 | // The block has at least one unused slot.
183 | if (pBlock->pFree != NULL)
184 | return pBlock;
185 | }
186 |
187 | #if defined(_M_X64) || defined(__x86_64__)
188 | // Alloc a new block above if not found.
189 | {
190 | LPVOID pAlloc = pOrigin;
191 | while ((ULONG_PTR)pAlloc >= minAddr)
192 | {
193 | pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
194 | if (pAlloc == NULL)
195 | break;
196 |
197 | pBlock = (PMEMORY_BLOCK)VirtualAlloc(
198 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
199 | if (pBlock != NULL)
200 | break;
201 | }
202 | }
203 |
204 | // Alloc a new block below if not found.
205 | if (pBlock == NULL)
206 | {
207 | LPVOID pAlloc = pOrigin;
208 | while ((ULONG_PTR)pAlloc <= maxAddr)
209 | {
210 | pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
211 | if (pAlloc == NULL)
212 | break;
213 |
214 | pBlock = (PMEMORY_BLOCK)VirtualAlloc(
215 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
216 | if (pBlock != NULL)
217 | break;
218 | }
219 | }
220 | #else
221 | // In x86 mode, a memory block can be placed anywhere.
222 | pBlock = (PMEMORY_BLOCK)VirtualAlloc(
223 | NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
224 | #endif
225 |
226 | if (pBlock != NULL)
227 | {
228 | // Build a linked list of all the slots.
229 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
230 | pBlock->pFree = NULL;
231 | pBlock->usedCount = 0;
232 | do
233 | {
234 | pSlot->pNext = pBlock->pFree;
235 | pBlock->pFree = pSlot;
236 | pSlot++;
237 | } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
238 |
239 | pBlock->pNext = g_pMemoryBlocks;
240 | g_pMemoryBlocks = pBlock;
241 | }
242 |
243 | return pBlock;
244 | }
245 |
246 | //-------------------------------------------------------------------------
247 | LPVOID AllocateBuffer(LPVOID pOrigin)
248 | {
249 | PMEMORY_SLOT pSlot;
250 | PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
251 | if (pBlock == NULL)
252 | return NULL;
253 |
254 | // Remove an unused slot from the list.
255 | pSlot = pBlock->pFree;
256 | pBlock->pFree = pSlot->pNext;
257 | pBlock->usedCount++;
258 | #ifdef _DEBUG
259 | // Fill the slot with INT3 for debugging.
260 | memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
261 | #endif
262 | return pSlot;
263 | }
264 |
265 | //-------------------------------------------------------------------------
266 | VOID FreeBuffer(LPVOID pBuffer)
267 | {
268 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
269 | PMEMORY_BLOCK pPrev = NULL;
270 | ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
271 |
272 | while (pBlock != NULL)
273 | {
274 | if ((ULONG_PTR)pBlock == pTargetBlock)
275 | {
276 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
277 | #ifdef _DEBUG
278 | // Clear the released slot for debugging.
279 | memset(pSlot, 0x00, sizeof(*pSlot));
280 | #endif
281 | // Restore the released slot to the list.
282 | pSlot->pNext = pBlock->pFree;
283 | pBlock->pFree = pSlot;
284 | pBlock->usedCount--;
285 |
286 | // Free if unused.
287 | if (pBlock->usedCount == 0)
288 | {
289 | if (pPrev)
290 | pPrev->pNext = pBlock->pNext;
291 | else
292 | g_pMemoryBlocks = pBlock->pNext;
293 |
294 | VirtualFree(pBlock, 0, MEM_RELEASE);
295 | }
296 |
297 | break;
298 | }
299 |
300 | pPrev = pBlock;
301 | pBlock = pBlock->pNext;
302 | }
303 | }
304 |
305 | //-------------------------------------------------------------------------
306 | BOOL IsExecutableAddress(LPVOID pAddress)
307 | {
308 | MEMORY_BASIC_INFORMATION mi;
309 | VirtualQuery(pAddress, &mi, sizeof(mi));
310 |
311 | return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
312 | }
313 |
--------------------------------------------------------------------------------
/sdk/hook/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 "./hde/hde64.h"
37 | typedef hde64s HDE;
38 | #define HDE_DISASM(code, hs) hde64_disasm(code, hs)
39 | #else
40 | #include "./hde/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 | }
284 | while (!finished);
285 |
286 | // Is there enough place for a long jump?
287 | if (oldPos < sizeof(JMP_REL)
288 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
289 | {
290 | // Is there enough place for a short jump?
291 | if (oldPos < sizeof(JMP_REL_SHORT)
292 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
293 | {
294 | return FALSE;
295 | }
296 |
297 | // Can we place the long jump above the function?
298 | if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
299 | return FALSE;
300 |
301 | if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
302 | return FALSE;
303 |
304 | ct->patchAbove = TRUE;
305 | }
306 |
307 | #if defined(_M_X64) || defined(__x86_64__)
308 | // Create a relay function.
309 | jmp.address = (ULONG_PTR)ct->pDetour;
310 |
311 | ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
312 | memcpy(ct->pRelay, &jmp, sizeof(jmp));
313 | #endif
314 |
315 | return TRUE;
316 | }
317 |
--------------------------------------------------------------------------------
/sdk/libraries/imgui/imgui_impl_opengl2.cpp:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer for OpenGL2 (legacy OpenGL, fixed pipeline)
2 | // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
6 |
7 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
8 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
9 | // https://github.com/ocornut/imgui
10 |
11 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
12 | // **Prefer using the code in imgui_impl_opengl3.cpp**
13 | // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
14 | // If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
15 | // complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
16 | // confuse your GPU driver.
17 | // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
18 |
19 | // CHANGELOG
20 | // (minor and older changes stripped away, please see git history for details)
21 | // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
22 | // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
23 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
24 | // 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
25 | // 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
26 | // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
27 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
28 | // 2017-09-01: OpenGL: Save and restore current polygon mode.
29 | // 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
30 | // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
31 |
32 | #include "imgui.h"
33 | #include "imgui_impl_opengl2.h"
34 | #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
35 | #include // intptr_t
36 | #else
37 | #include // intptr_t
38 | #endif
39 |
40 | // Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
41 | #if defined(_WIN32) && !defined(APIENTRY)
42 | #define APIENTRY __stdcall // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
43 | #endif
44 | #if defined(_WIN32) && !defined(WINGDIAPI)
45 | #define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
46 | #endif
47 | #if defined(__APPLE__)
48 | #define GL_SILENCE_DEPRECATION
49 | #include
50 | #else
51 | #include
52 | #endif
53 |
54 | // OpenGL Data
55 | static GLuint g_FontTexture = 0;
56 |
57 | // Functions
58 | bool ImGui_ImplOpenGL2_Init()
59 | {
60 | // Setup back-end capabilities flags
61 | ImGuiIO& io = ImGui::GetIO();
62 | io.BackendRendererName = "imgui_impl_opengl2";
63 | return true;
64 | }
65 |
66 | void ImGui_ImplOpenGL2_Shutdown()
67 | {
68 | ImGui_ImplOpenGL2_DestroyDeviceObjects();
69 | }
70 |
71 | void ImGui_ImplOpenGL2_NewFrame()
72 | {
73 | if (!g_FontTexture)
74 | ImGui_ImplOpenGL2_CreateDeviceObjects();
75 | }
76 |
77 | static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
78 | {
79 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
80 | glEnable(GL_BLEND);
81 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
82 | glDisable(GL_CULL_FACE);
83 | glDisable(GL_DEPTH_TEST);
84 | glDisable(GL_LIGHTING);
85 | glDisable(GL_COLOR_MATERIAL);
86 | glEnable(GL_SCISSOR_TEST);
87 | glEnableClientState(GL_VERTEX_ARRAY);
88 | glEnableClientState(GL_TEXTURE_COORD_ARRAY);
89 | glEnableClientState(GL_COLOR_ARRAY);
90 | glEnable(GL_TEXTURE_2D);
91 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
92 |
93 | // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
94 | // you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function:
95 | // GLint last_program;
96 | // glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
97 | // glUseProgram(0);
98 | // ImGui_ImplOpenGL2_RenderDrawData(...);
99 | // glUseProgram(last_program)
100 |
101 | // Setup viewport, orthographic projection matrix
102 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
103 | glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
104 | glMatrixMode(GL_PROJECTION);
105 | glPushMatrix();
106 | glLoadIdentity();
107 | glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
108 | glMatrixMode(GL_MODELVIEW);
109 | glPushMatrix();
110 | glLoadIdentity();
111 | }
112 |
113 | // OpenGL2 Render function.
114 | // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
115 | // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
116 | void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
117 | {
118 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
119 | int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
120 | int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
121 | if (fb_width == 0 || fb_height == 0)
122 | return;
123 |
124 | // Backup GL state
125 | GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
126 | GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
127 | GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
128 | GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
129 | glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
130 |
131 | // Setup desired GL state
132 | ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
133 |
134 | // Will project scissor/clipping rectangles into framebuffer space
135 | ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
136 | ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
137 |
138 | // Render command lists
139 | for (int n = 0; n < draw_data->CmdListsCount; n++)
140 | {
141 | const ImDrawList* cmd_list = draw_data->CmdLists[n];
142 | const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
143 | const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
144 | glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
145 | glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
146 | glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
147 |
148 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
149 | {
150 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
151 | if (pcmd->UserCallback)
152 | {
153 | // User callback, registered via ImDrawList::AddCallback()
154 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
155 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
156 | ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
157 | else
158 | pcmd->UserCallback(cmd_list, pcmd);
159 | }
160 | else
161 | {
162 | // Project scissor/clipping rectangles into framebuffer space
163 | ImVec4 clip_rect;
164 | clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
165 | clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
166 | clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
167 | clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
168 |
169 | if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
170 | {
171 | // Apply scissor/clipping rectangle
172 | glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
173 |
174 | // Bind texture, Draw
175 | glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
176 | glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
177 | }
178 | }
179 | idx_buffer += pcmd->ElemCount;
180 | }
181 | }
182 |
183 | // Restore modified GL state
184 | glDisableClientState(GL_COLOR_ARRAY);
185 | glDisableClientState(GL_TEXTURE_COORD_ARRAY);
186 | glDisableClientState(GL_VERTEX_ARRAY);
187 | glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
188 | glMatrixMode(GL_MODELVIEW);
189 | glPopMatrix();
190 | glMatrixMode(GL_PROJECTION);
191 | glPopMatrix();
192 | glPopAttrib();
193 | glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
194 | glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
195 | glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
196 | }
197 |
198 | bool ImGui_ImplOpenGL2_CreateFontsTexture()
199 | {
200 | // Build texture atlas
201 | ImGuiIO& io = ImGui::GetIO();
202 | unsigned char* pixels;
203 | int width, height;
204 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
205 |
206 | // Upload texture to graphics system
207 | GLint last_texture;
208 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
209 | glGenTextures(1, &g_FontTexture);
210 | glBindTexture(GL_TEXTURE_2D, g_FontTexture);
211 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
212 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
213 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
214 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
215 |
216 | // Store our identifier
217 | io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
218 |
219 | // Restore state
220 | glBindTexture(GL_TEXTURE_2D, last_texture);
221 |
222 | return true;
223 | }
224 |
225 | void ImGui_ImplOpenGL2_DestroyFontsTexture()
226 | {
227 | if (g_FontTexture)
228 | {
229 | ImGuiIO& io = ImGui::GetIO();
230 | glDeleteTextures(1, &g_FontTexture);
231 | io.Fonts->TexID = 0;
232 | g_FontTexture = 0;
233 | }
234 | }
235 |
236 | bool ImGui_ImplOpenGL2_CreateDeviceObjects()
237 | {
238 | return ImGui_ImplOpenGL2_CreateFontsTexture();
239 | }
240 |
241 | void ImGui_ImplOpenGL2_DestroyDeviceObjects()
242 | {
243 | ImGui_ImplOpenGL2_DestroyFontsTexture();
244 | }
245 |
--------------------------------------------------------------------------------
/sdk/libraries/imgui/imgui_impl_win32.cpp:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Binding for Windows (standard windows API for 32 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 imgui)
6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 |
10 | #include "imgui.h"
11 | #include "imgui_impl_win32.h"
12 | #ifndef WIN32_LEAN_AND_MEAN
13 | #define WIN32_LEAN_AND_MEAN
14 | #endif
15 | #include
16 | #include
17 | #include
18 |
19 | // CHANGELOG
20 | // (minor and older changes stripped away, please see git history for details)
21 | // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
22 | // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
23 | // 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
24 | // 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
25 | // 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
26 | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
27 | // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
28 | // 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads).
29 | // 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples.
30 | // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
31 | // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
32 | // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
33 | // 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
34 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
35 | // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
36 | // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert.
37 | // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag.
38 | // 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read.
39 | // 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
40 | // 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set.
41 |
42 | // Win32 Data
43 | static HWND g_hWnd = 0;
44 | static INT64 g_Time = 0;
45 | static INT64 g_TicksPerSecond = 0;
46 | static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT;
47 | static bool g_HasGamepad = false;
48 | static bool g_WantUpdateHasGamepad = true;
49 |
50 | // Functions
51 | bool ImGui_ImplWin32_Init(void* hwnd)
52 | {
53 | if (!::QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))
54 | return false;
55 | if (!::QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
56 | return false;
57 |
58 | // Setup back-end capabilities flags
59 | g_hWnd = (HWND)hwnd;
60 | ImGuiIO& io = ImGui::GetIO();
61 | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
62 | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
63 | io.BackendPlatformName = "imgui_impl_win32";
64 | io.ImeWindowHandle = hwnd;
65 |
66 | // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
67 | io.KeyMap[ImGuiKey_Tab] = VK_TAB;
68 | io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
69 | io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
70 | io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
71 | io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
72 | io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
73 | io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
74 | io.KeyMap[ImGuiKey_Home] = VK_HOME;
75 | io.KeyMap[ImGuiKey_End] = VK_END;
76 | io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
77 | io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
78 | io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
79 | io.KeyMap[ImGuiKey_Space] = VK_SPACE;
80 | io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
81 | io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
82 | io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
83 | io.KeyMap[ImGuiKey_A] = 'A';
84 | io.KeyMap[ImGuiKey_C] = 'C';
85 | io.KeyMap[ImGuiKey_V] = 'V';
86 | io.KeyMap[ImGuiKey_X] = 'X';
87 | io.KeyMap[ImGuiKey_Y] = 'Y';
88 | io.KeyMap[ImGuiKey_Z] = 'Z';
89 |
90 | return true;
91 | }
92 |
93 | void ImGui_ImplWin32_Shutdown()
94 | {
95 | g_hWnd = (HWND)0;
96 | }
97 |
98 | static bool ImGui_ImplWin32_UpdateMouseCursor()
99 | {
100 | ImGuiIO& io = ImGui::GetIO();
101 | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
102 | return false;
103 |
104 | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
105 | if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
106 | {
107 | // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
108 | ::SetCursor(NULL);
109 | }
110 | else
111 | {
112 | // Show OS mouse cursor
113 | LPTSTR win32_cursor = IDC_ARROW;
114 | switch (imgui_cursor)
115 | {
116 | case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
117 | case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
118 | case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
119 | case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
120 | case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
121 | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
122 | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
123 | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
124 | case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break;
125 | }
126 | ::SetCursor(::LoadCursor(NULL, win32_cursor));
127 | }
128 | return true;
129 | }
130 |
131 | static void ImGui_ImplWin32_UpdateMousePos()
132 | {
133 | ImGuiIO& io = ImGui::GetIO();
134 |
135 | // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
136 | if (io.WantSetMousePos)
137 | {
138 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
139 | ::ClientToScreen(g_hWnd, &pos);
140 | ::SetCursorPos(pos.x, pos.y);
141 | }
142 |
143 | // Set mouse position
144 | io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
145 | POINT pos;
146 | if (HWND active_window = ::GetForegroundWindow())
147 | if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd))
148 | if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos))
149 | io.MousePos = ImVec2((float)pos.x, (float)pos.y);
150 | }
151 |
152 | #ifdef _MSC_VER
153 | #pragma comment(lib, "xinput")
154 | #endif
155 |
156 | // Gamepad navigation mapping
157 | static void ImGui_ImplWin32_UpdateGamepads()
158 | {
159 | ImGuiIO& io = ImGui::GetIO();
160 | memset(io.NavInputs, 0, sizeof(io.NavInputs));
161 | if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
162 | return;
163 |
164 | // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
165 | // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
166 | if (g_WantUpdateHasGamepad)
167 | {
168 | XINPUT_CAPABILITIES caps;
169 | g_HasGamepad = (XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS);
170 | g_WantUpdateHasGamepad = false;
171 | }
172 |
173 | XINPUT_STATE xinput_state;
174 | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
175 | if (g_HasGamepad && XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
176 | {
177 | const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
178 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
179 |
180 | #define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; }
181 | #define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
182 | MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A
183 | MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B
184 | MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X
185 | MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y
186 | MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left
187 | MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right
188 | MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up
189 | MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down
190 | MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
191 | MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
192 | MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
193 | MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
194 | MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
195 | MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
196 | MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
197 | MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767);
198 | #undef MAP_BUTTON
199 | #undef MAP_ANALOG
200 | }
201 | }
202 |
203 | void ImGui_ImplWin32_NewFrame()
204 | {
205 | ImGuiIO& io = ImGui::GetIO();
206 | IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
207 |
208 | // Setup display size (every frame to accommodate for window resizing)
209 | RECT rect;
210 | ::GetClientRect(g_hWnd, &rect);
211 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
212 |
213 | // Setup time step
214 | INT64 current_time;
215 | ::QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
216 | io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
217 | g_Time = current_time;
218 |
219 | // Read keyboard modifiers inputs
220 | io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
221 | io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
222 | io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
223 | io.KeySuper = false;
224 | // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below.
225 |
226 | // Update OS mouse position
227 | ImGui_ImplWin32_UpdateMousePos();
228 |
229 | // Update OS mouse cursor with the cursor requested by imgui
230 | ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
231 | if (g_LastMouseCursor != mouse_cursor)
232 | {
233 | g_LastMouseCursor = mouse_cursor;
234 | ImGui_ImplWin32_UpdateMouseCursor();
235 | }
236 |
237 | // Update game controllers (if enabled and available)
238 | ImGui_ImplWin32_UpdateGamepads();
239 | }
240 |
241 | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
242 | #ifndef WM_MOUSEHWHEEL
243 | #define WM_MOUSEHWHEEL 0x020E
244 | #endif
245 | #ifndef DBT_DEVNODES_CHANGED
246 | #define DBT_DEVNODES_CHANGED 0x0007
247 | #endif
248 |
249 | // Process Win32 mouse/keyboard inputs.
250 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
251 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
252 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
253 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
254 | // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
255 | // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
256 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
257 | {
258 | if (ImGui::GetCurrentContext() == NULL)
259 | return 0;
260 |
261 | ImGuiIO& io = ImGui::GetIO();
262 | switch (msg)
263 | {
264 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
265 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
266 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
267 | case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
268 | {
269 | int button = 0;
270 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
271 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
272 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
273 | if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
274 | if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
275 | ::SetCapture(hwnd);
276 | io.MouseDown[button] = true;
277 | return 0;
278 | }
279 | case WM_LBUTTONUP:
280 | case WM_RBUTTONUP:
281 | case WM_MBUTTONUP:
282 | case WM_XBUTTONUP:
283 | {
284 | int button = 0;
285 | if (msg == WM_LBUTTONUP) { button = 0; }
286 | if (msg == WM_RBUTTONUP) { button = 1; }
287 | if (msg == WM_MBUTTONUP) { button = 2; }
288 | if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
289 | io.MouseDown[button] = false;
290 | if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
291 | ::ReleaseCapture();
292 | return 0;
293 | }
294 | case WM_MOUSEWHEEL:
295 | io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
296 | return 0;
297 | case WM_MOUSEHWHEEL:
298 | io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
299 | return 0;
300 | case WM_KEYDOWN:
301 | case WM_SYSKEYDOWN:
302 | if (wParam < 256)
303 | io.KeysDown[wParam] = 1;
304 | return 0;
305 | case WM_KEYUP:
306 | case WM_SYSKEYUP:
307 | if (wParam < 256)
308 | io.KeysDown[wParam] = 0;
309 | return 0;
310 | case WM_CHAR:
311 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
312 | io.AddInputCharacter((unsigned int)wParam);
313 | return 0;
314 | case WM_SETCURSOR:
315 | if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
316 | return 1;
317 | return 0;
318 | case WM_DEVICECHANGE:
319 | if ((UINT)wParam == DBT_DEVNODES_CHANGED)
320 | g_WantUpdateHasGamepad = true;
321 | return 0;
322 | }
323 | return 0;
324 | }
325 |
326 |
--------------------------------------------------------------------------------
/sdk/libraries/imgui/imstb_rectpack.h:
--------------------------------------------------------------------------------
1 | // [DEAR IMGUI]
2 | // This is a slightly modified version of stb_rect_pack.h 1.00.
3 | // Those changes would need to be pushed into nothings/stb:
4 | // - Added STBRP__CDECL
5 | // Grep for [DEAR IMGUI] to find the changes.
6 |
7 | // stb_rect_pack.h - v1.00 - public domain - rectangle packing
8 | // Sean Barrett 2014
9 | //
10 | // Useful for e.g. packing rectangular textures into an atlas.
11 | // Does not do rotation.
12 | //
13 | // Not necessarily the awesomest packing method, but better than
14 | // the totally naive one in stb_truetype (which is primarily what
15 | // this is meant to replace).
16 | //
17 | // Has only had a few tests run, may have issues.
18 | //
19 | // More docs to come.
20 | //
21 | // No memory allocations; uses qsort() and assert() from stdlib.
22 | // Can override those by defining STBRP_SORT and STBRP_ASSERT.
23 | //
24 | // This library currently uses the Skyline Bottom-Left algorithm.
25 | //
26 | // Please note: better rectangle packers are welcome! Please
27 | // implement them to the same API, but with a different init
28 | // function.
29 | //
30 | // Credits
31 | //
32 | // Library
33 | // Sean Barrett
34 | // Minor features
35 | // Martins Mozeiko
36 | // github:IntellectualKitty
37 | //
38 | // Bugfixes / warning fixes
39 | // Jeremy Jaussaud
40 | // Fabian Giesen
41 | //
42 | // Version history:
43 | //
44 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
45 | // 0.99 (2019-02-07) warning fixes
46 | // 0.11 (2017-03-03) return packing success/fail result
47 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings
48 | // 0.09 (2016-08-27) fix compiler warnings
49 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
50 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
51 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
52 | // 0.05: added STBRP_ASSERT to allow replacing assert
53 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support
54 | // 0.01: initial release
55 | //
56 | // LICENSE
57 | //
58 | // See end of file for license information.
59 |
60 | //////////////////////////////////////////////////////////////////////////////
61 | //
62 | // INCLUDE SECTION
63 | //
64 |
65 | #ifndef STB_INCLUDE_STB_RECT_PACK_H
66 | #define STB_INCLUDE_STB_RECT_PACK_H
67 |
68 | #define STB_RECT_PACK_VERSION 1
69 |
70 | #ifdef STBRP_STATIC
71 | #define STBRP_DEF static
72 | #else
73 | #define STBRP_DEF extern
74 | #endif
75 |
76 | #ifdef __cplusplus
77 | extern "C" {
78 | #endif
79 |
80 | typedef struct stbrp_context stbrp_context;
81 | typedef struct stbrp_node stbrp_node;
82 | typedef struct stbrp_rect stbrp_rect;
83 |
84 | #ifdef STBRP_LARGE_RECTS
85 | typedef int stbrp_coord;
86 | #else
87 | typedef unsigned short stbrp_coord;
88 | #endif
89 |
90 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
91 | // Assign packed locations to rectangles. The rectangles are of type
92 | // 'stbrp_rect' defined below, stored in the array 'rects', and there
93 | // are 'num_rects' many of them.
94 | //
95 | // Rectangles which are successfully packed have the 'was_packed' flag
96 | // set to a non-zero value and 'x' and 'y' store the minimum location
97 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left
98 | // if you imagine y increasing downwards). Rectangles which do not fit
99 | // have the 'was_packed' flag set to 0.
100 | //
101 | // You should not try to access the 'rects' array from another thread
102 | // while this function is running, as the function temporarily reorders
103 | // the array while it executes.
104 | //
105 | // To pack into another rectangle, you need to call stbrp_init_target
106 | // again. To continue packing into the same rectangle, you can call
107 | // this function again. Calling this multiple times with multiple rect
108 | // arrays will probably produce worse packing results than calling it
109 | // a single time with the full rectangle array, but the option is
110 | // available.
111 | //
112 | // The function returns 1 if all of the rectangles were successfully
113 | // packed and 0 otherwise.
114 |
115 | struct stbrp_rect
116 | {
117 | // reserved for your use:
118 | int id;
119 |
120 | // input:
121 | stbrp_coord w, h;
122 |
123 | // output:
124 | stbrp_coord x, y;
125 | int was_packed; // non-zero if valid packing
126 |
127 | }; // 16 bytes, nominally
128 |
129 |
130 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
131 | // Initialize a rectangle packer to:
132 | // pack a rectangle that is 'width' by 'height' in dimensions
133 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long
134 | //
135 | // You must call this function every time you start packing into a new target.
136 | //
137 | // There is no "shutdown" function. The 'nodes' memory must stay valid for
138 | // the following stbrp_pack_rects() call (or calls), but can be freed after
139 | // the call (or calls) finish.
140 | //
141 | // Note: to guarantee best results, either:
142 | // 1. make sure 'num_nodes' >= 'width'
143 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
144 | //
145 | // If you don't do either of the above things, widths will be quantized to multiples
146 | // of small integers to guarantee the algorithm doesn't run out of temporary storage.
147 | //
148 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm
149 | // may run out of temporary storage and be unable to pack some rectangles.
150 |
151 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
152 | // Optionally call this function after init but before doing any packing to
153 | // change the handling of the out-of-temp-memory scenario, described above.
154 | // If you call init again, this will be reset to the default (false).
155 |
156 |
157 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
158 | // Optionally select which packing heuristic the library should use. Different
159 | // heuristics will produce better/worse results for different data sets.
160 | // If you call init again, this will be reset to the default.
161 |
162 | enum
163 | {
164 | STBRP_HEURISTIC_Skyline_default=0,
165 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
166 | STBRP_HEURISTIC_Skyline_BF_sortHeight
167 | };
168 |
169 |
170 | //////////////////////////////////////////////////////////////////////////////
171 | //
172 | // the details of the following structures don't matter to you, but they must
173 | // be visible so you can handle the memory allocations for them
174 |
175 | struct stbrp_node
176 | {
177 | stbrp_coord x,y;
178 | stbrp_node *next;
179 | };
180 |
181 | struct stbrp_context
182 | {
183 | int width;
184 | int height;
185 | int align;
186 | int init_mode;
187 | int heuristic;
188 | int num_nodes;
189 | stbrp_node *active_head;
190 | stbrp_node *free_head;
191 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
192 | };
193 |
194 | #ifdef __cplusplus
195 | }
196 | #endif
197 |
198 | #endif
199 |
200 | //////////////////////////////////////////////////////////////////////////////
201 | //
202 | // IMPLEMENTATION SECTION
203 | //
204 |
205 | #ifdef STB_RECT_PACK_IMPLEMENTATION
206 | #ifndef STBRP_SORT
207 | #include
208 | #define STBRP_SORT qsort
209 | #endif
210 |
211 | #ifndef STBRP_ASSERT
212 | #include
213 | #define STBRP_ASSERT assert
214 | #endif
215 |
216 | // [DEAR IMGUI] Added STBRP__CDECL
217 | #ifdef _MSC_VER
218 | #define STBRP__NOTUSED(v) (void)(v)
219 | #define STBRP__CDECL __cdecl
220 | #else
221 | #define STBRP__NOTUSED(v) (void)sizeof(v)
222 | #define STBRP__CDECL
223 | #endif
224 |
225 | enum
226 | {
227 | STBRP__INIT_skyline = 1
228 | };
229 |
230 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
231 | {
232 | switch (context->init_mode) {
233 | case STBRP__INIT_skyline:
234 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
235 | context->heuristic = heuristic;
236 | break;
237 | default:
238 | STBRP_ASSERT(0);
239 | }
240 | }
241 |
242 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
243 | {
244 | if (allow_out_of_mem)
245 | // if it's ok to run out of memory, then don't bother aligning them;
246 | // this gives better packing, but may fail due to OOM (even though
247 | // the rectangles easily fit). @TODO a smarter approach would be to only
248 | // quantize once we've hit OOM, then we could get rid of this parameter.
249 | context->align = 1;
250 | else {
251 | // if it's not ok to run out of memory, then quantize the widths
252 | // so that num_nodes is always enough nodes.
253 | //
254 | // I.e. num_nodes * align >= width
255 | // align >= width / num_nodes
256 | // align = ceil(width/num_nodes)
257 |
258 | context->align = (context->width + context->num_nodes-1) / context->num_nodes;
259 | }
260 | }
261 |
262 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
263 | {
264 | int i;
265 | #ifndef STBRP_LARGE_RECTS
266 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
267 | #endif
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 | #ifdef STBRP_LARGE_RECTS
287 | context->extra[1].y = (1<<30);
288 | #else
289 | context->extra[1].y = 65535;
290 | #endif
291 | context->extra[1].next = NULL;
292 | }
293 |
294 | // find minimum y position if it starts at x1
295 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
296 | {
297 | stbrp_node *node = first;
298 | int x1 = x0 + width;
299 | int min_y, visited_width, waste_area;
300 |
301 | STBRP__NOTUSED(c);
302 |
303 | STBRP_ASSERT(first->x <= x0);
304 |
305 | #if 0
306 | // skip in case we're past the node
307 | while (node->next->x <= x0)
308 | ++node;
309 | #else
310 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
311 | #endif
312 |
313 | STBRP_ASSERT(node->x <= x0);
314 |
315 | min_y = 0;
316 | waste_area = 0;
317 | visited_width = 0;
318 | while (node->x < x1) {
319 | if (node->y > min_y) {
320 | // raise min_y higher.
321 | // we've accounted for all waste up to min_y,
322 | // but we'll now add more waste for everything we've visted
323 | waste_area += visited_width * (node->y - min_y);
324 | min_y = node->y;
325 | // the first time through, visited_width might be reduced
326 | if (node->x < x0)
327 | visited_width += node->next->x - x0;
328 | else
329 | visited_width += node->next->x - node->x;
330 | } else {
331 | // add waste area
332 | int under_width = node->next->x - node->x;
333 | if (under_width + visited_width > width)
334 | under_width = width - visited_width;
335 | waste_area += under_width * (min_y - node->y);
336 | visited_width += under_width;
337 | }
338 | node = node->next;
339 | }
340 |
341 | *pwaste = waste_area;
342 | return min_y;
343 | }
344 |
345 | typedef struct
346 | {
347 | int x,y;
348 | stbrp_node **prev_link;
349 | } stbrp__findresult;
350 |
351 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
352 | {
353 | int best_waste = (1<<30), best_x, best_y = (1 << 30);
354 | stbrp__findresult fr;
355 | stbrp_node **prev, *node, *tail, **best = NULL;
356 |
357 | // align to multiple of c->align
358 | width = (width + c->align - 1);
359 | width -= width % c->align;
360 | STBRP_ASSERT(width % c->align == 0);
361 |
362 | // if it can't possibly fit, bail immediately
363 | if (width > c->width || height > c->height) {
364 | fr.prev_link = NULL;
365 | fr.x = fr.y = 0;
366 | return fr;
367 | }
368 |
369 | node = c->active_head;
370 | prev = &c->active_head;
371 | while (node->x + width <= c->width) {
372 | int y,waste;
373 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
374 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
375 | // bottom left
376 | if (y < best_y) {
377 | best_y = y;
378 | best = prev;
379 | }
380 | } else {
381 | // best-fit
382 | if (y + height <= c->height) {
383 | // can only use it if it first vertically
384 | if (y < best_y || (y == best_y && waste < best_waste)) {
385 | best_y = y;
386 | best_waste = waste;
387 | best = prev;
388 | }
389 | }
390 | }
391 | prev = &node->next;
392 | node = node->next;
393 | }
394 |
395 | best_x = (best == NULL) ? 0 : (*best)->x;
396 |
397 | // if doing best-fit (BF), we also have to try aligning right edge to each node position
398 | //
399 | // e.g, if fitting
400 | //
401 | // ____________________
402 | // |____________________|
403 | //
404 | // into
405 | //
406 | // | |
407 | // | ____________|
408 | // |____________|
409 | //
410 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
411 | //
412 | // This makes BF take about 2x the time
413 |
414 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
415 | tail = c->active_head;
416 | node = c->active_head;
417 | prev = &c->active_head;
418 | // find first node that's admissible
419 | while (tail->x < width)
420 | tail = tail->next;
421 | while (tail) {
422 | int xpos = tail->x - width;
423 | int y,waste;
424 | STBRP_ASSERT(xpos >= 0);
425 | // find the left position that matches this
426 | while (node->next->x <= xpos) {
427 | prev = &node->next;
428 | node = node->next;
429 | }
430 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
431 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
432 | if (y + height <= c->height) {
433 | if (y <= best_y) {
434 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
435 | best_x = xpos;
436 | STBRP_ASSERT(y <= best_y);
437 | best_y = y;
438 | best_waste = waste;
439 | best = prev;
440 | }
441 | }
442 | }
443 | tail = tail->next;
444 | }
445 | }
446 |
447 | fr.prev_link = best;
448 | fr.x = best_x;
449 | fr.y = best_y;
450 | return fr;
451 | }
452 |
453 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
454 | {
455 | // find best position according to heuristic
456 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
457 | stbrp_node *node, *cur;
458 |
459 | // bail if:
460 | // 1. it failed
461 | // 2. the best node doesn't fit (we don't always check this)
462 | // 3. we're out of memory
463 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
464 | res.prev_link = NULL;
465 | return res;
466 | }
467 |
468 | // on success, create new node
469 | node = context->free_head;
470 | node->x = (stbrp_coord) res.x;
471 | node->y = (stbrp_coord) (res.y + height);
472 |
473 | context->free_head = node->next;
474 |
475 | // insert the new node into the right starting point, and
476 | // let 'cur' point to the remaining nodes needing to be
477 | // stiched back in
478 |
479 | cur = *res.prev_link;
480 | if (cur->x < res.x) {
481 | // preserve the existing one, so start testing with the next one
482 | stbrp_node *next = cur->next;
483 | cur->next = node;
484 | cur = next;
485 | } else {
486 | *res.prev_link = node;
487 | }
488 |
489 | // from here, traverse cur and free the nodes, until we get to one
490 | // that shouldn't be freed
491 | while (cur->next && cur->next->x <= res.x + width) {
492 | stbrp_node *next = cur->next;
493 | // move the current node to the free list
494 | cur->next = context->free_head;
495 | context->free_head = cur;
496 | cur = next;
497 | }
498 |
499 | // stitch the list back in
500 | node->next = cur;
501 |
502 | if (cur->x < res.x + width)
503 | cur->x = (stbrp_coord) (res.x + width);
504 |
505 | #ifdef _DEBUG
506 | cur = context->active_head;
507 | while (cur->x < context->width) {
508 | STBRP_ASSERT(cur->x < cur->next->x);
509 | cur = cur->next;
510 | }
511 | STBRP_ASSERT(cur->next == NULL);
512 |
513 | {
514 | int count=0;
515 | cur = context->active_head;
516 | while (cur) {
517 | cur = cur->next;
518 | ++count;
519 | }
520 | cur = context->free_head;
521 | while (cur) {
522 | cur = cur->next;
523 | ++count;
524 | }
525 | STBRP_ASSERT(count == context->num_nodes+2);
526 | }
527 | #endif
528 |
529 | return res;
530 | }
531 |
532 | // [DEAR IMGUI] Added STBRP__CDECL
533 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
534 | {
535 | const stbrp_rect *p = (const stbrp_rect *) a;
536 | const stbrp_rect *q = (const stbrp_rect *) b;
537 | if (p->h > q->h)
538 | return -1;
539 | if (p->h < q->h)
540 | return 1;
541 | return (p->w > q->w) ? -1 : (p->w < q->w);
542 | }
543 |
544 | // [DEAR IMGUI] Added STBRP__CDECL
545 | static int STBRP__CDECL rect_original_order(const void *a, const void *b)
546 | {
547 | const stbrp_rect *p = (const stbrp_rect *) a;
548 | const stbrp_rect *q = (const stbrp_rect *) b;
549 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
550 | }
551 |
552 | #ifdef STBRP_LARGE_RECTS
553 | #define STBRP__MAXVAL 0xffffffff
554 | #else
555 | #define STBRP__MAXVAL 0xffff
556 | #endif
557 |
558 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
559 | {
560 | int i, all_rects_packed = 1;
561 |
562 | // we use the 'was_packed' field internally to allow sorting/unsorting
563 | for (i=0; i < num_rects; ++i) {
564 | rects[i].was_packed = i;
565 | }
566 |
567 | // sort according to heuristic
568 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
569 |
570 | for (i=0; i < num_rects; ++i) {
571 | if (rects[i].w == 0 || rects[i].h == 0) {
572 | rects[i].x = rects[i].y = 0; // empty rect needs no space
573 | } else {
574 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
575 | if (fr.prev_link) {
576 | rects[i].x = (stbrp_coord) fr.x;
577 | rects[i].y = (stbrp_coord) fr.y;
578 | } else {
579 | rects[i].x = rects[i].y = STBRP__MAXVAL;
580 | }
581 | }
582 | }
583 |
584 | // unsort
585 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
586 |
587 | // set was_packed flags and all_rects_packed status
588 | for (i=0; i < num_rects; ++i) {
589 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
590 | if (!rects[i].was_packed)
591 | all_rects_packed = 0;
592 | }
593 |
594 | // return the all_rects_packed status
595 | return all_rects_packed;
596 | }
597 | #endif
598 |
599 | /*
600 | ------------------------------------------------------------------------------
601 | This software is available under 2 licenses -- choose whichever you prefer.
602 | ------------------------------------------------------------------------------
603 | ALTERNATIVE A - MIT License
604 | Copyright (c) 2017 Sean Barrett
605 | Permission is hereby granted, free of charge, to any person obtaining a copy of
606 | this software and associated documentation files (the "Software"), to deal in
607 | the Software without restriction, including without limitation the rights to
608 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
609 | of the Software, and to permit persons to whom the Software is furnished to do
610 | so, subject to the following conditions:
611 | The above copyright notice and this permission notice shall be included in all
612 | copies or substantial portions of the Software.
613 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
614 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
615 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
616 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
617 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
618 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
619 | SOFTWARE.
620 | ------------------------------------------------------------------------------
621 | ALTERNATIVE B - Public Domain (www.unlicense.org)
622 | This is free and unencumbered software released into the public domain.
623 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
624 | software, either in source code form or as a compiled binary, for any purpose,
625 | commercial or non-commercial, and by any means.
626 | In jurisdictions that recognize copyright laws, the author or authors of this
627 | software dedicate any and all copyright interest in the software to the public
628 | domain. We make this dedication for the benefit of the public at large and to
629 | the detriment of our heirs and successors. We intend this dedication to be an
630 | overt act of relinquishment in perpetuity of all present and future rights to
631 | this software under copyright law.
632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
635 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
636 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
637 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
638 | ------------------------------------------------------------------------------
639 | */
640 |
--------------------------------------------------------------------------------
/sdk/hook/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 |
--------------------------------------------------------------------------------