bool TestDX11Present() { HMODULE hD3D11 = LoadLibrary("d3d11.dll"); if (!hD3D11) { Msg("* DX11: failed to load d3d11.dll"); return false; } FuncPtrD3D11CreateDeviceAndSwapChain pD3D11CreateDeviceAndSwapChain = (FuncPtrD3D11CreateDeviceAndSwapChain)GetProcAddress(hD3D11, "D3D11CreateDeviceAndSwapChain"); if (!pD3D11CreateDeviceAndSwapChain) { Msg("* DX11: failed to get address of D3D11CreateDeviceAndSwapChain"); return false; } // Register class WNDCLASSEX wcex; ZeroMemory(&wcex, sizeof(wcex)); wcex.cbSize = sizeof( WNDCLASSEX ); wcex.lpfnWndProc = WndProc; wcex.hInstance = GetModuleHandle(NULL); wcex.lpszClassName = "TestDX11WindowClass"; if( !RegisterClassEx( &wcex ) ) { Msg("* DX11: failed to register window class"); return false; } // Create window HWND hWnd = CreateWindow( "TestDX11WindowClass", "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL ); DXGI_SWAP_CHAIN_DESC sd; if (!hWnd) { Msg("* DX11: failed to create window"); return false; } HRESULT hr = E_FAIL; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = 800; sd.BufferDesc.Height = 600; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; D3D_FEATURE_LEVEL pFeatureLevels[] = {D3D_FEATURE_LEVEL_11_0}; D3D_FEATURE_LEVEL FeatureLevel; ID3D11Device* pd3dDevice = NULL; ID3D11DeviceContext* pContext = NULL; IDXGISwapChain* pSwapChain = NULL; hr = pD3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, pFeatureLevels, 1, D3D11_SDK_VERSION, &sd, &pSwapChain, &pd3dDevice, &FeatureLevel, &pContext ); if (FAILED(hr)) Msg("* D3D11: device creation failed with hr=0x%08x", hr); if (pContext) pContext->Release(); if (pSwapChain) pSwapChain->Release(); if (pd3dDevice) pd3dDevice->Release(); FreeLibrary(hD3D11); DestroyWindow(hWnd); return SUCCEEDED(hr); }
/// Prepares DXGI and D3D11 data by trying to determine the module filepath /// and function offsets in memory. /// (This data can later be used for hooking / code injection.) /// /// Adjusts the data behind the global variables dxgi and d3d11. void PrepareDXGI11(IDXGIAdapter1* pAdapter, bool initializeDXGIData) { if (!dxgi || !d3d11 || !pAdapter) return; ods("D3D11: Preparing static data for DXGI and D3D11 Injection"); d3d11->wcFileName[0] = 0; d3d11->iOffsetAddRef = 0; d3d11->iOffsetRelease = 0; HMODULE hD3D11 = LoadLibrary("D3D11.DLL"); if (hD3D11 != NULL) { HWND hwnd = CreateWindowW(L"STATIC", L"Mumble DXGI Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 0, NULL, NULL, 0); D3D11CreateDeviceAndSwapChainType pD3D11CreateDeviceAndSwapChain = reinterpret_cast<D3D11CreateDeviceAndSwapChainType>(GetProcAddress(hD3D11, "D3D11CreateDeviceAndSwapChain")); DXGI_SWAP_CHAIN_DESC desc; ZeroMemory(&desc, sizeof(desc)); RECT rcWnd; BOOL success = GetClientRect(hwnd, &rcWnd); if (success) { desc.BufferDesc.Width = rcWnd.right - rcWnd.left; desc.BufferDesc.Height = rcWnd.bottom - rcWnd.top; ods("D3D11: Got ClientRect W %d H %d", desc.BufferDesc.Width, desc.BufferDesc.Height); desc.BufferDesc.RefreshRate.Numerator = 60; desc.BufferDesc.RefreshRate.Denominator = 1; desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; desc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferCount = 2; desc.OutputWindow = hwnd; desc.Windowed = true; desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; IDXGISwapChain *pSwapChain = NULL; ID3D11Device *pDevice = NULL; D3D_FEATURE_LEVEL featureLevel; ID3D11DeviceContext *pDeviceContext = NULL; HRESULT hr = pD3D11CreateDeviceAndSwapChain(pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &desc, &pSwapChain, &pDevice, &featureLevel, &pDeviceContext); if (FAILED(hr)) ods("D3D11: pD3D11CreateDeviceAndSwapChain failure!"); if (pDevice && pDeviceContext && pSwapChain) { // For VC++ the vtable is located at the base addr. of the object and each function entry is a single pointer. Since p.e. the base classes // of IDXGISwapChain have a total of 8 functions the 8+Xth entry points to the Xth added function in the derived interface. void ***vtbl = (void ***) pSwapChain; void *pPresent = (*vtbl)[8]; int offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pPresent), dxgi->wcFileName, ARRAY_NUM_ELEMENTS(dxgi->wcFileName), "D3D11", "Present"); if (offset >= 0) { if (initializeDXGIData) { dxgi->iOffsetPresent = offset; ods("D3D11: Successfully found Present offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetPresent); } else { if (dxgi->iOffsetPresent == offset) { ods("D3D11: Successfully verified Present offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetPresent); } else { ods("D3D11: Failed to verify Present offset for %ls. Found %d, but previously found %d.", dxgi->wcFileName, offset, dxgi->iOffsetPresent); } } } void *pResize = (*vtbl)[13]; offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pResize), dxgi->wcFileName, ARRAY_NUM_ELEMENTS(dxgi->wcFileName), "D3D11", "ResizeBuffers"); if (offset >= 0) { if (initializeDXGIData) { dxgi->iOffsetResize = offset; ods("D3D11: Successfully found ResizeBuffers offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetResize); } else { if (dxgi->iOffsetResize == offset) { ods("D3D11: Successfully verified ResizeBuffers offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetResize); } else { ods("D3D11: Failed to verify ResizeBuffers offset for %ls. Found %d, but previously found %d.", dxgi->wcFileName, offset, dxgi->iOffsetResize); } } } vtbl = (void ***) pDevice; void *pAddRef = (*vtbl)[1]; offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pAddRef), d3d11->wcFileName, ARRAY_NUM_ELEMENTS(d3d11->wcFileName), "D3D11", "AddRef"); if (offset >= 0) { d3d11->iOffsetAddRef = offset; ods("D3D11: Successfully found AddRef offset: %ls: %d", d3d11->wcFileName, d3d11->iOffsetAddRef); } void *pRelease = (*vtbl)[2]; offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pRelease), d3d11->wcFileName, ARRAY_NUM_ELEMENTS(d3d11->wcFileName), "D3D11", "Release"); if (offset >= 0) { d3d11->iOffsetRelease = offset; ods("D3D11: Successfully found Release offset: %ls: %d", d3d11->wcFileName, d3d11->iOffsetRelease); } } if (pDevice) pDevice->Release(); if (pDeviceContext) pDeviceContext->Release(); if (pSwapChain) pSwapChain->Release(); } else { FreeLibrary(hD3D11); } DestroyWindow(hwnd); } else { FreeLibrary(hD3D11); } }