Skip to content

Commit

Permalink
Fixed wndproc, hooked up inputs. Having a weird double render going o…
Browse files Browse the repository at this point in the history
…n, probably because endscene is called multiple times per frame
  • Loading branch information
FrankvdStam committed Jul 24, 2022
1 parent 76928b8 commit 4241d0b
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 58 deletions.
126 changes: 82 additions & 44 deletions hudhook/src/hooks/dx9.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ use once_cell::sync::OnceCell;
use std::ptr::null;
use detour::RawDetour;
use imgui::Context;
use log::{error};
use log::{debug, error, info, trace};
use parking_lot::Mutex;
use windows::core::{HRESULT, Interface, PCSTR};
use windows::Win32::Foundation::{BOOL, HWND, LPARAM, LRESULT, POINT, RECT, WPARAM};
use windows::Win32::Graphics::Direct3D9::{D3D_SDK_VERSION, D3DADAPTER_DEFAULT, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DDEVTYPE_HAL, D3DDISPLAYMODE, D3DFORMAT, D3DPRESENT_PARAMETERS, D3DSWAPEFFECT_DISCARD, Direct3DCreate9, IDirect3DDevice9};
use windows::Win32::Graphics::Gdi::{HBRUSH, RGNDATA};
use windows::Win32::Foundation::{GetLastError, BOOL, HWND, LPARAM, LRESULT, POINT, RECT, WPARAM};
use windows::Win32::Graphics::Direct3D9::{D3D_SDK_VERSION, D3DADAPTER_DEFAULT, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DDEVICE_CREATION_PARAMETERS, D3DDEVTYPE_HAL, D3DDISPLAYMODE, D3DFORMAT, D3DPRESENT_PARAMETERS, D3DSWAPEFFECT_DISCARD, Direct3DCreate9, IDirect3DDevice9};
use windows::Win32::Graphics::Gdi::{HBRUSH, RGNDATA, ScreenToClient};
use windows::Win32::System::LibraryLoader::GetModuleHandleA;
use windows::Win32::UI::WindowsAndMessaging::{CreateWindowExA, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, DefWindowProcA, DestroyWindow, GetCursorPos, GetForegroundWindow, HCURSOR, HICON, HMENU, RegisterClassA, WINDOW_EX_STYLE, WNDCLASSA, WS_OVERLAPPEDWINDOW, WS_VISIBLE};
use crate::hooks::common::{ImguiWindowsEventHandler, WndProcType};
use windows::Win32::UI::WindowsAndMessaging::{CreateWindowExA, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, DefWindowProcA, DefWindowProcW, DestroyWindow, GetCursorPos, GetForegroundWindow, GWLP_WNDPROC, HCURSOR, HICON, HMENU, IsChild, RegisterClassA, WINDOW_EX_STYLE, WNDCLASSA, WS_OVERLAPPEDWINDOW, WS_VISIBLE};
use crate::hooks::common::{imgui_wnd_proc_impl, ImguiWindowsEventHandler};
use crate::hooks::{Hooks, ImguiRenderLoop, ImguiRenderLoopFlags};

#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
use windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrA;

#[cfg(target_arch = "x86")]
use windows::Win32::UI::WindowsAndMessaging::SetWindowLongA;



type Dx9EndSceneFn = unsafe extern "system" fn(this: IDirect3DDevice9,) -> HRESULT;
Expand All @@ -25,53 +31,80 @@ type Dx9PresentFn = unsafe extern "system" fn(
pdirtyregion: *const RGNDATA
) -> HRESULT;

