Added DirectX hooks
Warning: DX9 doesn't support resizing (TODO), DX12 has not beed tested and is not finished. No OpenGL support for now.merge-requests/28/head
parent
bb9c516775
commit
2ba8cae64e
|
@ -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);
|
||||||
|
}
|
|
@ -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__
|
|
@ -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
|
||||||
|
}
|
|
@ -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__
|
|
@ -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
|
||||||
|
}
|
|
@ -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__
|
|
@ -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
|
||||||
|
}
|
|
@ -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__
|
|
@ -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, ¶ms, 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(¶m);
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -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__
|
|
@ -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,
|
||||||
|
};
|
|
@ -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);
|
||||||
|
}
|
|
@ -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__
|
Loading…
Reference in New Issue