1
0
Fork 0
mirror of https://gitlab.com/Mr_Goldberg/goldberg_emulator.git synced 2024-11-14 10:50:13 +01:00

Added DirectX hooks

Warning: DX9 doesn't support resizing (TODO), DX12 has not beed tested and is not finished.
No OpenGL support for now.
This commit is contained in:
Nemirtingas 2019-07-25 23:21:03 +02:00
parent bb9c516775
commit 2ba8cae64e
13 changed files with 1656 additions and 0 deletions

View file

@ -0,0 +1,40 @@
#include "Base_Hook.h"
#include <algorithm>
#include "Hook_Manager.h"
#include "../detours/detours.h"
Base_Hook::~Base_Hook()
{
UnhookAll();
}
void Base_Hook::BeginHook()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
}
void Base_Hook::EndHook()
{
DetourTransactionCommit();
}
void Base_Hook::UnhookAll()
{
if (_hooked_funcs.size())
{
BeginHook();
std::for_each(_hooked_funcs.begin(), _hooked_funcs.end(), [](std::pair<void**, void*>& hook) {
DetourDetach(hook.first, hook.second);
});
EndHook();
_hooked_funcs.clear();
}
}
void Base_Hook::HookFuncs(std::pair<void**, void*> hook)
{
DetourAttach(hook.first, hook.second);
}

View file

@ -0,0 +1,43 @@
#ifndef __INCLUDED_BASE_HOOK_H__
#define __INCLUDED_BASE_HOOK_H__
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <Windows.h>
#include <vector>
#include <utility>
class Base_Hook
{
protected:
std::vector<std::pair<void**, void*>> _hooked_funcs;
HMODULE _dll;
bool _hooked;
Base_Hook(const Base_Hook&) = delete;
Base_Hook(Base_Hook&&) = delete;
Base_Hook& operator =(const Base_Hook&) = delete;
Base_Hook& operator =(Base_Hook&&) = delete;
public:
Base_Hook() {}
virtual ~Base_Hook();
void BeginHook();
void EndHook();
void UnhookAll();
void HookFuncs(std::pair<void**, void*> hook);
template<typename T, typename ...Args>
void HookFuncs(std::pair<T*, T> funcs, Args... args)
{
_hooked_funcs.emplace_back(std::move(funcs));
HookFuncs(funcs);
HookFuncs(args...);
}
};
#endif//__INCLUDED_BASE_HOOK_H__

View file

