mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-04-22 17:47:38 -05:00
935 lines
24 KiB
C
935 lines
24 KiB
C
#define LOG_MODULE "hook-d3d9"
|
|
|
|
#include "hook/d3d9.h"
|
|
#include "hook/com-proxy.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 HRESULT(STDCALL *real_Reset)(
|
|
IDirect3DDevice9 *self, D3DPRESENT_PARAMETERS *pp);
|
|
|
|
static HRESULT(STDCALL *real_SetViewport)(
|
|
IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport);
|
|
|
|
static HRESULT(STDCALL *real_SetVertexShader)(
|
|
IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader);
|
|
|
|
static HRESULT(STDCALL *real_SetScissorRect)(
|
|
IDirect3DDevice9 *self, const RECT *pRect);
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
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 HRESULT STDCALL
|
|
my_Reset(IDirect3DDevice9 *self, D3DPRESENT_PARAMETERS *pp);
|
|
|
|
static HRESULT STDCALL
|
|
my_SetViewport(IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport);
|
|
|
|
static HRESULT STDCALL
|
|
my_SetVertexShader(IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader);
|
|
|
|
static HRESULT STDCALL
|
|
my_SetScissorRect(IDirect3DDevice9 *self, const RECT *pRect);
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
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 HRESULT hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp);
|
|
|
|
static HRESULT
|
|
hook_d3d9_irp_handler_real_dev_set_viewport(struct hook_d3d9_irp *irp);
|
|
|
|
static HRESULT
|
|
hook_d3d9_irp_handler_real_dev_set_vertex_shader(struct hook_d3d9_irp *irp);
|
|
|
|
static HRESULT
|
|
hook_d3d9_irp_handler_real_dev_set_scissor_rect(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,
|
|
[HOOK_D3D9_IRP_OP_DEV_RESET] = hook_d3d9_irp_handler_real_dev_reset,
|
|
[HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT] =
|
|
hook_d3d9_irp_handler_real_dev_set_viewport,
|
|
[HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER] =
|
|
hook_d3d9_irp_handler_real_dev_set_vertex_shader,
|
|
[HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT] =
|
|
hook_d3d9_irp_handler_real_dev_set_scissor_rect,
|
|
};
|
|
|
|
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 STDCALL
|
|
my_SetViewport(IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport)
|
|
{
|
|
struct hook_d3d9_irp irp;
|
|
HRESULT hr;
|
|
|
|
memset(&irp, 0, sizeof(irp));
|
|
|
|
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT;
|
|
irp.args.dev_set_viewport.self = self;
|
|
irp.args.dev_set_viewport.pViewport = pViewport;
|
|
|
|
hr = hook_d3d9_irp_invoke_next(&irp);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT STDCALL
|
|
my_SetVertexShader(IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader)
|
|
{
|
|
struct hook_d3d9_irp irp;
|
|
HRESULT hr;
|
|
|
|
memset(&irp, 0, sizeof(irp));
|
|
|
|
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER;
|
|
irp.args.dev_set_vertex_shader.self = self;
|
|
irp.args.dev_set_vertex_shader.pShader = pShader;
|
|
|
|
hr = hook_d3d9_irp_invoke_next(&irp);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT STDCALL
|
|
my_Reset(IDirect3DDevice9 *self, D3DPRESENT_PARAMETERS *pp)
|
|
{
|
|
struct hook_d3d9_irp irp;
|
|
HRESULT hr;
|
|
|
|
memset(&irp, 0, sizeof(irp));
|
|
|
|
irp.op = HOOK_D3D9_IRP_OP_DEV_RESET;
|
|
irp.args.dev_reset.self = self;
|
|
irp.args.dev_reset.pp = pp;
|
|
|
|
hr = hook_d3d9_irp_invoke_next(&irp);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT STDCALL
|
|
my_SetScissorRect(IDirect3DDevice9 *self, const RECT *pRect)
|
|
{
|
|
struct hook_d3d9_irp irp;
|
|
HRESULT hr;
|
|
|
|
memset(&irp, 0, sizeof(irp));
|
|
|
|
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT;
|
|
irp.args.dev_set_scissor_rect.self = self;
|
|
irp.args.dev_set_scissor_rect.pRect = pRect;
|
|
|
|
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;
|
|
HRESULT res;
|
|
|
|
log_assert(irp);
|
|
|
|
api = real_Direct3DCreate9(irp->args.ctx_create.sdk_ver);
|
|
|
|
if (api == NULL) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
res = com_proxy_wrap(&api_proxy, api, sizeof(*api->lpVtbl));
|
|
|
|
if (res != S_OK) {
|
|
log_fatal("Wrapping com proxy failed: %08lx", res);
|
|
}
|
|
|
|
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;
|
|
hr = com_proxy_wrap(&api_proxy, api, sizeof(*api->lpVtbl));
|
|
|
|
if (hr != S_OK) {
|
|
log_warning("Wrapping com proxy failed: %08lx", hr);
|
|
return hr;
|
|
}
|
|
|
|
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;
|
|
|
|
real_Reset = api_vtbl->Reset;
|
|
api_vtbl->Reset = my_Reset;
|
|
|
|
real_SetViewport = api_vtbl->SetViewport;
|
|
api_vtbl->SetViewport = my_SetViewport;
|
|
|
|
real_SetVertexShader = api_vtbl->SetVertexShader;
|
|
api_vtbl->SetVertexShader = my_SetVertexShader;
|
|
|
|
real_SetScissorRect = api_vtbl->SetScissorRect;
|
|
api_vtbl->SetScissorRect = my_SetScissorRect;
|
|
|
|
*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);
|
|
}
|
|
|
|
static HRESULT hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp)
|
|
{
|
|
log_assert(irp);
|
|
|
|
return real_Reset(irp->args.dev_reset.self, irp->args.dev_reset.pp);
|
|
}
|
|
|
|
static HRESULT
|
|
hook_d3d9_irp_handler_real_dev_set_viewport(struct hook_d3d9_irp *irp)
|
|
{
|
|
log_assert(irp);
|
|
|
|
return real_SetViewport(
|
|
irp->args.dev_set_viewport.self, irp->args.dev_set_viewport.pViewport);
|
|
}
|
|
|
|
static HRESULT
|
|
hook_d3d9_irp_handler_real_dev_set_vertex_shader(struct hook_d3d9_irp *irp)
|
|
{
|
|
log_assert(irp);
|
|
|
|
return real_SetVertexShader(
|
|
irp->args.dev_set_vertex_shader.self,
|
|
irp->args.dev_set_vertex_shader.pShader);
|
|
}
|
|
|
|
static HRESULT
|
|
hook_d3d9_irp_handler_real_dev_set_scissor_rect(struct hook_d3d9_irp *irp)
|
|
{
|
|
log_assert(irp);
|
|
|
|
return real_SetScissorRect(
|
|
irp->args.dev_set_scissor_rect.self,
|
|
irp->args.dev_set_scissor_rect.pRect);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
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;
|
|
} |