I do the same thing as you, and actually posted code for how I do it, but in a different thread, hence I'm reposting my post here, as it is more appropriate.
I used to think that hooking D3D was gonne be somewhat-challenging and put it off too, until today. It turned out to be extremely easy actually with a simple trick. Instead of looking for the D3D9 device pointer, create your own inside of an injected DLL in the WoW process space. When you do that you can hook the virtual functions you are interested in based off of your D3D9 device and because it inherits from the same objects as WoW's D3D9 device the pointer to the VFT of your's and their device points to the same location. So VFT hooks to your device will also affect WoW's device.
Below is the code to do this:
Code:
typedef HRESULT ( WINAPI * tEndScene )( IDirect3DDevice9 * pThis );
tEndScene oEndScene = 0;
typedef HRESULT ( WINAPI * tReset )( IDirect3DDevice9 * pDevice, void * pPresentationParameters );
tReset oReset = 0;
void HookDevice( IDirect3DDevice9 * pDevice, HWND hFocusWindow )
{
// Hook EndScene
oEndScene = *(tEndScene*)( *(DWORD*)pDevice + 0xA8 );
YOUR_DETOUR_LIB( &(PVOID&)oEndScene, (PBYTE)hook_EndScene, "EndScene" );
// Hook Reset
oReset = *(tReset*)( *(DWORD*)pDevice + 0x40 );
YOUR_DETOUR_LIB( &(PVOID&)oReset, (PBYTE)hook_Reset, "Reset" );
// Hook Anything else you like...
}
void InitDevice( IDirect3D9 * pD3D, HWND hWindow, IDirect3DDevice9 ** ppDevice, D3DPRESENT_PARAMETERS d3dPP )
{
d3dPP.BackBufferCount = 1;
d3dPP.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPP.hDeviceWindow = hWindow;
d3dPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dPP.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dPP.BackBufferFormat = D3DFMT_R5G6B5;
d3dPP.Windowed = TRUE;
pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dPP, ppDevice );
HookDevice( *ppDevice, hWindow );
}
void HookD3D()
{
D3DPRESENT_PARAMETERS d3dPP;
IDirect3DDevice9 * pDevice = 0;
HWND hWindow = 0;
IDirect3D9 * pD3D = Direct3DCreate9( D3D_SDK_VERSION );
hWindow = FindWindow(NULL, TEXT("World of Warcraft") );
if( !hWindow ) {
MessageBox(0, "Failed to obtain WoW hWindow", "Error", 0);
}
memset( &d3dPP, 0, sizeof( D3DPRESENT_PARAMETERS ) );
InitDevice( pD3D, hWindow, &pDevice, d3dPP );
}
Then after your bot-framework initializes just call HookD3D().
Obviously you will need to write you own hook_* functions.