@ -0,0 +1,208 @@
#include "../dll/base.h"
#include "DX10_Hook.h"
#include "Hook_Manager.h"
#include "../detours/detours.h"
#include <imgui.h>
#include <impls/imgui_impl_win32.h>
#include <impls/imgui_impl_dx10.h>
// This is created by DX10_Hook::Create, and deleted by the Hook_Manager if not used
static DX10_Hook* hook;
void DX10_Hook::hook_dx10(UINT SDKVersion)
{
if (!_hooked)
{
PRINT_DEBUG("Hooked DirectX 10\n");
_hooked = true;
Hook_Manager::Inst().FoundHook(this);
IDXGISwapChain* pSwapChain;
ID3D10Device* pDevice;
DXGI_SWAP_CHAIN_DESC SwapChainDesc = {};
SwapChainDesc.BufferCount = 2;
SwapChainDesc.BufferDesc.Width = 800;
SwapChainDesc.BufferDesc.Height = 600;
SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.OutputWindow = GetForegroundWindow();
SwapChainDesc.SampleDesc.Count = 1;
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.Windowed = TRUE;
D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, SDKVersion, &SwapChainDesc, &pSwapChain, &pDevice);
loadFunctions(pDevice, pSwapChain);
UnhookAll();
BeginHook();
HookFuncs(
std::make_pair<void**, void*>(&(PVOID&)DX10_Hook::Present , &DX10_Hook::MyPresent),
std::make_pair<void**, void*>(&(PVOID&)DX10_Hook::ResizeTarget , &DX10_Hook::MyResizeTarget),
std::make_pair<void**, void*>(&(PVOID&)DX10_Hook::ResizeBuffers, &DX10_Hook::MyResizeBuffers)
);
EndHook();
pDevice->Release();
pSwapChain->Release();
}
}
void DX10_Hook::resetRenderState()
{
if (initialized)
{
mainRenderTargetView->Release();
ImGui_ImplDX10_Shutdown();
initialized = false;
}
}
void DX10_Hook::prepareForOverlay(IDXGISwapChain* pSwapChain)
{
DXGI_SWAP_CHAIN_DESC desc;
pSwapChain->GetDesc(&desc);
if (!initialized)
{
if (FAILED(pSwapChain->GetDevice(__uuidof(ID3D10Device), (PVOID*)& pDevice)))
return;
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = NULL;
ID3D10Texture2D* pBackBuffer;
pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)& pBackBuffer);
pDevice->CreateRenderTargetView(pBackBuffer, NULL, &mainRenderTargetView);
pBackBuffer->Release();
Hook_Manager::Inst().ChangeGameWindow(desc.OutputWindow);
ImGui_ImplWin32_Init(desc.OutputWindow);
ImGui_ImplDX10_Init(pDevice);
initialized = true;
}
ImGui_ImplDX10_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
Hook_Manager::Inst().CallOverlayProc(desc.BufferDesc.Width, desc.BufferDesc.Height);
ImGui::EndFrame();
ImGui::Render();
pDevice->OMSetRenderTargets(1, &mainRenderTargetView, NULL);
ImGui_ImplDX10_RenderDrawData(ImGui::GetDrawData());
}
/////////////////////////////////////////////////////////////////////////////////////
// DirectX 10 Initialization functions
//HRESULT WINAPI DX10_Hook::MyD3D10CreateDevice(IDXGIAdapter* pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, UINT SDKVersion, ID3D10Device** ppDevice)
//{
// auto res = _D3D10CreateDevice(pAdapter, DriverType, Software, Flags, SDKVersion, ppDevice);
//
// if (SUCCEEDED(res))
// hook->hook_dx10(SDKVersion);
//
// return res;
//}
HRESULT WINAPI DX10_Hook::MyD3D10CreateDeviceAndSwapChain(IDXGIAdapter* pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, UINT SDKVersion,
DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, IDXGISwapChain** ppSwapChain, ID3D10Device** ppDevice)
{
auto res = hook->D3D10CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice);
if (SUCCEEDED(res))
hook->hook_dx10(SDKVersion);
return res;
}
/////////////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DX10_Hook::MyPresent(IDXGISwapChain *_this, UINT SyncInterval, UINT Flags)
{
hook->prepareForOverlay(_this);
return (_this->*hook->Present)(SyncInterval, Flags);
}
HRESULT STDMETHODCALLTYPE DX10_Hook::MyResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters)
{
hook->resetRenderState();
return (_this->*hook->ResizeTarget)(pNewTargetParameters);
}
HRESULT STDMETHODCALLTYPE DX10_Hook::MyResizeBuffers(IDXGISwapChain* _this, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
hook->resetRenderState();
return (_this->*hook->ResizeBuffers)(BufferCount, Width, Height, NewFormat, SwapChainFlags);
}
DX10_Hook::DX10_Hook():
initialized(false),
pDevice(nullptr),
mainRenderTargetView(nullptr)
{
_dll = GetModuleHandle(DLL_NAME);
_hooked = false;
// Hook to D3D10CreateDevice and D3D10CreateDeviceAndSwapChain so we know when it gets called.
// If its called, then DX10 will be used to render the overlay.
//_D3D10CreateDevice = (decltype(_D3D10CreateDevice))GetProcAddress(_dll, "D3D10CreateDevice");
D3D10CreateDeviceAndSwapChain = (decltype(D3D10CreateDeviceAndSwapChain))GetProcAddress(_dll, "D3D10CreateDeviceAndSwapChain");
BeginHook();
HookFuncs(
//std::make_pair<void**, void*>(&(PVOID&)_D3D10CreateDevice, &DX10_Hook::MyD3D10CreateDevice),
std::make_pair<void**, void*>(&(PVOID&)D3D10CreateDeviceAndSwapChain, &DX10_Hook::MyD3D10CreateDeviceAndSwapChain)
);
EndHook();
}
DX10_Hook::~DX10_Hook()
{
PRINT_DEBUG("DX10 Hook removed\n");
if (_hooked)
{
ImGui_ImplDX10_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
hook = nullptr;
}
void DX10_Hook::Create()
{
if (hook == nullptr)
{
hook = new DX10_Hook;
// Register the hook to the Hook Manager
Hook_Manager::Inst().AddHook(hook);
}
}
void DX10_Hook::loadFunctions(ID3D10Device *pDevice, IDXGISwapChain *pSwapChain)
{
void** vTable = *reinterpret_cast<void***>(pDevice);
#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D10DeviceVTable::X]
#undef LOAD_FUNC
vTable = *reinterpret_cast<void***>(pSwapChain);
#define LOAD_FUNC(X) (void*&)X = vTable[(int)IDXGISwapChainVTable::X]
LOAD_FUNC(Present);
LOAD_FUNC(ResizeBuffers);
LOAD_FUNC(ResizeTarget);
#undef LOAD_FUNC
}

View file

@ -0,0 +1,49 @@
#ifndef __INCLUDED_DX10_HOOK_H__
#define __INCLUDED_DX10_HOOK_H__
#include <d3d10.h>
#include "DirectX_VTables.h"
#include "Base_Hook.h"
class DX10_Hook : public Base_Hook
{
public:
static constexpr const char DLL_NAME[] = "d3d10.dll";
private:
// Variables
bool initialized;
ID3D10Device* pDevice;
ID3D10RenderTargetView* mainRenderTargetView;
// Functions
DX10_Hook();
virtual ~DX10_Hook();
void hook_dx10(UINT SDKVersion);
void resetRenderState();
void prepareForOverlay(IDXGISwapChain *pSwapChain);
// Hook to render functions
static HRESULT STDMETHODCALLTYPE MyPresent(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags);
static HRESULT STDMETHODCALLTYPE MyResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters);
static HRESULT STDMETHODCALLTYPE MyResizeBuffers(IDXGISwapChain* _this, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
decltype(&IDXGISwapChain::Present) Present;
decltype(&IDXGISwapChain::ResizeBuffers) ResizeBuffers;
decltype(&IDXGISwapChain::ResizeTarget) ResizeTarget;
// Hook functions so we know we use DX10
//static decltype(D3D10CreateDevice) MyD3D10CreateDevice;
static decltype(D3D10CreateDeviceAndSwapChain) MyD3D10CreateDeviceAndSwapChain;
//decltype(D3D10CreateDevice)* _D3D10CreateDevice;
decltype(D3D10CreateDeviceAndSwapChain)* D3D10CreateDeviceAndSwapChain;
public:
static void Create(); // Initialize DX10 Hook.
void loadFunctions(ID3D10Device *pDevice, IDXGISwapChain *pSwapChain);
};
#endif//__INCLUDED_DX10_HOOK_H__

View file

@ -0,0 +1,224 @@
#include "../dll/base.h"
#include "DX11_Hook.h"
#include "Hook_Manager.h"
#include <imgui.h>
#include <impls/imgui_impl_win32.h>
#include <impls/imgui_impl_dx11.h>
// This is created by DX11_Hook::Create, and deleted by the Hook_Manager if not used
static DX11_Hook* hook;
HRESULT GetDeviceAndCtxFromSwapchain(IDXGISwapChain* pSwapChain, ID3D11Device** ppDevice, ID3D11DeviceContext** ppContext)
{
HRESULT ret = pSwapChain->GetDevice(__uuidof(ID3D11Device), (PVOID*)ppDevice);
if (SUCCEEDED(ret))
(*ppDevice)->GetImmediateContext(ppContext);
return ret;
}
void DX11_Hook::hook_dx11(UINT SDKVersion)
{
if (!_hooked)
{
PRINT_DEBUG("Hooked DirectX 11\n");
_hooked = true;
Hook_Manager::Inst().FoundHook(this);
IDXGISwapChain* pSwapChain;
ID3D11Device* pDevice;
DXGI_SWAP_CHAIN_DESC SwapChainDesc = {};
SwapChainDesc.BufferCount = 2;
SwapChainDesc.BufferDesc.Width = 800;
SwapChainDesc.BufferDesc.Height = 600;
SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.OutputWindow = GetForegroundWindow();
SwapChainDesc.SampleDesc.Count = 1;
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.Windowed = TRUE;
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, NULL, SDKVersion, &SwapChainDesc, &pSwapChain, &pDevice, NULL, NULL);
loadFunctions(pDevice, pSwapChain);
UnhookAll();
BeginHook();
HookFuncs(
std::make_pair<void**, void*>(&(PVOID&)DX11_Hook::Present , &DX11_Hook::MyPresent),
std::make_pair<void**, void*>(&(PVOID&)DX11_Hook::ResizeTarget , &DX11_Hook::MyResizeTarget),
std::make_pair<void**, void*>(&(PVOID&)DX11_Hook::ResizeBuffers, &DX11_Hook::MyResizeBuffers)
);
EndHook();
pDevice->Release();
pSwapChain->Release();
}
}
void DX11_Hook::resetRenderState()
{
if (initialized)
{
mainRenderTargetView->Release();
pContext->Release();
ImGui_ImplDX11_Shutdown();
initialized = false;
}
}
void DX11_Hook::prepareForOverlay(IDXGISwapChain* pSwapChain)
{
DXGI_SWAP_CHAIN_DESC desc;
pSwapChain->GetDesc(&desc);
if (!initialized)
{
ID3D11Device* pDevice = nullptr;
if (FAILED(GetDeviceAndCtxFromSwapchain(pSwapChain, &pDevice, &pContext)))
return;
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = NULL;
ID3D11Texture2D* pBackBuffer;
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)& pBackBuffer);
pDevice->CreateRenderTargetView(pBackBuffer, NULL, &mainRenderTargetView);
pBackBuffer->Release();
Hook_Manager::Inst().ChangeGameWindow(desc.OutputWindow);
ImGui_ImplWin32_Init(desc.OutputWindow);
ImGui_ImplDX11_Init(pDevice, pContext);
initialized = true;
}
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
Hook_Manager::Inst().CallOverlayProc(desc.BufferDesc.Width, desc.BufferDesc.Height);
ImGui::EndFrame();
ImGui::Render();
pContext->OMSetRenderTargets(1, &mainRenderTargetView, NULL);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}
/////////////////////////////////////////////////////////////////////////////////////
// DirectX 11 Initialization functions
//HRESULT WINAPI DX11_Hook::MyD3D11CreateDevice(__in_opt IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags,
// __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, __out_opt ID3D11Device** ppDevice,
// __out_opt D3D_FEATURE_LEVEL* pFeatureLevel, __out_opt ID3D11DeviceContext** ppImmediateContext)
//{
// auto res = _D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext);
//
// if (SUCCEEDED(res))
// hook->hook_dx11(SDKVersion);
//
// return res;
//}
HRESULT WINAPI DX11_Hook::MyD3D11CreateDeviceAndSwapChain(__in_opt IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags,
__in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, UINT SDKVersion,
__in_opt CONST DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, __out_opt IDXGISwapChain** ppSwapChain, __out_opt ID3D11Device** ppDevice,
__out_opt D3D_FEATURE_LEVEL* pFeatureLevel, __out_opt ID3D11DeviceContext** ppImmediateContext)
{
auto res = hook->D3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
if (SUCCEEDED(res))
hook->hook_dx11(SDKVersion);
return res;
}
/////////////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DX11_Hook::MyPresent(IDXGISwapChain *_this, UINT SyncInterval, UINT Flags)
{
hook->prepareForOverlay(_this);
return (_this->*hook->Present)(SyncInterval, Flags);
}
HRESULT STDMETHODCALLTYPE DX11_Hook::MyResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters)
{
hook->resetRenderState();
return (_this->*hook->ResizeTarget)(pNewTargetParameters);
}
HRESULT STDMETHODCALLTYPE DX11_Hook::MyResizeBuffers(IDXGISwapChain* _this, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
hook->resetRenderState();
return (_this->*hook->ResizeBuffers)(BufferCount, Width, Height, NewFormat, SwapChainFlags);
}
DX11_Hook::DX11_Hook():
initialized(false),
pContext(nullptr),
mainRenderTargetView(nullptr)
{
_dll = GetModuleHandle(DLL_NAME);
_hooked = false;
// Hook to D3D11CreateDevice and D3D11CreateDeviceAndSwapChain so we know when it gets called.
// If its called, then DX11 will be used to render the overlay.
//_D3D11CreateDevice = (decltype(_D3D11CreateDevice))GetProcAddress(_dll, "D3D11CreateDevice");
D3D11CreateDeviceAndSwapChain = (decltype(D3D11CreateDeviceAndSwapChain))GetProcAddress(_dll, "D3D11CreateDeviceAndSwapChain");
BeginHook();
HookFuncs(
//std::make_pair<void**, void*>(&(PVOID&)_D3D11CreateDevice, &DX11_Hook::MyD3D11CreateDevice),
std::make_pair<void**, void*>(&(PVOID&)D3D11CreateDeviceAndSwapChain, &DX11_Hook::MyD3D11CreateDeviceAndSwapChain)
);
EndHook();
}
DX11_Hook::~DX11_Hook()
{
PRINT_DEBUG("DX11 Hook removed\n");
if (_hooked)
{
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
hook = nullptr;
}
void DX11_Hook::Create()
{
if (hook == nullptr)
{
hook = new DX11_Hook;
// Register the hook to the Hook Manager
Hook_Manager::Inst().AddHook(hook);
}
}
void DX11_Hook::loadFunctions(ID3D11Device *pDevice, IDXGISwapChain *pSwapChain)
{
void** vTable = *reinterpret_cast<void***>(pDevice);
#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D11DeviceVTable::X]
#undef LOAD_FUNC
vTable = *reinterpret_cast<void***>(pSwapChain);
#define LOAD_FUNC(X) (void*&)X = vTable[(int)IDXGISwapChainVTable::X]
LOAD_FUNC(Present);
LOAD_FUNC(ResizeBuffers);
LOAD_FUNC(ResizeTarget);
#undef LOAD_FUNC
}

View file

@ -0,0 +1,49 @@
#ifndef __INCLUDED_DX11_HOOK_H__
#define __INCLUDED_DX11_HOOK_H__
#include <d3d11.h>
#include "DirectX_VTables.h"
#include "Base_Hook.h"
class DX11_Hook : public Base_Hook
{
public:
static constexpr const char DLL_NAME[] = "d3d11.dll";
private:
// Variables
bool initialized;
ID3D11DeviceContext* pContext;
ID3D11RenderTargetView* mainRenderTargetView;
// Functions
DX11_Hook();
virtual ~DX11_Hook();
void hook_dx11(UINT SDKVersion);
void resetRenderState();
void prepareForOverlay(IDXGISwapChain* pSwapChain);
// Hook to render functions
static HRESULT STDMETHODCALLTYPE MyPresent(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags);
static HRESULT STDMETHODCALLTYPE MyResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters);
static HRESULT STDMETHODCALLTYPE MyResizeBuffers(IDXGISwapChain* _this, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
decltype(&IDXGISwapChain::Present) Present;
decltype(&IDXGISwapChain::ResizeBuffers) ResizeBuffers;
decltype(&IDXGISwapChain::ResizeTarget) ResizeTarget;
// Hook functions so we know we use DX11
//static decltype(D3D11CreateDevice) MyD3D11CreateDevice;
static decltype(D3D11CreateDeviceAndSwapChain) MyD3D11CreateDeviceAndSwapChain;
//decltype(D3D11CreateDevice)* D3D11CreateDevice;
decltype(D3D11CreateDeviceAndSwapChain)* D3D11CreateDeviceAndSwapChain;
public:
static void Create(); // Initialize DX11 Hook.
void loadFunctions(ID3D11Device *pDevice, IDXGISwapChain *pSwapChain);
};
#endif//__INCLUDED_DX11_HOOK_H__

View file

@ -0,0 +1,186 @@
#include "../dll/base.h"
#include "DX12_Hook.h"
#include "Hook_Manager.h"
#include <imgui.h>
#include <impls/imgui_impl_win32.h>
#include <impls/imgui_impl_dx12.h>
// This is created by DX12_Hook::Create, and deleted by the Hook_Manager if not used
static DX12_Hook* hook;
void DX12_Hook::hook_dx12(D3D_FEATURE_LEVEL MinimumFeatureLevel)
{
if (!_hooked)
{
PRINT_DEBUG("Hooked DirectX 12\n");
}
}
void DX12_Hook::resetRenderState()
{
if (initialized)
{
pCmdAlloc->Release();
pCmdList->Release();
pDescriptorHeap->Release();
ImGui_ImplDX12_Shutdown();
initialized = false;
}
}
void DX12_Hook::prepareForOverlay(IDXGISwapChain* pSwapChain)
{
DXGI_SWAP_CHAIN_DESC desc;
pSwapChain->GetDesc(&desc);
if (!initialized)
{
D3D12_DESCRIPTOR_HEAP_DESC d3d12_desc = {};
ID3D12Device* pDevice;
HRESULT ret = pSwapChain->GetDevice(__uuidof(ID3D12Device), (PVOID*)&pDevice);
d3d12_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
d3d12_desc.NumDescriptors = 1;
d3d12_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
d3d12_desc.NodeMask = 1;
if (pDevice->CreateDescriptorHeap(&d3d12_desc, IID_PPV_ARGS(&pDescriptorHeap)) != S_OK)
{
pDevice->Release();
return;
}
SIZE_T rtvDescriptorSize = pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = pDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
mainRenderTargetDescriptor = rtvHandle;
pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pCmdAlloc));
pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, pCmdAlloc, NULL, IID_PPV_ARGS(&pCmdList));
Hook_Manager::Inst().ChangeGameWindow(desc.OutputWindow);
ImGui_ImplWin32_Init(desc.OutputWindow);
ImGui_ImplDX12_Init(pDevice, 1, DXGI_FORMAT_R8G8B8A8_UNORM,
pDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
pDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
initialized = true;
}
ImGui_ImplDX12_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
Hook_Manager::Inst().CallOverlayProc(desc.BufferDesc.Width, desc.BufferDesc.Height);
ImGui::EndFrame();
ImGui::Render();
pCmdAlloc->Reset();
pCmdList->Reset(pCmdAlloc, NULL);
//pCmdList->ClearRenderTargetView(mainRenderTargetDescriptor, (float*)& clear_color, 0, NULL);
pCmdList->OMSetRenderTargets(1, &mainRenderTargetDescriptor, FALSE, NULL);
pCmdList->SetDescriptorHeaps(1, &pDescriptorHeap);
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), pCmdList);
}
/////////////////////////////////////////////////////////////////////////////////////
// DirectX 12 Initialization functions
HRESULT WINAPI DX12_Hook::MyD3D12CreateDevice(
_In_opt_ IUnknown* pAdapter,
D3D_FEATURE_LEVEL MinimumFeatureLevel,
_In_ REFIID riid, // Expected: ID3D12Device
_COM_Outptr_opt_ void** ppDevice)
{
auto res = hook->D3D12CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice);
if (SUCCEEDED(res))
hook->hook_dx12(MinimumFeatureLevel);
return res;
}
/////////////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DX12_Hook::MyPresent(IDXGISwapChain *_this, UINT SyncInterval, UINT Flags)
{
hook->prepareForOverlay(_this);
return (_this->*hook->Present)(SyncInterval, Flags);
}
HRESULT STDMETHODCALLTYPE DX12_Hook::MyResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters)
{
hook->resetRenderState();
return (_this->*hook->ResizeTarget)(pNewTargetParameters);
}
HRESULT STDMETHODCALLTYPE DX12_Hook::MyResizeBuffers(IDXGISwapChain* _this, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
hook->resetRenderState();
return (_this->*hook->ResizeBuffers)(BufferCount, Width, Height, NewFormat, SwapChainFlags);
}
DX12_Hook::DX12_Hook():
initialized(false),
pCmdAlloc(nullptr),
pCmdList(nullptr),
pDescriptorHeap(nullptr)
{
_dll = GetModuleHandle(DLL_NAME);
_hooked = false;
// Hook to D3D11CreateDevice and D3D11CreateDeviceAndSwapChain so we know when it gets called.
// If its called, then DX11 will be used to render the overlay.
D3D12CreateDevice = (decltype(D3D12CreateDevice))GetProcAddress(_dll, "D3D12CreateDevice");
BeginHook();
HookFuncs(
std::make_pair<void**, void*>(&(PVOID&)D3D12CreateDevice, &DX12_Hook::MyD3D12CreateDevice)
);
EndHook();
}
DX12_Hook::~DX12_Hook()
{
PRINT_DEBUG("DX11 Hook removed\n");
if (_hooked)
{
ImGui_ImplDX12_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
hook = nullptr;
}
void DX12_Hook::Create()
{
if (hook == nullptr)
{
hook = new DX12_Hook;
// Register the hook to the Hook Manager
Hook_Manager::Inst().AddHook(hook);
}
}
void DX12_Hook::loadFunctions(ID3D12Device *pDevice, IDXGISwapChain *pSwapChain)
{
void** vTable = *reinterpret_cast<void***>(pDevice);
/*
#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D12DeviceVTable::X]
#undef LOAD_FUNC
*/
vTable = *reinterpret_cast<void***>(pSwapChain);
#define LOAD_FUNC(X) (void*&)X = vTable[(int)IDXGISwapChainVTable::X]
LOAD_FUNC(Present);
LOAD_FUNC(ResizeBuffers);
LOAD_FUNC(ResizeTarget);
#undef LOAD_FUNC
}

View file

@ -0,0 +1,49 @@
#ifndef __INCLUDED_DX12_HOOK_H__
#define __INCLUDED_DX12_HOOK_H__
#include <d3d12.h>
#include "DirectX_VTables.h"
#include "Base_Hook.h"
class DX12_Hook : public Base_Hook
{
public:
static constexpr const char DLL_NAME[] = "d3d12.dll";
private:
// Variables
bool initialized;
ID3D12CommandAllocator* pCmdAlloc;
ID3D12GraphicsCommandList* pCmdList;
ID3D12DescriptorHeap* pDescriptorHeap;
D3D12_CPU_DESCRIPTOR_HANDLE mainRenderTargetDescriptor;
// Functions
DX12_Hook();
virtual ~DX12_Hook();
void hook_dx12(D3D_FEATURE_LEVEL MinimumFeatureLevel);
void resetRenderState();
void prepareForOverlay(IDXGISwapChain* pSwapChain);
// Hook to render functions
static HRESULT STDMETHODCALLTYPE MyPresent(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags);
static HRESULT STDMETHODCALLTYPE MyResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters);
static HRESULT STDMETHODCALLTYPE MyResizeBuffers(IDXGISwapChain* _this, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
decltype(&IDXGISwapChain::Present) Present;
decltype(&IDXGISwapChain::ResizeBuffers) ResizeBuffers;
decltype(&IDXGISwapChain::ResizeTarget) ResizeTarget;
// Hook functions so we know we use DX11
static decltype(D3D12CreateDevice) MyD3D12CreateDevice;
decltype(D3D12CreateDevice)* D3D12CreateDevice;
public:
static void Create(); // Initialize DX11 Hook.
void loadFunctions(ID3D12Device *pDevice, IDXGISwapChain *pSwapChain);
};
#endif//__INCLUDED_DX12_HOOK_H__

View file

@ -0,0 +1,204 @@
#include "../dll/base.h"
#include "DX9_Hook.h"
#include "Hook_Manager.h"
#include <imgui.h>
#include <impls/imgui_impl_win32.h>
#include <impls/imgui_impl_dx9.h>
static DX9_Hook* hook;
//////////////////////////////////////////////////////////////////
///////// /////////
///////// This hook doesn't support game resize for now /////////
///////// /////////
//////////////////////////////////////////////////////////////////
void DX9_Hook::hook_dx9(UINT SDKVersion)
{
if (!_hooked)
{
PRINT_DEBUG("Hooked DirectX 9\n");
_hooked = true;
Hook_Manager::Inst().FoundHook(this);
IDirect3D9Ex* pD3D;
IDirect3DDevice9Ex* pDevice;
Direct3DCreate9Ex(SDKVersion, &pD3D);
D3DPRESENT_PARAMETERS params = {};
params.BackBufferWidth = 1;
params.BackBufferHeight = 1;
params.hDeviceWindow = GetForegroundWindow();
pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &params, NULL, &pDevice);
loadFunctions(pDevice);
UnhookAll();
BeginHook();
HookFuncs(
//std::make_pair<void**, void*>(&(PVOID&)Reset, &DX9_Hook::MyReset),
std::make_pair<void**, void*>(&(PVOID&)Present, &DX9_Hook::MyPresent),
std::make_pair<void**, void*>(&(PVOID&)PresentEx, &DX9_Hook::MyPresentEx)
//std::make_pair<void**, void*>(&(PVOID&)EndScene, &DX9_Hook::MyEndScene)
);
EndHook();
pDevice->Release();
pD3D->Release();
}
}
void DX9_Hook::resetRenderState()
{
if (initialized)
{
initialized = false;
ImGui_ImplDX9_Shutdown();
}
}
void DX9_Hook::prepareForOverlay(IDirect3DDevice9 *pDevice)
{
IDirect3DSwapChain9* pSwapChain;
pDevice->GetSwapChain(0, &pSwapChain);
D3DPRESENT_PARAMETERS PresentParameters;
pSwapChain->GetPresentParameters(&PresentParameters);
pSwapChain->Release();
if (!initialized)
{
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = NULL;
D3DDEVICE_CREATION_PARAMETERS param;
pDevice->GetCreationParameters(&param);
Hook_Manager::Inst().ChangeGameWindow(param.hFocusWindow);
ImGui_ImplWin32_Init(param.hFocusWindow);
ImGui_ImplDX9_Init(pDevice);
initialized = true;
}
ImGui_ImplDX9_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
Hook_Manager::Inst().CallOverlayProc(PresentParameters.BackBufferWidth, PresentParameters.BackBufferHeight);
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
}
/////////////////////////////////////////////////////////////////////////////////////
// DirectX 9 Initialization functions
IDirect3D9* DX9_Hook::MyDirect3DCreate9(UINT SDKVersion)
{
auto res = hook->Direct3DCreate9(SDKVersion);
if( res != nullptr )
hook->hook_dx9(SDKVersion);
return res;
}
HRESULT DX9_Hook::MyDirect3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppDevice)
{
auto res = hook->Direct3DCreate9Ex(SDKVersion, ppDevice);
if (SUCCEEDED(res))
hook->hook_dx9(SDKVersion);
return res;
}
/////////////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DX9_Hook::MyReset(IDirect3DDevice9* _this, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
hook->resetRenderState();
return (_this->*hook->Reset)(pPresentationParameters);
}
HRESULT STDMETHODCALLTYPE DX9_Hook::MyEndScene(IDirect3DDevice9* _this)
{
//if( !hook->uses_present )
hook->prepareForOverlay(_this);
return (_this->*hook->EndScene)();
}
HRESULT STDMETHODCALLTYPE DX9_Hook::MyPresent(IDirect3DDevice9* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion)
{
hook->prepareForOverlay(_this);
return (_this->*hook->Present)(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
}
HRESULT STDMETHODCALLTYPE DX9_Hook::MyPresentEx(IDirect3DDevice9Ex* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags)
{
hook->prepareForOverlay(_this);
return (_this->*hook->PresentEx)(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
}
DX9_Hook::DX9_Hook():
initialized(false),
uses_present(false)
{
_dll = GetModuleHandle(DLL_NAME);
_hooked = false;
// Hook to Direct3DCreate9 and Direct3DCreate9Ex so we know when it gets called.
// If its called, then DX9 will be used to render the overlay.
Direct3DCreate9 = (decltype(Direct3DCreate9))GetProcAddress(_dll, "Direct3DCreate9");
Direct3DCreate9Ex = (decltype(Direct3DCreate9Ex))GetProcAddress(_dll, "Direct3DCreate9Ex");
BeginHook();
HookFuncs(
std::make_pair<void**, void*>(&(PVOID&)Direct3DCreate9, &DX9_Hook::MyDirect3DCreate9),
std::make_pair<void**, void*>(&(PVOID&)Direct3DCreate9Ex, &DX9_Hook::MyDirect3DCreate9Ex)
);
EndHook();
}
DX9_Hook::~DX9_Hook()
{
PRINT_DEBUG("DX9 Hook removed\n");
if (_hooked)
{
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
hook = nullptr;
}
void DX9_Hook::Create()
{
if( hook == nullptr )
{
hook = new DX9_Hook;
// Register the hook to the Hook Manager
Hook_Manager::Inst().AddHook(hook);
}
}
void DX9_Hook::loadFunctions(IDirect3DDevice9Ex* obj)
{
void** vTable = *reinterpret_cast<void***>(obj);
#define LOAD_FUNC(X) (void*&)X = vTable[(int)IDirect3DDevice9VTable::X]
LOAD_FUNC(Reset);
LOAD_FUNC(EndScene);
LOAD_FUNC(Present);
LOAD_FUNC(PresentEx);
#undef LOAD_FUNC
}

View file

@ -0,0 +1,50 @@
#ifndef __INCLUDED_DX9_HOOK_H__
#define __INCLUDED_DX9_HOOK_H__
#include <d3d9.h>
#include "DirectX_VTables.h"
#include "Base_Hook.h"
class DX9_Hook : public Base_Hook
{
public:
static constexpr const char DLL_NAME[] = "d3d9.dll";
private:
// Variables
bool initialized;
bool uses_present;
// Functions
DX9_Hook();
virtual ~DX9_Hook();
void hook_dx9(UINT SDKVersion);
void resetRenderState();
void prepareForOverlay(IDirect3DDevice9* pDevice);
// Hook to render functions
decltype(&IDirect3DDevice9::Reset) Reset;
decltype(&IDirect3DDevice9::EndScene) EndScene;
decltype(&IDirect3DDevice9::Present) Present;
decltype(&IDirect3DDevice9Ex::PresentEx) PresentEx;
static HRESULT STDMETHODCALLTYPE MyReset(IDirect3DDevice9* _this, D3DPRESENT_PARAMETERS* pPresentationParameters);
static HRESULT STDMETHODCALLTYPE MyEndScene(IDirect3DDevice9 *_this);
static HRESULT STDMETHODCALLTYPE MyPresent(IDirect3DDevice9* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion);
static HRESULT STDMETHODCALLTYPE MyPresentEx(IDirect3DDevice9Ex* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags);
// Hook functions so we know we use DX9
static decltype(Direct3DCreate9) MyDirect3DCreate9;
static decltype(Direct3DCreate9Ex) MyDirect3DCreate9Ex;
decltype(Direct3DCreate9)* Direct3DCreate9;
decltype(Direct3DCreate9Ex)* Direct3DCreate9Ex;
public:
static void Create(); // Initialize DX9 Hook.
void loadFunctions(IDirect3DDevice9Ex *obj);
};
#endif//__INCLUDED_DX9_HOOK_H__

View file

@ -0,0 +1,330 @@
#pragma once
#include <DXGI.h>
enum class IDXGISwapChainVTable
{
// IUnknown
QueryInterface,
AddRef,
Release,
// IDXGIObject
SetPrivateData,
SetPrivateDataInterface,
GetPrivateData,
GetParent,
// IDXGIDeviceSubObject
GetDevice,
// IDXGISwapChain
Present,
GetBuffer,
SetFullscreenState,
GetFullscreenState,
GetDesc,
ResizeBuffers,
ResizeTarget,
GetContainingOutput,
GetFrameStatistics,
GetLastPresentCount,
};
enum class ID3D11DeviceVTable
{
// IUnknown
QueryInterface,
AddRef,
Release,
// ID3D11Device
CreateBuffer,
CreateTexture1D,
CreateTexture2D,
CreateTexture3D,
CreateShaderResourceView,
CreateUnorderedAccessView,
CreateRenderTargetView,
CreateDepthStencilView,
CreateInputLayout,
CreateVertexShader,
CreateGeometryShader,
CreateGeometryShaderWithStreamOutput,
CreatePixelShader,
CreateHullShader,
CreateDomainShader,
CreateComputeShader,
CreateClassLinkage,
CreateBlendState,
CreateDepthStencilState,
CreateRasterizerState,
CreateSamplerState,
CreateQuery,
CreatePredicate,
CreateCounter,
CreateDeferredContext,
OpenSharedResource,
CheckFormatSupport,
CheckMultisampleQualityLevels,
CheckCounterInfo,
CheckCounter,
CheckFeatureSupport,
GetPrivateData,
SetPrivateData,
SetPrivateDataInterface,
GetFeatureLevel,
GetCreationFlags,
GetDeviceRemovedReason,
GetImmediateContext,
SetExceptionMode,
GetExceptionMode,
};
enum class ID3D10DeviceVTable
{
// IUnknown
QueryInterface,
AddRef,
Release,
// ID3D10Device
VSSetConstantBuffers,
PSSetShaderResources,
PSSetShader,
PSSetSamplers,
VSSetShader,
DrawIndexed,
Draw,
PSSetConstantBuffers,
IASetInputLayout,
IASetVertexBuffers,
IASetIndexBuffer,
DrawIndexedInstanced,
DrawInstanced,
GSSetConstantBuffers,
GSSetShader,
IASetPrimitiveTopology,
VSSetShaderResources,
VSSetSamplers,
SetPredication,
GSSetShaderResources,
GSSetSamplers,
OMSetRenderTargets,
OMSetBlendState,
OMSetDepthStencilState,
SOSetTargets,
DrawAuto,
RSSetState,
RSSetViewports,
RSSetScissorRects,
CopySubresourceRegion,
CopyResource,
UpdateSubresource,
ClearRenderTargetView,
ClearDepthStencilView,
GenerateMips,
ResolveSubresource,
VSGetConstantBuffers,
PSGetShaderResources,
PSGetShader,
PSGetSamplers,
VSGetShader,
PSGetConstantBuffers,
IAGetInputLayout,
IAGetVertexBuffers,
IAGetIndexBuffer,
GSGetConstantBuffers,
GSGetShader,
IAGetPrimitiveTopology,
VSGetShaderResources,
VSGetSamplers,
GetPredication,
GSGetShaderResources,
GSGetSamplers,
OMGetRenderTargets,
OMGetBlendState,
OMGetDepthStencilState,
SOGetTargets,
RSGetState,
RSGetViewports,
RSGetScissorRects,
GetDeviceRemovedReason,
SetExceptionMode,
GetExceptionMode,
GetPrivateData,
SetPrivateData,
SetPrivateDataInterface,
ClearState,
Flush,
CreateBuffer,
CreateTexture1D,
CreateTexture2D,
CreateTexture3D,
CreateShaderResourceView,
CreateRenderTargetView,
CreateDepthStencilView,
CreateInputLayout,
CreateVertexShader,
CreateGeometryShader,
CreateGeometryShaderWithStreamOutput,
CreatePixelShader,
CreateBlendState,
CreateDepthStencilState,
CreateRasterizerState,
CreateSamplerState,
CreateQuery,
CreatePredicate,
CreateCounter,
CheckFormatSupport,
CheckMultisampleQualityLevels,
CheckCounterInfo,
CheckCounter,
GetCreationFlags,
OpenSharedResource,
SetTextFilterSize,
GetTextFilterSize,
};
enum class IDirect3DDevice9VTable
{
// IUnknown
QueryInterface,
AddRef,
Release,
// IDirect3DDevice9
TestCooperativeLevel,
GetAvailableTextureMem,
EvictManagedResources,
GetDirect3D,
GetDeviceCaps,
GetDisplayMode,
GetCreationParameters,
SetCursorProperties,
SetCursorPosition,
ShowCursor,
CreateAdditionalSwapChain,
GetSwapChain,
GetNumberOfSwapChains,
Reset,
Present,
GetBackBuffer,
GetRasterStatus,
SetDialogBoxMode,
SetGammaRamp,
GetGammaRamp,
CreateTexture,
CreateVolumeTexture,
CreateCubeTexture,
CreateVertexBuffer,
CreateIndexBuffer,
CreateRenderTarget,
CreateDepthStencilSurface,
UpdateSurface,
UpdateTexture,
GetRenderTargetData,
GetFrontBufferData,
StretchRect,
ColorFill,
CreateOffscreenPlainSurface,
SetRenderTarget,
GetRenderTarget,
SetDepthStencilSurface,
GetDepthStencilSurface,
BeginScene,
EndScene,
Clear,
SetTransform,
GetTransform,
MultiplyTransform,
SetViewport,
GetViewport,
SetMaterial,
GetMaterial,
SetLight,
GetLight,
LightEnable,
GetLightEnable,
SetClipPlane,
GetClipPlane,
SetRenderState,
GetRenderState,
CreateStateBlock,
BeginStateBlock,
EndStateBlock,
SetClipStatus,
GetClipStatus,
GetTexture,
SetTexture,
GetTextureStageState,
SetTextureStageState,
GetSamplerState,
SetSamplerState,
ValidateDevice,
SetPaletteEntries,
GetPaletteEntries,
SetCurrentTexturePalette,
GetCurrentTexturePalette,
SetScissorRect,
GetScissorRect,
SetSoftwareVertexProcessing,
GetSoftwareVertexProcessing,
SetNPatchMode,
GetNPatchMode,
DrawPrimitive,
DrawIndexedPrimitive,
DrawPrimitiveUP,
DrawIndexedPrimitiveUP,
ProcessVertices,
CreateVertexDeclaration,
SetVertexDeclaration,
GetVertexDeclaration,
SetFVF,
GetFVF,
CreateVertexShader,
SetVertexShader,
GetVertexShader,
SetVertexShaderConstantF,
GetVertexShaderConstantF,
SetVertexShaderConstantI,
GetVertexShaderConstantI,
SetVertexShaderConstantB,
GetVertexShaderConstantB,
SetStreamSource,
GetStreamSource,
SetStreamSourceFreq,
GetStreamSourceFreq,
SetIndices,
GetIndices,
CreatePixelShader,
SetPixelShader,
GetPixelShader,
SetPixelShaderConstantF,
GetPixelShaderConstantF,
SetPixelShaderConstantI,
GetPixelShaderConstantI,
SetPixelShaderConstantB,
GetPixelShaderConstantB,
DrawRectPatch,
DrawTriPatch,
DeletePatch,
CreateQuery,
// IDirect3DDevice9Ex
SetConvolutionMonoKernel,
ComposeRects,
PresentEx,
GetGPUThreadPriority,
SetGPUThreadPriority,
WaitForVBlank,
CheckResourceResidency,
SetMaximumFrameLatency,
GetMaximumFrameLatency,
CheckDeviceState,
CreateRenderTargetEx,
CreateOffscreenPlainSurfaceEx,
CreateDepthStencilSurfaceEx,
ResetEx,
GetDisplayModeEx,
};

View file

@ -0,0 +1,178 @@
#include "../dll/dll.h"
#include "Hook_Manager.h"
#include "../detours/detours.h"
#include "DX12_Hook.h"
#include "DX11_Hook.h"
#include "DX10_Hook.h"
#include "DX9_Hook.h"
#include <algorithm>
decltype(LoadLibraryA )* _LoadLibraryA = LoadLibraryA;
decltype(LoadLibraryW )* _LoadLibraryW = LoadLibraryW;
decltype(LoadLibraryExA )* _LoadLibraryExA = LoadLibraryExA;
decltype(LoadLibraryExW )* _LoadLibraryExW = LoadLibraryExW;
void create_hookA(const char* libname)
{
if (!strcmp(libname, "d3d9.dll"))
DX9_Hook::Create();
else if (!strcmp(libname, "d3d10.dll"))
DX10_Hook::Create();
else if (!strcmp(libname, "d3d11.dll"))
DX11_Hook::Create();
else if (!strcmp(libname, "d3d12.dll"))
DX12_Hook::Create();
}
void create_hookW(const wchar_t *libname)
{
if (!wcscmp(libname, L"d3d9.dll"))
DX9_Hook::Create();
else if (!wcscmp(libname, L"d3d10.dll"))
DX10_Hook::Create();
else if (!wcscmp(libname, L"d3d11.dll"))
DX11_Hook::Create();
else if (!wcscmp(libname, L"d3d12.dll"))
DX12_Hook::Create();
}
HMODULE WINAPI mLoadLibraryA(LPCTSTR lpLibFileName)
{
auto res = _LoadLibraryA(lpLibFileName);
create_hookA(lpLibFileName);
return res;
}
HMODULE WINAPI mLoadLibraryW(LPCWSTR lpLibFileName)
{
auto res = _LoadLibraryW(lpLibFileName);
create_hookW(lpLibFileName);
return res;
}
HMODULE WINAPI mLoadLibraryExA(LPCTSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
auto res = _LoadLibraryA(lpLibFileName);
create_hookA(lpLibFileName);
return res;
}
HMODULE WINAPI mLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
auto res = _LoadLibraryExW(lpLibFileName, hFile, dwFlags);
create_hookW(lpLibFileName);
return res;
}
Hook_Manager::Hook_Manager():
_isSet(false),
_LoadLibraryHooked(false)
{}
Hook_Manager::~Hook_Manager()
{
for (auto& i : _hooks)
delete i;
}
Hook_Manager& Hook_Manager::Inst()
{
static Hook_Manager hook;
return hook;
}
void Hook_Manager::HookRenderer(Steam_Overlay *ovlay)
{
overlay = ovlay;
HookLoadLibrary();
std::vector<std::string> const libraries = { "d3d12.dll", "d3d11.dll", "d3d10.dll", "d3d9.dll" };
std::vector<std::string>::const_iterator it = libraries.begin();
while (it != libraries.end())
{
it = std::find_if(it, libraries.end(), [](std::string const& name) {
auto x = GetModuleHandle(name.c_str());
if (x != 0 && x != INVALID_HANDLE_VALUE)
return true;
return false;
});
if (it == libraries.end())
break;
if (*it == "d3d9.dll")
DX9_Hook::Create();
else if (*it == "d3d10.dll")
DX10_Hook::Create();
else if (*it == "d3d11.dll")
DX11_Hook::Create();
else if (*it == "d3d12.dll")
DX12_Hook::Create();
++it;
}
}
void Hook_Manager::UnHookLoadLibrary()
{
_LoadLibraryHooked = false;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach((PVOID*)& _LoadLibraryA, mLoadLibraryA);
DetourDetach((PVOID*)& _LoadLibraryW, mLoadLibraryW);
DetourDetach((PVOID*)& _LoadLibraryExA, mLoadLibraryExA);
DetourDetach((PVOID*)& _LoadLibraryExW, mLoadLibraryExW);
DetourTransactionCommit();
}
void Hook_Manager::HookLoadLibrary()
{
if (!_isSet && !_LoadLibraryHooked)
{
_LoadLibraryHooked = true;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID*)& _LoadLibraryA, mLoadLibraryA);
DetourAttach((PVOID*)& _LoadLibraryW, mLoadLibraryW);
DetourAttach((PVOID*)& _LoadLibraryExA, mLoadLibraryExA);
DetourAttach((PVOID*)& _LoadLibraryExW, mLoadLibraryExW);
DetourTransactionCommit();
}
}
void Hook_Manager::FoundHook(Base_Hook* hook)
{
if (!_isSet)
{
_isSet = true;
UnHookLoadLibrary();
// Remove all hooks that are unused
_hooks.erase(std::remove_if(_hooks.begin(), _hooks.end(), [&hook](Base_Hook* it_hook) {
if (hook != it_hook)
{
delete it_hook;
return true;
}
return false;
}), _hooks.end());
}
}
void Hook_Manager::ChangeGameWindow(HWND hWnd) const
{
overlay->HookReady(hWnd);
}
void Hook_Manager::CallOverlayProc(int width, int height) const
{
overlay->OverlayProc(width, height);
}

