2009-08-24 15:16:15 +00:00
|
|
|
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
|
|
|
|
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
- Redistributions of source code must retain the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer.
|
|
|
|
- Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
- Neither the name of the Mumble Developers nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived from this
|
|
|
|
software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
|
|
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "lib.h"
|
2009-08-25 16:28:10 +00:00
|
|
|
#include "overlay.hex"
|
2009-08-24 15:16:15 +00:00
|
|
|
#include <d3d10.h>
|
2009-08-25 16:11:31 +00:00
|
|
|
#include <d3dx10.h>
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
DXGIData *dxgi;
|
|
|
|
|
|
|
|
static bool bHooked = false;
|
|
|
|
static bool bChaining = false;
|
|
|
|
static HardHook hhPresent;
|
2009-08-25 16:11:31 +00:00
|
|
|
static HardHook hhResize;
|
2009-08-25 17:44:17 +00:00
|
|
|
static HardHook hhAddRef;
|
|
|
|
static HardHook hhRelease;
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
typedef HRESULT(__stdcall *CreateDXGIFactoryType)(REFIID, void **);
|
|
|
|
typedef HRESULT(__stdcall *D3D10CreateDeviceAndSwapChainType)(IDXGIAdapter *, D3D10_DRIVER_TYPE, HMODULE, UINT, UINT, DXGI_SWAP_CHAIN_DESC *, IDXGISwapChain **, ID3D10Device **);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
typedef HRESULT(__stdcall *D3D10CreateStateBlockType)(ID3D10Device *, D3D10_STATE_BLOCK_MASK *, ID3D10StateBlock **);
|
|
|
|
typedef HRESULT(__stdcall *D3D10StateBlockMaskEnableAllType)(D3D10_STATE_BLOCK_MASK *);
|
|
|
|
typedef HRESULT(__stdcall *D3D10CreateEffectFromMemoryType)(void *, SIZE_T, UINT, ID3D10Device *, ID3D10EffectPool *, ID3D10Effect **);
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
typedef HRESULT(__stdcall *PresentType)(IDXGISwapChain *, UINT, UINT);
|
2009-08-25 16:11:31 +00:00
|
|
|
typedef HRESULT(__stdcall *ResizeBuffersType)(IDXGISwapChain *, UINT, UINT, UINT, DXGI_FORMAT, UINT);
|
2009-08-25 17:44:17 +00:00
|
|
|
typedef ULONG(__stdcall *AddRefType)(ID3D10Device *);
|
|
|
|
typedef ULONG(__stdcall *ReleaseType)(ID3D10Device *);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
#define HMODREF(mod, func) func##Type p##func = (func##Type) GetProcAddress(mod, #func)
|
|
|
|
|
2009-09-02 15:41:45 +00:00
|
|
|
struct SimpleVertex {
|
|
|
|
D3DXVECTOR3 Pos;
|
2009-08-25 16:11:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct D10State {
|
2009-08-25 17:44:17 +00:00
|
|
|
LONG lHighMark;
|
|
|
|
|
|
|
|
LONG initRefCount;
|
|
|
|
LONG refCount;
|
|
|
|
LONG myRefCount;
|
|
|
|
DWORD dwMyThread;
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
ID3D10Device *pDevice;
|
2009-08-25 17:44:17 +00:00
|
|
|
IDXGISwapChain *pSwapChain;
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
ID3D10StateBlock *pOrigStateBlock;
|
|
|
|
ID3D10StateBlock *pMyStateBlock;
|
|
|
|
ID3D10RenderTargetView *pRTV;
|
|
|
|
ID3D10Effect *pEffect;
|
|
|
|
ID3D10EffectTechnique *pTechnique;
|
|
|
|
ID3D10InputLayout *pVertexLayout;
|
|
|
|
ID3D10Buffer *pVertexBuffer;
|
|
|
|
ID3D10BlendState *pBlendState;
|
|
|
|
|
|
|
|
D10State(IDXGISwapChain *, ID3D10Device *);
|
|
|
|
~D10State();
|
2009-08-25 17:44:17 +00:00
|
|
|
void init();
|
2009-08-25 16:11:31 +00:00
|
|
|
void draw();
|
|
|
|
};
|
|
|
|
|
2009-08-25 17:44:17 +00:00
|
|
|
map<IDXGISwapChain *, D10State *> chains;
|
|
|
|
map<ID3D10Device *, D10State *> devices;
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
D10State::D10State(IDXGISwapChain *pSwapChain, ID3D10Device *pDevice) {
|
2009-08-25 17:44:17 +00:00
|
|
|
this->pSwapChain = pSwapChain;
|
|
|
|
this->pDevice = pDevice;
|
|
|
|
|
|
|
|
dwMyThread = 0;
|
|
|
|
refCount = 0;
|
|
|
|
myRefCount = 0;
|
|
|
|
|
|
|
|
pDevice->AddRef();
|
|
|
|
initRefCount = pDevice->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void D10State::init() {
|
2009-08-25 16:11:31 +00:00
|
|
|
static HMODREF(GetModuleHandleW(L"D3D10.DLL"), D3D10CreateEffectFromMemory);
|
|
|
|
static HMODREF(GetModuleHandleW(L"D3D10.DLL"), D3D10CreateStateBlock);
|
|
|
|
static HMODREF(GetModuleHandleW(L"D3D10.DLL"), D3D10StateBlockMaskEnableAll);
|
2009-08-24 15:16:15 +00:00
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
HRESULT hr;
|
|
|
|
|
2009-08-25 17:44:17 +00:00
|
|
|
dwMyThread = GetCurrentThreadId();
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
D3D10_STATE_BLOCK_MASK StateBlockMask;
|
|
|
|
ZeroMemory(&StateBlockMask, sizeof(StateBlockMask));
|
|
|
|
pD3D10StateBlockMaskEnableAll(&StateBlockMask);
|
|
|
|
pD3D10CreateStateBlock(pDevice, &StateBlockMask, &pOrigStateBlock);
|
|
|
|
pD3D10CreateStateBlock(pDevice, &StateBlockMask, &pMyStateBlock);
|
|
|
|
|
|
|
|
pOrigStateBlock->Capture();
|
|
|
|
|
|
|
|
ID3D10Texture2D* pBackBuffer = NULL;
|
2009-09-02 15:41:45 +00:00
|
|
|
hr = pSwapChain->GetBuffer(0, __uuidof(*pBackBuffer), (LPVOID*)&pBackBuffer);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
pDevice->ClearState();
|
|
|
|
|
|
|
|
D3D10_TEXTURE2D_DESC backBufferSurfaceDesc;
|
2009-09-02 15:41:45 +00:00
|
|
|
pBackBuffer->GetDesc(&backBufferSurfaceDesc);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
D3D10_VIEWPORT vp;
|
|
|
|
vp.Width = backBufferSurfaceDesc.Width;
|
|
|
|
vp.Height = backBufferSurfaceDesc.Height;
|
|
|
|
vp.MinDepth = 0;
|
|
|
|
vp.MaxDepth = 1;
|
|
|
|
vp.TopLeftX = 0;
|
|
|
|
vp.TopLeftY = 0;
|
2009-09-02 15:41:45 +00:00
|
|
|
pDevice->RSSetViewports(1, &vp);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
2009-09-02 15:41:45 +00:00
|
|
|
hr = pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRTV);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
2009-09-02 15:41:45 +00:00
|
|
|
pDevice->OMSetRenderTargets(1, &pRTV, NULL);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
D3D10_BLEND_DESC blend;
|
|
|
|
ZeroMemory(&blend, sizeof(blend));
|
|
|
|
blend.BlendEnable[0] = TRUE;
|
|
|
|
blend.SrcBlend = D3D10_BLEND_SRC_ALPHA;
|
|
|
|
blend.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
|
|
|
|
blend.BlendOp = D3D10_BLEND_OP_ADD;
|
|
|
|
blend.SrcBlendAlpha = D3D10_BLEND_SRC_ALPHA;
|
|
|
|
blend.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
|
|
|
blend.BlendOpAlpha = D3D10_BLEND_OP_ADD;
|
|
|
|
blend.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
|
|
|
|
|
|
|
pDevice->CreateBlendState(&blend, &pBlendState);
|
|
|
|
float bf[4];
|
|
|
|
pDevice->OMSetBlendState(pBlendState, bf, 0xffffffff);
|
|
|
|
|
2009-08-25 16:28:10 +00:00
|
|
|
pD3D10CreateEffectFromMemory((void *) g_main, sizeof(g_main), 0, pDevice, NULL, &pEffect);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
2009-09-02 15:41:45 +00:00
|
|
|
pTechnique = pEffect->GetTechniqueByName("Render");
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
// Define the input layout
|
2009-09-02 15:41:45 +00:00
|
|
|
D3D10_INPUT_ELEMENT_DESC layout[] = {
|
2009-08-25 16:11:31 +00:00
|
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
|
|
|
};
|
2009-09-02 15:41:45 +00:00
|
|
|
UINT numElements = sizeof(layout) / sizeof(layout[0]);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
// Create the input layout
|
|
|
|
D3D10_PASS_DESC PassDesc;
|
2009-09-02 15:41:45 +00:00
|
|
|
pTechnique->GetPassByIndex(0)->GetDesc(&PassDesc);
|
|
|
|
hr = pDevice->CreateInputLayout(layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &pVertexLayout);
|
|
|
|
pDevice->IASetInputLayout(pVertexLayout);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
// Create vertex buffer
|
2009-09-02 15:41:45 +00:00
|
|
|
SimpleVertex vertices[] = {
|
|
|
|
D3DXVECTOR3(0.0f, 0.9f, 0.5f),
|
|
|
|
D3DXVECTOR3(0.9f, -0.9f, 0.5f),
|
|
|
|
D3DXVECTOR3(-0.9f, -0.9f, 0.5f),
|
2009-08-25 16:11:31 +00:00
|
|
|
};
|
|
|
|
D3D10_BUFFER_DESC bd;
|
|
|
|
bd.Usage = D3D10_USAGE_DEFAULT;
|
2009-09-02 15:41:45 +00:00
|
|
|
bd.ByteWidth = sizeof(SimpleVertex) * 3;
|
2009-08-25 16:11:31 +00:00
|
|
|
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
|
|
|
bd.CPUAccessFlags = 0;
|
|
|
|
bd.MiscFlags = 0;
|
|
|
|
D3D10_SUBRESOURCE_DATA InitData;
|
|
|
|
InitData.pSysMem = vertices;
|
2009-09-02 15:41:45 +00:00
|
|
|
hr = pDevice->CreateBuffer(&bd, &InitData, &pVertexBuffer);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
// Set vertex buffer
|
2009-09-02 15:41:45 +00:00
|
|
|
UINT stride = sizeof(SimpleVertex);
|
2009-08-25 16:11:31 +00:00
|
|
|
UINT offset = 0;
|
2009-09-02 15:41:45 +00:00
|
|
|
pDevice->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
// Set primitive topology
|
2009-09-02 15:41:45 +00:00
|
|
|
pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
pMyStateBlock->Capture();
|
|
|
|
pOrigStateBlock->Apply();
|
|
|
|
|
|
|
|
pBackBuffer->Release();
|
2009-08-25 17:44:17 +00:00
|
|
|
|
|
|
|
dwMyThread = 0;
|
2009-08-25 16:11:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
D10State::~D10State() {
|
|
|
|
pBlendState->Release();
|
|
|
|
pVertexBuffer->Release();
|
|
|
|
pVertexLayout->Release();
|
|
|
|
pEffect->Release();
|
|
|
|
pRTV->Release();
|
|
|
|
|
|
|
|
pMyStateBlock->ReleaseAllDeviceObjects();
|
|
|
|
pMyStateBlock->Release();
|
|
|
|
|
|
|
|
pOrigStateBlock->ReleaseAllDeviceObjects();
|
|
|
|
pOrigStateBlock->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void D10State::draw() {
|
2009-08-25 17:44:17 +00:00
|
|
|
dwMyThread = GetCurrentThreadId();
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
pOrigStateBlock->Capture();
|
|
|
|
pMyStateBlock->Apply();
|
|
|
|
|
|
|
|
// Render a triangle
|
|
|
|
D3D10_TECHNIQUE_DESC techDesc;
|
2009-09-02 15:41:45 +00:00
|
|
|
pTechnique->GetDesc(&techDesc);
|
|
|
|
for (UINT p = 0; p < techDesc.Passes; ++p) {
|
2009-08-25 16:11:31 +00:00
|
|
|
// ods("Pass %d", p);
|
2009-09-02 15:41:45 +00:00
|
|
|
pTechnique->GetPassByIndex(p)->Apply(0);
|
|
|
|
pDevice->Draw(3, 0);
|
2009-08-25 16:11:31 +00:00
|
|
|
}
|
|
|
|
pOrigStateBlock->Apply();
|
2009-08-25 17:44:17 +00:00
|
|
|
|
|
|
|
dwMyThread = 0;
|
2009-08-25 16:11:31 +00:00
|
|
|
}
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
|
|
|
|
static HRESULT __stdcall myPresent(IDXGISwapChain *pSwapChain, UINT SyncInterval, UINT Flags) {
|
|
|
|
HRESULT hr;
|
|
|
|
// ods("DXGI: Device Present");
|
|
|
|
|
|
|
|
ID3D10Device *pDevice = NULL;
|
2009-08-25 17:44:17 +00:00
|
|
|
|
|
|
|
ods("DXGI: DrawBegin");
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
hr = pSwapChain->GetDevice(__uuidof(ID3D10Device), (void **) &pDevice);
|
|
|
|
if (pDevice) {
|
2009-08-25 17:44:17 +00:00
|
|
|
D10State *ds = chains[pSwapChain];
|
2009-08-25 16:11:31 +00:00
|
|
|
if (ds && ds->pDevice != pDevice) {
|
|
|
|
ods("DXGI: SwapChain device changed");
|
|
|
|
delete ds;
|
2009-08-25 17:44:17 +00:00
|
|
|
devices.erase(ds->pDevice);
|
2009-08-25 16:11:31 +00:00
|
|
|
ds = NULL;
|
|
|
|
}
|
|
|
|
if (! ds) {
|
2009-08-25 17:44:17 +00:00
|
|
|
ods("DXGI: New state");
|
2009-08-25 16:11:31 +00:00
|
|
|
ds = new D10State(pSwapChain, pDevice);
|
2009-08-25 17:44:17 +00:00
|
|
|
chains[pSwapChain] = ds;
|
|
|
|
devices[pDevice] = ds;
|
|
|
|
ds->init();
|
2009-08-25 16:11:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ds->draw();
|
|
|
|
pDevice->Release();
|
2009-08-25 17:44:17 +00:00
|
|
|
ods("DXGI: DrawEnd");
|
2009-08-25 16:11:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PresentType oPresent = (PresentType) hhPresent.call;
|
2009-08-24 15:16:15 +00:00
|
|
|
hhPresent.restore();
|
2009-08-25 16:11:31 +00:00
|
|
|
hr = oPresent(pSwapChain, SyncInterval, Flags);
|
2009-08-24 15:16:15 +00:00
|
|
|
hhPresent.inject();
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
static HRESULT __stdcall myResize(IDXGISwapChain *pSwapChain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) {
|
|
|
|
HRESULT hr;
|
|
|
|
|
2009-08-25 17:44:17 +00:00
|
|
|
D10State *ds = chains[pSwapChain];
|
2009-08-25 16:11:31 +00:00
|
|
|
if (ds) {
|
2009-08-25 17:44:17 +00:00
|
|
|
devices.erase(ds->pDevice);
|
|
|
|
chains.erase(pSwapChain);
|
2009-08-25 16:11:31 +00:00
|
|
|
delete ds;
|
|
|
|
}
|
|
|
|
|
|
|
|
ResizeBuffersType oResize = (ResizeBuffersType) hhResize.call;
|
|
|
|
hhResize.restore();
|
|
|
|
hr = oResize(pSwapChain, BufferCount, Width, Height, NewFormat, SwapChainFlags);
|
|
|
|
hhResize.inject();
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2009-08-25 17:44:17 +00:00
|
|
|
static ULONG __stdcall myAddRef(ID3D10Device *pDevice) {
|
|
|
|
AddRefType oAddRef = (AddRefType) hhAddRef.call;
|
|
|
|
|
|
|
|
hhAddRef.restore();
|
|
|
|
LONG res = oAddRef(pDevice);
|
|
|
|
hhAddRef.inject();
|
|
|
|
|
|
|
|
Mutex m;
|
|
|
|
D10State *ds = devices[pDevice];
|
|
|
|
if (ds)
|
|
|
|
ds->lHighMark = res;
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG __stdcall myRelease(ID3D10Device *pDevice) {
|
|
|
|
ReleaseType oRelease = (ReleaseType) hhRelease.call;
|
|
|
|
|
|
|
|
hhRelease.restore();
|
|
|
|
LONG res = oRelease(pDevice);
|
|
|
|
hhRelease.inject();
|
|
|
|
|
|
|
|
Mutex m;
|
|
|
|
D10State *ds = devices[pDevice];
|
|
|
|
if (ds)
|
|
|
|
if (res < (ds->lHighMark / 2)) {
|
2009-08-25 17:52:11 +00:00
|
|
|
ods("D3D10: Deleting resources %d < .5 %d", res, ds->lHighMark);
|
2009-08-25 17:44:17 +00:00
|
|
|
devices.erase(ds->pDevice);
|
|
|
|
chains.erase(ds->pSwapChain);
|
|
|
|
delete ds;
|
|
|
|
ods("D3D10: Deleted");
|
|
|
|
ds = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void HookAddRelease(voidFunc vfAdd, voidFunc vfRelease) {
|
|
|
|
ods("D3D10: Injecting device add/remove");
|
|
|
|
hhAddRef.setup(vfAdd, reinterpret_cast<voidFunc>(myAddRef));
|
|
|
|
hhRelease.setup(vfRelease, reinterpret_cast<voidFunc>(myRelease));
|
|
|
|
}
|
2009-08-25 16:11:31 +00:00
|
|
|
|
2009-08-24 15:16:15 +00:00
|
|
|
static void HookPresentRaw(voidFunc vfPresent) {
|
|
|
|
hhPresent.setup(vfPresent, reinterpret_cast<voidFunc>(myPresent));
|
|
|
|
}
|
|
|
|
|
2009-08-25 16:11:31 +00:00
|
|
|
static void HookResizeRaw(voidFunc vfResize) {
|
|
|
|
ods("DXGI: Injecting ResizeBuffers Raw");
|
|
|
|
hhResize.setup(vfResize, reinterpret_cast<voidFunc>(myResize));
|
|
|
|
}
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
void checkDXGIHook(bool preonly) {
|
|
|
|
if (bChaining) {
|
|
|
|
return;
|
|
|
|
ods("DXGI: Causing a chain");
|
|
|
|
}
|
|
|
|
|
|
|
|
bChaining = true;
|
|
|
|
|
|
|
|
HMODULE hDXGI = GetModuleHandleW(L"DXGI.DLL");
|
2009-08-25 17:44:17 +00:00
|
|
|
HMODULE hD3D10 = GetModuleHandleW(L"D3D10CORE.DLL");
|
2009-08-24 15:16:15 +00:00
|
|
|
|
2009-08-25 17:44:17 +00:00
|
|
|
if (hDXGI && hD3D10) {
|
2009-08-24 15:16:15 +00:00
|
|
|
if (! bHooked) {
|
|
|
|
wchar_t procname[2048];
|
|
|
|
GetModuleFileNameW(NULL, procname, 2048);
|
|
|
|
fods("DXGI: Hookcheck '%ls'", procname);
|
|
|
|
bHooked = true;
|
|
|
|
|
|
|
|
// Add a ref to ourselves; we do NOT want to get unloaded directly from this process.
|
|
|
|
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<char *>(&checkDXGIHook), &hSelf);
|
|
|
|
|
|
|
|
// Can we use the prepatch data?
|
|
|
|
GetModuleFileNameW(hDXGI, procname, 2048);
|
2009-08-25 17:44:17 +00:00
|
|
|
if (_wcsicmp(dxgi->wcDXGIFileName, procname) == 0) {
|
2009-08-24 15:16:15 +00:00
|
|
|
unsigned char *raw = (unsigned char *) hDXGI;
|
|
|
|
HookPresentRaw((voidFunc)(raw + dxgi->iOffsetPresent));
|
2009-08-25 16:11:31 +00:00
|
|
|
HookResizeRaw((voidFunc)(raw + dxgi->iOffsetResize));
|
2009-08-25 17:44:17 +00:00
|
|
|
|
|
|
|
GetModuleFileNameW(hD3D10, procname, 2048);
|
|
|
|
if (_wcsicmp(dxgi->wcD3D10FileName, procname) == 0) {
|
|
|
|
unsigned char *raw = (unsigned char *) hD3D10;
|
|
|
|
HookAddRelease((voidFunc)(raw + dxgi->iOffsetAddRef), (voidFunc)(raw + dxgi->iOffsetRelease));
|
|
|
|
}
|
2009-08-24 15:16:15 +00:00
|
|
|
} else if (! preonly) {
|
|
|
|
fods("DXGI Interface changed, can't rawpatch");
|
|
|
|
} else {
|
|
|
|
bHooked = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bChaining = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" __declspec(dllexport) void __cdecl PrepareDXGI() {
|
|
|
|
ods("Preparing static data for DXGI Injection");
|
|
|
|
|
|
|
|
HMODULE hD3D10 = LoadLibrary("D3D10.DLL");
|
|
|
|
HMODULE hDXGI = LoadLibrary("DXGI.DLL");
|
|
|
|
HRESULT hr;
|
|
|
|
|
2009-08-25 17:44:17 +00:00
|
|
|
dxgi->wcDXGIFileName[0] = 0;
|
|
|
|
dxgi->wcD3D10FileName[0] = 0;
|
2009-08-24 15:16:15 +00:00
|
|
|
dxgi->iOffsetPresent = 0;
|
2009-08-25 17:44:17 +00:00
|
|
|
dxgi->iOffsetResize = 0;
|
|
|
|
dxgi->iOffsetAddRef = 0;
|
|
|
|
dxgi->iOffsetRelease = 0;
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
if (hDXGI != NULL && hD3D10 != NULL) {
|
|
|
|
CreateDXGIFactoryType pCreateDXGIFactory = reinterpret_cast<CreateDXGIFactoryType>(GetProcAddress(hDXGI, "CreateDXGIFactory"));
|
|
|
|
ods("Got %p", pCreateDXGIFactory);
|
|
|
|
if (pCreateDXGIFactory) {
|
|
|
|
IDXGIFactory * pFactory;
|
2009-09-02 15:41:45 +00:00
|
|
|
hr = pCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory));
|
2009-08-24 15:16:15 +00:00
|
|
|
if (pFactory) {
|
2009-09-02 15:41:45 +00:00
|
|
|
HWND hwnd = CreateWindowW(L"STATIC", L"Mumble DXGI Window", WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 0,
|
|
|
|
NULL, NULL, 0);
|
2009-08-24 15:16:15 +00:00
|
|
|
|
|
|
|
IDXGIAdapter *pAdapter = NULL;
|
|
|
|
pFactory->EnumAdapters(0, &pAdapter);
|
|
|
|
|
|
|
|
D3D10CreateDeviceAndSwapChainType pD3D10CreateDeviceAndSwapChain = reinterpret_cast<D3D10CreateDeviceAndSwapChainType>(GetProcAddress(hD3D10, "D3D10CreateDeviceAndSwapChain"));
|
|
|
|
|
|
|
|
IDXGISwapChain *pSwapChain = NULL;
|
|
|
|
ID3D10Device *pDevice = NULL;
|
|
|
|
|
|
|
|
DXGI_SWAP_CHAIN_DESC desc;
|
|
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
|
|
|
2009-09-02 15:41:45 +00:00
|
|
|
RECT rcWnd;
|
|
|
|
GetClientRect(hwnd, &rcWnd);
|
2009-08-24 15:16:15 +00:00
|
|
|
desc.BufferDesc.Width = rcWnd.right - rcWnd.left;
|
|
|
|
desc.BufferDesc.Height = rcWnd.bottom - rcWnd.top;
|
|
|
|
|
|
|
|
ods("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;
|
|
|
|
|
|
|
|
hr = pD3D10CreateDeviceAndSwapChain(pAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &desc, &pSwapChain, &pDevice);
|
|
|
|
|
|
|
|
if (pDevice && pSwapChain) {
|
2009-09-02 15:41:45 +00:00
|
|
|
HMODULE hRef;
|
|
|
|
void ***vtbl = (void ***) pSwapChain;
|
|
|
|
void *pPresent = (*vtbl)[8];
|
|
|
|
if (! GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (char *) pPresent, &hRef)) {
|
|
|
|
ods("DXGI: Failed to get module for Present");
|
|
|
|
} else {
|
|
|
|
GetModuleFileNameW(hRef, dxgi->wcDXGIFileName, 2048);
|
|
|
|
unsigned char *b = (unsigned char *) pPresent;
|
|
|
|
unsigned char *a = (unsigned char *) hRef;
|
|
|
|
dxgi->iOffsetPresent = b-a;
|
|
|
|
ods("DXGI: Successfully found Present offset: %ls: %d", dxgi->wcDXGIFileName, dxgi->iOffsetPresent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *pResize = (*vtbl)[13];
|
|
|
|
if (! GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (char *) pResize, &hRef)) {
|
|
|
|
ods("DXGI: Failed to get module for ResizeBuffers");
|
|
|
|
} else {
|
|
|
|
wchar_t buff[2048];
|
|
|
|
GetModuleFileNameW(hRef, buff, 2048);
|
|
|
|
if (wcscmp(buff, dxgi->wcDXGIFileName) == 0) {
|
|
|
|
unsigned char *b = (unsigned char *) pResize;
|
2009-08-24 15:16:15 +00:00
|
|
|
unsigned char *a = (unsigned char *) hRef;
|
2009-09-02 15:41:45 +00:00
|
|
|
dxgi->iOffsetResize = b-a;
|
|
|
|
ods("DXGI: Successfully found ResizeBuffers offset: %ls: %d", dxgi->wcDXGIFileName, dxgi->iOffsetPresent);
|
2009-08-25 16:11:31 +00:00
|
|
|
}
|
2009-09-02 15:41:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vtbl = (void ***) pDevice;
|
|
|
|
|
|
|
|
void *pAddRef = (*vtbl)[1];
|
|
|
|
if (! GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (char *) pAddRef, &hRef)) {
|
|
|
|
ods("D3D10: Failed to get module for AddRef");
|
|
|
|
} else {
|
|
|
|
GetModuleFileNameW(hRef, dxgi->wcD3D10FileName, 2048);
|
|
|
|
unsigned char *b = (unsigned char *) pAddRef;
|
|
|
|
unsigned char *a = (unsigned char *) hRef;
|
|
|
|
dxgi->iOffsetAddRef = b-a;
|
|
|
|
ods("D3D10: Successfully found AddRef offset: %ls: %d", dxgi->wcD3D10FileName, dxgi->iOffsetAddRef);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *pRelease = (*vtbl)[2];
|
|
|
|
if (! GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (char *) pRelease, &hRef)) {
|
|
|
|
ods("D3D10: Failed to get module for Release");
|
|
|
|
} else {
|
|
|
|
wchar_t buff[2048];
|
|
|
|
GetModuleFileNameW(hRef, buff, 2048);
|
|
|
|
if (wcscmp(buff, dxgi->wcD3D10FileName) == 0) {
|
|
|
|
unsigned char *b = (unsigned char *) pRelease;
|
2009-08-25 17:44:17 +00:00
|
|
|
unsigned char *a = (unsigned char *) hRef;
|
2009-09-02 15:41:45 +00:00
|
|
|
dxgi->iOffsetRelease = b-a;
|
|
|
|
ods("D3D10: Successfully found Release offset: %ls: %d", dxgi->wcD3D10FileName, dxgi->iOffsetRelease);
|
2009-08-24 15:16:15 +00:00
|
|
|
}
|
2009-09-02 15:41:45 +00:00
|
|
|
}
|
2009-08-24 15:16:15 +00:00
|
|
|
}
|
|
|
|
if (pDevice)
|
|
|
|
pDevice->Release();
|
|
|
|
if (pSwapChain)
|
|
|
|
pSwapChain->Release();
|
|
|
|
DestroyWindow(hwnd);
|
|
|
|
|
|
|
|
pFactory->Release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|