/*
* RA3INFO | 'Red Alert 3' By Gamer_Z/Grasmanek94 | http://g...content-available-to-author-only...e.com/
*/
#include <main.h>
#include <windows.h>
#include <d3d9.h>
#include <assert.h>
class VirtualMethodHook
{
public:
// Types.
typedef void (*func_ptr_t)();
typedef struct {
union {
func_ptr_t function;
ptrdiff_t offset;
};
ptrdiff_t delta;
} method_ptr_t;
typedef struct {
func_ptr_t func[1];
} vtable_t;
typedef struct {
vtable_t * vtable_ptr;
} class_instance_t;
private:
// Hook a vtable virtual method and replace its entry with another function.
static func_ptr_t _HookMethod(vtable_t * hookedVTable, method_ptr_t * oldMethod, func_ptr_t newFunction)
{
// We want the offset to be odd, indicating that this method pointer is an offset into a vtable.
if (!(oldMethod->offset & 0x1)) {
return NULL;
}
// Get the index into the vtable.
assert(!((oldMethod->offset - 1) % sizeof(func_ptr_t)));
size_t hookedIndex = (oldMethod->offset - 1) / sizeof(func_ptr_t);
// Replace the hooked method and return the original function pointer.
func_ptr_t original = hookedVTable->func[hookedIndex];
hookedVTable->func[hookedIndex] = newFunction;
return original;
}
public:
// Hook a virtual method with a function pointer, returning the original function pointer.
#if __cplusplus >= 201103L
template <class _HookedClass, typename _Ret, typename ..._Args>
static _Ret (*HookMethod(_HookedClass * instance, _Ret (_HookedClass::*oldMethod)(_Args...), _Ret (*newFunction)(_HookedClass *, _Args...)))(_HookedClass *, _Args...)
#else
template <class _HookedClass, typename _Method, typename _Func>
static _Func HookMethod(_HookedClass * instance, _Method oldMethod, _Func newFunction)
#endif
{
assert(sizeof(oldMethod) == sizeof(method_ptr_t));
// Get the vtable for the instance.
vtable_t * vtable = ((class_instance_t *) instance)->vtable_ptr;
if (!vtable) {
// This class has no virtual methods.
return NULL;
}
// Replace the function pointer in the virtual method.
return
#if __cplusplus >= 201103L
(_Ret (*)(_HookedClass *, _Args...))
#else
(_Func)
#endif
_HookMethod(vtable, (method_ptr_t *) &oldMethod, (func_ptr_t) newFunction);
}
// Unhook (restore) a virtual method from the original.
#if __cplusplus >= 201103L
template <class _HookedClass, typename _Ret, typename ..._Args>
static bool UnhookMethod(_HookedClass * instance, _Ret (_HookedClass::*hookedMethod)(_Args...), _Ret (*originalFunction)(_HookedClass *, _Args...))
#else
template <class _HookedClass, typename _Method, typename _Func>
static bool UnhookMethod(_HookedClass * instance, _Method hookedMethod, _Func originalFunction)
#endif
{
// Hook in reverse.
return (bool) HookMethod(instance, hookedMethod, originalFunction);
}
};
HMODULE gl_hOriginalDll = NULL;
IDirect3DDevice9 * device = NULL;
IDirect3D9 *pIDirect3D9_orig;
typedef HRESULT(_stdcall * orig_CreateDevice)(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface);
orig_CreateDevice OCD;
VirtualMethodHook * OriginalCreateDevice;
void LoadOriginalDll(void)
{
char buffer[MAX_PATH];
::GetSystemDirectory(buffer,MAX_PATH);
strcat(buffer,"\\d3d9.dll");
if (!gl_hOriginalDll) gl_hOriginalDll = ::LoadLibrary(buffer);
if (!gl_hOriginalDll)
{
OutputDebugString("PROXYDLL: Original d3d9.dll not loaded ERROR ****\r\n");
::ExitProcess(0);
}
}
HRESULT WINAPI myCreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface)
{
HRESULT hres = OCD( Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
return hres;
}
IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion)
{
if (!gl_hOriginalDll) LoadOriginalDll();
typedef IDirect3D9 *(WINAPI* D3D9_Type)(UINT SDKVersion);
D3D9_Type D3DCreate9_fn = (D3D9_Type) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9");
if (!D3DCreate9_fn)
{
OutputDebugString("PROXYDLL: Pointer to original D3DCreate9 function not received ERROR ****\r\n");
::ExitProcess(0);
}
pIDirect3D9_orig = D3DCreate9_fn(SDKVersion);
OriginalCreateDevice = new VirtualMethodHook();
OCD = OriginalCreateDevice->HookMethod(pIDirect3D9_orig,&IDirect3D9::CreateDevice,myCreateDevice);
//OCD = IDirect3D9::CreateDevice;
//*pIDirect3D9_orig->CreateDevice = &IDirect3D9::CreateDevice;
return (pIDirect3D9_orig);
}