// DX11Hook.cpp #include "stdafx.h" float DX11Hook::ScrX = 0, DX11Hook::ScrY = 0; float DX11Hook::ScrWidth = 0, DX11Hook::ScrHeight = 0; static BOOLEAN MenuInitialized = FALSE; //========================================================================================================================== typedef HRESULT(WINAPI *D3D11PresentHook) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); D3D11PresentHook originalD3D11PresentHook = NULL; HRESULT WINAPI detourD3D11PresentHook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) { static BOOLEAN Initialized = FALSE; if (!Initialized) Initialized = DX11->InitDX11RenderStuff(pSwapChain); DX11->DX11RenderScene(); return originalD3D11PresentHook(pSwapChain, SyncInterval, Flags); } //========================================================================================================================== void DX11Hook::DX11RenderScene() { try { // if (Hooking::GetGameState() == GameStatePlaying) { // Init Menu // if (!MenuInitialized) MenuInitialized = Menu::Init(); // Render Menu Menu::Render(); } } catch (const std::exception &e) { DEBUGMSG(e.what()); } } //========================================================================================================================== DWORD DX11Hook::InitDevice(HWND hWindow) { // Get window size RECT rc; GetWindowRect(hWindow, &rc); ScrX = (float)rc.left; ScrY = (float)rc.top; ScrWidth = (float)(rc.right - rc.left); ScrHeight = (float)(rc.bottom - rc.top); IDXGISwapChain* pSwapChain; D3D_FEATURE_LEVEL requestedLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 }; D3D_FEATURE_LEVEL obtainedLevel; ID3D11Device* d3dDevice = nullptr; ID3D11DeviceContext* d3dContext = nullptr; DXGI_SWAP_CHAIN_DESC scd; ZeroMemory(&scd, sizeof(scd)); scd.BufferCount = 1; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; scd.OutputWindow = hWindow; scd.SampleDesc.Count = 1; // Set to 1 to disable multisampling scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Windowed = true; // ((GetWindowLongPtr(hWindow, GWL_STYLE) & WS_POPUP) != 0) ? false : true; // LibOVR 0.4.3 requires that the width and height for the backbuffer is set even if // you use windowed mode, despite being optional according to the D3D11 documentation. scd.BufferDesc.Width = 1; scd.BufferDesc.Height = 1; scd.BufferDesc.RefreshRate.Numerator = 0; scd.BufferDesc.RefreshRate.Denominator = 1; UINT createFlags = 0; #ifdef _DEBUG // This flag gives you some quite wonderful debug text. Not wonderful for performance, though! createFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif IDXGISwapChain* d3dSwapChain = 0; HRESULT x = D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createFlags, requestedLevels, sizeof(requestedLevels) / sizeof(D3D_FEATURE_LEVEL), D3D11_SDK_VERSION, &scd, &pSwapChain, &DX11Device, &obtainedLevel, &DX11DeviceContext); if (FAILED(x)) { if (x == DXGI_ERROR_SDK_COMPONENT_MISSING) { MessageBox(hWindow, L"Failed to create directX device and swapchain: DXGI_ERROR_SDK_COMPONENT_MISSING\n\nYou seem to be missing some DirectX SDKs. If you are on Windows 8 or 10, see this article for information on enabling DirectX debug: https://goo.gl/tSeSif", L"Error", MB_ICONERROR); } else { MessageBox(hWindow, L"Failed to create directX device and swapchain!", L"Error", MB_ICONERROR); } Log::Msg("Failed DirectX with %d", x); return NULL; } Log::Msg("Created Device / Swap Chain"); SwapChainVtable = (DWORD_PTR*)pSwapChain; Log::Msg("Swap Chain VTable: 0x%I64X", SwapChainVtable); SwapChainVtable = (DWORD_PTR*)SwapChainVtable[0]; Log::Msg("Swap Chain VTable: 0x%I64X", SwapChainVtable); Log::Msg("Hooking Present Hook"); Log::Msg("Hooking From: 0x%I64X", (DWORD_PTR*)SwapChainVtable[8]); Log::Msg("Hooking From: 0x%I64X", (DWORD64)&SwapChainVtable[8]); Log::Msg("Hooking To : 0x%I64X", reinterpret_cast(&originalD3D11PresentHook)); Log::Msg("Hooking To : 0x%I64X", &originalD3D11PresentHook); if (MH_CreateHook((DWORD_PTR*)SwapChainVtable[8], detourD3D11PresentHook, reinterpret_cast(&originalD3D11PresentHook)) != MH_OK) { return 1; } if (MH_EnableHook((DWORD_PTR*)SwapChainVtable[8]) != MH_OK) { return 1; } DWORD dwOld; VirtualProtect(originalD3D11PresentHook, 2, PAGE_EXECUTE_READWRITE, &dwOld); Log::Msg("Hooked!"); while (true) { Sleep(10); } DX11Device->Release(); DX11DeviceContext->Release(); pSwapChain->Release(); return NULL; } void DX11Hook::CreateRenderTarget() { DXGI_SWAP_CHAIN_DESC sd; DX11SwapChain->GetDesc(&sd); // Create the render target ID3D11Texture2D* pBackBuffer; D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc; ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc)); render_target_view_desc.Format = sd.BufferDesc.Format; render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; DX11SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); DX11Device->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &DX11RenderTargetView); DX11DeviceContext->OMSetRenderTargets(1, &DX11RenderTargetView, NULL); pBackBuffer->Release(); } BOOLEAN DX11Hook::InitDX11RenderStuff(IDXGISwapChain* _SwapChain) { DX11SwapChain = _SwapChain; DX11SwapChain->GetDevice(__uuidof(DX11Device), (void**)&DX11Device); DX11Device->GetImmediateContext(&DX11DeviceContext); CreateRenderTarget(); // Setup ImGui binding ImGui_ImplDX11_Init(Hooking::getWindow(), DX11Device, DX11DeviceContext); Initialized = TRUE; return TRUE; } void DX11Hook::CleanupRenderTarget() { if (DX11RenderTargetView) { DX11RenderTargetView->Release(); DX11RenderTargetView = NULL; } } void DX11Hook::CleanupDeviceD3D() { CleanupRenderTarget(); if (DX11SwapChain) { DX11SwapChain->Release(); DX11SwapChain = NULL; } if (DX11DeviceContext) { DX11DeviceContext->Release(); DX11DeviceContext = NULL; } if (DX11Device) { DX11Device->Release(); DX11Device = NULL; } if (MH_DisableHook((DWORD_PTR*)SwapChainVtable[8]) != MH_OK) { return; } } void DX11Hook::ResizeBuffers(UINT width, UINT height) { if (DX11Device != NULL) { ImGui_ImplDX11_InvalidateDeviceObjects(); CleanupRenderTarget(); DX11SwapChain->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, 0); CreateRenderTarget(); ImGui_ImplDX11_CreateDeviceObjects(); } } std::unique_ptr DX11;