type WndProcType =
unsafe extern "system" fn(hwnd: HWND, umsg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT;

unsafe extern "system" fn imgui_dx9_end_scene_impl(this: IDirect3DDevice9) -> HRESULT
{
unsafe extern "system" fn def_window_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
DefWindowProcA(hwnd, msg, wparam, lparam)
}
info!("end scene");

let mut imgui_renderer = IMGUI_RENDERER.get_or_init(|| {
let mut creation_parameters = D3DDEVICE_CREATION_PARAMETERS{..core::mem::zeroed()};
this.GetCreationParameters(&mut creation_parameters).unwrap();

let mut context = imgui::Context::create();
context.set_ini_filename(None);
let renderer = imgui_dx9::Renderer::new(&mut context, this.clone()).unwrap();
let renderer = imgui_dx9::Renderer::new(&mut context, this.clone(), creation_parameters).unwrap();

#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
let wnd_proc = std::mem::transmute::<_, WndProcType>(SetWindowLongPtrA(
creation_parameters.hFocusWindow,
GWLP_WNDPROC,
imgui_wnd_proc as usize as isize,
));

#[cfg(target_arch = "x86")]
let wnd_proc = std::mem::transmute::<_, WndProcType>(SetWindowLongA(
creation_parameters.hFocusWindow,
GWLP_WNDPROC,
imgui_wnd_proc as usize as i32,
));

Mutex::new(Box::new(
ImguiRenderer
{
ctx: context,
renderer,
wnd_proc: def_window_proc,
wnd_proc,
flags: ImguiRenderLoopFlags { focused: false }
}
))
}).lock();

imgui_renderer.render();



//Ok(imgui_renderer) =>
//{
// let r = imgui_renderer.unwrap();
// r.renderer.render(r.ctx);
//}
//_ => error!("Failed to acquire imgui_renderer lock")




imgui_renderer.render();

let (trampoline_end_scene, _) = TRAMPOLINE.get().expect("dx9_Present trampoline uninitialized");
let result = trampoline_end_scene(this);
return result;
}

unsafe extern "system" fn imgui_wnd_proc(
hwnd: HWND,
umsg: u32,
WPARAM(wparam): WPARAM,
LPARAM(lparam): LPARAM,
) -> LRESULT {
match IMGUI_RENDERER.get().map(Mutex::try_lock) {
Some(Some(imgui_renderer)) => imgui_wnd_proc_impl(
hwnd,
umsg,
WPARAM(wparam),
LPARAM(lparam),
imgui_renderer,
IMGUI_RENDER_LOOP.get().unwrap(),
),
Some(None) => {
debug!("Could not lock in WndProc");
DefWindowProcW(hwnd, umsg, WPARAM(wparam), LPARAM(lparam))
},
None => {
debug!("WndProc called before hook was set");
DefWindowProcW(hwnd, umsg, WPARAM(wparam), LPARAM(lparam))
},
}
}



