Working D3D9 Hook With CEGUI as Base for Rendering.
Posted: Tue Aug 13, 2013 08:51
Finally managed to put it all together and have a working Hook using CEGUI with (minimal) Example , playing around would be easy from this point.
I will post my Code but keep in mind i'm not a C++ programmer , i just do it for fun. My initial Goal was to create Different hooks ( d3d9, d3d10 , d3d11 , opengl etc.. ) , but for the time beeing I will keep learning just CEGUI and create some kind of generic overlay ( Browser , Option Panel etc..).
Anwyays , back to this sample:
Used VC++ 2010 Express without problems , VC++ 2005 causes lots of problems so i dont recommend it.
The first thing you will need is a Test Application , you can use this one that works fine:
Removed all the comments because of Language ("spanish") , anyways we won't need to modify this code , so just create a new project and Paste it as windowdx.cpp or whatever you want.
Don't forget to point to DX9 libs and includes.
About "ods.h" , its borrowed from Mumble that helped me with the errors:
ods.h:
Ok , now we have a test application that use D3D9, now lets create another project , this project will be a Dynamic Library (.dll) using a Module Definition file called Ovr_dll.def.
Ovr_dll.def:
Ok , now lets start with the actual hook and CEGUI Code:
lib.cpp:
I use strcmp(pMyAppName,"\\windowdx.exe") to identify the application I would like to hook , so change it with the Test application name you used b4. If you r using XP , \\ is required but not with Win7.
lib.h:
misc.cpp
misc.h
ods.h and ods.cpp r the same I used for Test Application , so copy .cpp and .h to this Project Folder.
vhook.cpp
vhooh.h:
d3d.cpp
d3d.h
CEGUIBase.cpp
CEGUIBase.h
CEGUIMainMenu.cpp:
CEGUIMainMenu.h:
CEGUIInjections.cpp
CEGUIInjections.h
resources.h
That's everything you need for the DLL , we won't need anything else except the injector, I don't have a real example for that one , but it will be something like this :
If everything compiles correctly you will have 2 Exe and 1 Dll , execute The injector , then dxwindow.exe and within dxwindow.exe if you press Insert you could see CEGUI Window and interact with it.
Tryd it with other D3D9 Games and works too.
I hope it helps someone someday.
I will post my Code but keep in mind i'm not a C++ programmer , i just do it for fun. My initial Goal was to create Different hooks ( d3d9, d3d10 , d3d11 , opengl etc.. ) , but for the time beeing I will keep learning just CEGUI and create some kind of generic overlay ( Browser , Option Panel etc..).
Anwyays , back to this sample:
Used VC++ 2010 Express without problems , VC++ 2005 causes lots of problems so i dont recommend it.
The first thing you will need is a Test Application , you can use this one that works fine:
Code: Select all
#include <windows.h>
#include <d3dx9.h>
#include <dinput.h>
#include "ods.h"
LPDIRECTINPUT8 directInput;
LPDIRECTINPUTDEVICE8 keyboardDevice;
void doDirectInputEvents();
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
bool Init(HINSTANCE hThisInstance);
bool InitWindow(HINSTANCE hThisInstance);
bool InitD3D();
bool initialiseDirectInput(HWND window);
void Load();
void Unload();
void Draw();
void Update();
void SetProjection();
char *ClassName ;
IDirect3DDevice9 *Device ;
D3DXMATRIX World ;
IDirect3DVertexBuffer9* Triangle ;
HWND hwnd;
MSG messages;
struct ColorVertex
{
float _x, _y, _z;
D3DCOLOR _color;
ColorVertex(float x, float y, float z, D3DCOLOR color)
{
_x=x;_y=y;_z=z;_color=color;
}
static const DWORD FVF;
};
const DWORD ColorVertex::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
MSG Msg;
ZeroMemory(&Msg, sizeof(MSG));
if (Init( hThisInstance) ){
ShowWindow (hwnd, nFunsterStil);
Load();
SetProjection();
Device->SetRenderState(D3DRS_LIGHTING, false);
while(Msg.message != WM_QUIT) {
if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
} else {
Update();
Draw();
}
}
Unload();
}
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
bool InitWindow(HINSTANCE hThisInstance){
WNDCLASSEX wincl;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = ClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_NO);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return false;
RECT wr = {0, 0, 400, 300};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
hwnd = CreateWindowEx (
0,
ClassName,
"Test_1",
WS_OVERLAPPEDWINDOW,
200,
200,
wr.right - wr.left,
wr.bottom - wr.top,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);
return true;
}
bool InitD3D(){
HRESULT hr = 0;
IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if( !d3d9 )
{
MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
return false;
}
D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
int vp = 0;
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = 400;
d3dpp.BackBufferHeight = 300;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = true;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
vp,
&d3dpp,
&Device);
if( FAILED(hr) )
{
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
vp,
&d3dpp,
&Device);
if( FAILED(hr) )
{
d3d9->Release();
MessageBox(0, "CreateDevice() - FAILED", 0, 0);
return false;
}
}
d3d9->Release();
return true;
}
bool Init(HINSTANCE hThisInstance){
ClassName = "Test_1" ;
Device = 0 ;
Triangle = 0 ;
InitWindow(hThisInstance);
InitD3D();
//initialiseDirectInput(hwnd);
Device->CreateVertexBuffer(
3 * sizeof(ColorVertex),
D3DUSAGE_WRITEONLY,
ColorVertex::FVF,
D3DPOOL_MANAGED,
&Triangle,
0);
return true ;
}
void Load(){
ColorVertex* v;
Triangle->Lock(0, 0, (void**)&v, 0);
v[0] = ColorVertex(-1.0f, 0.0f, 2.0f, D3DCOLOR_XRGB(0, 255,0));
v[1] = ColorVertex( 0.0f, 1.0f, 2.0f, D3DCOLOR_XRGB( 0, 255,0));
v[2] = ColorVertex( 1.0f, 0.0f, 2.0f, D3DCOLOR_XRGB( 0, 255,0));
Triangle->Unlock();
}
void SetProjection(){
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI * 0.5f,
(float)800 / (float)600,
1.0f,
1000.0f);
Device->SetTransform(D3DTS_PROJECTION, &proj);
}
void Draw(){
Device->Clear(0, 0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0xffffffff, 1.0f, 0);
Device->BeginScene();
Device->SetStreamSource(0, Triangle, 0, sizeof(ColorVertex));
Device->SetFVF(ColorVertex::FVF);
Device->SetCursorPosition(0,0,D3DCURSOR_IMMEDIATE_UPDATE);
Device->ShowCursor(false);
D3DXMatrixTranslation(&World, 0.0f, 0.0f, 0.0f);
Device->SetTransform(D3DTS_WORLD, &World);
Device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
Device->EndScene();
Device->Present(0, 0, 0, 0);
}
void Update(){
}
void Unload(){
SAFE_RELEASE(Device);
SAFE_RELEASE(Triangle);
}
Removed all the comments because of Language ("spanish") , anyways we won't need to modify this code , so just create a new project and Paste it as windowdx.cpp or whatever you want.
Don't forget to point to DX9 libs and includes.
About "ods.h" , its borrowed from Mumble that helped me with the errors:
Code: Select all
/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>
Copyright (C) 2011-2011, Stefan Hacker <dd0t@users.sourceforge.net>
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 <stdio.h>
#include <ctype.h>
#include <windows.h>
#include "ods.h"
void __cdecl _ods_out(const char *format, va_list *args) {
char buf[4096], *p = buf + 2;
buf[0] = 'M'; // Add a prefix
buf[1] = ':';
// Format but be aware of space taken by prefix
int len = _vsnprintf_s(p, sizeof(buf) - 3, _TRUNCATE, format, *args);
if (len <= 0)
return;
p += len;
// Truncate trailing spaces
while (p > (buf + 2) && isspace(p[-1]))
*--p = '\0';
// Add custom termination
if (p > (buf + sizeof(buf) - 3)) { // Make sure there's space
p = buf + sizeof(buf) - 3;
}
*p++ = '\r';
*p++ = '\n';
*p = '\0';
OutputDebugStringA(buf);
}
void __cdecl fods(const char *format, ...) {
va_list args;
va_start(args, format);
_ods_out(format, &args);
va_end(args);
}
ods.h:
Code: Select all
/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>
Copyright (C) 2011-2011, Stefan Hacker <dd0t@users.sourceforge.net>
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.
*/
#ifndef ODS_H
#define ODS_H
#include <stdarg.h>
void __cdecl _ods_out(const char *format, va_list *args);
void __cdecl fods(const char *format, ...);
#endif // ODS_H
Ok , now we have a test application that use D3D9, now lets create another project , this project will be a Dynamic Library (.dll) using a Module Definition file called Ovr_dll.def.
Ovr_dll.def:
Code: Select all
EXPORTS
SetWHook
RemoveWHook
Ok , now lets start with the actual hook and CEGUI Code:
lib.cpp:
Code: Select all
#include "lib.h"
#include "ods.h"
#include "misc.h"
#include "vhook.h"
#include "CEGUIInjections.h"
HHOOK hkD3D = NULL;
HHOOK hkMsg = NULL;
HMODULE hSelf = NULL;
vHook * d3Dhook ;
CEGUIInjections * CeguiInjections;
static LRESULT CALLBACK MouseMsgProc(UINT nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK KeyBoardMsgProc( int nCode, WPARAM wParam, LPARAM lParam);
extern "C" BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
{
char procname[1024+64];
GetModuleFileNameA(NULL, procname, 1024);
char * pMyAppName = CleanPath(&procname[strlen(procname)]);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
//TO-DO : CleanPath for XP or Win7
if ( strcmp(pMyAppName,"\\windowdx.exe") == 0)
{
fods("Lib: Found %s\n",pMyAppName);
d3Dhook = new vHook();
CeguiInjections = new CEGUIInjections();
d3Dhook->startMyThread();
hkMsg = SetWindowsHookEx( WH_GETMESSAGE, (HOOKPROC)MouseMsgProc,
hModule, GetCurrentThreadId());
if ( hkMsg == NULL )
{
fods("Lib: Failed to Hook Messages...\n");
return FALSE;
}
}
break;
}
case DLL_PROCESS_DETACH:
{
fods("Lib: DLL Detach\n");
break;
}
default:
{
break;
}
}
return TRUE;
}
static LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
return CallNextHookEx(hkD3D, nCode, wParam, lParam);
}
extern "C" _declspec(dllexport) void __stdcall SetWHook()
{
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (char *) &SetWHook, &hSelf);
if (hSelf == NULL)
fods("Lib: Failed to find myself");
hkD3D = SetWindowsHookEx(WH_CBT, CallWndProc, hSelf, 0);
if (hkD3D == NULL)
fods("Lib: Failed to insert WNDProc hook");
}
static LRESULT CALLBACK MouseMsgProc(UINT nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)
{
CallNextHookEx(hkMsg, nCode, wParam, lParam);
return 0;
}
if (CeguiInjections)
CeguiInjections->InjectToCEGUI((LPMSG)lParam,wParam,lParam);
return CallNextHookEx(hkMsg, nCode, wParam, lParam);
}
extern "C" _declspec(dllexport) void __stdcall RemoveWHook()
{
if(hkD3D !=NULL)
UnhookWindowsHookEx(hkD3D);
hkD3D = NULL;
if(hkMsg)
UnhookWindowsHookEx(hkMsg);
hkMsg = NULL;
}
I use strcmp(pMyAppName,"\\windowdx.exe") to identify the application I would like to hook , so change it with the Test application name you used b4. If you r using XP , \\ is required but not with Win7.
lib.h:
Code: Select all
#ifndef __LIB_H
#define __LIB_H
#include <stdio.h>
#include <windows.h>
static LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) ;
extern "C" _declspec(dllexport) void __stdcall SetWHook();
extern "C" _declspec(dllexport) void __stdcall RemoveWHook();
#endif
misc.cpp
Code: Select all
#include <windows.h>
#include "misc.h"
bool __stdcall StrToBool( TCHAR * myChar )
{
if ( myChar[0] == 89 || myChar[0] == 121 )
return TRUE;
return FALSE;
}
char * __stdcall CleanPath( char * pMyChar)
{
while( pMyChar[0] != 92 )
pMyChar--;
return pMyChar++;
}
misc.h
Code: Select all
#ifndef __MISC_H
#define __MISC_H
bool __stdcall StrToBool( TCHAR * myChar );
char * __stdcall CleanPath(char * pMyPath);
#endif
ods.h and ods.cpp r the same I used for Test Application , so copy .cpp and .h to this Project Folder.
vhook.cpp
Code: Select all
#include <Windows.h>
#include "vhook.h"
#include "ods.h"
#include "d3d.h"
oReset pReset;
oEndScene pEndScene;
vHook::vHook()
{
}
vHook::~vHook()
{
}
DWORD vHook::D3D9VTable_1()
{
DWORD dwObjBase = (DWORD)LoadLibraryA("d3d9.dll");
while ( dwObjBase++ < dwObjBase + 0x127850 )
{
if ( (*(WORD*)(dwObjBase + 0x00)) == 0x06C7 &&
(*(WORD*)(dwObjBase + 0x06)) == 0x8689 &&
(*(WORD*)(dwObjBase + 0x0C)) == 0x8689 )
{
dwObjBase += 2;
break;
}
}
return ( dwObjBase );
}
VOID * vHook::DetourCreate(BYTE *src, const BYTE *dst, const int len)
{
BYTE *jmp = (BYTE*)malloc(len+5);
DWORD dwBack;
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &dwBack);
memcpy(jmp, src, len);
jmp += len;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5;
src[0] = 0xE9;
*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
DWORD oProt;
VirtualProtect(jmp,1,PAGE_EXECUTE_READWRITE,&oProt);
for (int i=5; i<len; i++) src[i]=0x90;
VirtualProtect(src, len+1, dwBack, &dwBack);
return (jmp-len);
}
VOID WINAPI vHook::ThreadStart()
{
PDWORD D3DVTable_1;
do
{
*(DWORD*)&D3DVTable_1 = *(DWORD*)D3D9VTable_1();
}
while ( !D3DVTable_1 );
pReset = (oReset) this->DetourCreate((PBYTE)D3DVTable_1[16],(PBYTE)myReset,5);
pEndScene = (oEndScene) this->DetourCreate((PBYTE)D3DVTable_1[42],(PBYTE)myEndScene,5);
}
VOID vHook::StopAll()
{
PDWORD D3DVTable_1;
do
{
*(DWORD*)&D3DVTable_1 = *(DWORD*)D3D9VTable_1();
}
while ( !D3DVTable_1 );
/* TO-DO : Detour Destroy ..
this->DetourCreate((PBYTE)D3DVTable_1[16],(PBYTE)pReset,5);
this->DetourCreate((PBYTE)D3DVTable_1[42],(PBYTE)pEndScene,5);*/
}
vhooh.h:
Code: Select all
#ifndef __V_HOOK
#define __V_HOOK
class vHook
{
public:
vHook();
~vHook();
VOID *DetourCreate( BYTE *src, const BYTE *dst, const int len );
VOID StopAll();
DWORD D3D9VTable_1();
static VOID WINAPI StaticThreadStart(void* Param)
{
vHook* This = (vHook*) Param;
return This->ThreadStart();
}
VOID WINAPI ThreadStart();
void startMyThread()
{
MyThread = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) StaticThreadStart, (void*) this, 0, &ThreadID);
}
void StopMyThread()
{
this->StopAll();
TerminateThread(MyThread, 0);
}
private:
DWORD ThreadID;
HANDLE MyThread;
};
#endif
d3d.cpp
Code: Select all
#include "ods.h"
#include "d3d.h"
#include "CEGUIBase.h"
#include "CEGUIMainMenu.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
LPD3DXFONT g_pFont = NULL; //D3D Font
LPD3DXLINE g_pLine = NULL; //D3D Line
D3DVIEWPORT9 g_ViewPort; //ViewPort
LPDIRECT3DDEVICE9 npDevice;
bool InitCEGUI = false;
bool MenuSet = false;
CEGUIBase * CEGuiBase;
CEGUIMainMenu * CEGuiMainMenu;
HRESULT WINAPI myReset(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
_asm pushad;
if( g_pFont )
g_pFont->OnLostDevice();
if( g_pLine )
g_pLine->OnLostDevice();
HRESULT iReturnValue = pReset(pDevice, pPresentationParameters);
if(iReturnValue == D3D_OK) {
if( g_pFont )
g_pFont->OnResetDevice();
if( g_pLine )
g_pLine->OnResetDevice();
}
_asm popad;
return iReturnValue;
}
HRESULT WINAPI myEndScene( LPDIRECT3DDEVICE9 pDevice )
{
_asm pushad;
if ( ! InitCEGUI )
{
CEGuiBase = new CEGUIBase(pDevice);
CEGuiMainMenu = new CEGUIMainMenu();
InitCEGUI = true;
}
SHORT PRESSED = GetAsyncKeyState(VK_INSERT);
if ((PRESSED&1) && (MenuSet == FALSE) )
{
CEGuiMainMenu->ShowMenu();
} else if ((PRESSED&1) && (MenuSet == TRUE) )
CEGuiMainMenu->ShowMenu();
CEGuiBase->RenderUI();
_asm popad;
return pEndScene( pDevice );
}
d3d.h
Code: Select all
#ifndef __D3D
#define __D3D
#include <d3d9.h>
#include <d3dx9.h>
typedef HRESULT ( WINAPI* oReset )( LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters );
typedef HRESULT ( WINAPI * oEndScene )( LPDIRECT3DDEVICE9 pDevice );
HRESULT WINAPI myReset(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT WINAPI myEndScene( LPDIRECT3DDEVICE9 pDevice );
extern oReset pReset;
extern oEndScene pEndScene;
#endif __D3D
CEGUIBase.cpp
Code: Select all
#include "ods.h"
#include "CEGUIBase.h"
#include "resources.h"
CEGUI::GeometryBuffer* d_logoGeometry;
bool overlayHandler(const CEGUI::EventArgs& args);
CEGUIBase::CEGUIBase(LPDIRECT3DDEVICE9 pDevice) :
d_lastFrameTime(0),
d_resourceProvider(0),
d_imageCodec(0),
d_renderer(0),
pDevice(pDevice)
{
try {
new CEGUI::DefaultLogger();
CEGUI::DefaultLogger::getSingleton().setLoggingLevel(CEGUI::Informative);
/*TO-DO: Obtain Path from ConfigFile */
CEGUI::DefaultLogger::getSingleton().setLogFilename("D:\\CEGUI_LOG\\GEGUI.log");
this->d_renderer = &CEGUI::Direct3D9Renderer::bootstrapSystem(this->pDevice);
this->initialiseResourceGroupDirectories();
this->initialiseDefaultResourceGroups();
//this->d_Context = &CEGUI::System::getSingleton().getDefaultGUIContext();
}
catch (CEGUI::Exception e)
{
fods("CEGUI Error: %s\n",e.what());
}
}
CEGUIBase::~CEGUIBase()
{
}
VOID CEGUIBase::initialiseResourceGroupDirectories()
{
CEGUI::DefaultResourceProvider* rp =
static_cast<CEGUI::DefaultResourceProvider*>
(CEGUI::System::getSingleton().getResourceProvider());
/* TO-DO : use config file.... */
const char* dataPathPrefix = CEGUI_DATAPATH;
fods("%s\n",dataPathPrefix);
char resourcePath[MAX_PATH];
size_t PathSize = strlen(CEGUI_DATAPATH);
fods("%i\n",PathSize);
sprintf_s(resourcePath, PathSize + 10 ,"%s/%s", dataPathPrefix, "schemes/");
rp->setResourceGroupDirectory("schemes", resourcePath);
sprintf_s(resourcePath, PathSize + 12 ,"%s/%s", dataPathPrefix, "imagesets/");
rp->setResourceGroupDirectory("imagesets", resourcePath);
sprintf_s(resourcePath, PathSize + 8 ,"%s/%s", dataPathPrefix, "fonts/");
rp->setResourceGroupDirectory("fonts", resourcePath);
sprintf_s(resourcePath, PathSize + 10 ,"%s/%s", dataPathPrefix, "layouts/");
rp->setResourceGroupDirectory("layouts", resourcePath);
sprintf_s(resourcePath, PathSize + 12 ,"%s/%s", dataPathPrefix, "looknfeel/");
rp->setResourceGroupDirectory("looknfeels", resourcePath);
sprintf_s(resourcePath, PathSize + 14 ,"%s/%s", dataPathPrefix, "lua_scripts/");
rp->setResourceGroupDirectory("lua_scripts", resourcePath);
sprintf_s(resourcePath, PathSize + 14 ,"%s/%s", dataPathPrefix, "xml_schemas/");
rp->setResourceGroupDirectory("schemas", resourcePath);
sprintf_s(resourcePath, PathSize + 13 ,"%s/%s", dataPathPrefix, "animations/");
rp->setResourceGroupDirectory("animations", resourcePath);
}
VOID CEGUIBase::initialiseDefaultResourceGroups()
{
CEGUI::ImageManager::setImagesetDefaultResourceGroup("imagesets");
CEGUI::Font::setDefaultResourceGroup("fonts");
CEGUI::Scheme::setDefaultResourceGroup("schemes");
CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
CEGUI::WindowManager::setDefaultResourceGroup("layouts");
CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
CEGUI::AnimationManager::setDefaultResourceGroup("animations");
CEGUI::XMLParser* parser = CEGUI::System::getSingleton().getXMLParser();
if (parser->isPropertyPresent("SchemaDefaultResourceGroup"))
parser->setProperty("SchemaDefaultResourceGroup", "schemas");
}
BOOL CEGUIBase::RenderUI()
{
static bool WaitingForReset = false;
HRESULT coop;
CEGUI::System& guiSystem = CEGUI::System::getSingleton();
DWORD thisTime = GetTickCount();
float elapsed = static_cast<float>(thisTime - this->d_lastFrameTime);
this->d_lastFrameTime = thisTime;
guiSystem.injectTimePulse( elapsed / 1000.0f );
coop = this->pDevice->TestCooperativeLevel();
if( coop == D3DERR_DEVICELOST || coop == D3DERR_DEVICENOTRESET )
{
if ( !WaitingForReset )
{
WaitingForReset = true;
static_cast<CEGUI::Direct3D9Renderer*>(d_renderer)->preD3DReset();
}
return true;
}
else if ( coop == D3D_OK )
{
if ( WaitingForReset )
{
WaitingForReset = false;
//d_renderer->postD3DReset();
static_cast<CEGUI::Direct3D9Renderer*>(d_renderer)->postD3DReset();
return true;
}
}
try
{
IDirect3DStateBlock9* pStateBlock = NULL;
this->pDevice->CreateStateBlock( D3DSBT_ALL, &pStateBlock );
CEGUI::System::getSingleton().renderAllGUIContexts();
if ( pStateBlock )
{
pStateBlock->Apply();
pStateBlock->Release();
return true;
}
}
catch ( CEGUI::Exception e )
{
fods( "MyGUIRender() -> renderGUI() FAILED: Error message: %s", e.what() );
}
return false;
}
CEGUIBase.h
Code: Select all
#ifndef __CEGUIBASE
#define __CEGUIBASE
#include <d3d9.h>
#include "CEGUI/CEGUI.h"
#include "CEGUI/RendererModules/Direct3D9/Renderer.h"
#include "CEGUI/System.h"
using namespace CEGUI;
class CEGUIBase
{
public:
CEGUIBase(LPDIRECT3DDEVICE9 pDevice);
~CEGUIBase();
BOOL RenderUI();
private:
VOID initialiseResourceGroupDirectories();
VOID initialiseDefaultResourceGroups();
protected:
LPDIRECT3DDEVICE9 pDevice;
CEGUI::Renderer * d_renderer;
CEGUI::ResourceProvider* d_resourceProvider;
CEGUI::ImageCodec* d_imageCodec;
DWORD d_lastFrameTime;
};
#endif __CEGUIBASE
CEGUIMainMenu.cpp:
Code: Select all
#include "CEGUIMainMenu.h"
#include "ods.h"
#include "CEGUI/CEGUI.h"
CEGUIMainMenu::CEGUIMainMenu() :
wRoot(0),
guiContext(0),
wnd(0)
{
this->guiContext = &CEGUI::System::getSingleton().getDefaultGUIContext();
//SchemeManager::getSingleton().createFromFile("TaharezLook.scheme");
SchemeManager::getSingleton().createFromFile("TaharezLook.scheme");
guiContext->getMouseCursor().setDefaultImage("TaharezLook/MouseArrow");
CEGUI::WindowManager& winMgr = WindowManager::getSingleton();
this->wRoot = (DefaultWindow*)winMgr.createWindow("DefaultWindow", "Root");
Font& defaultFont = FontManager::getSingleton().createFromFile("DejaVuSans-12.font");
guiContext->setDefaultFont(&defaultFont);
guiContext->setRootWindow(wRoot);
wnd = (FrameWindow*)winMgr.createWindow("TaharezLook/FrameWindow", "Demo1 Window");
this->wRoot->addChild(wnd);
this->wnd->setPosition(UVector2(cegui_reldim(0.25f), cegui_reldim( 0.25f)));
this->wnd->setSize(USize(cegui_reldim(0.5f), cegui_reldim( 0.5f)));
this->wnd->setMaxSize(USize(cegui_reldim(1.0f), cegui_reldim( 1.0f)));
this->wnd->setMinSize(USize(cegui_reldim(0.1f), cegui_reldim( 0.1f)));
this->wnd->setText("Hello!! World!");
this->wnd->hide();
this->wnd->subscribeEvent(CEGUI::Window::EventMouseButtonDown, Event::Subscriber(&CEGUIMainMenu::handleMainMenuClicked, this));
}
/*************************************************************************
Cleans up resources allocated in the initialiseSample call.
*************************************************************************/
VOID CEGUIMainMenu::ShowMenu()
{
this->wnd->show();
}
VOID CEGUIMainMenu::HideMenu()
{
this->wnd->hide();
}
bool CEGUIMainMenu::handleMainMenuClicked(const CEGUI::EventArgs& args)
{
fods("CLICKED1\n");
return false;
}
CEGUIMainMenu.h:
Code: Select all
#ifndef __MAINMENU
#define __MAINMENU
#include "CEGUI/String.h"
#include "CEGUI/ForwardRefs.h"
#include <d3d9.h>
#include "CEGUIBase.h"
using namespace CEGUI;
class CEGUIMainMenu
{
public:
CEGUIMainMenu();
~CEGUIMainMenu();
VOID ShowMenu();
VOID HideMenu();
private:
bool handleMainMenuClicked(const CEGUI::EventArgs& args);
CEGUI::DefaultWindow* wRoot;
CEGUI::GUIContext * guiContext;
CEGUI::FrameWindow* wnd;
};
#endif
CEGUIInjections.cpp
Code: Select all
#include "CEGUIInjections.h"
#include "ods.h"
HWND hWndServer = NULL;
bool s_mouseInWindow = false;
RECT clientArea;
int MAX_SCXSIZE = GetSystemMetrics(SM_CXSCREEN);
int MAX_SCYSIZE = GetSystemMetrics(SM_CYSCREEN);
CEGUIInjections::CEGUIInjections()
{
}
CEGUIInjections::~CEGUIInjections()
{
}
bool CEGUIInjections::InjectToCEGUI( LPMSG msg ,WPARAM wParam, LPARAM lParam)
{
this->thisTime = GetTickCount();
this->elapsed = static_cast<float>(this->thisTime - this->d_lastFrameTime);
this->d_lastFrameTime = thisTime;
switch( msg->message )
{
case WM_CHAR:
this->injectChar((CEGUI::utf32)wParam);
SendMessage( hWndServer, WM_CHAR, 0, 0);
break;
case WM_MOUSELEAVE:
this->mouseLeaves();
SendMessage( hWndServer, WM_MOUSELEAVE, 0, 0);
break;
case WM_NCMOUSEMOVE:
this->mouseLeaves();
SendMessage( hWndServer, UWM_MOUSEMOVE, 0, 0);
break;
case WM_MOUSEMOVE:
GetCursorPos(&this->Point);
ScreenToClient(msg->hwnd,&this->Point);
this->injectMousePosition((float)Point.x ,(float)Point.y);
SendMessage( hWndServer, UWM_MOUSEMOVE, 0, 0);
break;
case WM_LBUTTONUP:
this->injectMouseButtonUp(CEGUI::LeftButton);
SendMessage( hWndServer, UWM_MOUSELBUTTONUP, 0 , 0 );
break;
case WM_LBUTTONDOWN:
this->injectMouseButtonDown(CEGUI::LeftButton);
SendMessage( hWndServer, UWM_MOUSELBUTTONUP, 0 , 0 );
break;
case WM_RBUTTONDOWN:
injectMouseButtonDown(CEGUI::RightButton);
SendMessage( hWndServer, WM_RBUTTONDOWN, 0 , 0 );
break;
case WM_RBUTTONUP:
this->injectMouseButtonUp(CEGUI::RightButton);
SendMessage( hWndServer, WM_RBUTTONUP, 0 , 0 );
break;
case WM_MBUTTONDOWN:
this->injectMouseButtonDown(CEGUI::MiddleButton);
SendMessage( hWndServer, WM_MBUTTONDOWN, 0 , 0 );
break;
case WM_MBUTTONUP:
this->injectMouseButtonUp(CEGUI::MiddleButton);
SendMessage( hWndServer, WM_MBUTTONUP, 0 , 0 );
break;
case 0x020A: // WM_MOUSEWHEEL:
this->injectMouseWheelChange(static_cast<float>((short)HIWORD(wParam)) / static_cast<float>(120));
SendMessage( hWndServer, 0x020A, 0 , 0 );
break;
default:
break;
}
return true;
}
bool CEGUIInjections::injectKeyDown(const CEGUI::Key::Scan& ceguiKey)
{
if (Key::Escape != ceguiKey)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
return ceguiSystem->getDefaultGUIContext().injectKeyDown(ceguiKey);
else
return false;
}
else
//TO-DO:: ESC Must quit the actual menu
//setQuitting(true);
return false;
return false;
}
bool CEGUIInjections::injectKeyUp(const CEGUI::Key::Scan& ceguiKey)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectKeyUp(ceguiKey);
}
return false;
}
bool CEGUIInjections::injectChar(int character)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectChar(character);
}
return false;
}
bool CEGUIInjections::injectMouseButtonDown(const CEGUI::MouseButton& ceguiMouseButton)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectMouseButtonDown(ceguiMouseButton);
}
return false;
}
bool CEGUIInjections::injectMouseButtonUp(const CEGUI::MouseButton& ceguiMouseButton)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectMouseButtonUp(ceguiMouseButton);
}
return false;
}
bool CEGUIInjections::injectMouseWheelChange(float position)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectMouseWheelChange(position);
}
return false;
}
bool CEGUIInjections::injectMousePosition(float x, float y)
{
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectMousePosition(x,y);
}
return false;
}
void CEGUIInjections::mouseLeaves(void)
{
if (!s_mouseInWindow)
{
s_mouseInWindow = false;
ShowCursor(true);
}
if (CEGUI::System* ceguiSystem = CEGUI::System::getSingletonPtr())
{
ceguiSystem->injectTimePulse( elapsed / 1000.0f );
ceguiSystem->getDefaultGUIContext().injectMouseLeaves();
}
}
void CEGUIInjections::mouseEnters(void)
{
if (!s_mouseInWindow)
{
s_mouseInWindow = true;
ShowCursor(false);
}
}
CEGUIInjections.h
Code: Select all
#ifndef __CEGUI_INJECTIONS
#define __CEGUI_INJECTIONS
#include "windows.h"
#include "CEGUIBase.h"
using namespace CEGUI;
class CEGUIInjections
{
public:
CEGUIInjections();
~CEGUIInjections();
bool InjectToCEGUI( LPMSG msg ,WPARAM wParam, LPARAM lParam);
private:
virtual bool injectKeyDown(const CEGUI::Key::Scan& ceguiKey);
virtual bool injectKeyUp(const CEGUI::Key::Scan& ceguiKey);
virtual bool injectChar(int character);
virtual bool injectMouseButtonDown(const CEGUI::MouseButton& ceguiMouseButton);
virtual bool injectMouseButtonUp(const CEGUI::MouseButton& ceguiMouseButton);
virtual bool injectMouseWheelChange(float position);
virtual bool injectMousePosition(float x, float y);
virtual void mouseLeaves(void);
virtual void mouseEnters(void);
DWORD d_lastFrameTime;
DWORD thisTime;
float elapsed;
UINT UWM_MOUSEMOVE;
UINT UWM_MOUSELBUTTONUP;
UINT UWM_MOUSELBUTTONDOWN;
UINT UWM_MOUSERBUTTONUP;
UINT UWM_MOUSERBUTTONDOWN;
UINT UWM_MOUSELDBCLICK;
UINT UWN_KEYSTROKE;
POINT Point;
RECT Rect;
};
#endif
resources.h
Code: Select all
#ifndef __RESOURCES
#define __RESOURCES
#define CEGUI_DATAPATH "D:\\CEGUI_DATA"
#endif __RESOURCES
That's everything you need for the DLL , we won't need anything else except the injector, I don't have a real example for that one , but it will be something like this :
Code: Select all
typedef void (__stdcall *pFunc)(void);
typedef void (__cdecl *pD3DFunc)(void);
static HMODULE hmodDll = NULL;
static pFunc pSetHookFunc;
static pFunc pRemHookFunc;
static pD3DFunc pPrepareD3D;
int main()
{
hmodDll = LoadLibrary("Ovr_dll.dll");
hmodDll = LoadLibrary("Ovr_dll.dll");
if ( hmodDll == NULL )
HookError = TRUE;
pSetHookFunc = (pFunc)GetProcAddress(hmodDll,"SetWHook");
if ( pSetHookFunc == NULL )
HookError = TRUE;
pRemHookFunc = (pFunc)GetProcAddress(hmodDll,"RemoveWHook");
if ( pSetHookFunc == NULL )
HookError = TRUE;
pSetHookFunc();
//On leave..
pRemHookFunc();
}
If everything compiles correctly you will have 2 Exe and 1 Dll , execute The injector , then dxwindow.exe and within dxwindow.exe if you press Insert you could see CEGUI Window and interact with it.
Tryd it with other D3D9 Games and works too.
I hope it helps someone someday.