win-capture: Add get-graphics-offsets helper

Before, game capture would find addresses to important graphics
functions by creating a graphics context for the desired API inside of
the hook, and then find the function addresses that way.

The big problem with that is that the context could often cause the
hooked application to crash, especially if another hook was active.

This bypasses that entire need by a simple console application that
creates the contexts, finds the hook address offsets and then returns
them via console output.
master
jp9000 2014-11-10 14:56:57 -08:00
parent afbd376f71
commit f02342ac0c
8 changed files with 379 additions and 0 deletions

View File

@ -23,3 +23,5 @@ target_link_libraries(win-capture
psapi.lib)
install_obs_plugin_with_data(win-capture data)
add_subdirectory(get-graphics-offsets)

View File

@ -0,0 +1,33 @@
project(get-graphics-offsets)
set(get-graphics-offsets_HEADERS
../graphics-hook-info.h
../hook-helpers.h
get-graphics-offsets.h)
set(get-graphics-offsets_SOURCES
get-graphics-offsets.c
dxgi-offsets.cpp
d3d8-offsets.cpp
d3d9-offsets.cpp)
add_executable(get-graphics-offsets
${get-graphics-offsets_SOURCES}
${get-graphics-offsets_HEADERS})
target_link_libraries(get-graphics-offsets
d3d9.lib
dxgi.lib
d3d11.lib)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_output_suffix "64")
else()
set(_output_suffix "32")
endif()
set_target_properties(get-graphics-offsets
PROPERTIES
OUTPUT_NAME "get-graphics-offsets${_output_suffix}")
install_obs_datatarget(get-graphics-offsets "obs-plugins/win-capture")

View File

@ -0,0 +1,83 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include "../d3d8-api/d3d8.h"
#include "get-graphics-offsets.h"
typedef IDirect3D8 *(WINAPI *d3d8create_t)(UINT);
struct d3d8_info {
HMODULE module;
HWND hwnd;
IDirect3D8 *d3d8;
IDirect3DDevice8 *device;
};
static inline bool d3d8_init(d3d8_info &info)
{
d3d8create_t create;
HRESULT hr;
info.hwnd = CreateWindowExA(0, DUMMY_WNDCLASS, "d3d8 get-addr window",
WS_POPUP, 0, 0, 1, 1, nullptr, nullptr,
GetModuleHandleA(nullptr), nullptr);
if (!info.hwnd) {
return false;
}
info.module = LoadLibraryA("d3d8.dll");
if (!info.module) {
return false;
}
create = (d3d8create_t)GetProcAddress(info.module, "Direct3DCreate8");
if (!create) {
return false;
}
info.d3d8 = create(D3D_SDK_VERSION);
if (!info.d3d8) {
return false;
}
D3DPRESENT_PARAMETERS pp = {};
pp.Windowed = true;
pp.SwapEffect = D3DSWAPEFFECT_FLIP;
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
pp.BackBufferWidth = 2;
pp.BackBufferHeight = 2;
pp.BackBufferCount = 1;
pp.hDeviceWindow = info.hwnd;
hr = info.d3d8->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
info.hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp,
&info.device);
if (FAILED(hr)) {
return false;
}
return true;
}
static inline void d3d8_free(d3d8_info &info)
{
if (info.device)
info.device->Release();
if (info.d3d8)
info.d3d8->Release();
if (info.hwnd)
DestroyWindow(info.hwnd);
}
void get_d3d8_offsets(struct d3d8_offsets *offsets)
{
d3d8_info info = {};
bool success = d3d8_init(info);
if (success) {
offsets->present = vtable_offset(info.module, info.device, 15);
offsets->reset = vtable_offset(info.module, info.device, 14);
}
d3d8_free(info);
}

View File

@ -0,0 +1,100 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <d3d9.h>
#include "get-graphics-offsets.h"
typedef HRESULT (WINAPI *d3d9createex_t)(UINT, IDirect3D9Ex**);
struct d3d9_info {
HMODULE module;
HWND hwnd;
IDirect3D9Ex *d3d9ex;
IDirect3DDevice9Ex *device;
IDirect3DSwapChain9 *swap;
};
static inline bool d3d9_init(d3d9_info &info)
{
d3d9createex_t create;
HRESULT hr;
info.hwnd = CreateWindowExA(0, DUMMY_WNDCLASS, "d3d9 get-offset window",
WS_POPUP, 0, 0, 1, 1, nullptr, nullptr,
GetModuleHandleA(nullptr), nullptr);
if (!info.hwnd) {
return false;
}
info.module = LoadLibraryA("d3d9.dll");
if (!info.module) {
return false;
}
create = (d3d9createex_t)GetProcAddress(info.module,
"Direct3DCreate9Ex");
if (!create) {
return false;
}
hr = create(D3D_SDK_VERSION, &info.d3d9ex);
if (FAILED(hr)) {
return false;
}
D3DPRESENT_PARAMETERS pp = {};
pp.Windowed = true;
pp.SwapEffect = D3DSWAPEFFECT_FLIP;
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
pp.BackBufferWidth = 2;
pp.BackBufferHeight = 2;
pp.BackBufferCount = 1;
pp.hDeviceWindow = info.hwnd;
pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
hr = info.d3d9ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
info.hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING |
D3DCREATE_NOWINDOWCHANGES, &pp, nullptr, &info.device);
if (FAILED(hr)) {
return false;
}
hr = info.device->GetSwapChain(0, &info.swap);
if (FAILED(hr)) {
return false;
}
return true;
}
static inline void d3d9_free(d3d9_info &info)
{
if (info.swap)
info.swap->Release();
if (info.device)
info.device->Release();
if (info.d3d9ex)
info.d3d9ex->Release();
if (info.hwnd)
DestroyWindow(info.hwnd);
}
void get_d3d9_offsets(struct d3d9_offsets *offsets)
{
d3d9_info info = {};
bool success = d3d9_init(info);
if (success) {
offsets->present = vtable_offset(info.module, info.device, 17);
offsets->reset = vtable_offset(info.module, info.device, 16);
offsets->present_ex = vtable_offset(info.module, info.device,
121);
offsets->reset_ex = vtable_offset(info.module, info.device,
132);
offsets->present_swap = vtable_offset(info.module, info.swap,
3);
}
d3d9_free(info);
}

