mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2025-02-17 11:18:31 +01:00
hook: Add d3d9 hook module
This module serves as a general base for any d3d9 hooks to be implemented. It implements the IRP pattern like the iohook module. This allows us to create irp handlers which can be chained, easier structured and maintained compared to static IAT hooking. The latter was the previous solution and did not work out well anymore for IIDX which grew regarding d3d9 features.
This commit is contained in:
parent
3436838b85
commit
60050d0d09
@ -2,6 +2,7 @@ libs += hook
|
||||
|
||||
src_hook := \
|
||||
com-proxy.c \
|
||||
d3d9.c \
|
||||
iohook.c \
|
||||
pe.c \
|
||||
peb.c \
|
||||
|
654
src/main/hook/d3d9.c
Normal file
654
src/main/hook/d3d9.c
Normal file
@ -0,0 +1,654 @@
|
||||
#define LOG_MODULE "hook-d3d9"
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
#include "hook/d3d9.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static IDirect3D9* (STDCALL* real_Direct3DCreate9)(UINT sdk_ver);
|
||||
|
||||
static BOOL (STDCALL *real_EnumDisplayDevicesA)(
|
||||
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info,
|
||||
DWORD flags);
|
||||
|
||||
static HWND (STDCALL *real_CreateWindowExA)(
|
||||
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
|
||||
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
|
||||
HINSTANCE hInstance, LPVOID lpParam);
|
||||
|
||||
static BOOL (STDCALL* real_GetClientRect)(HWND hWnd, LPRECT lpRect);
|
||||
|
||||
static HRESULT (STDCALL* real_CreateDevice)(IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, HWND hwnd, DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev);
|
||||
|
||||
static HRESULT (STDCALL* real_CreateTexture)(IDirect3DDevice9* self, UINT width, UINT height, UINT levels, DWORD usage,
|
||||
D3DFORMAT format, D3DPOOL pool, IDirect3DTexture9** texture, HANDLE* shared_handle);
|
||||
|
||||
static HRESULT (STDCALL* real_BeginScene)(IDirect3DDevice9* self);
|
||||
|
||||
static HRESULT (STDCALL* real_EndScene)(IDirect3DDevice9* self);
|
||||
|
||||
static HRESULT (STDCALL* real_Present)(IDirect3DDevice9* self,
|
||||
CONST RECT *pSourceRect, CONST RECT *pDestRect,
|
||||
HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion);
|
||||
|
||||
static HRESULT (STDCALL* real_SetRenderState)(IDirect3DDevice9* self,
|
||||
D3DRENDERSTATETYPE State, DWORD Value);
|
||||
|
||||
static HRESULT (STDCALL *real_DrawPrimitiveUP)(
|
||||
IDirect3DDevice9* self, D3DPRIMITIVETYPE primitive_type,
|
||||
UINT primitive_count, const void *data, UINT stride);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static IDirect3D9* STDCALL my_Direct3DCreate9(UINT sdk_ver);
|
||||
|
||||
static BOOL STDCALL my_EnumDisplayDevicesA(const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
|
||||
|
||||
static HWND STDCALL my_CreateWindowExA(
|
||||
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
|
||||
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
|
||||
HINSTANCE hInstance, LPVOID lpParam);
|
||||
|
||||
static BOOL STDCALL my_GetClientRect(HWND hWnd, LPRECT lpRect);
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, HWND hwnd, DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev);
|
||||
|
||||
static HRESULT STDCALL my_CreateTexture(IDirect3DDevice9* self, UINT width, UINT height, UINT levels, DWORD usage,
|
||||
D3DFORMAT format, D3DPOOL pool, IDirect3DTexture9** texture, HANDLE* shared_handle);
|
||||
|
||||
static HRESULT STDCALL my_BeginScene(IDirect3DDevice9* self);
|
||||
|
||||
static HRESULT STDCALL my_EndScene(IDirect3DDevice9* self);
|
||||
|
||||
static HRESULT STDCALL my_Present(IDirect3DDevice9* self,
|
||||
CONST RECT *pSourceRect, CONST RECT *pDestRect,
|
||||
HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion);
|
||||
|
||||
static HRESULT STDCALL my_SetRenderState(IDirect3DDevice9* self,
|
||||
D3DRENDERSTATETYPE State, DWORD Value);
|
||||
|
||||
static HRESULT STDCALL my_DrawPrimitiveUP(
|
||||
IDirect3DDevice9* self, D3DPRIMITIVETYPE primitive_type,
|
||||
UINT primitive_count, const void *data, UINT stride);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static const struct hook_symbol hook_d3d9_hook_syms[] = {
|
||||
{
|
||||
.name = "Direct3DCreate9",
|
||||
.patch = my_Direct3DCreate9,
|
||||
.link = (void **) &real_Direct3DCreate9
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hook_symbol hook_d3d9_hook_user32_syms[] = {
|
||||
{
|
||||
.name = "EnumDisplayDevicesA",
|
||||
.patch = my_EnumDisplayDevicesA,
|
||||
.link = (void **) &real_EnumDisplayDevicesA
|
||||
},
|
||||
{
|
||||
.name = "CreateWindowExA",
|
||||
.patch = my_CreateWindowExA,
|
||||
.link = (void **) &real_CreateWindowExA
|
||||
},
|
||||
{
|
||||
.name = "GetClientRect",
|
||||
.patch = my_GetClientRect,
|
||||
.link = (void **) &real_GetClientRect
|
||||
},
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_invalid(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_ctx_create(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_enum_display_devices(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_create_window_ex(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_get_client_rect(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_create_device(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_create_texture(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_begin_scene(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_end_scene(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_present(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_set_render_state(struct hook_d3d9_irp* irp);
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_draw_primitive_up(struct hook_d3d9_irp* irp);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static const hook_d3d9_irp_handler_t hook_d3d9_irp_real_handlers[] = {
|
||||
[HOOK_D3D9_IRP_OP_INVALID] = hook_d3d9_irp_handler_real_invalid,
|
||||
[HOOK_D3D9_IRP_OP_CTX_CREATE] = hook_d3d9_irp_handler_real_ctx_create,
|
||||
[HOOK_D3D9_IRP_OP_ENUM_DISPLAY_DEVICES] = hook_d3d9_irp_handler_real_enum_display_devices,
|
||||
[HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX] = hook_d3d9_irp_handler_real_create_window_ex,
|
||||
[HOOK_D3D9_IRP_OP_GET_CLIENT_RECT] = hook_d3d9_irp_handler_real_get_client_rect,
|
||||
[HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE] = hook_d3d9_irp_handler_real_dev_create_device,
|
||||
[HOOK_D3D9_IRP_OP_DEV_CREATE_TEXTURE] = hook_d3d9_irp_handler_real_dev_create_texture,
|
||||
[HOOK_D3D9_IRP_OP_DEV_BEGIN_SCENE] = hook_d3d9_irp_handler_real_dev_begin_scene,
|
||||
[HOOK_D3D9_IRP_OP_DEV_END_SCENE] = hook_d3d9_irp_handler_real_dev_end_scene,
|
||||
[HOOK_D3D9_IRP_OP_DEV_PRESENT] = hook_d3d9_irp_handler_real_dev_present,
|
||||
[HOOK_D3D9_IRP_OP_DEV_SET_RENDER_STATE] = hook_d3d9_irp_handler_real_dev_set_render_state,
|
||||
[HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP] = hook_d3d9_irp_handler_real_dev_draw_primitive_up,
|
||||
};
|
||||
|
||||
static const hook_d3d9_irp_handler_t* hook_d3d9_handlers;
|
||||
static size_t hook_d3d9_nhandlers;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static IDirect3D9* STDCALL my_Direct3DCreate9(UINT sdk_ver)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_CTX_CREATE;
|
||||
irp.args.ctx_create.sdk_ver = sdk_ver;
|
||||
irp.args.ctx_create.ctx = NULL;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
if (hr == S_OK && irp.args.ctx_create.ctx) {
|
||||
return irp.args.ctx_create.ctx;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL STDCALL my_EnumDisplayDevicesA(const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_ENUM_DISPLAY_DEVICES;
|
||||
irp.args.enum_display_devices.dev_name = dev_name;
|
||||
irp.args.enum_display_devices.dev_num = dev_num;
|
||||
irp.args.enum_display_devices.info = info;
|
||||
irp.args.enum_display_devices.flags = flags;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
if (hr == S_OK) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static HWND STDCALL my_CreateWindowExA(
|
||||
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
|
||||
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
|
||||
HINSTANCE hInstance, LPVOID lpParam)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX;
|
||||
irp.args.create_window_ex.ex_style = dwExStyle;
|
||||
irp.args.create_window_ex.class_name = lpClassName;
|
||||
irp.args.create_window_ex.window_name = lpWindowName;
|
||||
irp.args.create_window_ex.style = dwStyle;
|
||||
irp.args.create_window_ex.x = X;
|
||||
irp.args.create_window_ex.y = Y;
|
||||
irp.args.create_window_ex.width = nWidth;
|
||||
irp.args.create_window_ex.height = nHeight;
|
||||
irp.args.create_window_ex.wnd_parent = hWndParent;
|
||||
irp.args.create_window_ex.menu = hMenu;
|
||||
irp.args.create_window_ex.instance = hInstance;
|
||||
irp.args.create_window_ex.param = lpParam;
|
||||
irp.args.create_window_ex.result = NULL;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
if (hr == S_OK && irp.args.create_window_ex.result != NULL) {
|
||||
return irp.args.create_window_ex.result;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL STDCALL my_GetClientRect(HWND hWnd, LPRECT lpRect)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_GET_CLIENT_RECT;
|
||||
irp.args.get_client_rect.wnd = hWnd;
|
||||
irp.args.get_client_rect.rect = lpRect;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
if (hr == S_OK) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(
|
||||
IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, HWND hwnd, DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE;
|
||||
irp.args.ctx_create_device.self = self;
|
||||
irp.args.ctx_create_device.adapter = adapter;
|
||||
irp.args.ctx_create_device.type = type;
|
||||
irp.args.ctx_create_device.hwnd = hwnd;
|
||||
irp.args.ctx_create_device.flags = flags;
|
||||
irp.args.ctx_create_device.pp = pp;
|
||||
irp.args.ctx_create_device.pdev = pdev;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_CreateTexture(IDirect3DDevice9* self, UINT width, UINT height, UINT levels, DWORD usage,
|
||||
D3DFORMAT format, D3DPOOL pool, IDirect3DTexture9** texture, HANDLE* shared_handle)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_CREATE_TEXTURE;
|
||||
irp.args.dev_create_texture.self = self;
|
||||
irp.args.dev_create_texture.width = width;
|
||||
irp.args.dev_create_texture.height = height;
|
||||
irp.args.dev_create_texture.levels = levels;
|
||||
irp.args.dev_create_texture.usage = usage;
|
||||
irp.args.dev_create_texture.format = format;
|
||||
irp.args.dev_create_texture.pool = pool;
|
||||
irp.args.dev_create_texture.texture = texture;
|
||||
irp.args.dev_create_texture.shared_handle = shared_handle;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_BeginScene(IDirect3DDevice9* self)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_BEGIN_SCENE;
|
||||
irp.args.dev_begin_scene.self = self;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_EndScene(IDirect3DDevice9* self)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_END_SCENE;
|
||||
irp.args.dev_end_scene.self = self;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_Present(IDirect3DDevice9* self,
|
||||
CONST RECT *pSourceRect, CONST RECT *pDestRect,
|
||||
HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_PRESENT;
|
||||
irp.args.dev_present.self = self;
|
||||
irp.args.dev_present.source_rect = pSourceRect;
|
||||
irp.args.dev_present.dest_rect = pDestRect;
|
||||
irp.args.dev_present.dest_window_override = hDestWindowOverride;
|
||||
irp.args.dev_present.dirty_region = pDirtyRegion;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_SetRenderState(IDirect3DDevice9* self,
|
||||
D3DRENDERSTATETYPE State, DWORD Value)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_RENDER_STATE;
|
||||
irp.args.dev_set_render_state.self = self;
|
||||
irp.args.dev_set_render_state.state = State;
|
||||
irp.args.dev_set_render_state.value = Value;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_DrawPrimitiveUP(
|
||||
IDirect3DDevice9* self, D3DPRIMITIVETYPE primitive_type,
|
||||
UINT primitive_count, const void *data, UINT stride)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP;
|
||||
irp.args.dev_draw_primitive_up.self = self;
|
||||
irp.args.dev_draw_primitive_up.primitive_type = primitive_type;
|
||||
irp.args.dev_draw_primitive_up.primitive_count = primitive_count;
|
||||
irp.args.dev_draw_primitive_up.data = data;
|
||||
irp.args.dev_draw_primitive_up.stride = stride;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_invoke_real(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
hook_d3d9_irp_handler_t handler;
|
||||
|
||||
log_assert(irp != NULL);
|
||||
log_assert(irp->op < lengthof(hook_d3d9_irp_real_handlers));
|
||||
|
||||
handler = hook_d3d9_irp_real_handlers[irp->op];
|
||||
|
||||
log_assert(handler != NULL);
|
||||
|
||||
return handler(irp);
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_invalid(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_fatal("Called invalid handler");
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_ctx_create(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
IDirect3D9* api;
|
||||
IDirect3D9Vtbl* api_vtbl;
|
||||
struct com_proxy* api_proxy;
|
||||
|
||||
log_assert(irp);
|
||||
|
||||
api = real_Direct3DCreate9(irp->args.ctx_create.sdk_ver);
|
||||
|
||||
if (api == NULL) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
|
||||
api_vtbl = api_proxy->vptr;
|
||||
|
||||
real_CreateDevice = api_vtbl->CreateDevice;
|
||||
api_vtbl->CreateDevice = my_CreateDevice;
|
||||
|
||||
irp->args.ctx_create.ctx = (IDirect3D9*) api_proxy;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_enum_display_devices(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
log_assert(irp);
|
||||
|
||||
res = real_EnumDisplayDevicesA(
|
||||
irp->args.enum_display_devices.dev_name,
|
||||
irp->args.enum_display_devices.dev_num,
|
||||
irp->args.enum_display_devices.info,
|
||||
irp->args.enum_display_devices.flags);
|
||||
|
||||
if (res == TRUE) {
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_create_window_ex(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
irp->args.create_window_ex.result = real_CreateWindowExA(
|
||||
irp->args.create_window_ex.ex_style,
|
||||
irp->args.create_window_ex.class_name,
|
||||
irp->args.create_window_ex.window_name,
|
||||
irp->args.create_window_ex.style,
|
||||
irp->args.create_window_ex.x,
|
||||
irp->args.create_window_ex.y,
|
||||
irp->args.create_window_ex.width,
|
||||
irp->args.create_window_ex.height,
|
||||
irp->args.create_window_ex.wnd_parent,
|
||||
irp->args.create_window_ex.menu,
|
||||
irp->args.create_window_ex.instance,
|
||||
irp->args.create_window_ex.param);
|
||||
|
||||
if (irp->args.create_window_ex.result) {
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_get_client_rect(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
log_assert(irp);
|
||||
|
||||
res = real_GetClientRect(
|
||||
irp->args.get_client_rect.wnd,
|
||||
irp->args.get_client_rect.rect);
|
||||
|
||||
if (res == TRUE) {
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_create_device(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDirect3DDevice9* api;
|
||||
IDirect3DDevice9Vtbl* api_vtbl;
|
||||
struct com_proxy *api_proxy;
|
||||
|
||||
log_assert(irp);
|
||||
|
||||
hr = real_CreateDevice(
|
||||
irp->args.ctx_create_device.self,
|
||||
irp->args.ctx_create_device.adapter,
|
||||
irp->args.ctx_create_device.type,
|
||||
irp->args.ctx_create_device.hwnd,
|
||||
irp->args.ctx_create_device.flags,
|
||||
irp->args.ctx_create_device.pp,
|
||||
irp->args.ctx_create_device.pdev);
|
||||
|
||||
if (hr != S_OK) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
api = *irp->args.ctx_create_device.pdev;
|
||||
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
|
||||
api_vtbl = api_proxy->vptr;
|
||||
|
||||
real_CreateTexture = api_vtbl->CreateTexture;
|
||||
api_vtbl->CreateTexture = my_CreateTexture;
|
||||
|
||||
real_BeginScene = api_vtbl->BeginScene;
|
||||
api_vtbl->BeginScene = my_BeginScene;
|
||||
|
||||
real_EndScene = api_vtbl->EndScene;
|
||||
api_vtbl->EndScene = my_EndScene;
|
||||
|
||||
real_Present = api_vtbl->Present;
|
||||
api_vtbl->Present = my_Present;
|
||||
|
||||
real_SetRenderState = api_vtbl->SetRenderState;
|
||||
api_vtbl->SetRenderState = my_SetRenderState;
|
||||
|
||||
real_DrawPrimitiveUP = api_vtbl->DrawPrimitiveUP;
|
||||
api_vtbl->DrawPrimitiveUP = my_DrawPrimitiveUP;
|
||||
|
||||
*irp->args.ctx_create_device.pdev = (IDirect3DDevice9*) api_proxy;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_create_texture(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_CreateTexture(
|
||||
irp->args.dev_create_texture.self,
|
||||
irp->args.dev_create_texture.width,
|
||||
irp->args.dev_create_texture.height,
|
||||
irp->args.dev_create_texture.levels,
|
||||
irp->args.dev_create_texture.usage,
|
||||
irp->args.dev_create_texture.format,
|
||||
irp->args.dev_create_texture.pool,
|
||||
irp->args.dev_create_texture.texture,
|
||||
irp->args.dev_create_texture.shared_handle);
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_begin_scene(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_BeginScene(irp->args.dev_begin_scene.self);
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_end_scene(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_EndScene(irp->args.dev_end_scene.self);
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_present(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_Present(
|
||||
irp->args.dev_present.self,
|
||||
irp->args.dev_present.source_rect,
|
||||
irp->args.dev_present.dest_rect,
|
||||
irp->args.dev_present.dest_window_override,
|
||||
irp->args.dev_present.dirty_region);
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_set_render_state(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_SetRenderState(
|
||||
irp->args.dev_set_render_state.self,
|
||||
irp->args.dev_set_render_state.state,
|
||||
irp->args.dev_set_render_state.value);
|
||||
}
|
||||
|
||||
static HRESULT hook_d3d9_irp_handler_real_dev_draw_primitive_up(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_DrawPrimitiveUP(
|
||||
irp->args.dev_draw_primitive_up.self,
|
||||
irp->args.dev_draw_primitive_up.primitive_type,
|
||||
irp->args.dev_draw_primitive_up.primitive_count,
|
||||
irp->args.dev_draw_primitive_up.data,
|
||||
irp->args.dev_draw_primitive_up.stride);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void hook_d3d9_init(const hook_d3d9_irp_handler_t *handlers, size_t nhandlers)
|
||||
{
|
||||
log_assert(handlers);
|
||||
log_assert(nhandlers > 0);
|
||||
|
||||
hook_d3d9_handlers = handlers;
|
||||
hook_d3d9_nhandlers = nhandlers;
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"d3d9.dll",
|
||||
hook_d3d9_hook_syms,
|
||||
lengthof(hook_d3d9_hook_syms));
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"user32.dll",
|
||||
hook_d3d9_hook_user32_syms,
|
||||
lengthof(hook_d3d9_hook_user32_syms));
|
||||
}
|
||||
|
||||
HRESULT hook_d3d9_irp_invoke_next(struct hook_d3d9_irp* irp)
|
||||
{
|
||||
hook_d3d9_irp_handler_t handler;
|
||||
HRESULT hr;
|
||||
|
||||
log_assert(irp != NULL);
|
||||
log_assert(irp->next_handler <= hook_d3d9_nhandlers);
|
||||
|
||||
if (irp->next_handler < hook_d3d9_nhandlers) {
|
||||
handler = hook_d3d9_handlers[irp->next_handler++];
|
||||
hr = handler(irp);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
irp->next_handler = (size_t) -1;
|
||||
}
|
||||
} else {
|
||||
irp->next_handler = (size_t) -1;
|
||||
hr = hook_d3d9_irp_handler_invoke_real(irp);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
192
src/main/hook/d3d9.h
Normal file
192
src/main/hook/d3d9.h
Normal file
@ -0,0 +1,192 @@
|
||||
#ifndef HOOK_D3D9_H
|
||||
#define HOOK_D3D9_H
|
||||
|
||||
/**
|
||||
* This module hooks the d3d9 API and abstracts it using IRPs (like iohook).
|
||||
* It allows hiding the COM stuff which is required to be handled when interacting with d3d9.
|
||||
* Furthermore, this module supports chaining of multiple handlers and more flexible and structured
|
||||
* dispatching on the available operations (more can be added when required, obviously).
|
||||
*
|
||||
* @author icex2
|
||||
*/
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* D3D9 ops (currently) supported by this hook module.
|
||||
*/
|
||||
enum hook_d3d9_irp_op {
|
||||
HOOK_D3D9_IRP_OP_INVALID = 0,
|
||||
HOOK_D3D9_IRP_OP_CTX_CREATE = 1,
|
||||
HOOK_D3D9_IRP_OP_ENUM_DISPLAY_DEVICES = 2,
|
||||
HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX = 3,
|
||||
HOOK_D3D9_IRP_OP_GET_CLIENT_RECT = 4,
|
||||
HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE = 5,
|
||||
HOOK_D3D9_IRP_OP_DEV_CREATE_TEXTURE = 6,
|
||||
HOOK_D3D9_IRP_OP_DEV_BEGIN_SCENE = 7,
|
||||
HOOK_D3D9_IRP_OP_DEV_END_SCENE = 8,
|
||||
HOOK_D3D9_IRP_OP_DEV_PRESENT = 9,
|
||||
HOOK_D3D9_IRP_OP_DEV_SET_RENDER_STATE = 10,
|
||||
HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP = 11,
|
||||
};
|
||||
|
||||
/**
|
||||
* Main irp structure which gets passed around as a parameter to chain multiple
|
||||
* handler calls and avoiding one handler per request/function.
|
||||
*/
|
||||
struct hook_d3d9_irp {
|
||||
enum hook_d3d9_irp_op op;
|
||||
|
||||
union {
|
||||
/**
|
||||
* Params of Direct3DCreate9.
|
||||
*/
|
||||
struct {
|
||||
UINT sdk_ver;
|
||||
// Return value of call
|
||||
IDirect3D9* ctx;
|
||||
} ctx_create;
|
||||
|
||||
/**
|
||||
* Params of EnumDisplayDevicesA.
|
||||
*/
|
||||
struct {
|
||||
const char* dev_name;
|
||||
DWORD dev_num;
|
||||
DISPLAY_DEVICEA* info;
|
||||
DWORD flags;
|
||||
} enum_display_devices;
|
||||
|
||||
/**
|
||||
* Params of CreateWindowExA.
|
||||
*/
|
||||
struct {
|
||||
DWORD ex_style;
|
||||
LPCSTR class_name;
|
||||
LPCSTR window_name;
|
||||
DWORD style;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
HWND wnd_parent;
|
||||
HMENU menu;
|
||||
HINSTANCE instance;
|
||||
LPVOID param;
|
||||
HWND result;
|
||||
} create_window_ex;
|
||||
|
||||
/**
|
||||
* Params of GetClientRect.
|
||||
*/
|
||||
struct {
|
||||
HWND wnd;
|
||||
LPRECT rect;
|
||||
} get_client_rect;
|
||||
|
||||
/**
|
||||
* Params of IDirect3D9_CreateDevice.
|
||||
*/
|
||||
struct {
|
||||
IDirect3D9* self;
|
||||
UINT adapter;
|
||||
D3DDEVTYPE type;
|
||||
HWND hwnd;
|
||||
DWORD flags;
|
||||
D3DPRESENT_PARAMETERS* pp;
|
||||
IDirect3DDevice9** pdev;
|
||||
} ctx_create_device;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_CreateTexture.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9* self;
|
||||
UINT width;
|
||||
UINT height;
|
||||
UINT levels;
|
||||
DWORD usage;
|
||||
D3DFORMAT format;
|
||||
D3DPOOL pool;
|
||||
IDirect3DTexture9** texture;
|
||||
HANDLE* shared_handle;
|
||||
} dev_create_texture;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_BeginScene.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9* self;
|
||||
} dev_begin_scene;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_EndScene.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9* self;
|
||||
} dev_end_scene;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_Present.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9* self;
|
||||
CONST RECT* source_rect;
|
||||
CONST RECT* dest_rect;
|
||||
HWND dest_window_override;
|
||||
CONST RGNDATA* dirty_region;
|
||||
} dev_present;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_SetRenderState.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9* self;
|
||||
D3DRENDERSTATETYPE state;
|
||||
DWORD value;
|
||||
} dev_set_render_state;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_DrawPrimitiveUP.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9* self;
|
||||
D3DPRIMITIVETYPE primitive_type;
|
||||
UINT primitive_count;
|
||||
const void *data;
|
||||
UINT stride;
|
||||
} dev_draw_primitive_up;
|
||||
} args;
|
||||
|
||||
size_t next_handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* D3D9 IRP handler function typedef.
|
||||
*/
|
||||
typedef HRESULT (*hook_d3d9_irp_handler_t)(struct hook_d3d9_irp* irp);
|
||||
|
||||
/**
|
||||
* Initialize the d3d9 hook module.
|
||||
*
|
||||
* @param handlers The handlers to install which will be called once one of the hooked functions is called.
|
||||
* @param nhandlers Number of handlers to install (length of provided array above).
|
||||
*/
|
||||
void hook_d3d9_init(const hook_d3d9_irp_handler_t *handlers, size_t nhandlers);
|
||||
|
||||
/**
|
||||
* Main invoke next function.
|
||||
*
|
||||
* Call this from your handlers if you are done handling and to pass on the IRP to the further installed IRP handlers.
|
||||
* At the end of the chain, calls the real function.
|
||||
*
|
||||
* @param irp Pointer to a valid IRP.
|
||||
* @return S_OK on success, error otherwise (depending on the irp op).
|
||||
*/
|
||||
HRESULT hook_d3d9_irp_invoke_next(struct hook_d3d9_irp* irp);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user