unsafe extern "system" fn imgui_dx9_present_impl(
this: IDirect3DDevice9,
Expand All @@ -81,6 +114,8 @@ unsafe extern "system" fn imgui_dx9_present_impl(
pdirtyregion: *const RGNDATA
) -> HRESULT
{
info!("present");

let (_, trampoline_present) = TRAMPOLINE.get().expect("dx9_Present trampoline uninitialized");
let result = trampoline_present(this, psourcerect, pdestrect, hdestwindowoverride, pdirtyregion);
return result;
Expand All @@ -104,24 +139,27 @@ impl ImguiRenderer
{
unsafe fn render(&mut self)
{


{
if let Some(rect) = self.renderer.get_window_rect() {
let mut io = self.ctx.io_mut();
let rect = self.renderer.get_window_rect();
io.display_size = [(rect.right - rect.left) as f32, (rect.bottom - rect.top) as f32];
}


let mut pos = POINT { x: 0, y: 0 };
io.display_size = [(rect.right - rect.left) as f32, (rect.bottom - rect.top) as f32];

//let active_window = GetForegroundWindow();
let mut pos = POINT { x: 0, y: 0 };

//let gcp = GetCursorPos(&mut pos as *mut _);
//if gcp.as_bool() && ScreenToClient(sd.OutputWindow, &mut pos as *mut _).as_bool() {
// io.mouse_pos[0] = pos.x as _;
// io.mouse_pos[1] = pos.y as _;
//}
let active_window = GetForegroundWindow();
if !active_window.is_invalid()
&& (active_window == self.renderer.get_hwnd()
|| IsChild(active_window, self.renderer.get_hwnd()).as_bool())
{
let gcp = GetCursorPos(&mut pos as *mut _);
if gcp.as_bool() && ScreenToClient(self.renderer.get_hwnd(), &mut pos as *mut _).as_bool() {
io.mouse_pos[0] = pos.x as _;
io.mouse_pos[1] = pos.y as _;
}
}
} else {
trace!("GetWindowRect error: {:x}", GetLastError().0);
}


//let ctx = &mut self.ctx;
Expand Down
35 changes: 21 additions & 14 deletions imgui-dx9/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ use imgui::{
internal::RawWrapper, BackendFlags, Context, DrawCmd, DrawCmdParams, DrawData, DrawIdx,
TextureId, Textures,
};
use windows::Win32::Graphics::Direct3D9::{IDirect3DBaseTexture9, IDirect3DDevice9, IDirect3DIndexBuffer9, IDirect3DStateBlock9, IDirect3DTexture9, IDirect3DVertexBuffer9, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_SRCALPHA, D3DCULL_NONE, D3DFMT_A8R8G8B8, D3DFMT_INDEX16, D3DFMT_INDEX32, D3DLOCKED_RECT, D3DLOCK_DISCARD, D3DPOOL_DEFAULT, D3DPT_TRIANGLELIST, D3DRS_ALPHABLENDENABLE, D3DRS_ALPHATESTENABLE, D3DRS_BLENDOP, D3DRS_CULLMODE, D3DRS_DESTBLEND, D3DRS_FOGENABLE, D3DRS_LIGHTING, D3DRS_SCISSORTESTENABLE, D3DRS_SHADEMODE, D3DRS_SRCBLEND, D3DRS_ZENABLE, D3DSAMP_MAGFILTER, D3DSAMP_MINFILTER, D3DSBT_ALL, D3DSHADE_GOURAUD, D3DTEXF_LINEAR, D3DTOP_MODULATE, D3DTRANSFORMSTATETYPE, D3DTSS_ALPHAARG1, D3DTSS_ALPHAARG2, D3DTSS_ALPHAOP, D3DTSS_COLORARG1, D3DTSS_COLORARG2, D3DTSS_COLOROP, D3DTS_PROJECTION, D3DTS_VIEW, D3DUSAGE_DYNAMIC, D3DUSAGE_WRITEONLY, D3DVIEWPORT9, IDirect3DSurface9, D3DBACKBUFFER_TYPE_MONO, D3DSURFACE_DESC};
use windows::Win32::Graphics::Direct3D9::{IDirect3DBaseTexture9, IDirect3DDevice9, IDirect3DIndexBuffer9, IDirect3DStateBlock9, IDirect3DTexture9, IDirect3DVertexBuffer9, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_SRCALPHA, D3DCULL_NONE, D3DFMT_A8R8G8B8, D3DFMT_INDEX16, D3DFMT_INDEX32, D3DLOCKED_RECT, D3DLOCK_DISCARD, D3DPOOL_DEFAULT, D3DPT_TRIANGLELIST, D3DRS_ALPHABLENDENABLE, D3DRS_ALPHATESTENABLE, D3DRS_BLENDOP, D3DRS_CULLMODE, D3DRS_DESTBLEND, D3DRS_FOGENABLE, D3DRS_LIGHTING, D3DRS_SCISSORTESTENABLE, D3DRS_SHADEMODE, D3DRS_SRCBLEND, D3DRS_ZENABLE, D3DSAMP_MAGFILTER, D3DSAMP_MINFILTER, D3DSBT_ALL, D3DSHADE_GOURAUD, D3DTEXF_LINEAR, D3DTOP_MODULATE, D3DTRANSFORMSTATETYPE, D3DTSS_ALPHAARG1, D3DTSS_ALPHAARG2, D3DTSS_ALPHAOP, D3DTSS_COLORARG1, D3DTSS_COLORARG2, D3DTSS_COLOROP, D3DTS_PROJECTION, D3DTS_VIEW, D3DUSAGE_DYNAMIC, D3DUSAGE_WRITEONLY, D3DVIEWPORT9, D3DDEVICE_CREATION_PARAMETERS};

use windows::Win32::Foundation::RECT;
use windows::Win32::Foundation::{BOOL, HWND, RECT};
use windows::Win32::Graphics::Direct3D::{D3DMATRIX, D3DMATRIX_0};
use windows::Win32::Graphics::Dxgi::DXGI_ERROR_INVALID_CALL;
use windows::Win32::System::SystemServices::D3DFVF_TEX1;
use windows::Win32::System::SystemServices::D3DFVF_XYZ;
use windows::Win32::System::SystemServices::{D3DFVF_DIFFUSE, D3DTA_DIFFUSE, D3DTA_TEXTURE};
use windows::Win32::UI::WindowsAndMessaging::GetWindowRect;

const FONT_TEX_ID: usize = !0;
const D3DFVF_CUSTOMVERTEX: u32 = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
Expand Down Expand Up @@ -69,6 +70,7 @@ struct CustomVertex {

/// A DirectX 9 renderer for (Imgui-rs)[https://docs.rs/imgui/*/imgui/].
pub struct Renderer {
device_creation_parameters: D3DDEVICE_CREATION_PARAMETERS,
device: IDirect3DDevice9,
font_tex: IDirect3DBaseTexture9,
vertex_buffer: (IDirect3DVertexBuffer9, usize),
Expand All @@ -84,7 +86,7 @@ impl Renderer {
/// `device` must be a valid [`IDirect3DDevice9`] pointer.
///
/// [`IDirect3DDevice9`]: https://docs.rs/winapi/0.3/x86_64-pc-windows-msvc/winapi/shared/d3d9/struct.IDirect3DDevice9.html
pub unsafe fn new(ctx: &mut Context, device: IDirect3DDevice9) -> Result<Self> {
pub unsafe fn new(ctx: &mut Context, device: IDirect3DDevice9, device_creation_parameters: D3DDEVICE_CREATION_PARAMETERS) -> Result<Self> {
let font_tex =
IDirect3DBaseTexture9::from(Self::create_font_texture(ctx.fonts(), &device)?);

Expand All @@ -96,35 +98,40 @@ impl Renderer {
Ok(Renderer {
vertex_buffer: Self::create_vertex_buffer(&device, 0)?,
index_buffer: Self::create_index_buffer(&device, 0)?,
device_creation_parameters,
device,
font_tex,
textures: Textures::new(),
})
}

///Gets the window width & height via the backbuffer
pub fn get_window_rect(&self) -> RECT
pub fn get_window_rect(&self) -> Option<RECT>
{
let surface = unsafe{ self.device.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO).expect("Failed to get backbuffer") };
let mut description = unsafe{ D3DSURFACE_DESC{..core::mem::zeroed() }};
unsafe{ surface.GetDesc(&mut description) };
RECT{
left: 0,
right: description.Width as i32,
top: 0,
bottom: description.Height as i32,
unsafe{
let mut rect: RECT = RECT{..core::mem::zeroed()};
if GetWindowRect(self.device_creation_parameters.hFocusWindow, &mut rect) != BOOL(0) {
Some(rect)
} else {
None
}
}
}

///Returns the hFocuswindow HWND from the device creation parameters
pub fn get_hwnd(&self) -> HWND{
self.device_creation_parameters.hFocusWindow
}

/// Creates a new renderer for the given [`IDirect3DDevice9`].
///
/// # Safety
///
/// `device` must be a valid [`IDirect3DDevice9`] pointer.
///
/// [`IDirect3DDevice9`]: https://docs.rs/winapi/0.3/x86_64-pc-windows-msvc/winapi/shared/d3d9/struct.IDirect3DDevice9.html
pub unsafe fn new_raw(im_ctx: &mut imgui::Context, device: IDirect3DDevice9) -> Result<Self> {
Self::new(im_ctx, device)
pub unsafe fn new_raw(im_ctx: &mut imgui::Context, device: IDirect3DDevice9, device_creation_parameters: D3DDEVICE_CREATION_PARAMETERS) -> Result<Self> {
Self::new(im_ctx, device, device_creation_parameters)
}

/// The textures registry of this renderer.
Expand Down

0 comments on commit 4241d0b

Please sign in to comment.