View file

@ -0,0 +1,46 @@
#ifndef __INCLUDED_HOOK_BASE_H__
#define __INCLUDED_HOOK_BASE_H__
#include <Windows.h>
#include <vector>
#include "Base_Hook.h"
class Hook_Manager
{
friend class Base_Hook;
public:
using overlayProc_t = void(*)(int,int);
using hookReady_t = void(*)(void*);
protected:
std::vector<Base_Hook*> _hooks;
WNDPROC _gameWndProc; // The game main windows proc
HWND _gameHWnd; // The game main window
bool _showOverlay; // Should we render the overlay
bool _isSet; // Is the renderer hooked ?
bool _LoadLibraryHooked; // Are the LoadLibrary functions hooked ?
class Steam_Overlay* overlay;
Hook_Manager();
virtual ~Hook_Manager();
void HookLoadLibrary();
void UnHookLoadLibrary();
public:
static Hook_Manager& Inst();
void HookRenderer(Steam_Overlay *overlay);
// Set the found hook and free all other hooks
void FoundHook(Base_Hook *hook);
inline void AddHook(Base_Hook* hook) { _hooks.push_back(hook); }
void ChangeGameWindow(HWND hWnd) const;
void CallOverlayProc(int width, int height) const;
Steam_Overlay* GetOverlay() const { return overlay; }
};
#endif//__INCLUDED_HOOK_BASE_H__