Compare commits
No commits in common. "faf15e5d88e864a5e03e3820cbca1cb3049203ba" and "51702b898e99ad111b57e4259198adaa7d23452e" have entirely different histories.
faf15e5d88
...
51702b898e
|
@ -20,9 +20,7 @@
|
||||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
|
|
||||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
// 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.
|
// 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.
|
||||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
|
||||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
|
||||||
//#define IMGUI_API __declspec( dllexport )
|
//#define IMGUI_API __declspec( dllexport )
|
||||||
//#define IMGUI_API __declspec( dllimport )
|
//#define IMGUI_API __declspec( dllimport )
|
||||||
|
|
||||||
|
@ -33,11 +31,11 @@
|
||||||
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
|
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
|
||||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||||
#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
|
#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
|
||||||
#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
|
#define IMGUI_DISABLE_METRICS_WINDOW // Disable debug/metrics window: ShowMetricsWindow() will be empty.
|
||||||
|
|
||||||
//---- Don't implement some functions to reduce linkage requirements.
|
//---- Don't implement some functions to reduce linkage requirements.
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
|
||||||
#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a)
|
#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
|
||||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
||||||
//#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).
|
//#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).
|
||||||
//#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)
|
//#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)
|
||||||
|
@ -51,29 +49,20 @@
|
||||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
|
||||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
//---- Use 32-bit for ImWchar (default is 16-bit) to support full unicode code points.
|
||||||
//#define IMGUI_USE_WCHAR32
|
//#define IMGUI_USE_WCHAR32
|
||||||
|
|
||||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
// By default the embedded implementations are declared static and not available outside of imgui cpp files.
|
||||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
|
||||||
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
//---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library.
|
||||||
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
// Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
||||||
// #define IMGUI_USE_STB_SPRINTF
|
// #define IMGUI_USE_STB_SPRINTF
|
||||||
|
|
||||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
|
||||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
|
||||||
// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'.
|
|
||||||
//#define IMGUI_ENABLE_FREETYPE
|
|
||||||
|
|
||||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
|
||||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
|
||||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
|
||||||
|
|
||||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||||
/*
|
/*
|
||||||
|
@ -87,12 +76,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
// Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bit indices).
|
||||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||||
//#define ImDrawIdx unsigned int
|
//#define ImDrawIdx unsigned int
|
||||||
|
|
||||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
//---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly)
|
||||||
//struct ImDrawList;
|
//struct ImDrawList;
|
||||||
//struct ImDrawCmd;
|
//struct ImDrawCmd;
|
||||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||||
|
@ -110,7 +99,6 @@
|
||||||
|
|
||||||
//---- Debug Tools: Enable slower asserts
|
//---- Debug Tools: Enable slower asserts
|
||||||
//#define IMGUI_DEBUG_PARANOID
|
//#define IMGUI_DEBUG_PARANOID
|
||||||
|
|
||||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||||
/*
|
/*
|
||||||
namespace ImGui
|
namespace ImGui
|
||||||
|
|
2963
ImGui/imgui.cpp
2963
ImGui/imgui.cpp
File diff suppressed because it is too large
Load Diff
929
ImGui/imgui.h
929
ImGui/imgui.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +1,18 @@
|
||||||
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
|
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
|
||||||
// - Desktop GL: 2.x 3.x 4.x
|
// - Desktop GL: 2.x 3.x 4.x
|
||||||
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
|
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
|
||||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
|
|
||||||
// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
|
|
||||||
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
|
|
||||||
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
|
|
||||||
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
|
|
||||||
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
|
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
|
||||||
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
|
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
|
||||||
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
|
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
|
||||||
|
@ -78,7 +73,7 @@
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "../imgui.h"
|
||||||
#include "imgui_impl_opengl3.h"
|
#include "imgui_impl_opengl3.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
||||||
|
@ -138,11 +133,6 @@ using namespace gl;
|
||||||
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
|
|
||||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
|
|
||||||
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// OpenGL Data
|
// OpenGL Data
|
||||||
static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
|
static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
|
||||||
static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings.
|
static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings.
|
||||||
|
@ -157,22 +147,15 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
{
|
{
|
||||||
// Query for GL version (e.g. 320 for GL 3.2)
|
// Query for GL version (e.g. 320 for GL 3.2)
|
||||||
#if !defined(IMGUI_IMPL_OPENGL_ES2)
|
#if !defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
GLint major = 0;
|
GLint major, minor;
|
||||||
GLint minor = 0;
|
|
||||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||||
if (major == 0 && minor == 0)
|
|
||||||
{
|
|
||||||
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
|
||||||
const char* gl_version = (const char*)glGetString(GL_VERSION);
|
|
||||||
sscanf(gl_version, "%d.%d", &major, &minor);
|
|
||||||
}
|
|
||||||
g_GlVersion = (GLuint)(major * 100 + minor * 10);
|
g_GlVersion = (GLuint)(major * 100 + minor * 10);
|
||||||
#else
|
#else
|
||||||
g_GlVersion = 200; // GLES 2
|
g_GlVersion = 200; // GLES 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendRendererName = "imgui_impl_opengl3";
|
io.BackendRendererName = "imgui_impl_opengl3";
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||||
|
@ -250,28 +233,20 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_STENCIL_TEST);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
|
||||||
if (g_GlVersion >= 310)
|
|
||||||
glDisable(GL_PRIMITIVE_RESTART);
|
|
||||||
#endif
|
|
||||||
#ifdef GL_POLYGON_MODE
|
#ifdef GL_POLYGON_MODE
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
|
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
|
||||||
#if defined(GL_CLIP_ORIGIN)
|
|
||||||
bool clip_origin_lower_left = true;
|
bool clip_origin_lower_left = true;
|
||||||
if (g_GlVersion >= 450)
|
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
|
||||||
{
|
|
||||||
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin);
|
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin);
|
||||||
if (current_clip_origin == GL_UPPER_LEFT)
|
if (current_clip_origin == GL_UPPER_LEFT)
|
||||||
clip_origin_lower_left = false;
|
clip_origin_lower_left = false;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
// Setup viewport, orthographic projection matrix
|
||||||
|
@ -281,9 +256,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||||
float T = draw_data->DisplayPos.y;
|
float T = draw_data->DisplayPos.y;
|
||||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||||
#if defined(GL_CLIP_ORIGIN)
|
|
||||||
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
|
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
|
||||||
#endif
|
|
||||||
const float ortho_projection[4][4] =
|
const float ortho_projection[4][4] =
|
||||||
{
|
{
|
||||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||||
|
@ -317,8 +290,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenGL3 Render function.
|
// OpenGL3 Render function.
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||||
// This is in order to be able to run within an OpenGL engine that doesn't do so.
|
// 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.
|
||||||
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
@ -353,11 +326,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||||
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||||
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
|
|
||||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
|
||||||
GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Setup desired GL state
|
// Setup desired GL state
|
||||||
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
|
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
|
||||||
|
@ -442,12 +411,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
||||||
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
||||||
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||||
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
|
|
||||||
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
|
||||||
if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef GL_POLYGON_MODE
|
#ifdef GL_POLYGON_MODE
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -476,7 +440,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
|
||||||
// Store our identifier
|
// Store our identifier
|
||||||
io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);
|
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
|
||||||
|
|
||||||
// Restore state
|
// Restore state
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
@ -490,7 +454,7 @@ void ImGui_ImplOpenGL3_DestroyFontsTexture()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
glDeleteTextures(1, &g_FontTexture);
|
glDeleteTextures(1, &g_FontTexture);
|
||||||
io.Fonts->SetTexID(0);
|
io.Fonts->TexID = 0;
|
||||||
g_FontTexture = 0;
|
g_FontTexture = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
|
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
|
||||||
// - Desktop GL: 2.x 3.x 4.x
|
// - Desktop GL: 2.x 3.x 4.x
|
||||||
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
|
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
|
||||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
// About Desktop OpenGL function loaders:
|
// About Desktop OpenGL function loaders:
|
||||||
// Modern Desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
|
// Modern Desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
|
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "../imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
// Backend API
|
// Backend API
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
|
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
// dear imgui: Renderer Backend for DirectX10
|
// dear imgui: Renderer for DirectX10
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer.
|
|
||||||
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
|
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
|
||||||
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||||
// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||||
|
@ -20,12 +19,12 @@
|
||||||
// 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions.
|
// 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions.
|
||||||
// 2018-06-08: Misc: Extracted imgui_impl_dx10.cpp/.h away from the old combined DX10+Win32 example.
|
// 2018-06-08: Misc: Extracted imgui_impl_dx10.cpp/.h away from the old combined DX10+Win32 example.
|
||||||
// 2018-06-08: DirectX10: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
// 2018-06-08: DirectX10: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||||
// 2018-04-09: Misc: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) on other backends.
|
// 2018-04-09: Misc: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) on other back-ends.
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself.
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself.
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
// 2016-05-07: DirectX10: Disabling depth-write.
|
// 2016-05-07: DirectX10: Disabling depth-write.
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "../../imgui.h"
|
||||||
#include "imgui_impl_dx10.h"
|
#include "imgui_impl_dx10.h"
|
||||||
|
|
||||||
// DirectX
|
// DirectX
|
||||||
|
@ -89,6 +88,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render function
|
// Render function
|
||||||
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||||
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized
|
// Avoid rendering when minimized
|
||||||
|
@ -291,7 +291,6 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||||
subResource.SysMemPitch = desc.Width * 4;
|
subResource.SysMemPitch = desc.Width * 4;
|
||||||
subResource.SysMemSlicePitch = 0;
|
subResource.SysMemSlicePitch = 0;
|
||||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||||
IM_ASSERT(pTexture != NULL);
|
|
||||||
|
|
||||||
// Create texture view
|
// Create texture view
|
||||||
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||||
|
@ -305,7 +304,7 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store our identifier
|
// Store our identifier
|
||||||
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
|
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
|
||||||
|
|
||||||
// Create texture sampler
|
// Create texture sampler
|
||||||
{
|
{
|
||||||
|
@ -379,8 +378,8 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||||
desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
|
desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
|
||||||
desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
|
desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
|
||||||
desc.BlendOp = D3D10_BLEND_OP_ADD;
|
desc.BlendOp = D3D10_BLEND_OP_ADD;
|
||||||
desc.SrcBlendAlpha = D3D10_BLEND_ONE;
|
desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
||||||
desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
desc.DestBlendAlpha = D3D10_BLEND_ZERO;
|
||||||
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
|
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
|
||||||
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
||||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||||
|
@ -422,7 +421,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||||
|
|
||||||
|
@ -437,7 +436,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
|
||||||
|
|
||||||
bool ImGui_ImplDX10_Init(ID3D10Device* device)
|
bool ImGui_ImplDX10_Init(ID3D10Device* device)
|
||||||
{
|
{
|
||||||
// Setup backend capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendRendererName = "imgui_impl_dx10";
|
io.BackendRendererName = "imgui_impl_dx10";
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
// dear imgui: Renderer Backend for DirectX10
|
// dear imgui: Renderer for DirectX10
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "../../imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
struct ID3D10Device;
|
struct ID3D10Device;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
// dear imgui: Renderer Backend for DirectX11
|
// dear imgui: Renderer for DirectX11
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
|
|
||||||
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
|
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
|
||||||
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
||||||
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||||
|
@ -26,7 +25,7 @@
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
// 2016-05-07: DirectX11: Disabling depth-write.
|
// 2016-05-07: DirectX11: Disabling depth-write.
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "../../imgui.h"
|
||||||
#include "imgui_impl_dx11.h"
|
#include "imgui_impl_dx11.h"
|
||||||
|
|
||||||
// DirectX
|
// DirectX
|
||||||
|
@ -93,6 +92,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render function
|
// Render function
|
||||||
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||||
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized
|
// Avoid rendering when minimized
|
||||||
|
@ -303,7 +303,6 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||||
subResource.SysMemPitch = desc.Width * 4;
|
subResource.SysMemPitch = desc.Width * 4;
|
||||||
subResource.SysMemSlicePitch = 0;
|
subResource.SysMemSlicePitch = 0;
|
||||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||||
IM_ASSERT(pTexture != NULL);
|
|
||||||
|
|
||||||
// Create texture view
|
// Create texture view
|
||||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
|
@ -317,7 +316,7 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store our identifier
|
// Store our identifier
|
||||||
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
|
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
|
||||||
|
|
||||||
// Create texture sampler
|
// Create texture sampler
|
||||||
{
|
{
|
||||||
|
@ -504,8 +503,8 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||||
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||||
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||||
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||||
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||||
|
@ -547,7 +546,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||||
|
|
||||||
|
@ -562,7 +561,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||||
|
|
||||||
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
||||||
{
|
{
|
||||||
// Setup backend capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendRendererName = "imgui_impl_dx11";
|
io.BackendRendererName = "imgui_impl_dx11";
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
// dear imgui: Renderer Backend for DirectX11
|
// dear imgui: Renderer for DirectX11
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "../../imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
struct ID3D11Device;
|
struct ID3D11Device;
|
||||||
struct ID3D11DeviceContext;
|
struct ID3D11DeviceContext;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
|
|
||||||
// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
|
// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
|
||||||
// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
|
// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
|
||||||
// 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID.
|
// 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID.
|
||||||
|
@ -30,7 +29,7 @@
|
||||||
// 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport).
|
// 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport).
|
||||||
// 2018-02-22: Merged into master with all Win32 code synchronized to other examples.
|
// 2018-02-22: Merged into master with all Win32 code synchronized to other examples.
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "../../imgui.h"
|
||||||
#include "imgui_impl_dx12.h"
|
#include "imgui_impl_dx12.h"
|
||||||
|
|
||||||
// DirectX
|
// DirectX
|
||||||
|
@ -394,7 +393,7 @@ static void ImGui_ImplDX12_CreateFontsTexture()
|
||||||
|
|
||||||
// Store our identifier
|
// Store our identifier
|
||||||
static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
|
static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
|
||||||
io.Fonts->SetTexID((ImTextureID)g_hFontSrvGpuDescHandle.ptr);
|
io.Fonts->TexID = (ImTextureID)g_hFontSrvGpuDescHandle.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplDX12_CreateDeviceObjects()
|
bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||||
|
@ -530,8 +529,8 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||||
desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||||
desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||||
desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||||
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
|
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||||
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
|
||||||
desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||||
}
|
}
|
||||||
|
@ -583,7 +582,7 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
|
||||||
SafeRelease(g_pFontTextureResource);
|
SafeRelease(g_pFontTextureResource);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
io.Fonts->TexID = NULL; // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||||
|
|
||||||
for (UINT i = 0; i < g_numFramesInFlight; i++)
|
for (UINT i = 0; i < g_numFramesInFlight; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "../../imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning (push)
|
#pragma warning (push)
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
// dear imgui: Renderer Backend for DirectX9
|
// dear imgui: Renderer for DirectX9
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
|
|
||||||
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
|
|
||||||
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
|
|
||||||
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
|
|
||||||
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||||
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||||
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
|
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
|
||||||
|
@ -26,11 +22,13 @@
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "../../imgui.h"
|
||||||
#include "imgui_impl_dx9.h"
|
#include "imgui_impl_dx9.h"
|
||||||
|
|
||||||
// DirectX
|
// DirectX
|
||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
|
#include <dinput.h>
|
||||||
|
|
||||||
// DirectX data
|
// DirectX data
|
||||||
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
|
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
|
||||||
|
@ -47,12 +45,6 @@ struct CUSTOMVERTEX
|
||||||
};
|
};
|
||||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||||
|
|
||||||
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL)
|
|
||||||
#else
|
|
||||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Setup viewport
|
// Setup viewport
|
||||||
|
@ -67,26 +59,17 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
|
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
|
||||||
g_pd3dDevice->SetPixelShader(NULL);
|
g_pd3dDevice->SetPixelShader(NULL);
|
||||||
g_pd3dDevice->SetVertexShader(NULL);
|
g_pd3dDevice->SetVertexShader(NULL);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||||
|
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||||
|
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||||
|
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
|
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
|
||||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||||
|
@ -119,6 +102,7 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render function.
|
// Render function.
|
||||||
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized
|
// Avoid rendering when minimized
|
||||||
|
@ -145,37 +129,24 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||||
IDirect3DStateBlock9* d3d9_state_block = NULL;
|
IDirect3DStateBlock9* d3d9_state_block = NULL;
|
||||||
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
||||||
return;
|
return;
|
||||||
if (d3d9_state_block->Capture() < 0)
|
|
||||||
{
|
|
||||||
d3d9_state_block->Release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
d3d9_state_block->Capture();
|
||||||
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
||||||
D3DMATRIX last_world, last_view, last_projection;
|
D3DMATRIX last_world, last_view, last_projection;
|
||||||
g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
|
g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
|
||||||
g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
|
g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
|
||||||
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
|
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
|
||||||
|
|
||||||
// Allocate buffers
|
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
|
||||||
|
// FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and
|
||||||
|
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||||
CUSTOMVERTEX* vtx_dst;
|
CUSTOMVERTEX* vtx_dst;
|
||||||
ImDrawIdx* idx_dst;
|
ImDrawIdx* idx_dst;
|
||||||
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||||
{
|
|
||||||
d3d9_state_block->Release();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||||
{
|
|
||||||
g_pVB->Unlock();
|
|
||||||
d3d9_state_block->Release();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
|
|
||||||
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
|
|
||||||
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
{
|
{
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
@ -185,7 +156,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
vtx_dst->pos[0] = vtx_src->pos.x;
|
||||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
vtx_dst->pos[1] = vtx_src->pos.y;
|
||||||
vtx_dst->pos[2] = 0.0f;
|
vtx_dst->pos[2] = 0.0f;
|
||||||
vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col);
|
vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9
|
||||||
vtx_dst->uv[0] = vtx_src->uv.x;
|
vtx_dst->uv[0] = vtx_src->uv.x;
|
||||||
vtx_dst->uv[1] = vtx_src->uv.y;
|
vtx_dst->uv[1] = vtx_src->uv.y;
|
||||||
vtx_dst++;
|
vtx_dst++;
|
||||||
|
@ -248,7 +219,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||||
|
|
||||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||||
{
|
{
|
||||||
// Setup backend capabilities flags
|
// Setup back-end capabilities flags
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendRendererName = "imgui_impl_dx9";
|
io.BackendRendererName = "imgui_impl_dx9";
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
@ -272,17 +243,6 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
|
||||||
int width, height, bytes_per_pixel;
|
int width, height, bytes_per_pixel;
|
||||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
|
||||||
|
|
||||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
|
||||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
if (io.Fonts->TexPixelsUseColors)
|
|
||||||
{
|
|
||||||
ImU32* dst_start = (ImU32*)ImGui::MemAlloc(width * height * bytes_per_pixel);
|
|
||||||
for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + width * height; dst < dst_end; src++, dst++)
|
|
||||||
*dst = IMGUI_COL_TO_DX9_ARGB(*src);
|
|
||||||
pixels = (unsigned char*)dst_start;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
// Upload texture to graphics system
|
||||||
g_FontTexture = NULL;
|
g_FontTexture = NULL;
|
||||||
if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
|
if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
|
||||||
|
@ -295,12 +255,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
|
||||||
g_FontTexture->UnlockRect(0);
|
g_FontTexture->UnlockRect(0);
|
||||||
|
|
||||||
// Store our identifier
|
// Store our identifier
|
||||||
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
|
io.Fonts->TexID = (ImTextureID)g_FontTexture;
|
||||||
|
|
||||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
if (io.Fonts->TexPixelsUseColors)
|
|
||||||
ImGui::MemFree(pixels);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -320,7 +275,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
|
||||||
return;
|
return;
|
||||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||||
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplDX9_NewFrame()
|
bool ImGui_ImplDX9_NewFrame()
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
// dear imgui: Renderer Backend for DirectX9
|
// dear imgui: Renderer for DirectX9
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "../../imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
struct IDirect3DDevice9;
|
struct IDirect3DDevice9;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
|
// dear imgui: Platform Binding for Windows (standard windows API for 32 and 64 bits applications)
|
||||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
|
@ -7,36 +7,27 @@
|
||||||
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
|
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
|
||||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
#include "../../imgui.h"
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_impl_win32.h"
|
#include "imgui_impl_win32.h"
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <dwmapi.h>
|
|
||||||
|
|
||||||
// Configuration flags to add in your imconfig.h file:
|
// Using XInput library for gamepad (with recent Windows SDK this may leads to executables which won't run on Windows 7)
|
||||||
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support (this used to be meaningful before <1.81) but we know load XInput dynamically so the option is less relevant now.
|
|
||||||
|
|
||||||
// Using XInput for gamepad (will load DLL dynamically)
|
|
||||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
#include <xinput.h>
|
#include <XInput.h>
|
||||||
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
#else
|
||||||
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
|
||||||
|
#endif
|
||||||
|
#if defined(_MSC_VER) && !defined(IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT)
|
||||||
|
#pragma comment(lib, "xinput")
|
||||||
|
//#pragma comment(lib, "Xinput9_1_0")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
|
|
||||||
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
|
|
||||||
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
|
|
||||||
// 2021-01-25: Inputs: Dynamically loading XInput DLL.
|
|
||||||
// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed.
|
|
||||||
// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
|
// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
|
||||||
// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
|
// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
|
||||||
// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT.
|
// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT.
|
||||||
|
@ -69,13 +60,6 @@ static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||||
static bool g_HasGamepad = false;
|
static bool g_HasGamepad = false;
|
||||||
static bool g_WantUpdateHasGamepad = true;
|
static bool g_WantUpdateHasGamepad = true;
|
||||||
|
|
||||||
// XInput DLL and functions
|
|
||||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
|
||||||
static HMODULE g_XInputDLL = NULL;
|
|
||||||
static PFN_XInputGetCapabilities g_XInputGetCapabilities = NULL;
|
|
||||||
static PFN_XInputGetState g_XInputGetState = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
bool ImGui_ImplWin32_Init(void* hwnd)
|
bool ImGui_ImplWin32_Init(void* hwnd)
|
||||||
{
|
{
|
||||||
|
@ -84,7 +68,7 @@ bool ImGui_ImplWin32_Init(void* hwnd)
|
||||||
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time))
|
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup back-end capabilities flags
|
||||||
g_hWnd = (HWND)hwnd;
|
g_hWnd = (HWND)hwnd;
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
@ -92,7 +76,7 @@ bool ImGui_ImplWin32_Init(void* hwnd)
|
||||||
io.BackendPlatformName = "imgui_impl_win32";
|
io.BackendPlatformName = "imgui_impl_win32";
|
||||||
io.ImeWindowHandle = hwnd;
|
io.ImeWindowHandle = hwnd;
|
||||||
|
|
||||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
|
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
|
||||||
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
||||||
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
||||||
|
@ -116,46 +100,12 @@ bool ImGui_ImplWin32_Init(void* hwnd)
|
||||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||||
|
|
||||||
// Dynamically load XInput library
|
|
||||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
|
||||||
const char* xinput_dll_names[] =
|
|
||||||
{
|
|
||||||
"xinput1_4.dll", // Windows 8+
|
|
||||||
"xinput1_3.dll", // DirectX SDK
|
|
||||||
"xinput9_1_0.dll", // Windows Vista, Windows 7
|
|
||||||
"xinput1_2.dll", // DirectX SDK
|
|
||||||
"xinput1_1.dll" // DirectX SDK
|
|
||||||
};
|
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
|
|
||||||
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
|
|
||||||
{
|
|
||||||
g_XInputDLL = dll;
|
|
||||||
g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
|
|
||||||
g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplWin32_Shutdown()
|
void ImGui_ImplWin32_Shutdown()
|
||||||
{
|
{
|
||||||
// Unload XInput library
|
g_hWnd = (HWND)0;
|
||||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
|
||||||
if (g_XInputDLL)
|
|
||||||
::FreeLibrary(g_XInputDLL);
|
|
||||||
g_XInputDLL = NULL;
|
|
||||||
g_XInputGetCapabilities = NULL;
|
|
||||||
g_XInputGetState = NULL;
|
|
||||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
|
||||||
|
|
||||||
g_hWnd = NULL;
|
|
||||||
g_Time = 0;
|
|
||||||
g_TicksPerSecond = 0;
|
|
||||||
g_LastMouseCursor = ImGuiMouseCursor_COUNT;
|
|
||||||
g_HasGamepad = false;
|
|
||||||
g_WantUpdateHasGamepad = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ImGui_ImplWin32_UpdateMouseCursor()
|
static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||||
|
@ -194,13 +144,12 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||||
static void ImGui_ImplWin32_UpdateMousePos()
|
static void ImGui_ImplWin32_UpdateMousePos()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
IM_ASSERT(g_hWnd != 0);
|
|
||||||
|
|
||||||
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
if (io.WantSetMousePos)
|
if (io.WantSetMousePos)
|
||||||
{
|
{
|
||||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||||
if (::ClientToScreen(g_hWnd, &pos))
|
::ClientToScreen(g_hWnd, &pos);
|
||||||
::SetCursorPos(pos.x, pos.y);
|
::SetCursorPos(pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,13 +176,13 @@ static void ImGui_ImplWin32_UpdateGamepads()
|
||||||
if (g_WantUpdateHasGamepad)
|
if (g_WantUpdateHasGamepad)
|
||||||
{
|
{
|
||||||
XINPUT_CAPABILITIES caps;
|
XINPUT_CAPABILITIES caps;
|
||||||
g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
|
g_HasGamepad = (XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS);
|
||||||
g_WantUpdateHasGamepad = false;
|
g_WantUpdateHasGamepad = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
|
||||||
XINPUT_STATE xinput_state;
|
XINPUT_STATE xinput_state;
|
||||||
if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
|
if (g_HasGamepad && XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
|
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||||
|
@ -265,15 +214,15 @@ static void ImGui_ImplWin32_UpdateGamepads()
|
||||||
void ImGui_ImplWin32_NewFrame()
|
void ImGui_ImplWin32_NewFrame()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
|
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().");
|
||||||
|
|
||||||
// Setup display size (every frame to accommodate for window resizing)
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
RECT rect = { 0, 0, 0, 0 };
|
RECT rect;
|
||||||
::GetClientRect(g_hWnd, &rect);
|
::GetClientRect(g_hWnd, &rect);
|
||||||
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
||||||
|
|
||||||
// Setup time step
|
// Setup time step
|
||||||
INT64 current_time = 0;
|
INT64 current_time;
|
||||||
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time);
|
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time);
|
||||||
io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
|
io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
|
||||||
g_Time = current_time;
|
g_Time = current_time;
|
||||||
|
@ -310,7 +259,7 @@ void ImGui_ImplWin32_NewFrame()
|
||||||
|
|
||||||
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
|
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
|
||||||
// Call from your application's message handler.
|
// Call from your application's message handler.
|
||||||
// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
|
// When implementing your own back-end, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
|
||||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||||
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
|
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
|
||||||
|
@ -374,9 +323,6 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||||
if (wParam < 256)
|
if (wParam < 256)
|
||||||
io.KeysDown[wParam] = 0;
|
io.KeysDown[wParam] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
case WM_KILLFOCUS:
|
|
||||||
memset(io.KeysDown, 0, sizeof(io.KeysDown));
|
|
||||||
return 0;
|
|
||||||
case WM_CHAR:
|
case WM_CHAR:
|
||||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||||
if (wParam > 0 && wParam < 0x10000)
|
if (wParam > 0 && wParam < 0x10000)
|
||||||
|
@ -406,7 +352,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||||
//---------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------
|
||||||
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
|
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
|
||||||
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
|
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
|
||||||
// If you are trying to implement your own backend for your own engine, you may ignore that noise.
|
// If you are trying to implement your own back-end for your own engine, you may ignore that noise.
|
||||||
//---------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Implement some of the functions and types normally declared in recent Windows SDK.
|
// Implement some of the functions and types normally declared in recent Windows SDK.
|
||||||
|
@ -420,9 +366,7 @@ static BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
|
||||||
cond = ::VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
cond = ::VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||||
return ::VerifyVersionInfoW(&osvi, mask, cond);
|
return ::VerifyVersionInfoW(&osvi, mask, cond);
|
||||||
}
|
}
|
||||||
#define IsWindowsVistaOrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA
|
#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WINBLUE
|
||||||
#define IsWindows8OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8
|
|
||||||
#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DPI_ENUMS_DECLARED
|
#ifndef DPI_ENUMS_DECLARED
|
||||||
|
@ -467,7 +411,7 @@ void ImGui_ImplWin32_EnableDpiAwareness()
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(NOGDI)
|
#if defined(_MSC_VER) && !defined(NOGDI)
|
||||||
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
|
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
||||||
|
@ -500,43 +444,3 @@ float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------
|
||||||
// Transparency related helpers (optional)
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// [experimental]
|
|
||||||
// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c
|
|
||||||
// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW)
|
|
||||||
void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
|
|
||||||
{
|
|
||||||
if (!IsWindowsVistaOrGreater())
|
|
||||||
return;
|
|
||||||
|
|
||||||
BOOL composition;
|
|
||||||
if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BOOL opaque;
|
|
||||||
DWORD color;
|
|
||||||
if (IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque))
|
|
||||||
{
|
|
||||||
HRGN region = ::CreateRectRgn(0, 0, -1, -1);
|
|
||||||
DWM_BLURBEHIND bb = {};
|
|
||||||
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
|
||||||
bb.hRgnBlur = region;
|
|
||||||
bb.fEnable = TRUE;
|
|
||||||
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
|
|
||||||
::DeleteObject(region);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DWM_BLURBEHIND bb = {};
|
|
||||||
bb.dwFlags = DWM_BB_ENABLE;
|
|
||||||
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
|
// dear imgui: Platform Binding for Windows (standard windows API for 32 and 64 bits applications)
|
||||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
|
@ -7,17 +7,18 @@
|
||||||
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
|
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
|
||||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
|
||||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
|
||||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "../../imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
|
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||||
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
||||||
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
// - Disable gamepad support or linking with xinput.lib
|
||||||
|
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
//#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
|
||||||
|
|
||||||
// Win32 message handler your application need to call.
|
// Win32 message handler your application need to call.
|
||||||
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||||
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||||
|
@ -34,8 +35,3 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
|
||||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||||
|
|
||||||
// Transparency related helpers (optional) [experimental]
|
|
||||||
// - Use to enable alpha compositing transparency with the desktop.
|
|
||||||
// - Use together with e.g. clearing your framebuffer with zero-alpha.
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
|
|
||||||
|
|
|
@ -4302,7 +4302,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||||
int winding = 0;
|
int winding = 0;
|
||||||
|
|
||||||
orig[0] = x;
|
orig[0] = x;
|
||||||
//orig[1] = y; // [DEAR IMGUI] commented double assignment
|
//orig[1] = y; // [DEAR IMGUI] commmented double assignment
|
||||||
|
|
||||||
// make sure y never passes through a vertex of the shape
|
// make sure y never passes through a vertex of the shape
|
||||||
y_frac = (float) STBTT_fmod(y, 1.0f);
|
y_frac = (float) STBTT_fmod(y, 1.0f);
|
||||||
|
|
|
@ -29,32 +29,32 @@ const GUID DETOUR_EXE_HELPER_GUID = { /* ea0251b9-5cde-41b5-98d0-2af4a26b0fee */
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Enumerate through modules in the target process.
|
// Enumate through modules in the target process.
|
||||||
//
|
//
|
||||||
static PVOID LoadNtHeaderFromProcess(_In_ HANDLE hProcess,
|
static BOOL WINAPI LoadNtHeaderFromProcess(HANDLE hProcess,
|
||||||
_In_ HMODULE hModule,
|
HMODULE hModule,
|
||||||
_Out_ PIMAGE_NT_HEADERS32 pNtHeader)
|
PIMAGE_NT_HEADERS32 pNtHeader)
|
||||||
{
|
{
|
||||||
ZeroMemory(pNtHeader, sizeof(*pNtHeader));
|
|
||||||
PBYTE pbModule = (PBYTE)hModule;
|
PBYTE pbModule = (PBYTE)hModule;
|
||||||
|
|
||||||
if (pbModule == NULL) {
|
if (pbModule == NULL) {
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
ZeroMemory(&mbi, sizeof(mbi));
|
ZeroMemory(&mbi, sizeof(mbi));
|
||||||
|
|
||||||
if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) {
|
if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) {
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMAGE_DOS_HEADER idh;
|
IMAGE_DOS_HEADER idh;
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n",
|
||||||
pbModule, pbModule + sizeof(idh), GetLastError()));
|
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idh.e_magic != IMAGE_DOS_SIGNATURE ||
|
if (idh.e_magic != IMAGE_DOS_SIGNATURE ||
|
||||||
|
@ -62,37 +62,31 @@ static PVOID LoadNtHeaderFromProcess(_In_ HANDLE hProcess,
|
||||||
(DWORD)idh.e_lfanew < sizeof(idh)) {
|
(DWORD)idh.e_lfanew < sizeof(idh)) {
|
||||||
|
|
||||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew,
|
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew,
|
||||||
pNtHeader, sizeof(*pNtHeader), NULL)) {
|
pNtHeader, sizeof(*pNtHeader), NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p:%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p:%p) failed: %d\n",
|
||||||
pbModule + idh.e_lfanew,
|
pbModule + idh.e_lfanew,
|
||||||
pbModule + idh.e_lfanew + sizeof(*pNtHeader),
|
pbModule + idh.e_lfanew + sizeof(*pNtHeader),
|
||||||
pbModule,
|
pbModule,
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pbModule + idh.e_lfanew;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HMODULE EnumerateModulesInProcess(_In_ HANDLE hProcess,
|
static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess,
|
||||||
_In_opt_ HMODULE hModuleLast,
|
HMODULE hModuleLast,
|
||||||
_Out_ PIMAGE_NT_HEADERS32 pNtHeader,
|
PIMAGE_NT_HEADERS32 pNtHeader)
|
||||||
_Out_opt_ PVOID *pRemoteNtHeader)
|
|
||||||
{
|
{
|
||||||
ZeroMemory(pNtHeader, sizeof(*pNtHeader));
|
|
||||||
if (pRemoteNtHeader) {
|
|
||||||
*pRemoteNtHeader = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
|
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
@ -124,147 +118,13 @@ static HMODULE EnumerateModulesInProcess(_In_ HANDLE hProcess,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID remoteHeader
|
if (LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader)) {
|
||||||
= LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader);
|
|
||||||
if (remoteHeader) {
|
|
||||||
if (pRemoteNtHeader) {
|
|
||||||
*pRemoteNtHeader = remoteHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (HMODULE)pbLast;
|
return (HMODULE)pbLast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Find payloads in target process.
|
|
||||||
//
|
|
||||||
|
|
||||||
static PVOID FindDetourSectionInRemoteModule(_In_ HANDLE hProcess,
|
|
||||||
_In_ HMODULE hModule,
|
|
||||||
_In_ const IMAGE_NT_HEADERS32 *pNtHeader,
|
|
||||||
_In_ PVOID pRemoteNtHeader)
|
|
||||||
{
|
|
||||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
|
||||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PIMAGE_SECTION_HEADER pRemoteSectionHeaders
|
|
||||||
= (PIMAGE_SECTION_HEADER)((PBYTE)pRemoteNtHeader
|
|
||||||
+ sizeof(pNtHeader->Signature)
|
|
||||||
+ sizeof(pNtHeader->FileHeader)
|
|
||||||
+ pNtHeader->FileHeader.SizeOfOptionalHeader);
|
|
||||||
|
|
||||||
IMAGE_SECTION_HEADER header;
|
|
||||||
for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; ++n) {
|
|
||||||
if (!ReadProcessMemory(hProcess, pRemoteSectionHeaders + n, &header, sizeof(header), NULL)) {
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n",
|
|
||||||
pRemoteSectionHeaders + n,
|
|
||||||
(PBYTE)(pRemoteSectionHeaders + n) + sizeof(header),
|
|
||||||
GetLastError()));
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp((PCHAR)header.Name, ".detour") == 0) {
|
|
||||||
if (header.VirtualAddress == 0 ||
|
|
||||||
header.SizeOfRawData == 0) {
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetLastError(NO_ERROR);
|
|
||||||
return (PBYTE)hModule + header.VirtualAddress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PVOID FindPayloadInRemoteDetourSection(_In_ HANDLE hProcess,
|
|
||||||
_In_ REFGUID rguid,
|
|
||||||
_Out_opt_ DWORD *pcbData,
|
|
||||||
_In_ PVOID pvRemoteDetoursSection)
|
|
||||||
{
|
|
||||||
if (pcbData) {
|
|
||||||
*pcbData = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PBYTE pbData = (PBYTE)pvRemoteDetoursSection;
|
|
||||||
|
|
||||||
DETOUR_SECTION_HEADER header;
|
|
||||||
if (!ReadProcessMemory(hProcess, pbData, &header, sizeof(header), NULL)) {
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(dsh@%p..%p) failed: %lu\n",
|
|
||||||
pbData,
|
|
||||||
pbData + sizeof(header),
|
|
||||||
GetLastError()));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header.cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
|
|
||||||
header.nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
|
|
||||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header.nDataOffset == 0) {
|
|
||||||
header.nDataOffset = header.cbHeaderSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PVOID pvSection = pbData + header.nDataOffset; pvSection < pbData + header.cbDataSize;) {
|
|
||||||
DETOUR_SECTION_RECORD section;
|
|
||||||
if (!ReadProcessMemory(hProcess, pvSection, §ion, sizeof(section), NULL)) {
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(dsr@%p..%p) failed: %lu\n",
|
|
||||||
pvSection,
|
|
||||||
(PBYTE)pvSection + sizeof(section),
|
|
||||||
GetLastError()));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DetourAreSameGuid(section.guid, rguid)) {
|
|
||||||
if (pcbData) {
|
|
||||||
*pcbData = section.cbBytes - sizeof(section);
|
|
||||||
}
|
|
||||||
SetLastError(NO_ERROR);
|
|
||||||
return (DETOUR_SECTION_RECORD *)pvSection + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pvSection = (PBYTE)pvSection + section.cbBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Success_(return != NULL)
|
|
||||||
PVOID WINAPI DetourFindRemotePayload(_In_ HANDLE hProcess,
|
|
||||||
_In_ REFGUID rguid,
|
|
||||||
_Out_opt_ DWORD *pcbData)
|
|
||||||
{
|
|
||||||
if (hProcess == NULL) {
|
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMAGE_NT_HEADERS32 header;
|
|
||||||
PVOID pvRemoteHeader;
|
|
||||||
for (HMODULE hMod = NULL; (hMod = EnumerateModulesInProcess(hProcess, hMod, &header, &pvRemoteHeader)) != NULL;) {
|
|
||||||
PVOID pvData = FindDetourSectionInRemoteModule(hProcess, hMod, &header, pvRemoteHeader);
|
|
||||||
if (pvData != NULL) {
|
|
||||||
pvData = FindPayloadInRemoteDetourSection(hProcess, rguid, pcbData, pvData);
|
|
||||||
if (pvData != NULL) {
|
|
||||||
return pvData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetLastError(ERROR_MOD_NOT_FOUND);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Find a region of memory in which we can create a replacement import table.
|
// Find a region of memory in which we can create a replacement import table.
|
||||||
|
@ -282,7 +142,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa
|
||||||
if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("VirtualQueryEx(%p) failed: %lu\n",
|
DETOUR_TRACE(("VirtualQueryEx(%p) failed: %d\n",
|
||||||
pbLast, GetLastError()));
|
pbLast, GetLastError()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -327,7 +187,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa
|
||||||
PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
|
PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
|
||||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||||
if (pbAlloc == NULL) {
|
if (pbAlloc == NULL) {
|
||||||
DETOUR_TRACE(("VirtualAllocEx(%p) failed: %lu\n", pbAddress, GetLastError()));
|
DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
@ -386,7 +246,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
der.pidh = (PBYTE)hModule;
|
der.pidh = (PBYTE)hModule;
|
||||||
der.cbidh = sizeof(der.idh);
|
der.cbidh = sizeof(der.idh);
|
||||||
if (!ReadProcessMemory(hProcess, der.pidh, &der.idh, sizeof(der.idh), NULL)) {
|
if (!ReadProcessMemory(hProcess, der.pidh, &der.idh, sizeof(der.idh), NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n",
|
||||||
der.pidh, der.pidh + der.cbidh, GetLastError()));
|
der.pidh, der.pidh + der.cbidh, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +257,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
der.pinh = der.pidh + der.idh.e_lfanew;
|
der.pinh = der.pidh + der.idh.e_lfanew;
|
||||||
der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader);
|
der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader);
|
||||||
if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) {
|
if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n",
|
||||||
der.pinh, der.pinh + der.cbinh, GetLastError()));
|
der.pinh, der.pinh + der.cbinh, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +272,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) {
|
if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n",
|
||||||
der.pinh, der.pinh + der.cbinh, GetLastError()));
|
der.pinh, der.pinh + der.cbinh, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -424,7 +284,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 &&
|
if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 &&
|
||||||
der.inh32.CLR_DIRECTORY.Size != 0) {
|
der.inh32.CLR_DIRECTORY.Size != 0) {
|
||||||
|
|
||||||
DETOUR_TRACE(("CLR32.VirtAddr=%08lx, CLR.Size=%lu\n",
|
DETOUR_TRACE(("CLR32.VirtAddr=%x, CLR.Size=%x\n",
|
||||||
der.inh32.CLR_DIRECTORY.VirtualAddress,
|
der.inh32.CLR_DIRECTORY.VirtualAddress,
|
||||||
der.inh32.CLR_DIRECTORY.Size));
|
der.inh32.CLR_DIRECTORY.Size));
|
||||||
|
|
||||||
|
@ -435,7 +295,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
if (der.inh64.CLR_DIRECTORY.VirtualAddress != 0 &&
|
if (der.inh64.CLR_DIRECTORY.VirtualAddress != 0 &&
|
||||||
der.inh64.CLR_DIRECTORY.Size != 0) {
|
der.inh64.CLR_DIRECTORY.Size != 0) {
|
||||||
|
|
||||||
DETOUR_TRACE(("CLR64.VirtAddr=%08lx, CLR.Size=%lu\n",
|
DETOUR_TRACE(("CLR64.VirtAddr=%x, CLR.Size=%x\n",
|
||||||
der.inh64.CLR_DIRECTORY.VirtualAddress,
|
der.inh64.CLR_DIRECTORY.VirtualAddress,
|
||||||
der.inh64.CLR_DIRECTORY.Size));
|
der.inh64.CLR_DIRECTORY.Size));
|
||||||
|
|
||||||
|
@ -446,7 +306,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
if (der.pclr != 0) {
|
if (der.pclr != 0) {
|
||||||
der.cbclr = sizeof(der.clr);
|
der.cbclr = sizeof(der.clr);
|
||||||
if (!ReadProcessMemory(hProcess, der.pclr, &der.clr, der.cbclr, NULL)) {
|
if (!ReadProcessMemory(hProcess, der.pclr, &der.clr, der.cbclr, NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(clr@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(clr@%p..%p) failed: %d\n",
|
||||||
der.pclr, der.pclr + der.cbclr, GetLastError()));
|
der.pclr, der.pclr + der.cbclr, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -463,7 +323,6 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32
|
#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32
|
||||||
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||||
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32
|
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32
|
||||||
#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA32
|
|
||||||
#define UPDATE_IMPORTS_XX UpdateImports32
|
#define UPDATE_IMPORTS_XX UpdateImports32
|
||||||
#define DETOURS_BITS_XX 32
|
#define DETOURS_BITS_XX 32
|
||||||
#include "uimports.cc"
|
#include "uimports.cc"
|
||||||
|
@ -480,7 +339,6 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64
|
#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64
|
||||||
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
||||||
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64
|
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64
|
||||||
#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA64
|
|
||||||
#define UPDATE_IMPORTS_XX UpdateImports64
|
#define UPDATE_IMPORTS_XX UpdateImports64
|
||||||
#define DETOURS_BITS_XX 64
|
#define DETOURS_BITS_XX 64
|
||||||
#include "uimports.cc"
|
#include "uimports.cc"
|
||||||
|
@ -516,7 +374,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
//////////////////////////////////////////////////////// Read old headers.
|
//////////////////////////////////////////////////////// Read old headers.
|
||||||
//
|
//
|
||||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n",
|
||||||
pbModule, pbModule + sizeof(idh), GetLastError()));
|
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -525,7 +383,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
|
|
||||||
PBYTE pnh = pbModule + idh.e_lfanew;
|
PBYTE pnh = pbModule + idh.e_lfanew;
|
||||||
if (!ReadProcessMemory(hProcess, pnh, &inh32, sizeof(inh32), NULL)) {
|
if (!ReadProcessMemory(hProcess, pnh, &inh32, sizeof(inh32), NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n",
|
||||||
pnh, pnh + sizeof(inh32), GetLastError()));
|
pnh, pnh + sizeof(inh32), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -540,7 +398,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
inh32.FileHeader.SizeOfOptionalHeader;
|
inh32.FileHeader.SizeOfOptionalHeader;
|
||||||
ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||||
if (!ReadProcessMemory(hProcess, psects, §s, cb, NULL)) {
|
if (!ReadProcessMemory(hProcess, psects, §s, cb, NULL)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n",
|
||||||
psects, psects + cb, GetLastError()));
|
psects, psects + cb, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -597,7 +455,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) {
|
if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %d\n",
|
||||||
pnh, pnh + sizeof(inh64), GetLastError()));
|
pnh, pnh + sizeof(inh64), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +466,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
inh64.FileHeader.SizeOfOptionalHeader;
|
inh64.FileHeader.SizeOfOptionalHeader;
|
||||||
cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||||
if (!WriteProcessMemory(hProcess, psects, §s, cb, NULL)) {
|
if (!WriteProcessMemory(hProcess, psects, §s, cb, NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p) failed: %d\n",
|
||||||
psects, psects + cb, GetLastError()));
|
psects, psects + cb, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -620,12 +478,12 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the import table.
|
// Remove the import table.
|
||||||
if (der.pclr != NULL && (der.clr.Flags & COMIMAGE_FLAGS_ILONLY)) {
|
if (der.pclr != NULL && (der.clr.Flags & 1)) {
|
||||||
inh64.IMPORT_DIRECTORY.VirtualAddress = 0;
|
inh64.IMPORT_DIRECTORY.VirtualAddress = 0;
|
||||||
inh64.IMPORT_DIRECTORY.Size = 0;
|
inh64.IMPORT_DIRECTORY.Size = 0;
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) {
|
if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %d\n",
|
||||||
pnh, pnh + sizeof(inh64), GetLastError()));
|
pnh, pnh + sizeof(inh64), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -641,37 +499,6 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
}
|
}
|
||||||
#endif // DETOURS_64BIT
|
#endif // DETOURS_64BIT
|
||||||
|
|
||||||
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
|
||||||
|
|
||||||
static BOOL IsWow64ProcessHelper(HANDLE hProcess,
|
|
||||||
PBOOL Wow64Process)
|
|
||||||
{
|
|
||||||
#ifdef _X86_
|
|
||||||
if (Wow64Process == NULL) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsWow64Process is not available on all supported versions of Windows.
|
|
||||||
//
|
|
||||||
HMODULE hKernel32 = LoadLibraryW(L"KERNEL32.DLL");
|
|
||||||
if (hKernel32 == NULL) {
|
|
||||||
DETOUR_TRACE(("LoadLibraryW failed: %lu\n", GetLastError()));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
|
|
||||||
hKernel32, "IsWow64Process");
|
|
||||||
|
|
||||||
if (pfnIsWow64Process == NULL) {
|
|
||||||
DETOUR_TRACE(("GetProcAddress failed: %lu\n", GetLastError()));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return pfnIsWow64Process(hProcess, Wow64Process);
|
|
||||||
#else
|
|
||||||
return IsWow64Process(hProcess, Wow64Process);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
||||||
|
@ -680,17 +507,18 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
||||||
{
|
{
|
||||||
// Find the next memory region that contains a mapped PE image.
|
// Find the next memory region that contains a mapped PE image.
|
||||||
//
|
//
|
||||||
|
BOOL bHas64BitDll = FALSE;
|
||||||
|
BOOL bHas32BitExe = FALSE;
|
||||||
BOOL bIs32BitProcess;
|
BOOL bIs32BitProcess;
|
||||||
BOOL bIs64BitOS = FALSE;
|
|
||||||
HMODULE hModule = NULL;
|
HMODULE hModule = NULL;
|
||||||
HMODULE hLast = NULL;
|
HMODULE hLast = NULL;
|
||||||
|
|
||||||
DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%lu)\n", hProcess, nDlls));
|
DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%d)\n", hProcess, nDlls));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
IMAGE_NT_HEADERS32 inh;
|
IMAGE_NT_HEADERS32 inh;
|
||||||
|
|
||||||
if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh, NULL)) == NULL) {
|
if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh)) == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,8 +527,20 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
||||||
|
|
||||||
if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
|
if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
|
||||||
hModule = hLast;
|
hModule = hLast;
|
||||||
|
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||||
|
&& inh.FileHeader.Machine != 0) {
|
||||||
|
|
||||||
|
bHas32BitExe = TRUE;
|
||||||
|
}
|
||||||
DETOUR_TRACE(("%p Found EXE\n", hLast));
|
DETOUR_TRACE(("%p Found EXE\n", hLast));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
||||||
|
&& inh.FileHeader.Machine != 0) {
|
||||||
|
|
||||||
|
bHas64BitDll = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hModule == NULL) {
|
if (hModule == NULL) {
|
||||||
|
@ -708,37 +548,19 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if the target process is 32bit or 64bit. This is a two-stop process:
|
if (!bHas32BitExe) {
|
||||||
//
|
bIs32BitProcess = FALSE;
|
||||||
// 1. First, determine if we're running on a 64bit operating system.
|
|
||||||
// - If we're running 64bit code (i.e. _WIN64 is defined), this is trivially true.
|
|
||||||
// - If we're running 32bit code (i.e. _WIN64 is not defined), test if
|
|
||||||
// we're running under Wow64. If so, it implies that the operating system
|
|
||||||
// is 64bit.
|
|
||||||
//
|
|
||||||
#ifdef _WIN64
|
|
||||||
bIs64BitOS = TRUE;
|
|
||||||
#else
|
|
||||||
if (!IsWow64ProcessHelper(GetCurrentProcess(), &bIs64BitOS)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
#endif
|
else if (!bHas64BitDll) {
|
||||||
|
|
||||||
// 2. With the operating system bitness known, we can now consider the target process:
|
|
||||||
// - If we're running on a 64bit OS, the target process is 32bit in case
|
|
||||||
// it is running under Wow64. Otherwise, it's 64bit, running natively
|
|
||||||
// (without Wow64).
|
|
||||||
// - If we're running on a 32bit OS, the target process must be 32bit, too.
|
|
||||||
//
|
|
||||||
if (bIs64BitOS) {
|
|
||||||
if (!IsWow64ProcessHelper(hProcess, &bIs32BitProcess)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bIs32BitProcess = TRUE;
|
bIs32BitProcess = TRUE;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (!IsWow64Process(hProcess, &bIs32BitProcess)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" 32BitProcess=%d\n", bIs32BitProcess));
|
DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess));
|
||||||
|
|
||||||
return DetourUpdateProcessWithDllEx(hProcess,
|
return DetourUpdateProcessWithDllEx(hProcess,
|
||||||
hModule,
|
hModule,
|
||||||
|
@ -757,11 +579,11 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
//
|
//
|
||||||
BOOL bIs32BitExe = FALSE;
|
BOOL bIs32BitExe = FALSE;
|
||||||
|
|
||||||
DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%lu)\n", hProcess, hModule, nDlls));
|
DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%d)\n", hProcess, hModule, nDlls));
|
||||||
|
|
||||||
IMAGE_NT_HEADERS32 inh;
|
IMAGE_NT_HEADERS32 inh;
|
||||||
|
|
||||||
if (hModule == NULL || !LoadNtHeaderFromProcess(hProcess, hModule, &inh)) {
|
if (hModule == NULL || LoadNtHeaderFromProcess(hProcess, hModule, &inh) == NULL) {
|
||||||
SetLastError(ERROR_INVALID_OPERATION);
|
SetLastError(ERROR_INVALID_OPERATION);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -772,7 +594,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
bIs32BitExe = TRUE;
|
bIs32BitExe = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" 32BitExe=%d\n", bIs32BitExe));
|
DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bIs32BitExe, bIs32BitProcess));
|
||||||
|
|
||||||
if (hModule == NULL) {
|
if (hModule == NULL) {
|
||||||
SetLastError(ERROR_INVALID_OPERATION);
|
SetLastError(ERROR_INVALID_OPERATION);
|
||||||
|
@ -791,8 +613,8 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
// Try to convert a neutral 32-bit managed binary to a 64-bit managed binary.
|
// Try to convert a neutral 32-bit managed binary to a 64-bit managed binary.
|
||||||
if (bIs32BitExe && !bIs32BitProcess) {
|
if (bIs32BitExe && !bIs32BitProcess) {
|
||||||
if (!der.pclr // Native binary
|
if (!der.pclr // Native binary
|
||||||
|| (der.clr.Flags & COMIMAGE_FLAGS_ILONLY) == 0 // Or mixed-mode MSIL
|
|| (der.clr.Flags & 1) == 0 // Or mixed-mode MSIL
|
||||||
|| (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) != 0) { // Or 32BIT Required MSIL
|
|| (der.clr.Flags & 2) != 0) { // Or 32BIT Required MSIL
|
||||||
|
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -855,30 +677,30 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
if (der.pclr != NULL) {
|
if (der.pclr != NULL) {
|
||||||
DETOUR_CLR_HEADER clr;
|
DETOUR_CLR_HEADER clr;
|
||||||
CopyMemory(&clr, &der.clr, sizeof(clr));
|
CopyMemory(&clr, &der.clr, sizeof(clr));
|
||||||
clr.Flags &= ~COMIMAGE_FLAGS_ILONLY; // Clear the IL_ONLY flag.
|
clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
|
||||||
|
|
||||||
DWORD dwProtect;
|
DWORD dwProtect;
|
||||||
if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) {
|
if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) {
|
||||||
DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %d\n", GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) {
|
if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(clr) failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) {
|
if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) {
|
||||||
DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %d\n", GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr));
|
DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr));
|
||||||
|
|
||||||
#if DETOURS_64BIT
|
#if DETOURS_64BIT
|
||||||
if (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) { // Is the 32BIT Required Flag set?
|
if (der.clr.Flags & 0x2) { // Is the 32BIT Required Flag set?
|
||||||
// X64 never gets here because the process appears as a WOW64 process.
|
// X64 never gets here because the process appears as a WOW64 process.
|
||||||
// However, on IA64, it doesn't appear to be a WOW process.
|
// However, on IA64, it doesn't appear to be a WOW process.
|
||||||
DETOUR_TRACE(("CLR Requires 32-bit\n"));
|
DETOUR_TRACE(("CLR Requires 32-bit\n", der.pclr, der.pclr + der.cbclr));
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -888,7 +710,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
//////////////////////////////// Save the undo data to the target process.
|
//////////////////////////////// Save the undo data to the target process.
|
||||||
//
|
//
|
||||||
if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) {
|
if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) {
|
||||||
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1012,23 +834,9 @@ BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName,
|
||||||
|
|
||||||
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_In_reads_bytes_(cbData) LPCVOID pvData,
|
_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
_In_ DWORD cbData)
|
_In_ DWORD cbData)
|
||||||
{
|
{
|
||||||
return DetourCopyPayloadToProcessEx(hProcess, rguid, pvData, cbData) != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Success_(return != NULL)
|
|
||||||
PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
|
||||||
_In_ REFGUID rguid,
|
|
||||||
_In_reads_bytes_(cbData) LPCVOID pvData,
|
|
||||||
_In_ DWORD cbData)
|
|
||||||
{
|
|
||||||
if (hProcess == NULL) {
|
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) +
|
DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) +
|
||||||
sizeof(IMAGE_NT_HEADERS) +
|
sizeof(IMAGE_NT_HEADERS) +
|
||||||
sizeof(IMAGE_SECTION_HEADER) +
|
sizeof(IMAGE_SECTION_HEADER) +
|
||||||
|
@ -1039,15 +847,10 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
||||||
PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
|
PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
|
||||||
MEM_COMMIT, PAGE_READWRITE);
|
MEM_COMMIT, PAGE_READWRITE);
|
||||||
if (pbBase == NULL) {
|
if (pbBase == NULL) {
|
||||||
DETOUR_TRACE(("VirtualAllocEx(%lu) failed: %lu\n", cbTotal, GetLastError()));
|
DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError()));
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// As you can see in the following code,
|
|
||||||
// the memory layout of the payload range "[pbBase, pbBase+cbTotal]" is a PE executable file,
|
|
||||||
// so DetourFreePayload can use "DetourGetContainingModule(Payload pointer)" to get the above "pbBase" pointer,
|
|
||||||
// pbBase: the memory block allocated by VirtualAllocEx will be released in DetourFreePayload by VirtualFree.
|
|
||||||
|
|
||||||
PBYTE pbTarget = pbBase;
|
PBYTE pbTarget = pbBase;
|
||||||
IMAGE_DOS_HEADER idh;
|
IMAGE_DOS_HEADER idh;
|
||||||
IMAGE_NT_HEADERS inh;
|
IMAGE_NT_HEADERS inh;
|
||||||
|
@ -1061,8 +864,8 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
||||||
idh.e_lfanew = sizeof(idh);
|
idh.e_lfanew = sizeof(idh);
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
|
||||||
cbWrote != sizeof(idh)) {
|
cbWrote != sizeof(idh)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(idh);
|
pbTarget += sizeof(idh);
|
||||||
|
|
||||||
|
@ -1074,7 +877,7 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
||||||
inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
|
inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
|
||||||
cbWrote != sizeof(inh)) {
|
cbWrote != sizeof(inh)) {
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(inh);
|
pbTarget += sizeof(inh);
|
||||||
|
|
||||||
|
@ -1086,7 +889,7 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
||||||
cbData);
|
cbData);
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
|
||||||
cbWrote != sizeof(ish)) {
|
cbWrote != sizeof(ish)) {
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(ish);
|
pbTarget += sizeof(ish);
|
||||||
|
|
||||||
|
@ -1099,7 +902,7 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
||||||
cbData);
|
cbData);
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
|
||||||
cbWrote != sizeof(dsh)) {
|
cbWrote != sizeof(dsh)) {
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(dsh);
|
pbTarget += sizeof(dsh);
|
||||||
|
|
||||||
|
@ -1109,20 +912,19 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
||||||
dsr.guid = rguid;
|
dsr.guid = rguid;
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
|
||||||
cbWrote != sizeof(dsr)) {
|
cbWrote != sizeof(dsr)) {
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(dsr);
|
pbTarget += sizeof(dsr);
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) ||
|
||||||
cbWrote != cbData) {
|
cbWrote != cbData) {
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
pbTarget += cbData;
|
||||||
|
|
||||||
DETOUR_TRACE(("Copied %lu byte payload into target process at %p\n",
|
DETOUR_TRACE(("Copied %d byte payload into target process at %p\n",
|
||||||
cbData, pbTarget));
|
cbTotal, pbTarget - cbTotal));
|
||||||
|
return TRUE;
|
||||||
SetLastError(NO_ERROR);
|
|
||||||
return pbTarget;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL s_fSearchedForHelper = FALSE;
|
static BOOL s_fSearchedForHelper = FALSE;
|
||||||
|
@ -1147,7 +949,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
|
|
||||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid);
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid);
|
||||||
if (hProcess == NULL) {
|
if (hProcess == NULL) {
|
||||||
DETOUR_TRACE(("OpenProcess(pid=%lu) failed: %lu\n",
|
DETOUR_TRACE(("OpenProcess(pid=%d) failed: %d\n",
|
||||||
s_pHelper->pid, GetLastError()));
|
s_pHelper->pid, GetLastError()));
|
||||||
Result = 9901;
|
Result = 9901;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1168,7 +970,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DetourUpdateProcessWithDll(hProcess, rlpDlls, s_pHelper->nDlls)) {
|
if (!DetourUpdateProcessWithDll(hProcess, rlpDlls, s_pHelper->nDlls)) {
|
||||||
DETOUR_TRACE(("DetourUpdateProcessWithDll(pid=%lu) failed: %lu\n",
|
DETOUR_TRACE(("DetourUpdateProcessWithDll(pid=%d) failed: %d\n",
|
||||||
s_pHelper->pid, GetLastError()));
|
s_pHelper->pid, GetLastError()));
|
||||||
Result = 9903;
|
Result = 9903;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1181,15 +983,6 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
rlpDlls = NULL;
|
rlpDlls = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: s_pHelper is allocated as part of injecting the payload in DetourCopyPayloadToProcess(..),
|
|
||||||
// it's a fake section and not data allocated by the system PE loader.
|
|
||||||
|
|
||||||
// Delete the payload after execution to release the memory occupied by it
|
|
||||||
if (s_pHelper != NULL) {
|
|
||||||
DetourFreePayload(s_pHelper);
|
|
||||||
s_pHelper = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExitProcess(Result);
|
ExitProcess(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,7 +1146,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD nLen = GetEnvironmentVariableA("WINDIR", szExe, ARRAYSIZE(szExe));
|
DWORD nLen = GetEnvironmentVariableA("WINDIR", szExe, ARRAYSIZE(szExe));
|
||||||
|
|
||||||
DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%lu,dlls=%lu)\n", dwTargetPid, nDlls));
|
DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%d,dlls=%d)\n", dwTargetPid, nDlls));
|
||||||
if (nDlls < 1 || nDlls > 4096) {
|
if (nDlls < 1 || nDlls > 4096) {
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1379,10 +1172,8 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP"));
|
|
||||||
//so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before
|
|
||||||
hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand),
|
hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand),
|
||||||
"rundll32.exe \"%s\",#1", &helper->rDlls[0]);
|
"rundll32.exe \"%hs\",#1", &helper->rDlls[0]);
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -1398,7 +1189,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
||||||
DETOUR_EXE_HELPER_GUID,
|
DETOUR_EXE_HELPER_GUID,
|
||||||
helper, helper->cb)) {
|
helper, helper->cb)) {
|
||||||
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
|
||||||
TerminateProcess(pi.hProcess, ~0u);
|
TerminateProcess(pi.hProcess, ~0u);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
@ -1415,13 +1206,13 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
if (dwResult != 0) {
|
if (dwResult != 0) {
|
||||||
DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult));
|
DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
Result = TRUE;
|
Result = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError()));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,11 +1240,9 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
WCHAR szCommand[MAX_PATH];
|
WCHAR szCommand[MAX_PATH];
|
||||||
PDETOUR_EXE_HELPER helper = NULL;
|
PDETOUR_EXE_HELPER helper = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
WCHAR szDllName[MAX_PATH];
|
|
||||||
int cchWrittenWideChar;
|
|
||||||
DWORD nLen = GetEnvironmentVariableW(L"WINDIR", szExe, ARRAYSIZE(szExe));
|
DWORD nLen = GetEnvironmentVariableW(L"WINDIR", szExe, ARRAYSIZE(szExe));
|
||||||
|
|
||||||
DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%lu,dlls=%lu)\n", dwTargetPid, nDlls));
|
DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%d,dlls=%d)\n", dwTargetPid, nDlls));
|
||||||
if (nDlls < 1 || nDlls > 4096) {
|
if (nDlls < 1 || nDlls > 4096) {
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1479,15 +1268,8 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP"));
|
|
||||||
//so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before
|
|
||||||
|
|
||||||
cchWrittenWideChar = MultiByteToWideChar(CP_ACP, 0, &helper->rDlls[0], -1, szDllName, ARRAYSIZE(szDllName));
|
|
||||||
if (cchWrittenWideChar >= ARRAYSIZE(szDllName) || cchWrittenWideChar <= 0) {
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand),
|
hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand),
|
||||||
L"rundll32.exe \"%s\",#1", szDllName);
|
L"rundll32.exe \"%hs\",#1", &helper->rDlls[0]);
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -1503,13 +1285,15 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
||||||
DETOUR_EXE_HELPER_GUID,
|
DETOUR_EXE_HELPER_GUID,
|
||||||
helper, helper->cb)) {
|
helper, helper->cb)) {
|
||||||
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
|
||||||
TerminateProcess(pi.hProcess, ~0u);
|
TerminateProcess(pi.hProcess, ~0u);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResumeThread(pi.hThread);
|
||||||
|
|
||||||
ResumeThread(pi.hThread);
|
ResumeThread(pi.hThread);
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
@ -1520,13 +1304,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
if (dwResult != 0) {
|
if (dwResult != 0) {
|
||||||
DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult));
|
DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
Result = TRUE;
|
Result = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError()));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,27 +18,6 @@
|
||||||
|
|
||||||
#define NOTHROW
|
#define NOTHROW
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
|
||||||
int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg)
|
|
||||||
{
|
|
||||||
int nRet = 0;
|
|
||||||
DWORD dwLastError = GetLastError();
|
|
||||||
CHAR szModuleNameWithFunctionName[MAX_PATH * 2];
|
|
||||||
szModuleNameWithFunctionName[0] = 0;
|
|
||||||
GetModuleFileNameA((HMODULE)&__ImageBase, szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName));
|
|
||||||
StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), ",", ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1);
|
|
||||||
StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), FunctionName, ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1);
|
|
||||||
SetLastError(dwLastError);
|
|
||||||
nRet = _CrtDbgReport(reportType, filename, linenumber, szModuleNameWithFunctionName, msg);
|
|
||||||
SetLastError(dwLastError);
|
|
||||||
return nRet;
|
|
||||||
}
|
|
||||||
#endif// _DEBUG
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct _DETOUR_ALIGN
|
struct _DETOUR_ALIGN
|
||||||
|
@ -207,7 +186,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
// We have to place trampolines within +/- 2GB of code.
|
// We have to place trampolines within +/- 2GB of code.
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
||||||
DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi));
|
||||||
|
|
||||||
// And, within +/- 2GB of relative jmp targets.
|
// And, within +/- 2GB of relative jmp targets.
|
||||||
if (pbCode[0] == 0xe9) { // jmp +imm32
|
if (pbCode[0] == 0xe9) { // jmp +imm32
|
||||||
|
@ -219,7 +198,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
else {
|
else {
|
||||||
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("[%p..%p..%p] +imm32\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi));
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
||||||
|
@ -420,7 +399,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
// We have to place trampolines within +/- 2GB of code.
|
// We have to place trampolines within +/- 2GB of code.
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
||||||
DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi));
|
||||||
|
|
||||||
// And, within +/- 2GB of relative jmp vectors.
|
// And, within +/- 2GB of relative jmp vectors.
|
||||||
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
|
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
|
||||||
|
@ -432,7 +411,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
else {
|
else {
|
||||||
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", lo, pbCode, hi));
|
||||||
}
|
}
|
||||||
// And, within +/- 2GB of relative jmp targets.
|
// And, within +/- 2GB of relative jmp targets.
|
||||||
else if (pbCode[0] == 0xe9) { // jmp +imm32
|
else if (pbCode[0] == 0xe9) { // jmp +imm32
|
||||||
|
@ -444,7 +423,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
else {
|
else {
|
||||||
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("[%p..%p..%p] +imm32\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi));
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
||||||
|
@ -839,7 +818,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
// We have to place trampolines within +/- 2GB of code.
|
// We have to place trampolines within +/- 2GB of code.
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
||||||
DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi));
|
||||||
|
|
||||||
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
||||||
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
||||||
|
@ -1145,7 +1124,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
|
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
|
||||||
DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi));
|
DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi));
|
||||||
|
|
||||||
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
||||||
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
||||||
|
@ -1258,7 +1237,7 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" Try %p => %p..%p %6lx\n",
|
DETOUR_TRACE((" Try %p => %p..%p %6x\n",
|
||||||
pbTry,
|
pbTry,
|
||||||
mbi.BaseAddress,
|
mbi.BaseAddress,
|
||||||
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
||||||
|
@ -1273,9 +1252,6 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi)
|
||||||
if (pv != NULL) {
|
if (pv != NULL) {
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
else if (GetLastError() == ERROR_DYNAMIC_CODE_BLOCKED) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pbTry += DETOUR_REGION_SIZE;
|
pbTry += DETOUR_REGION_SIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1308,7 +1284,7 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" Try %p => %p..%p %6lx\n",
|
DETOUR_TRACE((" Try %p => %p..%p %6x\n",
|
||||||
pbTry,
|
pbTry,
|
||||||
mbi.BaseAddress,
|
mbi.BaseAddress,
|
||||||
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
||||||
|
@ -1323,9 +1299,6 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
|
||||||
if (pv != NULL) {
|
if (pv != NULL) {
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
else if (GetLastError() == ERROR_DYNAMIC_CODE_BLOCKED) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pbTry -= DETOUR_REGION_SIZE;
|
pbTry -= DETOUR_REGION_SIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1725,7 +1698,7 @@ LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer)
|
||||||
#endif // DETOURS_ARM
|
#endif // DETOURS_ARM
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%u\n",
|
DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%d\n",
|
||||||
o->pTrampoline,
|
o->pTrampoline,
|
||||||
o->pTrampoline->pbRemain,
|
o->pTrampoline->pbRemain,
|
||||||
o->pTrampoline->pbDetour,
|
o->pTrampoline->pbDetour,
|
||||||
|
@ -2017,13 +1990,13 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
|
if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
|
||||||
DETOUR_TRACE(("transaction conflict with thread id=%ld\n", s_nPendingThreadId));
|
DETOUR_TRACE(("transaction conflict with thread id=%d\n", s_nPendingThreadId));
|
||||||
return ERROR_INVALID_OPERATION;
|
return ERROR_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any of the pending operations failed, then we don't need to do this.
|
// If any of the pending operations failed, then we don't need to do this.
|
||||||
if (s_nPendingError != NO_ERROR) {
|
if (s_nPendingError != NO_ERROR) {
|
||||||
DETOUR_TRACE(("pending transaction error=%ld\n", s_nPendingError));
|
DETOUR_TRACE(("pending transaction error=%d\n", s_nPendingError));
|
||||||
return s_nPendingError;
|
return s_nPendingError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2204,7 +2177,7 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
|
||||||
pTrampoline->rAlign[n].obTrampoline == 0) {
|
pTrampoline->rAlign[n].obTrampoline == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE((" %u/%u",
|
DETOUR_TRACE((" %d/%d",
|
||||||
pTrampoline->rAlign[n].obTarget,
|
pTrampoline->rAlign[n].obTarget,
|
||||||
pTrampoline->rAlign[n].obTrampoline
|
pTrampoline->rAlign[n].obTrampoline
|
||||||
));
|
));
|
||||||
|
@ -2572,20 +2545,4 @@ BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress,
|
||||||
pAddress, nSize, dwNewProtect, pdwOldProtect);
|
pAddress, nSize, dwNewProtect, pdwOldProtect);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
left.Data1 == right.Data1 &&
|
|
||||||
left.Data2 == right.Data2 &&
|
|
||||||
left.Data3 == right.Data3 &&
|
|
||||||
left.Data4[0] == right.Data4[0] &&
|
|
||||||
left.Data4[1] == right.Data4[1] &&
|
|
||||||
left.Data4[2] == right.Data4[2] &&
|
|
||||||
left.Data4[3] == right.Data4[3] &&
|
|
||||||
left.Data4[4] == right.Data4[4] &&
|
|
||||||
left.Data4[5] == right.Data4[5] &&
|
|
||||||
left.Data4[6] == right.Data4[6] &&
|
|
||||||
left.Data4[7] == right.Data4[7];
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of File
|
// End of File
|
||||||
|
|
|
@ -28,15 +28,6 @@
|
||||||
#pragma warning(disable:4091) // empty typedef
|
#pragma warning(disable:4091) // empty typedef
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Suppress declspec(dllimport) for the sake of Detours
|
|
||||||
// users that provide kernel32 functionality themselves.
|
|
||||||
// This is ok in the mainstream case, it will just cost
|
|
||||||
// an extra instruction calling some functions, which
|
|
||||||
// LTCG optimizes away.
|
|
||||||
//
|
|
||||||
#define _KERNEL32_ 1
|
|
||||||
#define _USER32_ 1
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#if (_MSC_VER < 1310)
|
#if (_MSC_VER < 1310)
|
||||||
#else
|
#else
|
||||||
|
@ -45,28 +36,8 @@
|
||||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||||
#endif
|
#endif
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <intsafe.h>
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
#include <crtdbg.h>
|
|
||||||
|
|
||||||
// Allow Detours to cleanly compile with the MingW toolchain.
|
|
||||||
//
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define __try
|
|
||||||
#define __except(x) if (0)
|
|
||||||
#include <strsafe.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// From winerror.h, as this error isn't found in some SDKs:
|
|
||||||
//
|
|
||||||
// MessageId: ERROR_DYNAMIC_CODE_BLOCKED
|
|
||||||
//
|
|
||||||
// MessageText:
|
|
||||||
//
|
|
||||||
// The operation was blocked as the process prohibits dynamic code generation.
|
|
||||||
//
|
|
||||||
#define ERROR_DYNAMIC_CODE_BLOCKED 1655L
|
|
||||||
|
|
||||||
#endif // DETOURS_INTERNAL
|
#endif // DETOURS_INTERNAL
|
||||||
|
|
||||||
|
@ -128,7 +99,7 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
#if (_MSC_VER < 1299) && !defined(__MINGW32__)
|
#if (_MSC_VER < 1299)
|
||||||
typedef LONG LONG_PTR;
|
typedef LONG LONG_PTR;
|
||||||
typedef ULONG ULONG_PTR;
|
typedef ULONG ULONG_PTR;
|
||||||
#endif
|
#endif
|
||||||
|
@ -149,7 +120,6 @@ typedef ULONG ULONG_PTR;
|
||||||
#undef _In_
|
#undef _In_
|
||||||
#undef _In_bytecount_
|
#undef _In_bytecount_
|
||||||
#undef _In_count_
|
#undef _In_count_
|
||||||
#undef __in_ecount
|
|
||||||
#undef _In_opt_
|
#undef _In_opt_
|
||||||
#undef _In_opt_bytecount_
|
#undef _In_opt_bytecount_
|
||||||
#undef _In_opt_count_
|
#undef _In_opt_count_
|
||||||
|
@ -206,10 +176,6 @@ typedef ULONG ULONG_PTR;
|
||||||
#define _In_count_(x)
|
#define _In_count_(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __in_ecount
|
|
||||||
#define __in_ecount(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _In_opt_
|
#ifndef _In_opt_
|
||||||
#define _In_opt_
|
#define _In_opt_
|
||||||
#endif
|
#endif
|
||||||
|
@ -615,17 +581,16 @@ _Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_Out_opt_ DWORD *pcbData);
|
_Out_ DWORD *pcbData);
|
||||||
|
|
||||||
_Writable_bytes_(*pcbData)
|
_Writable_bytes_(*pcbData)
|
||||||
_Readable_bytes_(*pcbData)
|
_Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||||
_Out_opt_ DWORD *pcbData);
|
_Out_ DWORD * pcbData);
|
||||||
|
|
||||||
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule);
|
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule);
|
||||||
|
|
||||||
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData);
|
|
||||||
///////////////////////////////////////////////// Persistent Binary Functions.
|
///////////////////////////////////////////////// Persistent Binary Functions.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -664,11 +629,6 @@ BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary);
|
||||||
|
|
||||||
/////////////////////////////////////////////////// Create Process & Load Dll.
|
/////////////////////////////////////////////////// Create Process & Load Dll.
|
||||||
//
|
//
|
||||||
_Success_(return != NULL)
|
|
||||||
PVOID WINAPI DetourFindRemotePayload(_In_ HANDLE hProcess,
|
|
||||||
_In_ REFGUID rguid,
|
|
||||||
_Out_opt_ DWORD *pcbData);
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)(
|
typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)(
|
||||||
_In_opt_ LPCSTR lpApplicationName,
|
_In_opt_ LPCSTR lpApplicationName,
|
||||||
_Inout_opt_ LPSTR lpCommandLine,
|
_Inout_opt_ LPSTR lpCommandLine,
|
||||||
|
@ -835,14 +795,8 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
|
|
||||||
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_In_reads_bytes_(cbData) LPCVOID pvData,
|
_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
_In_ DWORD cbData);
|
_In_ DWORD cbData);
|
||||||
_Success_(return != NULL)
|
|
||||||
PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
|
|
||||||
_In_ REFGUID rguid,
|
|
||||||
_In_reads_bytes_(cbData) LPCVOID pvData,
|
|
||||||
_In_ DWORD cbData);
|
|
||||||
|
|
||||||
BOOL WINAPI DetourRestoreAfterWith(VOID);
|
BOOL WINAPI DetourRestoreAfterWith(VOID);
|
||||||
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
_In_ DWORD cbData);
|
_In_ DWORD cbData);
|
||||||
|
@ -858,60 +812,6 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
}
|
}
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
/////////////////////////////////////////////////// Type-safe overloads for C++
|
|
||||||
//
|
|
||||||
#if __cplusplus >= 201103L || _MSVC_LANG >= 201103L
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct DetoursIsFunctionPointer : std::false_type {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct DetoursIsFunctionPointer<T*> : std::is_function<typename std::remove_pointer<T>::type> {};
|
|
||||||
|
|
||||||
template<
|
|
||||||
typename T,
|
|
||||||
typename std::enable_if<DetoursIsFunctionPointer<T>::value, int>::type = 0>
|
|
||||||
LONG DetourAttach(_Inout_ T *ppPointer,
|
|
||||||
_In_ T pDetour) noexcept
|
|
||||||
{
|
|
||||||
return DetourAttach(
|
|
||||||
reinterpret_cast<void**>(ppPointer),
|
|
||||||
reinterpret_cast<void*>(pDetour));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
|
||||||
typename T,
|
|
||||||
typename std::enable_if<DetoursIsFunctionPointer<T>::value, int>::type = 0>
|
|
||||||
LONG DetourAttachEx(_Inout_ T *ppPointer,
|
|
||||||
_In_ T pDetour,
|
|
||||||
_Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline,
|
|
||||||
_Out_opt_ T *ppRealTarget,
|
|
||||||
_Out_opt_ T *ppRealDetour) noexcept
|
|
||||||
{
|
|
||||||
return DetourAttachEx(
|
|
||||||
reinterpret_cast<void**>(ppPointer),
|
|
||||||
reinterpret_cast<void*>(pDetour),
|
|
||||||
ppRealTrampoline,
|
|
||||||
reinterpret_cast<void**>(ppRealTarget),
|
|
||||||
reinterpret_cast<void**>(ppRealDetour));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
|
||||||
typename T,
|
|
||||||
typename std::enable_if<DetoursIsFunctionPointer<T>::value, int>::type = 0>
|
|
||||||
LONG DetourDetach(_Inout_ T *ppPointer,
|
|
||||||
_In_ T pDetour) noexcept
|
|
||||||
{
|
|
||||||
return DetourDetach(
|
|
||||||
reinterpret_cast<void**>(ppPointer),
|
|
||||||
reinterpret_cast<void*>(pDetour));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __cplusplus >= 201103L || _MSVC_LANG >= 201103L
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//////////////////////////////////////////////// Detours Internal Definitions.
|
//////////////////////////////////////////////// Detours Internal Definitions.
|
||||||
//
|
//
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -922,7 +822,7 @@ LONG DetourDetach(_Inout_ T *ppPointer,
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
#if (_MSC_VER < 1299) && !defined(__GNUC__)
|
#if (_MSC_VER < 1299)
|
||||||
#include <imagehlp.h>
|
#include <imagehlp.h>
|
||||||
typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
|
typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
|
||||||
typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
|
typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
|
||||||
|
@ -984,21 +884,6 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID);
|
||||||
#endif
|
#endif
|
||||||
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
|
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
|
|
||||||
int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg);
|
|
||||||
|
|
||||||
#define DETOUR_ASSERT_EXPR_WITH_FUNCTION(expr, msg) \
|
|
||||||
(void) ((expr) || \
|
|
||||||
(1 != Detour_AssertExprWithFunctionName(_CRT_ASSERT, __FILE__, __LINE__,__FUNCTION__, msg)) || \
|
|
||||||
(_CrtDbgBreak(), 0))
|
|
||||||
|
|
||||||
#define DETOUR_ASSERT(expr) DETOUR_ASSERT_EXPR_WITH_FUNCTION((expr), #expr)
|
|
||||||
|
|
||||||
#else// _DEBUG
|
|
||||||
#define DETOUR_ASSERT(expr)
|
|
||||||
#endif// _DEBUG
|
|
||||||
|
|
||||||
#ifndef DETOUR_TRACE
|
#ifndef DETOUR_TRACE
|
||||||
#if DETOUR_DEBUG
|
#if DETOUR_DEBUG
|
||||||
#define DETOUR_TRACE(x) printf x
|
#define DETOUR_TRACE(x) printf x
|
||||||
|
@ -1205,9 +1090,6 @@ BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress,
|
||||||
_In_ SIZE_T nSize,
|
_In_ SIZE_T nSize,
|
||||||
_In_ DWORD dwNewProtect,
|
_In_ DWORD dwNewProtect,
|
||||||
_Out_ PDWORD pdwOldProtect);
|
_Out_ PDWORD pdwOldProtect);
|
||||||
|
|
||||||
// Detours must depend only on kernel32.lib, so we cannot use IsEqualGUID
|
|
||||||
BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right);
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
1316
detours/disasm.cpp
1316
detours/disasm.cpp
File diff suppressed because it is too large
Load Diff
|
@ -146,8 +146,6 @@ protected:
|
||||||
DWORD m_cbAlloc;
|
DWORD m_cbAlloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CImageImportName;
|
|
||||||
|
|
||||||
class CImageImportFile
|
class CImageImportFile
|
||||||
{
|
{
|
||||||
friend class CImage;
|
friend class CImage;
|
||||||
|
@ -536,7 +534,18 @@ PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DetourAreSameGuid(pRecord->guid, rguid)) {
|
if (pRecord->guid.Data1 == rguid.Data1 &&
|
||||||
|
pRecord->guid.Data2 == rguid.Data2 &&
|
||||||
|
pRecord->guid.Data3 == rguid.Data3 &&
|
||||||
|
pRecord->guid.Data4[0] == rguid.Data4[0] &&
|
||||||
|
pRecord->guid.Data4[1] == rguid.Data4[1] &&
|
||||||
|
pRecord->guid.Data4[2] == rguid.Data4[2] &&
|
||||||
|
pRecord->guid.Data4[3] == rguid.Data4[3] &&
|
||||||
|
pRecord->guid.Data4[4] == rguid.Data4[4] &&
|
||||||
|
pRecord->guid.Data4[5] == rguid.Data4[5] &&
|
||||||
|
pRecord->guid.Data4[6] == rguid.Data4[6] &&
|
||||||
|
pRecord->guid.Data4[7] == rguid.Data4[7]) {
|
||||||
|
|
||||||
*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
|
*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
|
||||||
return (PBYTE)(pRecord + 1);
|
return (PBYTE)(pRecord + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
const GUID DETOUR_EXE_RESTORE_GUID = {
|
const GUID DETOUR_EXE_RESTORE_GUID = {
|
||||||
0xbda26f34, 0xbc82, 0x4829,
|
0x2ed7a3ff, 0x3339, 0x4a8d,
|
||||||
{ 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } };
|
{ 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -142,11 +142,6 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
|
||||||
PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
_In_ LPCSTR pszFunction)
|
_In_ LPCSTR pszFunction)
|
||||||
{
|
{
|
||||||
if (pszFunction == NULL) {
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////// First, try GetProcAddress.
|
/////////////////////////////////////////////// First, try GetProcAddress.
|
||||||
//
|
//
|
||||||
#pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
|
#pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
|
||||||
|
@ -165,7 +160,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
|
DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
|
||||||
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
|
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
|
||||||
if (pSymInfo == NULL) {
|
if (pSymInfo == NULL) {
|
||||||
DETOUR_TRACE(("DetourLoadImageHlp failed: %lu\n",
|
DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +169,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
(PCHAR)pszModule, NULL,
|
(PCHAR)pszModule, NULL,
|
||||||
(DWORD64)hModule, 0) == 0) {
|
(DWORD64)hModule, 0) == 0) {
|
||||||
if (ERROR_SUCCESS != GetLastError()) {
|
if (ERROR_SUCCESS != GetLastError()) {
|
||||||
DETOUR_TRACE(("SymLoadModule64(%p) failed: %lu\n",
|
DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n",
|
||||||
pSymInfo->hProcess, GetLastError()));
|
pSymInfo->hProcess, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -186,24 +181,24 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
ZeroMemory(&modinfo, sizeof(modinfo));
|
ZeroMemory(&modinfo, sizeof(modinfo));
|
||||||
modinfo.SizeOfStruct = sizeof(modinfo);
|
modinfo.SizeOfStruct = sizeof(modinfo);
|
||||||
if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
|
if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
|
||||||
DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %lu\n",
|
DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %d\n",
|
||||||
pSymInfo->hProcess, hModule, GetLastError()));
|
pSymInfo->hProcess, hModule, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
|
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
|
DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
|
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
|
DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
|
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
|
DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +215,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
|
if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
|
||||||
DETOUR_TRACE(("SymFromName(%hs) failed: %lu\n", szFullName, GetLastError()));
|
DETOUR_TRACE(("SymFromName(%hs) failed: %d\n", szFullName, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +277,6 @@ HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastError(NO_ERROR);
|
|
||||||
return (HMODULE)pDosHeader;
|
return (HMODULE)pDosHeader;
|
||||||
}
|
}
|
||||||
#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
|
#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
|
||||||
|
@ -346,7 +340,7 @@ PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastError(NO_ERROR);
|
SetLastError(NO_ERROR);
|
||||||
return (PVOID)GetProcAddress(hClr, "_CorExeMain");
|
return GetProcAddress(hClr, "_CorExeMain");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastError(NO_ERROR);
|
SetLastError(NO_ERROR);
|
||||||
|
@ -462,11 +456,6 @@ BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
|
||||||
_In_opt_ PVOID pContext,
|
_In_opt_ PVOID pContext,
|
||||||
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
|
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
|
||||||
{
|
{
|
||||||
if (pfExport == NULL) {
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||||
if (hModule == NULL) {
|
if (hModule == NULL) {
|
||||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
||||||
|
@ -669,11 +658,6 @@ BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
|
||||||
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
|
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
|
||||||
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
|
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
|
||||||
{
|
{
|
||||||
if (pfImportFile == NULL || pfImportFunc == NULL) {
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
|
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
|
||||||
|
|
||||||
return DetourEnumerateImportsEx(hModule,
|
return DetourEnumerateImportsEx(hModule,
|
||||||
|
@ -777,7 +761,7 @@ _Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_Out_opt_ DWORD *pcbData)
|
_Out_ DWORD *pcbData)
|
||||||
{
|
{
|
||||||
PBYTE pbData = NULL;
|
PBYTE pbData = NULL;
|
||||||
if (pcbData) {
|
if (pcbData) {
|
||||||
|
@ -805,13 +789,24 @@ PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||||
for (pbData = pbBeg; pbData < pbEnd;) {
|
for (pbData = pbBeg; pbData < pbEnd;) {
|
||||||
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
|
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
|
||||||
|
|
||||||
if (DetourAreSameGuid(pSection->guid, rguid)) {
|
if (pSection->guid.Data1 == rguid.Data1 &&
|
||||||
|
pSection->guid.Data2 == rguid.Data2 &&
|
||||||
|
pSection->guid.Data3 == rguid.Data3 &&
|
||||||
|
pSection->guid.Data4[0] == rguid.Data4[0] &&
|
||||||
|
pSection->guid.Data4[1] == rguid.Data4[1] &&
|
||||||
|
pSection->guid.Data4[2] == rguid.Data4[2] &&
|
||||||
|
pSection->guid.Data4[3] == rguid.Data4[3] &&
|
||||||
|
pSection->guid.Data4[4] == rguid.Data4[4] &&
|
||||||
|
pSection->guid.Data4[5] == rguid.Data4[5] &&
|
||||||
|
pSection->guid.Data4[6] == rguid.Data4[6] &&
|
||||||
|
pSection->guid.Data4[7] == rguid.Data4[7]) {
|
||||||
|
|
||||||
if (pcbData) {
|
if (pcbData) {
|
||||||
*pcbData = pSection->cbBytes - sizeof(*pSection);
|
*pcbData = pSection->cbBytes - sizeof(*pSection);
|
||||||
}
|
|
||||||
SetLastError(NO_ERROR);
|
SetLastError(NO_ERROR);
|
||||||
return (PBYTE)(pSection + 1);
|
return (PBYTE)(pSection + 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pbData = (PBYTE)pSection + pSection->cbBytes;
|
pbData = (PBYTE)pSection + pSection->cbBytes;
|
||||||
}
|
}
|
||||||
|
@ -829,7 +824,7 @@ _Writable_bytes_(*pcbData)
|
||||||
_Readable_bytes_(*pcbData)
|
_Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||||
_Out_opt_ DWORD *pcbData)
|
_Out_ DWORD * pcbData)
|
||||||
{
|
{
|
||||||
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
|
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
|
||||||
PVOID pvData;
|
PVOID pvData;
|
||||||
|
@ -843,24 +838,6 @@ PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData)
|
|
||||||
{
|
|
||||||
BOOL fSucceeded = FALSE;
|
|
||||||
|
|
||||||
// If you have any doubts about the following code, please refer to the comments in DetourCopyPayloadToProcess.
|
|
||||||
HMODULE hModule = DetourGetContainingModule(pvData);
|
|
||||||
DETOUR_ASSERT(hModule != NULL);
|
|
||||||
if (hModule != NULL) {
|
|
||||||
fSucceeded = VirtualFree(hModule, 0, MEM_RELEASE);
|
|
||||||
DETOUR_ASSERT(fSucceeded);
|
|
||||||
if (fSucceeded) {
|
|
||||||
hModule = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fSucceeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
_In_ DWORD cbData)
|
_In_ DWORD cbData)
|
||||||
{
|
{
|
||||||
|
@ -907,11 +884,6 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
}
|
}
|
||||||
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
|
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
|
||||||
}
|
}
|
||||||
// Delete the payload after successful recovery to prevent repeated restore
|
|
||||||
if (fSucceeded) {
|
|
||||||
DetourFreePayload(pder);
|
|
||||||
pder = NULL;
|
|
||||||
}
|
|
||||||
return fSucceeded;
|
return fSucceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|
||||||
|| cbRead < sizeof(idh)) {
|
|| cbRead < sizeof(idh)) {
|
||||||
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n",
|
||||||
pbModule, pbModule + sizeof(idh), GetLastError()));
|
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
@ -51,7 +51,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|
||||||
|| cbRead < sizeof(inh)) {
|
|| cbRead < sizeof(inh)) {
|
||||||
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n",
|
||||||
pbModule + idh.e_lfanew,
|
pbModule + idh.e_lfanew,
|
||||||
pbModule + idh.e_lfanew + sizeof(inh),
|
pbModule + idh.e_lfanew + sizeof(inh),
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
|
@ -82,21 +82,16 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
sizeof(ish), &cbRead)
|
sizeof(ish), &cbRead)
|
||||||
|| cbRead < sizeof(ish)) {
|
|| cbRead < sizeof(ish)) {
|
||||||
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n",
|
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n",
|
||||||
pbModule + dwSec + sizeof(ish) * i,
|
pbModule + dwSec + sizeof(ish) * i,
|
||||||
pbModule + dwSec + sizeof(ish) * (i + 1),
|
pbModule + dwSec + sizeof(ish) * (i + 1),
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData));
|
DETOUR_TRACE(("ish[%d] : va=%08x sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData));
|
||||||
|
|
||||||
// If the linker didn't suggest an IAT in the data directories, the
|
// If the file didn't have an IAT_DIRECTORY, we assign it...
|
||||||
// loader will look for the section of the import directory to be used
|
|
||||||
// for this instead. Since we put out new IMPORT_DIRECTORY outside any
|
|
||||||
// section boundary, the loader will not find it. So we provide one
|
|
||||||
// explicitly to avoid the search.
|
|
||||||
//
|
|
||||||
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
|
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
|
||||||
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
|
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
|
||||||
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
|
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
|
||||||
|
@ -106,78 +101,25 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0 && inh.IMPORT_DIRECTORY.Size == 0) {
|
|
||||||
|
|
||||||
// Don't worry about changing the PE file,
|
|
||||||
// because the load information of the original PE header has been saved and will be restored.
|
|
||||||
// The change here is just for the following code to work normally
|
|
||||||
|
|
||||||
PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + inh.IMPORT_DIRECTORY.VirtualAddress);
|
|
||||||
|
|
||||||
do {
|
|
||||||
IMAGE_IMPORT_DESCRIPTOR ImageImport;
|
|
||||||
if (!ReadProcessMemory(hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) {
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory failed: %lu\n", GetLastError()));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
inh.IMPORT_DIRECTORY.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
|
||||||
if (!ImageImport.Name) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++pImageImport;
|
|
||||||
} while (TRUE);
|
|
||||||
|
|
||||||
DWORD dwLastError = GetLastError();
|
|
||||||
OutputDebugString(TEXT("[This PE file has an import table, but the import table size is marked as 0. This is an error.")
|
|
||||||
TEXT("If it is not repaired, the launched program will not work properly, Detours has automatically repaired its import table size for you! ! !]\r\n"));
|
|
||||||
if (GetLastError() != dwLastError) {
|
|
||||||
SetLastError(dwLastError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_TRACE((" Imports: %p..%p\n",
|
DETOUR_TRACE((" Imports: %p..%p\n",
|
||||||
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||||
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
|
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
|
||||||
inh.IMPORT_DIRECTORY.Size));
|
inh.IMPORT_DIRECTORY.Size));
|
||||||
|
|
||||||
// Calculate new import directory size. Note that since inh is from another
|
|
||||||
// process, inh could have been corrupted. We need to protect against
|
|
||||||
// integer overflow in allocation calculations.
|
|
||||||
DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
||||||
DWORD obRem;
|
DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls;
|
||||||
if (DWordMult(sizeof(IMAGE_IMPORT_DESCRIPTOR), nDlls, &obRem) != S_OK) {
|
DWORD obOld = obRem + sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls;
|
||||||
DETOUR_TRACE(("too many new DLLs.\n"));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
DWORD obOld;
|
|
||||||
if (DWordAdd(obRem, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls, &obOld) != S_OK) {
|
|
||||||
DETOUR_TRACE(("DLL entries overflow.\n"));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
DWORD obTab = PadToDwordPtr(obOld);
|
DWORD obTab = PadToDwordPtr(obOld);
|
||||||
// Check for integer overflow.
|
DWORD obDll = obTab + sizeof(DWORD_XX) * 4 * nDlls;
|
||||||
if (obTab < obOld) {
|
|
||||||
DETOUR_TRACE(("DLL entries padding overflow.\n"));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
DWORD stSize;
|
|
||||||
if (DWordMult(sizeof(DWORD_XX) * 4, nDlls, &stSize) != S_OK) {
|
|
||||||
DETOUR_TRACE(("String table overflow.\n"));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
DWORD obDll;
|
|
||||||
if (DWordAdd(obTab, stSize, &obDll) != S_OK) {
|
|
||||||
DETOUR_TRACE(("Import table size overflow\n"));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
DWORD obStr = obDll;
|
DWORD obStr = obDll;
|
||||||
cbNew = obStr;
|
cbNew = obStr;
|
||||||
for (n = 0; n < nDlls; n++) {
|
for (n = 0; n < nDlls; n++) {
|
||||||
if (DWordAdd(cbNew, PadToDword((DWORD)strlen(plpDlls[n]) + 1), &cbNew) != S_OK) {
|
cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
|
||||||
DETOUR_TRACE(("Overflow adding string table entry\n"));
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Analysis_assume_(cbNew >
|
||||||
|
sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nDlls + nOldDlls)
|
||||||
|
+ sizeof(DWORD_XX) * 4 * nDlls);
|
||||||
pbNew = new BYTE [cbNew];
|
pbNew = new BYTE [cbNew];
|
||||||
if (pbNew == NULL) {
|
if (pbNew == NULL) {
|
||||||
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
|
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
|
||||||
|
@ -203,14 +145,14 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
}
|
}
|
||||||
|
|
||||||
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
|
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
|
||||||
IMAGE_THUNK_DATAXX *pt = NULL;
|
DWORD_XX *pt;
|
||||||
|
|
||||||
DWORD obBase = (DWORD)(pbNewIid - pbModule);
|
DWORD obBase = (DWORD)(pbNewIid - pbModule);
|
||||||
DWORD dwProtect = 0;
|
DWORD dwProtect = 0;
|
||||||
|
|
||||||
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
|
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
|
||||||
// Read the old import directory if it exists.
|
// Read the old import directory if it exists.
|
||||||
DETOUR_TRACE(("IMPORT_DIRECTORY perms=%lx\n", dwProtect));
|
DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect));
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess,
|
if (!ReadProcessMemory(hProcess,
|
||||||
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||||
|
@ -218,7 +160,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|
||||||
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
|
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
|
||||||
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +168,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
for (n = 0; n < nDlls; n++) {
|
for (n = 0; n < nDlls; n++) {
|
||||||
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
|
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
|
DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,24 +177,21 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
cbNew - obStr,
|
cbNew - obStr,
|
||||||
DETOURS_STRINGIFY(DETOURS_BITS_XX));
|
DETOURS_STRINGIFY(DETOURS_BITS_XX));
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet));
|
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n));
|
DWORD nOffset = obTab + (sizeof(DWORD_XX) * (4 * n));
|
||||||
piid[n].OriginalFirstThunk = obBase + nOffset;
|
piid[n].OriginalFirstThunk = obBase + nOffset;
|
||||||
|
pt = ((DWORD_XX*)(pbNew + nOffset));
|
||||||
|
pt[0] = IMAGE_ORDINAL_FLAG_XX + 1;
|
||||||
|
pt[1] = 0;
|
||||||
|
|
||||||
// We need 2 thunks for the import table and 2 thunks for the IAT.
|
nOffset = obTab + (sizeof(DWORD_XX) * ((4 * n) + 2));
|
||||||
// One for an ordinal import and one to mark the end of the list.
|
|
||||||
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
|
|
||||||
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
|
|
||||||
pt[1].u1.Ordinal = 0;
|
|
||||||
|
|
||||||
nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * ((4 * n) + 2));
|
|
||||||
piid[n].FirstThunk = obBase + nOffset;
|
piid[n].FirstThunk = obBase + nOffset;
|
||||||
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
|
pt = ((DWORD_XX*)(pbNew + nOffset));
|
||||||
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
|
pt[0] = IMAGE_ORDINAL_FLAG_XX + 1;
|
||||||
pt[1].u1.Ordinal = 0;
|
pt[1] = 0;
|
||||||
piid[n].TimeDateStamp = 0;
|
piid[n].TimeDateStamp = 0;
|
||||||
piid[n].ForwarderChain = 0;
|
piid[n].ForwarderChain = 0;
|
||||||
piid[n].Name = obBase + obStr;
|
piid[n].Name = obBase + obStr;
|
||||||
|
@ -277,19 +216,16 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
|
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(iid) failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE(("obBaseBef = %08lx..%08lx\n",
|
DETOUR_TRACE(("obBaseBef = %08x..%08x\n",
|
||||||
inh.IMPORT_DIRECTORY.VirtualAddress,
|
inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||||
inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
|
inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
|
||||||
DETOUR_TRACE(("obBaseAft = %08lx..%08lx\n", obBase, obBase + obStr));
|
DETOUR_TRACE(("obBaseAft = %08x..%08x\n", obBase, obBase + obStr));
|
||||||
|
|
||||||
// In this case the file didn't have an import directory in first place,
|
// If the file doesn't have an IAT_DIRECTORY, we create it...
|
||||||
// so we couldn't fix the missing IAT above. We still need to explicitly
|
|
||||||
// provide an IAT to prevent to loader from looking for one.
|
|
||||||
//
|
|
||||||
if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
|
if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
|
||||||
inh.IAT_DIRECTORY.VirtualAddress = obBase;
|
inh.IAT_DIRECTORY.VirtualAddress = obBase;
|
||||||
inh.IAT_DIRECTORY.Size = cbNew;
|
inh.IAT_DIRECTORY.Size = cbNew;
|
||||||
|
@ -302,20 +238,20 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
//
|
//
|
||||||
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
||||||
PAGE_EXECUTE_READWRITE, &dwProtect)) {
|
PAGE_EXECUTE_READWRITE, &dwProtect)) {
|
||||||
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
inh.OptionalHeader.CheckSum = 0;
|
inh.OptionalHeader.CheckSum = 0;
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
|
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
|
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(inh) failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
|
DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
|
||||||
|
@ -324,7 +260,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
|
|
||||||
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
||||||
dwProtect, &dwProtect)) {
|
dwProtect, &dwProtect)) {
|
||||||
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError()));
|
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %d\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -812,25 +812,11 @@ ISteamHTTP *Steam_Client::GetISteamHTTP( HSteamUser hSteamuser, HSteamPipe hStea
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("GetISteamHTTP %s\n", pchVersion);
|
PRINT_DEBUG("GetISteamHTTP %s\n", pchVersion);
|
||||||
if (!steam_pipes.count(hSteamPipe) || !hSteamuser) return NULL;
|
if (!steam_pipes.count(hSteamPipe) || !hSteamuser) return NULL;
|
||||||
Steam_HTTP *steam_http_temp;
|
|
||||||
|
|
||||||
if (steam_pipes[hSteamPipe] == Steam_Pipe::SERVER) {
|
if (steam_pipes[hSteamPipe] == Steam_Pipe::SERVER) {
|
||||||
steam_http_temp = steam_gameserver_http;
|
return steam_gameserver_http;
|
||||||
} else {
|
|
||||||
steam_http_temp = steam_http;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(pchVersion, "STEAMHTTP_INTERFACE_VERSION001") == 0) {
|
return steam_http;
|
||||||
return (ISteamHTTP *)(void *)(ISteamHTTP001 *)steam_http_temp;
|
|
||||||
} else if (strcmp(pchVersion, "STEAMHTTP_INTERFACE_VERSION002") == 0) {
|
|
||||||
return (ISteamHTTP *)(void *)(ISteamHTTP002 *)steam_http_temp;
|
|
||||||
} else if (strcmp(pchVersion, STEAMHTTP_INTERFACE_VERSION) == 0) {
|
|
||||||
return (ISteamHTTP *)(void *)(ISteamHTTP *)steam_http_temp;
|
|
||||||
} else {
|
|
||||||
return (ISteamHTTP *)(void *)(ISteamHTTP *)steam_http_temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return steam_http_temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated - the ISteamUnifiedMessages interface is no longer intended for public consumption.
|
// Deprecated - the ISteamUnifiedMessages interface is no longer intended for public consumption.
|
||||||
|
|
|
@ -25,10 +25,7 @@ struct Steam_Http_Request {
|
||||||
std::string response;
|
std::string response;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Steam_HTTP :
|
class Steam_HTTP : public ISteamHTTP
|
||||||
public ISteamHTTP001,
|
|
||||||
public ISteamHTTP002,
|
|
||||||
public ISteamHTTP
|
|
||||||
{
|
{
|
||||||
class Settings *settings;
|
class Settings *settings;
|
||||||
class Networking *network;
|
class Networking *network;
|
||||||
|
|
|
@ -623,10 +623,7 @@ bool GetItemDefinitionIDs(
|
||||||
|
|
||||||
PRINT_DEBUG("array_size %u\n", *punItemDefIDsArraySize);
|
PRINT_DEBUG("array_size %u\n", *punItemDefIDsArraySize);
|
||||||
|
|
||||||
if (!item_definitions_loaded)
|
if (pItemDefIDs == nullptr)
|
||||||
return false;
|
|
||||||
|
|
||||||
if (pItemDefIDs == nullptr || *punItemDefIDsArraySize == 0)
|
|
||||||
{
|
{
|
||||||
*punItemDefIDsArraySize = defined_items.size();
|
*punItemDefIDsArraySize = defined_items.size();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -657,8 +657,7 @@ void Steam_Overlay::OverlayProc()
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
||||||
if (!friends.empty())
|
if (!friends.empty())
|
||||||
{
|
{
|
||||||
if (ImGui::ListBoxHeader("##label", friends.size()))
|
ImGui::ListBoxHeader("##label", friends.size());
|
||||||
{
|
|
||||||
std::for_each(friends.begin(), friends.end(), [this](std::pair<Friend const, friend_window_state> &i)
|
std::for_each(friends.begin(), friends.end(), [this](std::pair<Friend const, friend_window_state> &i)
|
||||||
{
|
{
|
||||||
ImGui::PushID(i.second.id-base_friend_window_id+base_friend_item_id);
|
ImGui::PushID(i.second.id-base_friend_window_id+base_friend_item_id);
|
||||||
|
@ -676,7 +675,6 @@ void Steam_Overlay::OverlayProc()
|
||||||
ImGui::ListBoxFooter();
|
ImGui::ListBoxFooter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
#ifndef ISTEAMHTTP001_H
|
|
||||||
#define ISTEAMHTTP001_H
|
|
||||||
#ifdef STEAM_WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class ISteamHTTP001
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Initializes a new HTTP request, returning a handle to use in further operations on it. Requires
|
|
||||||
// the method (GET or POST) and the absolute URL for the request. Only http requests (ie, not https) are
|
|
||||||
// currently supported, so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/
|
|
||||||
// or such.
|
|
||||||
virtual HTTPRequestHandle CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL ) = 0;
|
|
||||||
|
|
||||||
// Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after
|
|
||||||
// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data.
|
|
||||||
virtual bool SetHTTPRequestContextValue( HTTPRequestHandle hRequest, uint64 ulContextValue ) = 0;
|
|
||||||
|
|
||||||
// Set a timeout in seconds for the HTTP request, must be called prior to sending the request. Default
|
|
||||||
// timeout is 60 seconds if you don't call this. Returns false if the handle is invalid, or the request
|
|
||||||
// has already been sent.
|
|
||||||
virtual bool SetHTTPRequestNetworkActivityTimeout( HTTPRequestHandle hRequest, uint32 unTimeoutSeconds ) = 0;
|
|
||||||
|
|
||||||
// Set a request header value for the request, must be called prior to sending the request. Will
|
|
||||||
// return false if the handle is invalid or the request is already sent.
|
|
||||||
virtual bool SetHTTPRequestHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, const char *pchHeaderValue ) = 0;
|
|
||||||
|
|
||||||
// Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified
|
|
||||||
// when creating the request. Must be called prior to sending the request. Will return false if the
|
|
||||||
// handle is invalid or the request is already sent.
|
|
||||||
virtual bool SetHTTPRequestGetOrPostParameter( HTTPRequestHandle hRequest, const char *pchParamName, const char *pchParamValue ) = 0;
|
|
||||||
|
|
||||||
// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on
|
|
||||||
// asyncronous response via callback.
|
|
||||||
//
|
|
||||||
// Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control
|
|
||||||
// header and only do a local cache lookup rather than sending any actual remote request.
|
|
||||||
virtual bool SendHTTPRequest( HTTPRequestHandle hRequest, SteamAPICall_t *pCallHandle ) = 0;
|
|
||||||
|
|
||||||
// Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move
|
|
||||||
// the specified request to the tail of the queue. Returns false on invalid handle, or if the request is not yet sent.
|
|
||||||
virtual bool DeferHTTPRequest( HTTPRequestHandle hRequest ) = 0;
|
|
||||||
|
|
||||||
// Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move
|
|
||||||
// the specified request to the head of the queue. Returns false on invalid handle, or if the request is not yet sent.
|
|
||||||
virtual bool PrioritizeHTTPRequest( HTTPRequestHandle hRequest ) = 0;
|
|
||||||
|
|
||||||
// Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also
|
|
||||||
// returns the size of the header value if present so the caller and allocate a correctly sized buffer for
|
|
||||||
// GetHTTPResponseHeaderValue.
|
|
||||||
virtual bool GetHTTPResponseHeaderSize( HTTPRequestHandle hRequest, const char *pchHeaderName, uint32 *unResponseHeaderSize ) = 0;
|
|
||||||
|
|
||||||
// Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
|
|
||||||
// header is not present or if your buffer is too small to contain it's value. You should first call
|
|
||||||
// BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed.
|
|
||||||
virtual bool GetHTTPResponseHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, uint8 *pHeaderValueBuffer, uint32 unBufferSize ) = 0;
|
|
||||||
|
|
||||||
// Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
|
|
||||||
// handle is invalid.
|
|
||||||
virtual bool GetHTTPResponseBodySize( HTTPRequestHandle hRequest, uint32 *unBodySize ) = 0;
|
|
||||||
|
|
||||||
// Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
|
|
||||||
// handle is invalid or if the provided buffer is not the correct size. Use BGetHTTPResponseBodySize first to find out
|
|
||||||
// the correct buffer size to use.
|
|
||||||
virtual bool GetHTTPResponseBodyData( HTTPRequestHandle hRequest, uint8 *pBodyDataBuffer, uint32 unBufferSize ) = 0;
|
|
||||||
|
|
||||||
// Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t
|
|
||||||
// callback and finishing using the response.
|
|
||||||
virtual bool ReleaseHTTPRequest( HTTPRequestHandle hRequest ) = 0;
|
|
||||||
|
|
||||||
// Gets progress on downloading the body for the request. This will be zero unless a response header has already been
|
|
||||||
// received which included a content-length field. For responses that contain no content-length it will report
|
|
||||||
// zero for the duration of the request as the size is unknown until the connection closes.
|
|
||||||
virtual bool GetHTTPDownloadProgressPct( HTTPRequestHandle hRequest, float *pflPercentOut ) = 0;
|
|
||||||
|
|
||||||
// Sets the body for an HTTP Post request. Will fail and return false on a GET request, and will fail if POST params
|
|
||||||
// have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType
|
|
||||||
// parameter will set the content-type header for the request so the server may know how to interpret the body.
|
|
||||||
virtual bool SetHTTPRequestRawPostBody( HTTPRequestHandle hRequest, const char *pchContentType, uint8 *pubBody, uint32 unBodyLen ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ISTEAMHTTP001_H
|
|
|
@ -1,124 +0,0 @@
|
||||||
|
|
||||||
#ifndef ISTEAMHTTP002_H
|
|
||||||
#define ISTEAMHTTP002_H
|
|
||||||
#ifdef STEAM_WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class ISteamHTTP002
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Initializes a new HTTP request, returning a handle to use in further operations on it. Requires
|
|
||||||
// the method (GET or POST) and the absolute URL for the request. Both http and https are supported,
|
|
||||||
// so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/
|
|
||||||
// or such.
|
|
||||||
virtual HTTPRequestHandle CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL ) = 0;
|
|
||||||
|
|
||||||
// Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after
|
|
||||||
// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data.
|
|
||||||
virtual bool SetHTTPRequestContextValue( HTTPRequestHandle hRequest, uint64 ulContextValue ) = 0;
|
|
||||||
|
|
||||||
// Set a timeout in seconds for the HTTP request, must be called prior to sending the request. Default
|
|
||||||
// timeout is 60 seconds if you don't call this. Returns false if the handle is invalid, or the request
|
|
||||||
// has already been sent.
|
|
||||||
virtual bool SetHTTPRequestNetworkActivityTimeout( HTTPRequestHandle hRequest, uint32 unTimeoutSeconds ) = 0;
|
|
||||||
|
|
||||||
// Set a request header value for the request, must be called prior to sending the request. Will
|
|
||||||
// return false if the handle is invalid or the request is already sent.
|
|
||||||
virtual bool SetHTTPRequestHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, const char *pchHeaderValue ) = 0;
|
|
||||||
|
|
||||||
// Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified
|
|
||||||
// when creating the request. Must be called prior to sending the request. Will return false if the
|
|
||||||
// handle is invalid or the request is already sent.
|
|
||||||
virtual bool SetHTTPRequestGetOrPostParameter( HTTPRequestHandle hRequest, const char *pchParamName, const char *pchParamValue ) = 0;
|
|
||||||
|
|
||||||
// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on
|
|
||||||
// asynchronous response via callback.
|
|
||||||
//
|
|
||||||
// Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control
|
|
||||||
// header and only do a local cache lookup rather than sending any actual remote request.
|
|
||||||
virtual bool SendHTTPRequest( HTTPRequestHandle hRequest, SteamAPICall_t *pCallHandle ) = 0;
|
|
||||||
|
|
||||||
// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on
|
|
||||||
// asynchronous response via callback for completion, and listen for HTTPRequestHeadersReceived_t and
|
|
||||||
// HTTPRequestDataReceived_t callbacks while streaming.
|
|
||||||
virtual bool SendHTTPRequestAndStreamResponse( HTTPRequestHandle hRequest, SteamAPICall_t *pCallHandle ) = 0;
|
|
||||||
|
|
||||||
// Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move
|
|
||||||
// the specified request to the tail of the queue. Returns false on invalid handle, or if the request is not yet sent.
|
|
||||||
virtual bool DeferHTTPRequest( HTTPRequestHandle hRequest ) = 0;
|
|
||||||
|
|
||||||
// Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move
|
|
||||||
// the specified request to the head of the queue. Returns false on invalid handle, or if the request is not yet sent.
|
|
||||||
virtual bool PrioritizeHTTPRequest( HTTPRequestHandle hRequest ) = 0;
|
|
||||||
|
|
||||||
// Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also
|
|
||||||
// returns the size of the header value if present so the caller and allocate a correctly sized buffer for
|
|
||||||
// GetHTTPResponseHeaderValue.
|
|
||||||
virtual bool GetHTTPResponseHeaderSize( HTTPRequestHandle hRequest, const char *pchHeaderName, uint32 *unResponseHeaderSize ) = 0;
|
|
||||||
|
|
||||||
// Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
|
|
||||||
// header is not present or if your buffer is too small to contain it's value. You should first call
|
|
||||||
// BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed.
|
|
||||||
virtual bool GetHTTPResponseHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, uint8 *pHeaderValueBuffer, uint32 unBufferSize ) = 0;
|
|
||||||
|
|
||||||
// Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
|
|
||||||
// handle is invalid.
|
|
||||||
virtual bool GetHTTPResponseBodySize( HTTPRequestHandle hRequest, uint32 *unBodySize ) = 0;
|
|
||||||
|
|
||||||
// Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
|
|
||||||
// handle is invalid or is to a streaming response, or if the provided buffer is not the correct size. Use BGetHTTPResponseBodySize first to find out
|
|
||||||
// the correct buffer size to use.
|
|
||||||
virtual bool GetHTTPResponseBodyData( HTTPRequestHandle hRequest, uint8 *pBodyDataBuffer, uint32 unBufferSize ) = 0;
|
|
||||||
|
|
||||||
// Gets the body data from a streaming HTTP response given a handle from HTTPRequestDataReceived_t. Will return false if the
|
|
||||||
// handle is invalid or is to a non-streaming response (meaning it wasn't sent with SendHTTPRequestAndStreamResponse), or if the buffer size and offset
|
|
||||||
// do not match the size and offset sent in HTTPRequestDataReceived_t.
|
|
||||||
virtual bool GetHTTPStreamingResponseBodyData( HTTPRequestHandle hRequest, uint32 cOffset, uint8 *pBodyDataBuffer, uint32 unBufferSize ) = 0;
|
|
||||||
|
|
||||||
// Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t
|
|
||||||
// callback and finishing using the response.
|
|
||||||
virtual bool ReleaseHTTPRequest( HTTPRequestHandle hRequest ) = 0;
|
|
||||||
|
|
||||||
// Gets progress on downloading the body for the request. This will be zero unless a response header has already been
|
|
||||||
// received which included a content-length field. For responses that contain no content-length it will report
|
|
||||||
// zero for the duration of the request as the size is unknown until the connection closes.
|
|
||||||
virtual bool GetHTTPDownloadProgressPct( HTTPRequestHandle hRequest, float *pflPercentOut ) = 0;
|
|
||||||
|
|
||||||
// Sets the body for an HTTP Post request. Will fail and return false on a GET request, and will fail if POST params
|
|
||||||
// have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType
|
|
||||||
// parameter will set the content-type header for the request so the server may know how to interpret the body.
|
|
||||||
virtual bool SetHTTPRequestRawPostBody( HTTPRequestHandle hRequest, const char *pchContentType, uint8 *pubBody, uint32 unBodyLen ) = 0;
|
|
||||||
|
|
||||||
// Creates a cookie container handle which you must later free with ReleaseCookieContainer(). If bAllowResponsesToModify=true
|
|
||||||
// than any response to your requests using this cookie container may add new cookies which may be transmitted with
|
|
||||||
// future requests. If bAllowResponsesToModify=false than only cookies you explicitly set will be sent. This API is just for
|
|
||||||
// during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across
|
|
||||||
// repeat executions of your process.
|
|
||||||
virtual HTTPCookieContainerHandle CreateCookieContainer( bool bAllowResponsesToModify ) = 0;
|
|
||||||
|
|
||||||
// Release a cookie container you are finished using, freeing it's memory
|
|
||||||
virtual bool ReleaseCookieContainer( HTTPCookieContainerHandle hCookieContainer ) = 0;
|
|
||||||
|
|
||||||
// Adds a cookie to the specified cookie container that will be used with future requests.
|
|
||||||
virtual bool SetCookie( HTTPCookieContainerHandle hCookieContainer, const char *pchHost, const char *pchUrl, const char *pchCookie ) = 0;
|
|
||||||
|
|
||||||
// Set the cookie container to use for a HTTP request
|
|
||||||
virtual bool SetHTTPRequestCookieContainer( HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer ) = 0;
|
|
||||||
|
|
||||||
// Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end
|
|
||||||
virtual bool SetHTTPRequestUserAgentInfo( HTTPRequestHandle hRequest, const char *pchUserAgentInfo ) = 0;
|
|
||||||
|
|
||||||
// Set that https request should require verified SSL certificate via machines certificate trust store
|
|
||||||
virtual bool SetHTTPRequestRequiresVerifiedCertificate( HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate ) = 0;
|
|
||||||
|
|
||||||
// Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout
|
|
||||||
// which can bump everytime we get more data
|
|
||||||
virtual bool SetHTTPRequestAbsoluteTimeoutMS( HTTPRequestHandle hRequest, uint32 unMilliseconds ) = 0;
|
|
||||||
|
|
||||||
// Check if the reason the request failed was because we timed it out (rather than some harder failure)
|
|
||||||
virtual bool GetHTTPRequestWasTimedOut( HTTPRequestHandle hRequest, bool *pbWasTimedOut ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ISTEAMHTTP002_H
|
|
|
@ -128,8 +128,6 @@
|
||||||
#include "isteammusic.h"
|
#include "isteammusic.h"
|
||||||
#include "isteammusicremote.h"
|
#include "isteammusicremote.h"
|
||||||
#include "isteamhttp.h"
|
#include "isteamhttp.h"
|
||||||
#include "isteamhttp001.h"
|
|
||||||
#include "isteamhttp002.h"
|
|
||||||
#include "isteamcontroller.h"
|
#include "isteamcontroller.h"
|
||||||
#include "isteamcontroller001.h"
|
#include "isteamcontroller001.h"
|
||||||
#include "isteamcontroller003.h"
|
#include "isteamcontroller003.h"
|
||||||
|
|
|
@ -10,13 +10,13 @@
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
bool IsNotRelativePathOrRemoveFileName(WCHAR* output, bool Remove)
|
bool IsNotRelativePathOrRemoveFileName(CHAR* output, bool Remove)
|
||||||
{
|
{
|
||||||
int LG = lstrlenW(output);
|
int LG = lstrlenA(output);
|
||||||
for (int i = LG; i > 0; i--) {
|
for (int i = LG; i > 0; i--) {
|
||||||
if (output[i] == '\\') {
|
if (output[i] == '\\') {
|
||||||
if(Remove)
|
if(Remove)
|
||||||
RtlFillMemory(&output[i], (LG - i) * sizeof(WCHAR), NULL);
|
RtlFillMemory(&output[i], LG - i, NULL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,84 +25,81 @@ bool IsNotRelativePathOrRemoveFileName(WCHAR* output, bool Remove)
|
||||||
|
|
||||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
|
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
|
||||||
{
|
{
|
||||||
WCHAR CurrentDirectory[MAX_PATH] = { 0 };
|
CHAR CurrentDirectory[MAX_PATH] = { 0 };
|
||||||
WCHAR Client64Path[MAX_PATH] = { 0 };
|
CHAR Client64Path[MAX_PATH] = { 0 };
|
||||||
WCHAR ClientPath[MAX_PATH] = { 0 };
|
CHAR ClientPath[MAX_PATH] = { 0 };
|
||||||
WCHAR ExeFile[MAX_PATH] = { 0 };
|
CHAR ExeFile[MAX_PATH] = { 0 };
|
||||||
WCHAR ExeRunDir[MAX_PATH] = { 0 };
|
CHAR ExeRunDir[MAX_PATH] = { 0 };
|
||||||
WCHAR ExeCommandLine[4096] = { 0 };
|
CHAR ExeCommandLine[4096] = { 0 };
|
||||||
WCHAR AppId[128] = { 0 };
|
CHAR AppId[128] = { 0 };
|
||||||
|
|
||||||
STARTUPINFOW info = { sizeof(info) };
|
STARTUPINFOA info = { sizeof(info) };
|
||||||
PROCESS_INFORMATION processInfo;
|
PROCESS_INFORMATION processInfo;
|
||||||
|
|
||||||
int Length = GetModuleFileNameW(GetModuleHandleW(NULL), CurrentDirectory, sizeof(CurrentDirectory)) + 1;
|
int Length = GetModuleFileNameA(GetModuleHandleA(NULL), CurrentDirectory, sizeof(CurrentDirectory)) + 1;
|
||||||
for (int i = Length; i > 0; i--) {
|
for (int i = Length; i > 0; i--) {
|
||||||
if (CurrentDirectory[i] == '\\') {
|
if (CurrentDirectory[i] == '\\') {
|
||||||
lstrcpyW(&CurrentDirectory[i + 1], L"ColdClientLoader.ini");
|
lstrcpyA(&CurrentDirectory[i + 1], "ColdClientLoader.ini");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GetFileAttributesW(CurrentDirectory) == INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(CurrentDirectory) == INVALID_FILE_ATTRIBUTES) {
|
||||||
MessageBoxA(NULL, "Couldn't find the configuration file(ColdClientLoader.ini).", "ColdClientLoader", MB_ICONERROR);
|
MessageBoxA(NULL, "Couldn't find the configuration file(ColdClientLoader.ini).", "ColdClientLoader", MB_ICONERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetPrivateProfileStringW(L"SteamClient", L"SteamClient64Dll", L"", Client64Path, MAX_PATH, CurrentDirectory);
|
GetPrivateProfileStringA("SteamClient", "SteamClient64Dll", "", Client64Path, MAX_PATH, CurrentDirectory);
|
||||||
GetPrivateProfileStringW(L"SteamClient", L"SteamClientDll", L"", ClientPath, MAX_PATH, CurrentDirectory);
|
GetPrivateProfileStringA("SteamClient", "SteamClientDll", "", ClientPath, MAX_PATH, CurrentDirectory);
|
||||||
GetPrivateProfileStringW(L"SteamClient", L"Exe", NULL, ExeFile, MAX_PATH, CurrentDirectory);
|
GetPrivateProfileStringA("SteamClient", "Exe", NULL, ExeFile, MAX_PATH, CurrentDirectory);
|
||||||
GetPrivateProfileStringW(L"SteamClient", L"ExeRunDir", NULL, ExeRunDir, MAX_PATH, CurrentDirectory);
|
GetPrivateProfileStringA("SteamClient", "ExeRunDir", NULL, ExeRunDir, MAX_PATH, CurrentDirectory);
|
||||||
GetPrivateProfileStringW(L"SteamClient", L"ExeCommandLine", NULL, ExeCommandLine, 4096, CurrentDirectory);
|
GetPrivateProfileStringA("SteamClient", "ExeCommandLine", NULL, ExeCommandLine, 4096, CurrentDirectory);
|
||||||
GetPrivateProfileStringW(L"SteamClient", L"AppId", NULL, AppId, sizeof(AppId), CurrentDirectory);
|
GetPrivateProfileStringA("SteamClient", "AppId", NULL, AppId, sizeof(AppId), CurrentDirectory);
|
||||||
|
|
||||||
if (AppId[0]) {
|
if (AppId[0]) {
|
||||||
SetEnvironmentVariableW(L"SteamAppId", AppId);
|
SetEnvironmentVariableA("SteamAppId", AppId);
|
||||||
SetEnvironmentVariableW(L"SteamGameId", AppId);
|
SetEnvironmentVariableA("SteamGameId", AppId);
|
||||||
} else {
|
|
||||||
MessageBoxA(NULL, "You forgot to set the AppId.", "ColdClientLoader", MB_ICONERROR);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR TMP[MAX_PATH] = {};
|
CHAR TMP[MAX_PATH] = {};
|
||||||
if (!IsNotRelativePathOrRemoveFileName(Client64Path, false)) {
|
if (!IsNotRelativePathOrRemoveFileName(Client64Path, false)) {
|
||||||
lstrcpyW(TMP, Client64Path);
|
lstrcpyA(TMP, Client64Path);
|
||||||
ZeroMemory(Client64Path, sizeof(Client64Path));
|
ZeroMemory(Client64Path, sizeof(Client64Path));
|
||||||
GetFullPathNameW(TMP, MAX_PATH, Client64Path, NULL);
|
GetFullPathNameA(TMP, MAX_PATH, Client64Path, NULL);
|
||||||
}
|
}
|
||||||
if (!IsNotRelativePathOrRemoveFileName(ClientPath, false)) {
|
if (!IsNotRelativePathOrRemoveFileName(ClientPath, false)) {
|
||||||
lstrcpyW(TMP, ClientPath);
|
lstrcpyA(TMP, ClientPath);
|
||||||
ZeroMemory(ClientPath, sizeof(ClientPath));
|
ZeroMemory(ClientPath, sizeof(ClientPath));
|
||||||
GetFullPathNameW(TMP, MAX_PATH, ClientPath, NULL);
|
GetFullPathNameA(TMP, MAX_PATH, ClientPath, NULL);
|
||||||
}
|
}
|
||||||
if (!IsNotRelativePathOrRemoveFileName(ExeFile, false)) {
|
if (!IsNotRelativePathOrRemoveFileName(ExeFile, false)) {
|
||||||
lstrcpyW(TMP, ExeFile);
|
lstrcpyA(TMP, ExeFile);
|
||||||
ZeroMemory(ExeFile, sizeof(ExeFile));
|
ZeroMemory(ExeFile, sizeof(ExeFile));
|
||||||
GetFullPathNameW(TMP, MAX_PATH, ExeFile, NULL);
|
GetFullPathNameA(TMP, MAX_PATH, ExeFile, NULL);
|
||||||
}
|
}
|
||||||
if (!IsNotRelativePathOrRemoveFileName(ExeRunDir, false)) {
|
if (!IsNotRelativePathOrRemoveFileName(ExeRunDir, false)) {
|
||||||
lstrcpyW(TMP, ExeRunDir);
|
lstrcpyA(TMP, ExeRunDir);
|
||||||
ZeroMemory(ExeRunDir, sizeof(ExeRunDir));
|
ZeroMemory(ExeRunDir, sizeof(ExeRunDir));
|
||||||
GetFullPathNameW(TMP, MAX_PATH, ExeRunDir, NULL);
|
GetFullPathNameA(TMP, MAX_PATH, ExeRunDir, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetFileAttributesW(Client64Path) == INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(Client64Path) == INVALID_FILE_ATTRIBUTES) {
|
||||||
MessageBoxA(NULL, "Couldn't find the requested SteamClient64Dll.", "ColdClientLoader", MB_ICONERROR);
|
MessageBoxA(NULL, "Couldn't find the requested SteamClient64Dll.", "ColdClientLoader", MB_ICONERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetFileAttributesW(ClientPath) == INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(ClientPath) == INVALID_FILE_ATTRIBUTES) {
|
||||||
MessageBoxA(NULL, "Couldn't find the requested SteamClientDll.", "ColdClientLoader", MB_ICONERROR);
|
MessageBoxA(NULL, "Couldn't find the requested SteamClientDll.", "ColdClientLoader", MB_ICONERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetFileAttributesW(ExeFile) == INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(ExeFile) == INVALID_FILE_ATTRIBUTES) {
|
||||||
MessageBoxA(NULL, "Couldn't find the requested Exe file.", "ColdClientLoader", MB_ICONERROR);
|
MessageBoxA(NULL, "Couldn't find the requested Exe file.", "ColdClientLoader", MB_ICONERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR CommandLine[8192];
|
CHAR CommandLine[8192];
|
||||||
_snwprintf(CommandLine, _countof(CommandLine), L"\"%ls\" %ls", ExeFile, ExeCommandLine);
|
snprintf(CommandLine, sizeof(CommandLine), "\"%s\" %s", ExeFile, ExeCommandLine);
|
||||||
if (!ExeFile[0] || !CreateProcessW(ExeFile, CommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo))
|
if (!ExeFile[0] || !CreateProcessA(ExeFile, CommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR);
|
MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -114,18 +111,18 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
||||||
|
|
||||||
bool orig_steam = false;
|
bool orig_steam = false;
|
||||||
DWORD keyType = REG_SZ;
|
DWORD keyType = REG_SZ;
|
||||||
WCHAR OrgSteamCDir[MAX_PATH] = { 0 };
|
CHAR OrgSteamCDir[MAX_PATH] = { 0 };
|
||||||
WCHAR OrgSteamCDir64[MAX_PATH] = { 0 };
|
CHAR OrgSteamCDir64[MAX_PATH] = { 0 };
|
||||||
DWORD Size1 = MAX_PATH;
|
DWORD Size1 = MAX_PATH;
|
||||||
DWORD Size2 = MAX_PATH;
|
DWORD Size2 = MAX_PATH;
|
||||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
|
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
orig_steam = true;
|
orig_steam = true;
|
||||||
// Get original values to restore later.
|
// Get original values to restore later.
|
||||||
RegQueryValueExW(Registrykey, L"SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1);
|
RegQueryValueExA(Registrykey, "SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1);
|
||||||
RegQueryValueExW(Registrykey, L"SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2);
|
RegQueryValueExA(Registrykey, "SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2);
|
||||||
} else {
|
} else {
|
||||||
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE,
|
if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE,
|
||||||
KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS)
|
KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR);
|
MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR);
|
||||||
|
@ -140,17 +137,17 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
||||||
|
|
||||||
{
|
{
|
||||||
// Before saving to the registry check again if the path was valid and if the file exist
|
// Before saving to the registry check again if the path was valid and if the file exist
|
||||||
if (GetFileAttributesW(ClientPath) != INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) {
|
||||||
RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)(lstrlenW(ClientPath) * sizeof(WCHAR)) + 1);
|
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
|
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||||
}
|
}
|
||||||
if (GetFileAttributesW(Client64Path) != INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) {
|
||||||
RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)(lstrlenW(Client64Path) * sizeof(WCHAR)) + 1);
|
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
|
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
|
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
|
||||||
|
@ -164,11 +161,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
||||||
CloseHandle(processInfo.hThread);
|
CloseHandle(processInfo.hThread);
|
||||||
|
|
||||||
if (orig_steam) {
|
if (orig_steam) {
|
||||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
|
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
// Restore the values.
|
// Restore the values.
|
||||||
RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)OrgSteamCDir, Size1);
|
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)OrgSteamCDir, (DWORD)lstrlenA(OrgSteamCDir) + 1);
|
||||||
RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)OrgSteamCDir64, Size2);
|
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)OrgSteamCDir64, (DWORD)lstrlenA(OrgSteamCDir64) + 1);
|
||||||
|
|
||||||
// Close the HKEY Handle.
|
// Close the HKEY Handle.
|
||||||
RegCloseKey(Registrykey);
|
RegCloseKey(Registrykey);
|
||||||
|
|
Loading…
Reference in New Issue