[SOLVED]Assertion failed ceguisingleton.h
Posted: Sat Mar 19, 2011 06:16
Hi all,
Firstly I must excuse myself for being quite useless at OOP and C++ ...but my determination will see me getting this thing working!
I have spent a few hours now reading documentation, forum posts etc, and I am still at a loss as to what I am doing wrong. I am trying to get a very simple CEGUI to render over an existing DX9 app. I am hooking EndScene and using System::getSingleton().renderGUI() to try to draw the CEGUI I have set up, but it isn't working for me. I am using CEGUI code based on the First Window sample (just using that as the basic GUI to test the rendering). There are obviously similar posts here and here but I don't think it's the same as I am using bootstrap but not trying to set up System a second time, and I thingk I am doing it in the right order...
Just to give you a bit of background: I am compiling a dll. That contains all the hook and CEGUI code I have set up (see below). I am then loading that library with a speparate small launcher that literally uses LoadLibrary on my dll and then calls my InstallHook() which uses SetWindowsHookEx to inject itself into all processes. It then has some code in my DllMain() that checks the current process name, and only hooks the D3D API calls when the process is the one I want.
Then, within EndScene() I check to see whether the GUI (and other things) have been initialised, and if not then my function Init() is called. This is where I do all the ResourceGroup setups and create renderer,etc. as well as defining the GUI window. This is not done on every frame, only if it has never been initilised before.
The first problem is: when my Dll is injected, it complains that it needs CEGUIBase.dll and CEGUIDirect3D9Renderer.dll... is there any way to include this in the DLL? Otherwise I have to put these in a system directory which I would like to avoid if possible. However this is only a minor issue.
The code actually compiles fine, and the dll definitely gets injected, as I can see the other stuff on the screen (a simple quad and some text in the top left corner) rendering fine, so the general setup of my DLL seems to be OK at first glance... however the main problem is that I can't get any CEGUI stuff to show up. I also don't seem to be getting anything in a CEGUI.log, otherwise I would have posted that!
I set everything up, and as long as I don't call System::getSingleton().renderGUI (which I am doing in in EndScene), then the DLL is injected and my other test things render fine. However, as soon as I uncomment the renderGUI() call, the DLL still compiles and gets injected, but then I get an "Assertion failed" error:
The weird thing is that the directory mentioned in that error is not where CEGUI is installed/built... but anyway regardless, I am not sure why it is not working. The actual directory is C:\Utilities\CEGUI-SDK-0.7.5-vc10 in case it makes any difference.
I will also mention that I am using MSVC++ 2010 Express, compiling in release mode and the code below is building without any errors or warnings at all. It took me a while to get that far, but now I am really stuck. Would someone be able to take a look and tell me what stupid thing I am doing wrong please?
A caveat: I didn't write most of the code in the below, other than the CEGUI related stuff, it was based on code from this page.
Just to make it easier (or maybe harder for you, but easier for me), all the relevant code is in one file (Direct3D-Hook.cpp) and these are the functions where the relevant code is:
DllMain() - check process name and hook if correct
Init() called from EndScene() just the first tme if it hasn't been called already. Sets up GUI, and other test items that are successfully rendered.
InstallHook() - installs system hook to inject the DLL into all processes (called by an external launcher)
RemoveHook() removes the hook (called by an external launcher)
MyDirect3DCreate9() the hook function. Will beep when called to let you know a process has been hooked properly.
EndScene() - obviously where renderGUI() is being called among other things.
There is another file (apihijack) that I didn't write - this just implements the D3D9 API hook as far as I am aware. I have included it below anyway for completeness.
TIA!
Direct3D-Hook.h:
Direct3D-Hook.cpp: (this is where all the relevant stuff is)
apihijack.h:
apihijack.cpp
stdafx.h:
stdafx.cpp:
Firstly I must excuse myself for being quite useless at OOP and C++ ...but my determination will see me getting this thing working!
I have spent a few hours now reading documentation, forum posts etc, and I am still at a loss as to what I am doing wrong. I am trying to get a very simple CEGUI to render over an existing DX9 app. I am hooking EndScene and using System::getSingleton().renderGUI() to try to draw the CEGUI I have set up, but it isn't working for me. I am using CEGUI code based on the First Window sample (just using that as the basic GUI to test the rendering). There are obviously similar posts here and here but I don't think it's the same as I am using bootstrap but not trying to set up System a second time, and I thingk I am doing it in the right order...
Just to give you a bit of background: I am compiling a dll. That contains all the hook and CEGUI code I have set up (see below). I am then loading that library with a speparate small launcher that literally uses LoadLibrary on my dll and then calls my InstallHook() which uses SetWindowsHookEx to inject itself into all processes. It then has some code in my DllMain() that checks the current process name, and only hooks the D3D API calls when the process is the one I want.
Then, within EndScene() I check to see whether the GUI (and other things) have been initialised, and if not then my function Init() is called. This is where I do all the ResourceGroup setups and create renderer,etc. as well as defining the GUI window. This is not done on every frame, only if it has never been initilised before.
The first problem is: when my Dll is injected, it complains that it needs CEGUIBase.dll and CEGUIDirect3D9Renderer.dll... is there any way to include this in the DLL? Otherwise I have to put these in a system directory which I would like to avoid if possible. However this is only a minor issue.
The code actually compiles fine, and the dll definitely gets injected, as I can see the other stuff on the screen (a simple quad and some text in the top left corner) rendering fine, so the general setup of my DLL seems to be OK at first glance... however the main problem is that I can't get any CEGUI stuff to show up. I also don't seem to be getting anything in a CEGUI.log, otherwise I would have posted that!
I set everything up, and as long as I don't call System::getSingleton().renderGUI (which I am doing in in EndScene), then the DLL is injected and my other test things render fine. However, as soon as I uncomment the renderGUI() call, the DLL still compiles and gets injected, but then I get an "Assertion failed" error:
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Assertion failed!
Program: ...
File: c:\cegui-0.7.5\cegui\include\ceguisingleton.h
Line: 79
Expression: ms_Singleton
The weird thing is that the directory mentioned in that error is not where CEGUI is installed/built... but anyway regardless, I am not sure why it is not working. The actual directory is C:\Utilities\CEGUI-SDK-0.7.5-vc10 in case it makes any difference.
I will also mention that I am using MSVC++ 2010 Express, compiling in release mode and the code below is building without any errors or warnings at all. It took me a while to get that far, but now I am really stuck. Would someone be able to take a look and tell me what stupid thing I am doing wrong please?
A caveat: I didn't write most of the code in the below, other than the CEGUI related stuff, it was based on code from this page.
Just to make it easier (or maybe harder for you, but easier for me), all the relevant code is in one file (Direct3D-Hook.cpp) and these are the functions where the relevant code is:
DllMain() - check process name and hook if correct
Init() called from EndScene() just the first tme if it hasn't been called already. Sets up GUI, and other test items that are successfully rendered.
InstallHook() - installs system hook to inject the DLL into all processes (called by an external launcher)
RemoveHook() removes the hook (called by an external launcher)
MyDirect3DCreate9() the hook function. Will beep when called to let you know a process has been hooked properly.
EndScene() - obviously where renderGUI() is being called among other things.
There is another file (apihijack) that I didn't write - this just implements the D3D9 API hook as far as I am aware. I have included it below anyway for completeness.
TIA!
Direct3D-Hook.h:
Code: Select all
#pragma once
#ifdef DIRECT3DHOOK_EXPORTS
#define D3DHOOK_API extern "C" __declspec(dllexport)
#else
#define D3DHOOK_API extern "C" __declspec(dllimport)
#endif
D3DHOOK_API void InstallHook();
D3DHOOK_API void RemoveHook();
D3DHOOK_API bool setTesty(int i, char string[256]);
D3DHOOK_API int getTesty();
Direct3D-Hook.cpp: (this is where all the relevant stuff is)
Code: Select all
// Direct3D-Hook.cpp : Defines the entry point for the DLL application.
//
#pragma once
#include "stdafx.h"
#include "apihijack.h"
#include "Direct3D-Hook.h"
#include "d3dx9.h"
#include "CEGUI.h"
#include "CEGUIDirect3D9Renderer.h"
#pragma comment(lib, "d3dx9.lib")
#pragma data_seg (".shared")
int testy = 0;
char topString[256] = "hello world";
#pragma data_seg()
#pragma comment(linker, "/section:.shared,rws")
#define CEGUI_STATIC
#define CEGUI_WITH_TINYXML
#define CEGUI_FALAGARD_RENDERER
#define CEGUI_CODEC_SILLY
#define yellow D3DCOLOR_ARGB(255,255,255,0)
// Function pointer types.
typedef IDirect3D9* (WINAPI *Direct3DCreate9_t)(UINT sdk_version);
// Function prototypes.
IDirect3D9* WINAPI MyDirect3DCreate9(UINT sdk_version);
HINSTANCE hDLL;
// Hook structure.
enum
{
D3DFN_Direct3DCreate9 = 0
};
SDLLHook D3DHook =
{
"D3D9.DLL",
false, NULL, // Default hook disabled, NULL function pointer.
{
{ "Direct3DCreate9", MyDirect3DCreate9},
{ NULL, NULL }
}
};
class MyDirect3DDevice9 : public IDirect3DDevice9
{
public:
// We need d3d so that we'd use a pointer to MyDirect3D9 instead of the original IDirect3D9 implementor
// in functions like GetDirect3D9
MyDirect3DDevice9(IDirect3D9* d3d, IDirect3DDevice9* device) :
m_d3d(d3d), m_device(device), Font(NULL), p_D3DDev(NULL)
{
}
void RenderText(LPD3DXSPRITE pSprite, LPCTSTR pString, int x, int y, D3DCOLOR Color)
{
RECT fontRect;
SetRect( &fontRect, x, y, 0, 0 );
Font->DrawText( NULL, pString, -1, &fontRect, DT_LEFT|DT_NOCLIP, Color );
}
void Init()
{
OutputDebugString( "Direct3D-Hook: Init() -> Initialising...\n" );
if( FAILED( D3DXCreateFont( m_device,
18, 0, 0, 1, 0,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
"Arial",
&Font ) ) )
{
OutputDebugString( "Direct3D-Hook: Init() -> D3DXCreateFont FAILED!\n" );
}
else
{
OutputDebugString( "Direct3D-Hook: Init() -> D3DXCreateFont SUCCEEDED!\n" );
}
/////////////////////////////////////////////////////
/////////////////// CEGUI ///////////////////////////
/////////////////////////////////////////////////////
using namespace CEGUI;
try
{
// CEGUI BOOTSTRAP
CEGUI::Direct3D9Renderer& m_CEGUI = CEGUI::Direct3D9Renderer::bootstrapSystem(m_device);
// initialise the required dirs for the DefaultResourceProvider
CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*>(CEGUI::System::getSingleton().getResourceProvider());
rp->setResourceGroupDirectory("schemes", "datafiles/schemes/");
rp->setResourceGroupDirectory("imagesets", "datafiles/imagesets/");
rp->setResourceGroupDirectory("fonts", "datafiles/fonts/");
rp->setResourceGroupDirectory("layouts", "datafiles/layouts/");
rp->setResourceGroupDirectory("looknfeels", "datafiles/looknfeel/");
rp->setResourceGroupDirectory("lua_scripts", "datafiles/lua_scripts/");
// set the default resource groups to be used
CEGUI::Imageset::setDefaultResourceGroup("imagesets");
CEGUI::Font::setDefaultResourceGroup("fonts");
CEGUI::Scheme::setDefaultResourceGroup("schemes");
CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
CEGUI::WindowManager::setDefaultResourceGroup("layouts");
CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
// setup default group for validation schemas
CEGUI::XMLParser* parser = CEGUI::System::getSingleton().getXMLParser();
if (parser->isPropertyPresent("SchemaDefaultResourceGroup"))
parser->setProperty("SchemaDefaultResourceGroup", "schemas");
CEGUI::DefaultLogger::getSingleton().setLogFilename("H:/ceguilog.log");
CEGUI::DefaultLogger::getSingleton().setLoggingLevel(CEGUI::Informative);
CEGUI::SchemeManager::getSingleton().create("TaharezLook.scheme");
CEGUI::WindowManager& winMgr = CEGUI::WindowManager::getSingleton();
// Create a DefaultWindow called 'Root'.
DefaultWindow* root = (DefaultWindow*)winMgr.createWindow("DefaultWindow", "Root");
System::getSingleton().setGUISheet(root);
// create frame window and add as a child to root
FrameWindow* wnd = (FrameWindow*)winMgr.createWindow("TaharezLook/FrameWindow", "Demo Window");
root->addChildWindow(wnd);
wnd->setPosition(UVector2(cegui_reldim(0.25f), cegui_reldim( 0.25f)));
wnd->setSize(UVector2(cegui_reldim(0.5f), cegui_reldim( 0.5f)));
wnd->setMaxSize(UVector2(cegui_reldim(1.0f), cegui_reldim( 1.0f)));
wnd->setMinSize(UVector2(cegui_reldim(0.1f), cegui_reldim( 0.1f)));
wnd->setText("Hello World!");
// not sure if this is needed either but fixed a different issue I saw on the forum with no rendering
m_CEGUI.setDisplaySize( CEGUI::Size(800,600) );
}
catch (Exception e)
{
e.getMessage();
}
OutputDebugString( "Direct3D-Hook: Init() -> Finished Initialising.\n" );
}
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj)
{
return m_device->QueryInterface(riid, ppvObj);
}
STDMETHOD_(ULONG,AddRef)(THIS)
{
return m_device->AddRef();
}
STDMETHOD_(ULONG,Release)(THIS)
{
ULONG count = m_device->Release();
if(0 == count)
delete this;
return count;
}
/*** IDirect3DDevice9 methods ***/
STDMETHOD(TestCooperativeLevel)(THIS)
{
return m_device->TestCooperativeLevel();
}
STDMETHOD_(UINT, GetAvailableTextureMem)(THIS)
{
return m_device->GetAvailableTextureMem();
}
STDMETHOD(EvictManagedResources)(THIS)
{
return m_device->EvictManagedResources();
}
STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9)
{
// Let the device validate the incoming pointer for us
HRESULT hr = m_device->GetDirect3D(ppD3D9);
if(SUCCEEDED(hr))
*ppD3D9 = m_d3d;
return hr;
}
STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps)
{
return m_device->GetDeviceCaps(pCaps);
}
STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain,D3DDISPLAYMODE* pMode)
{
return m_device->GetDisplayMode(iSwapChain, pMode);
}
STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters)
{
return m_device->GetCreationParameters(pParameters);
}
STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap)
{
return m_device->SetCursorProperties(XHotSpot, YHotSpot, pCursorBitmap);
}
STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y,DWORD Flags)
{
m_device->SetCursorPosition(X, Y, Flags);
}
STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow)
{
return m_device->ShowCursor(bShow);
}
STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain)
{
return m_device->CreateAdditionalSwapChain(pPresentationParameters, pSwapChain);
}
STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain,IDirect3DSwapChain9** pSwapChain)
{
return m_device->GetSwapChain(iSwapChain, pSwapChain);
}
STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS)
{
return m_device->GetNumberOfSwapChains();
}
STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters)
{
OutputDebugString( "Direct3D-Hook: RESETTING!" );
return m_device->Reset(pPresentationParameters);
}
STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion)
{
return m_device->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
}
STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer)
{
return m_device->GetBackBuffer(iSwapChain, iBackBuffer, Type, ppBackBuffer);
}
STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain,D3DRASTER_STATUS* pRasterStatus)
{
return m_device->GetRasterStatus(iSwapChain, pRasterStatus);
}
STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs)
{
return m_device->SetDialogBoxMode(bEnableDialogs);
}
STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp)
{
return m_device->SetGammaRamp(iSwapChain, Flags, pRamp);
}
STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain,D3DGAMMARAMP* pRamp)
{
return m_device->GetGammaRamp(iSwapChain, pRamp);
}
STDMETHOD(CreateTexture)(THIS_ UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle)
{
return m_device->CreateTexture(Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle);
}
STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,HANDLE* pSharedHandle)
{
return m_device->CreateVolumeTexture(Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle);
}
STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle)
{
return m_device->CreateCubeTexture(EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle);
}
STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle)
{
return m_device->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
}
STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,HANDLE* pSharedHandle)
{
return m_device->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle);
}
STDMETHOD(CreateRenderTarget)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle)
{
return m_device->CreateRenderTarget(Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle);
}
STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle)
{
return m_device->CreateDepthStencilSurface(Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle);
}
STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint)
{
return m_device->UpdateSurface(pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
}
STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture,IDirect3DBaseTexture9* pDestinationTexture)
{
return m_device->UpdateTexture(pSourceTexture, pDestinationTexture);
}
STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface)
{
return m_device->GetRenderTargetData(pRenderTarget, pDestSurface);
}
STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IDirect3DSurface9* pDestSurface)
{
return m_device->GetFrontBufferData(iSwapChain, pDestSurface);
}
STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter)
{
return m_device->StretchRect(pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
}
STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface,CONST RECT* pRect,D3DCOLOR color)
{
return m_device->ColorFill(pSurface, pRect, color);
}
STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle)
{
return m_device->CreateOffscreenPlainSurface(Width, Height, Format, Pool, ppSurface, pSharedHandle);
}
STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget)
{
return m_device->SetRenderTarget(RenderTargetIndex, pRenderTarget);
}
STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget)
{
return m_device->GetRenderTarget(RenderTargetIndex, ppRenderTarget);
}
STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil)
{
return m_device->SetDepthStencilSurface(pNewZStencil);
}
STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface)
{
return m_device->GetDepthStencilSurface(ppZStencilSurface);
}
STDMETHOD(BeginScene)(THIS)
{
return m_device->BeginScene();
}
STDMETHOD(EndScene)(THIS)
{
if ( !p_D3DDev )
{
p_D3DDev = m_device;
Init();
}
// Draw a custom quad to the screen
struct TLVertex
{
float x, y, z, rhw;
DWORD color;
};
TLVertex vertices[] =
{
{ -0.5f, -0.5f, 0.0f, 1.0f, 0xffff0000 },
{ 99.5f, -0.5f, 0.0f, 1.0f, 0xff00ff00 },
{ -0.5f, 99.5f, 0.0f, 1.0f, 0xff0000ff },
{ 99.5f, 99.5f, 0.0f, 1.0f, 0xffff0000 }
};
SetVertexShader(0);
SetPixelShader(0);
SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
SetRenderState(D3DRS_ZENABLE, false);
SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(TLVertex));
RenderText( NULL, topString, 30, 30, yellow );
try
{
// draw GUI
CEGUI::System::getSingleton().renderGUI(); // <== crash with this uncommented
}
catch (CEGUI::Exception e)
{
e.getMessage();
}
// not sure if the below is needed after renderGUI? Maybe for some DX9 apps.
//SetVertexShader(0);
//SetPixelShader(0);
//SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
//SetRenderState(D3DRS_ZENABLE, false);
//SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
//SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
//SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
//SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
//SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
//SetRenderState(D3DRS_ZENABLE, true);
SetRenderState(D3DRS_ZENABLE, true);
return m_device->EndScene();
}
STDMETHOD(Clear)(THIS_ DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil)
{
return m_device->Clear(Count, pRects, Flags, Color, Z, Stencil);
}
STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
{
return m_device->SetTransform(State, pMatrix);
}
STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix)
{
return m_device->GetTransform(State, pMatrix);
}
STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
{
return m_device->MultiplyTransform(State, pMatrix);
}
STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport)
{
return m_device->SetViewport(pViewport);
}
STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport)
{
return m_device->GetViewport(pViewport);
}
STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial)
{
return m_device->SetMaterial(pMaterial);
}
STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial)
{
return m_device->GetMaterial(pMaterial);
}
STDMETHOD(SetLight)(THIS_ DWORD Index,CONST D3DLIGHT9* pLight)
{
return m_device->SetLight(Index, pLight);
}
STDMETHOD(GetLight)(THIS_ DWORD Index,D3DLIGHT9* pLight)
{
return m_device->GetLight(Index, pLight);
}
STDMETHOD(LightEnable)(THIS_ DWORD Index,BOOL Enable)
{
return m_device->LightEnable(Index, Enable);
}
STDMETHOD(GetLightEnable)(THIS_ DWORD Index,BOOL* pEnable)
{
return m_device->GetLightEnable(Index, pEnable);
}
STDMETHOD(SetClipPlane)(THIS_ DWORD Index,CONST float* pPlane)
{
return m_device->SetClipPlane(Index, pPlane);
}
STDMETHOD(GetClipPlane)(THIS_ DWORD Index,float* pPlane)
{
return m_device->GetClipPlane(Index, pPlane);
}
STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value)
{
return m_device->SetRenderState(State, Value);
}
STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD* pValue)
{
return m_device->GetRenderState(State, pValue);
}
STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type,IDirect3DStateBlock9** ppSB)
{
return m_device->CreateStateBlock(Type, ppSB);
}
STDMETHOD(BeginStateBlock)(THIS)
{
return m_device->BeginStateBlock();
}
STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB)
{
return m_device->EndStateBlock(ppSB);
}
STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus)
{
return m_device->SetClipStatus(pClipStatus);
}
STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus)
{
return m_device->GetClipStatus(pClipStatus);
}
STDMETHOD(GetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9** ppTexture)
{
return m_device->GetTexture(Stage, ppTexture);
}
STDMETHOD(SetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9* pTexture)
{
return m_device->SetTexture(Stage, pTexture);
}
STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue)
{
return m_device->GetTextureStageState(Stage, Type, pValue);
}
STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value)
{
return m_device->SetTextureStageState(Stage, Type, Value);
}
STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD* pValue)
{
return m_device->GetSamplerState(Sampler, Type, pValue);
}
STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value)
{
return m_device->SetSamplerState(Sampler, Type, Value);
}
STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses)
{
return m_device->ValidateDevice(pNumPasses);
}
STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber,CONST PALETTEENTRY* pEntries)
{
return m_device->SetPaletteEntries(PaletteNumber, pEntries);
}
STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries)
{
return m_device->GetPaletteEntries(PaletteNumber, pEntries);
}
STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber)
{
return m_device->SetCurrentTexturePalette(PaletteNumber);
}
STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber)
{
return m_device->GetCurrentTexturePalette(PaletteNumber);
}
STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect)
{
return m_device->SetScissorRect(pRect);
}
STDMETHOD(GetScissorRect)(THIS_ RECT* pRect)
{
return m_device->GetScissorRect(pRect);
}
STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware)
{
return m_device->SetSoftwareVertexProcessing(bSoftware);
}
STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS)
{
return m_device->GetSoftwareVertexProcessing();
}
STDMETHOD(SetNPatchMode)(THIS_ float nSegments)
{
return m_device->SetNPatchMode(nSegments);
}
STDMETHOD_(float, GetNPatchMode)(THIS)
{
return m_device->GetNPatchMode();
}
STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount)
{
return m_device->DrawPrimitive(PrimitiveType, StartVertex, PrimitiveCount);
}
STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount)
{
return m_device->DrawIndexedPrimitive(PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
}
STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
{
return m_device->DrawPrimitiveUP(PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
}
STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
{
return m_device->DrawIndexedPrimitiveUP(PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
}
STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer9* pDestBuffer,IDirect3DVertexDeclaration9* pVertexDecl,DWORD Flags)
{
return m_device->ProcessVertices(SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
}
STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl)
{
return m_device->CreateVertexDeclaration(pVertexElements, ppDecl);
}
STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl)
{
return m_device->SetVertexDeclaration(pDecl);
}
STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl)
{
return m_device->GetVertexDeclaration(ppDecl);
}
STDMETHOD(SetFVF)(THIS_ DWORD FVF)
{
return m_device->SetFVF(FVF);
}
STDMETHOD(GetFVF)(THIS_ DWORD* pFVF)
{
return m_device->GetFVF(pFVF);
}
STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader)
{
return m_device->CreateVertexShader(pFunction, ppShader);
}
STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader)
{
return m_device->SetVertexShader(pShader);
}
STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader)
{
return m_device->GetVertexShader(ppShader);
}
STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
{
return m_device->SetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount);
}
STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount)
{
return m_device->GetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount);
}
STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
{
return m_device->SetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount);
}
STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount)
{
return m_device->GetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount);
}
STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount)
{
return m_device->SetVertexShaderConstantB(StartRegister, pConstantData, BoolCount);
}
STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount)
{
return m_device->GetVertexShaderConstantB(StartRegister, pConstantData, BoolCount);
}
STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
{
return m_device->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
}
STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9** ppStreamData,UINT* pOffsetInBytes,UINT* pStride)
{
return m_device->GetStreamSource(StreamNumber, ppStreamData, pOffsetInBytes, pStride);
}
STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT Setting)
{
return m_device->SetStreamSourceFreq(StreamNumber, Setting);
}
STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT* pSetting)
{
return m_device->GetStreamSourceFreq(StreamNumber, pSetting);
}
STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData)
{
return m_device->SetIndices(pIndexData);
}
STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData)
{
return m_device->GetIndices(ppIndexData);
}
STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader)
{
return m_device->CreatePixelShader(pFunction, ppShader);
}
STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader)
{
return m_device->SetPixelShader(pShader);
}
STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader)
{
return m_device->GetPixelShader(ppShader);
}
STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
{
return m_device->SetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount);
}
STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount)
{
return m_device->GetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount);
}
STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
{
return m_device->SetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount);
}
STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount)
{
return m_device->GetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount);
}
STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount)
{
return m_device->SetPixelShaderConstantB(StartRegister, pConstantData, BoolCount);
}
STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount)
{
return m_device->GetPixelShaderConstantB(StartRegister, pConstantData, BoolCount);
}
STDMETHOD(DrawRectPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo)
{
return m_device->DrawRectPatch(Handle, pNumSegs, pRectPatchInfo);
}
STDMETHOD(DrawTriPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo)
{
return m_device->DrawTriPatch(Handle, pNumSegs, pTriPatchInfo);
}
STDMETHOD(DeletePatch)(THIS_ UINT Handle)
{
return m_device->DeletePatch(Handle);
}
STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery)
{
return m_device->CreateQuery(Type, ppQuery);
}
private:
IDirect3DDevice9* m_device;
IDirect3D9* m_d3d;
LPD3DXFONT Font; // DirectX font object.
LPDIRECT3DDEVICE9 p_D3DDev;
};
class MyDirect3D9 : public IDirect3D9
{
public:
MyDirect3D9(IDirect3D9* d3d) : m_d3d(d3d)
{
}
/*** IUnknown methods ***/
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObj)
{
return m_d3d->QueryInterface(riid, ppvObj);
}
ULONG STDMETHODCALLTYPE AddRef()
{
return m_d3d->AddRef();
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG count = m_d3d->Release();
if(0 == count)
delete this;
return count;
}
/*** IDirect3D9 methods ***/
HRESULT STDMETHODCALLTYPE RegisterSoftwareDevice(void* pInitializeFunction)
{
return m_d3d->RegisterSoftwareDevice(pInitializeFunction);
}
UINT STDMETHODCALLTYPE GetAdapterCount()
{
return m_d3d->GetAdapterCount();
}
HRESULT STDMETHODCALLTYPE GetAdapterIdentifier( UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier)
{
return m_d3d->GetAdapterIdentifier(Adapter, Flags, pIdentifier);
}
UINT STDMETHODCALLTYPE GetAdapterModeCount( UINT Adapter,D3DFORMAT Format)
{
return m_d3d->GetAdapterModeCount(Adapter, Format);
}
HRESULT STDMETHODCALLTYPE EnumAdapterModes( UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode)
{
return m_d3d->EnumAdapterModes(Adapter, Format, Mode, pMode);
}
HRESULT STDMETHODCALLTYPE GetAdapterDisplayMode( UINT Adapter,D3DDISPLAYMODE* pMode)
{
return m_d3d->GetAdapterDisplayMode(Adapter, pMode);
}
HRESULT STDMETHODCALLTYPE CheckDeviceType( UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed)
{
return m_d3d->CheckDeviceType(Adapter, DevType, AdapterFormat, BackBufferFormat, bWindowed);
}
HRESULT STDMETHODCALLTYPE CheckDeviceFormat( UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)
{
return m_d3d->CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat);
}
HRESULT STDMETHODCALLTYPE CheckDeviceMultiSampleType( UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels)
{
return m_d3d->CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels);
}
HRESULT STDMETHODCALLTYPE CheckDepthStencilMatch( UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat)
{
return m_d3d->CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat);
}
HRESULT STDMETHODCALLTYPE CheckDeviceFormatConversion( UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat)
{
return m_d3d->CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat);
}
HRESULT STDMETHODCALLTYPE GetDeviceCaps( UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps)
{
return m_d3d->GetDeviceCaps(Adapter, DeviceType, pCaps);
}
HMONITOR STDMETHODCALLTYPE GetAdapterMonitor( UINT Adapter)
{
return m_d3d->GetAdapterMonitor(Adapter);
}
HRESULT STDMETHODCALLTYPE CreateDevice( UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface)
{
HRESULT hr = m_d3d->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags,
pPresentationParameters, ppReturnedDeviceInterface);
if(SUCCEEDED(hr))
{
// Return our device
*ppReturnedDeviceInterface = new MyDirect3DDevice9(this, *ppReturnedDeviceInterface);
}
return hr;
}
private:
IDirect3D9* m_d3d;
};
// Hook function.
IDirect3D9* WINAPI MyDirect3DCreate9(UINT sdk_version)
{
// Let the world know we're working.
MessageBeep(MB_ICONINFORMATION);
OutputDebugString( "Direct3D-Hook: MyDirect3DCreate9 called.\n" );
Direct3DCreate9_t old_func = (Direct3DCreate9_t) D3DHook.Functions[D3DFN_Direct3DCreate9].OrigFn;
IDirect3D9* d3d = old_func(sdk_version);
return d3d? new MyDirect3D9(d3d) : 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if(ul_reason_for_call == DLL_PROCESS_ATTACH) // When initializing....
{
hDLL = hModule;
// We don't need thread notifications for what we're doing. Thus, get
// rid of them, thereby eliminating some of the overhead of this DLL
DisableThreadLibraryCalls( hModule );
char targetProcess[256] = "AppName.exe";
char process[256];
GetModuleFileName(GetModuleHandle(0), process, sizeof(process));
PathStripPath(process);
if(_strnicmp(targetProcess, process, 512) == 0)
HookAPICalls( &D3DHook );
}
return TRUE;
}
// This segment must be defined as SHARED in the .DEF
#pragma data_seg (".HookSection")
// Shared instance for all processes.
HHOOK hHook = NULL;
#pragma data_seg ()
D3DHOOK_API LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx( hHook, nCode, wParam, lParam);
}
D3DHOOK_API void InstallHook()
{
OutputDebugString( "Direct3D-Hook: hook installed.\n" );
hHook = SetWindowsHookEx( WH_CBT, HookProc, hDLL, 0 );
}
D3DHOOK_API void RemoveHook()
{
OutputDebugString( "Direct3D-Hook: hook removed.\n" );
UnhookWindowsHookEx( hHook );
}
D3DHOOK_API bool setTesty(int i, char string[256])
{
testy = i;
strcpy_s(topString, string);
return true;
}
D3DHOOK_API int getTesty()
{
return testy;
}
apihijack.h:
Code: Select all
/*--------------------------------------------------------------------------------------------------------
APIHIJACK.H - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
Adapted by Wade Brainerd, wadeb@wadeb.com
--------------------------------------------------------------------------------------------------------*/
#ifndef APIHIJACK_H
#define APIHIJACK_H
#pragma warning(disable:4200)
// Macro for convenient pointer addition.
// Essentially treats the last two parameters as DWORDs. The first
// parameter is used to typecast the result to the appropriate pointer type.
#define MakePtr(cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
// Default Hook Stub Structure: Contains data about the original function, Name/Ordinal, Address
// and a Count field. This is actually a block of assembly code.
#pragma pack( push, 1 )
struct DLPD_IAT_STUB
{
BYTE instr_CALL;
DWORD data_call;
BYTE instr_JMP;
DWORD data_JMP;
DWORD count;
DWORD pszNameOrOrdinal;
DLPD_IAT_STUB() : instr_CALL( 0xE8 ), instr_JMP( 0xE9 ), count( 0 ) {}
};
#pragma pack( pop )
// Example DefaultHook procedure, called from the DLPD_IAT_STUB stubs.
// Increments "count" field of the stub.
// See the implementation for more information.
void __cdecl DefaultHook( PVOID dummy );
struct SFunctionHook
{
char* Name; // Function name, e.g. "DirectDrawCreateEx".
void* HookFn; // Address of your function.
void* OrigFn; // Stored by HookAPICalls, the address of the original function.
};
struct SDLLHook
{
// Name of the DLL, e.g. "DDRAW.DLL"
char* Name;
// Set true to call the default for all non-hooked functions before they are executed.
bool UseDefault;
void* DefaultFn;
// Function hook array. Terminated with a NULL Name field.
SFunctionHook Functions[];
};
// Hook functions one or more DLLs.
bool HookAPICalls( SDLLHook* Hook );
#endif
apihijack.cpp
Code: Select all
/*--------------------------------------------------------------------------------------------------------
APIHIJACK.CPP - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
Adapted by Wade Brainerd, wadeb@wadeb.com
--------------------------------------------------------------------------------------------------------*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "apihijack.h"
//===========================================================================
// Called from the DLPD_IAT_STUB stubs. Increments "count" field of the stub
void __cdecl DefaultHook( PVOID dummy )
{
__asm pushad // Save all general purpose registers
// Get return address, then subtract 5 (size of a CALL X instruction)
// The result points at a DLPD_IAT_STUB
// pointer math! &dummy-1 really subtracts sizeof(PVOID)
PDWORD pRetAddr = (PDWORD)(&dummy - 1);
DLPD_IAT_STUB * pDLPDStub = (DLPD_IAT_STUB *)(*pRetAddr - 5);
pDLPDStub->count++;
#if 0
// Remove the above conditional to get a cheezy API trace from
// the loader process. It's slow!
if ( !IMAGE_SNAP_BY_ORDINAL( pDLPDStub->pszNameOrOrdinal) )
{
OutputDebugString( "Called hooked function: " );
OutputDebugString( (PSTR)pDLPDStub->pszNameOrOrdinal );
OutputDebugString( "\n" );
}
#endif
__asm popad // Restore all general purpose registers
}
// This function must be __cdecl!!!
void __cdecl DelayLoadProfileDLL_UpdateCount( PVOID dummy );
PIMAGE_IMPORT_DESCRIPTOR g_pFirstImportDesc;
//===========================================================================
// Given an HMODULE, returns a pointer to the PE header
PIMAGE_NT_HEADERS PEHeaderFromHModule(HMODULE hModule)
{
PIMAGE_NT_HEADERS pNTHeader = 0;
__try
{
if ( PIMAGE_DOS_HEADER(hModule)->e_magic != IMAGE_DOS_SIGNATURE )
__leave;
pNTHeader = PIMAGE_NT_HEADERS(PBYTE(hModule)
+ PIMAGE_DOS_HEADER(hModule)->e_lfanew);
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
pNTHeader = 0;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
return pNTHeader;
}
//===========================================================================
// Builds stubs for and redirects the IAT for one DLL (pImportDesc)
bool RedirectIAT( SDLLHook* DLLHook, PIMAGE_IMPORT_DESCRIPTOR pImportDesc, PVOID pBaseLoadAddr )
{
PIMAGE_THUNK_DATA pIAT; // Ptr to import address table
PIMAGE_THUNK_DATA pINT; // Ptr to import names table
PIMAGE_THUNK_DATA pIteratingIAT;
// Figure out which OS platform we're on
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx( &osvi );
// If no import names table, we can't redirect this, so bail
if ( pImportDesc->OriginalFirstThunk == 0 )
return false;
pIAT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->FirstThunk );
pINT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->OriginalFirstThunk );
// Count how many entries there are in this IAT. Array is 0 terminated
pIteratingIAT = pIAT;
unsigned cFuncs = 0;
while ( pIteratingIAT->u1.Function )
{
cFuncs++;
pIteratingIAT++;
}
if ( cFuncs == 0 ) // If no imported functions, we're done!
return false;
// These next few lines ensure that we'll be able to modify the IAT,
// which is often in a read-only section in the EXE.
DWORD flOldProtect, flNewProtect, flDontCare;
MEMORY_BASIC_INFORMATION mbi;
// Get the current protection attributes
VirtualQuery( pIAT, &mbi, sizeof(mbi) );
// remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag
flNewProtect = mbi.Protect;
flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
flNewProtect |= (PAGE_READWRITE);
if ( !VirtualProtect( pIAT, sizeof(PVOID) * cFuncs,
flNewProtect, &flOldProtect) )
{
return false;
}
// If the Default hook is enabled, build an array of redirection stubs in the processes memory.
DLPD_IAT_STUB * pStubs = 0;
if ( DLLHook->UseDefault )
{
// Allocate memory for the redirection stubs. Make one extra stub at the
// end to be a sentinel
pStubs = new DLPD_IAT_STUB[ cFuncs + 1];
if ( !pStubs )
return false;
}
// Scan through the IAT, completing the stubs and redirecting the IAT
// entries to point to the stubs
pIteratingIAT = pIAT;
while ( pIteratingIAT->u1.Function )
{
void* HookFn = 0; // Set to either the SFunctionHook or pStubs.
if ( !IMAGE_SNAP_BY_ORDINAL( pINT->u1.Ordinal ) ) // import by name
{
PIMAGE_IMPORT_BY_NAME pImportName = MakePtr( PIMAGE_IMPORT_BY_NAME, pBaseLoadAddr, pINT->u1.AddressOfData );
// Iterate through the hook functions, searching for this import.
SFunctionHook* FHook = DLLHook->Functions;
while ( FHook->Name )
{
if ( lstrcmpi( FHook->Name, (char*)pImportName->Name ) == 0 )
{
OutputDebugString( "Hooked function: " );
OutputDebugString( (char*)pImportName->Name );
OutputDebugString( "\n" );
// Save the old function in the SFunctionHook structure and get the new one.
FHook->OrigFn = reinterpret_cast<void*>(pIteratingIAT->u1.Function);
HookFn = FHook->HookFn;
break;
}
FHook++;
}
// If the default function is enabled, store the name for the user.
if ( DLLHook->UseDefault )
pStubs->pszNameOrOrdinal = (DWORD)&pImportName->Name;
}
else
{
// If the default function is enabled, store the ordinal for the user.
if ( DLLHook->UseDefault )
pStubs->pszNameOrOrdinal = pINT->u1.Ordinal;
}
// If the default function is enabled, fill in the fields to the stub code.
if ( DLLHook->UseDefault )
{
pStubs->data_call = (DWORD)(PDWORD)DLLHook->DefaultFn
- (DWORD)(PDWORD)&pStubs->instr_JMP;
pStubs->data_JMP = *(PDWORD)pIteratingIAT - (DWORD)(PDWORD)&pStubs->count;
// If it wasn't manually hooked, use the Stub function.
if ( !HookFn )
HookFn = (void*)pStubs;
}
// Replace the IAT function pointer if we have a hook.
if ( HookFn )
{
// Cheez-o hack to see if what we're importing is code or data.
// If it's code, we shouldn't be able to write to it
if ( IsBadWritePtr( (PVOID)pIteratingIAT->u1.Function, 1 ) )
{
pIteratingIAT->u1.Function = reinterpret_cast<DWORD>(HookFn);
}
else if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
// Special hack for Win9X, which builds stubs for imported
// functions in system DLLs (Loaded above 2GB). These stubs are
// writeable, so we have to explicitly check for this case
if ( pIteratingIAT->u1.Function > 0x80000000 )
pIteratingIAT->u1.Function = reinterpret_cast<DWORD>(HookFn);
}
}
if ( DLLHook->UseDefault )
pStubs++; // Advance to next stub
pIteratingIAT++; // Advance to next IAT entry
pINT++; // Advance to next INT entry
}
if ( DLLHook->UseDefault )
pStubs->pszNameOrOrdinal = 0; // Final stub is a sentinel
// Put the page attributes back the way they were.
VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flOldProtect, &flDontCare);
return true;
}
//===========================================================================
// Top level routine to find the EXE's imports, and redirect them
bool HookAPICalls( SDLLHook* Hook )
{
if ( !Hook )
return false;
HMODULE hModEXE = GetModuleHandle( 0 );
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule( hModEXE );
if ( !pExeNTHdr )
return false;
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if ( !importRVA )
return false;
// Convert imports RVA to a usable pointer
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR,
hModEXE, importRVA );
// Save off imports address in a global for later use
g_pFirstImportDesc = pImportDesc;
// Iterate through each import descriptor, and redirect if appropriate
while ( pImportDesc->FirstThunk )
{
PSTR pszImportModuleName = MakePtr( PSTR, hModEXE, pImportDesc->Name);
if ( lstrcmpi( pszImportModuleName, Hook->Name ) == 0 )
{
OutputDebugString( "Found " );
OutputDebugString( Hook->Name );
OutputDebugString( "...\n" );
RedirectIAT( Hook, pImportDesc, (PVOID)hModEXE );
}
pImportDesc++; // Advance to next import descriptor
}
return true;
}
stdafx.h:
Code: Select all
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Allow use of features specific to Windows XP or later.
#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
#endif
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <d3d9.h>
#include <shlwapi.h>
// TODO: reference additional headers your program requires here
stdafx.cpp:
Code: Select all
// stdafx.cpp : source file that includes just the standard includes
// Direct3D-Hook.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file