View File

@ -0,0 +1 @@
/* TODO */

View File

@ -0,0 +1,86 @@
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <d3d10.h>
#include <dxgi.h>
#include "get-graphics-offsets.h"
typedef HRESULT (WINAPI *d3d10create_t)(IDXGIAdapter*, D3D10_DRIVER_TYPE,
HMODULE, UINT, UINT, DXGI_SWAP_CHAIN_DESC*,
IDXGISwapChain**, IUnknown**);
struct dxgi_info {
HMODULE module;
HWND hwnd;
IDXGISwapChain *swap;
};
static inline bool dxgi_init(dxgi_info &info)
{
HMODULE d3d10_module;
d3d10create_t create;
IUnknown *device;
HRESULT hr;
info.hwnd = CreateWindowExA(0, DUMMY_WNDCLASS, "d3d10 get-offset window",
WS_POPUP, 0, 0, 2, 2, nullptr, nullptr,
GetModuleHandleA(nullptr), nullptr);
if (!info.hwnd) {
return false;
}
info.module = LoadLibraryA("dxgi.dll");
if (!info.module) {
return false;
}
d3d10_module = LoadLibraryA("d3d10.dll");
if (!d3d10_module) {
return false;
}
create = (d3d10create_t)GetProcAddress(d3d10_module,
"D3D10CreateDeviceAndSwapChain");
if (!create) {
return false;
}
DXGI_SWAP_CHAIN_DESC desc = {};
desc.BufferCount = 2;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.Width = 2;
desc.BufferDesc.Height = 2;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.OutputWindow = info.hwnd;
desc.SampleDesc.Count = 1;
desc.Windowed = true;
hr = create(nullptr, D3D10_DRIVER_TYPE_NULL, nullptr, 0,
D3D10_SDK_VERSION, &desc, &info.swap, &device);
if (FAILED(hr)) {
return false;
}
device->Release();
return true;
}
static inline void dxgi_free(dxgi_info &info)
{
if (info.swap)
info.swap->Release();
if (info.hwnd)
DestroyWindow(info.hwnd);
}
void get_dxgi_offsets(struct dxgi_offsets *offsets)
{
dxgi_info info = {};
bool success = dxgi_init(info);
if (success) {
offsets->present = vtable_offset(info.module, info.swap, 8);
offsets->resize = vtable_offset(info.module, info.swap, 13);
}
dxgi_free(info);
}

View File

@ -0,0 +1,44 @@
#define _CRT_SECURE_NO_WARNINGS
#include <inttypes.h>
#include <stdio.h>
#include <windows.h>
#include "get-graphics-offsets.h"
int main(int argc, char *argv[])
{
struct d3d8_offsets d3d8 = {0};
struct d3d9_offsets d3d9 = {0};
struct dxgi_offsets dxgi = {0};
WNDCLASSA wc = {0};
wc.style = CS_OWNDC;
wc.hInstance = GetModuleHandleA(NULL);
wc.lpfnWndProc = (WNDPROC)DefWindowProcA;
wc.lpszClassName = DUMMY_WNDCLASS;
if (!RegisterClassA(&wc)) {
printf("failed to register '%s'\n", DUMMY_WNDCLASS);
return -1;
}
get_d3d9_offsets(&d3d9);
get_d3d8_offsets(&d3d8);
get_dxgi_offsets(&dxgi);
printf("[d3d8]\n");
printf("present=0x%"PRIxPTR"\n", d3d8.present);
printf("reset=0x%"PRIxPTR"\n", d3d8.reset);
printf("[d3d9]\n");
printf("present=0x%"PRIxPTR"\n", d3d9.present);
printf("present_ex=0x%"PRIxPTR"\n", d3d9.present_ex);
printf("present_swap=0x%"PRIxPTR"\n", d3d9.present_swap);
printf("reset=0x%"PRIxPTR"\n", d3d9.reset);
printf("reset_ex=0x%"PRIxPTR"\n", d3d9.reset_ex);
printf("[dxgi]\n");
printf("present=0x%"PRIxPTR"\n", dxgi.present);
printf("resize=0x%"PRIxPTR"\n", dxgi.resize);
(void)argc;
(void)argv;
return 0;
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "../graphics-hook-info.h"
#define DUMMY_WNDCLASS "get_addrs_wndclass"
#ifdef __cplusplus
extern "C" {
#else
#ifndef inline
#define inline __inline
#endif
#endif
static inline uint32_t vtable_offset(HMODULE module, void *cls,
unsigned int offset)
{
uintptr_t *vtable = *(uintptr_t**)cls;
return (uint32_t)(vtable[offset] - (uintptr_t)module);
}
extern void get_dxgi_offsets(struct dxgi_offsets *offsets);
extern void get_d3d9_offsets(struct d3d9_offsets *offsets);
extern void get_d3d8_offsets(struct d3d8_offsets *offsets);
#ifdef __cplusplus
}
#endif