From c23eda8db16cede8dbe238fa8abf7597ea7f3c6f Mon Sep 17 00:00:00 2001 From: "code@koerner-de.net" Date: Tue, 30 Jul 2013 17:19:44 +0000 Subject: [PATCH] Added class for Detour. It also detours the LoadLibrary function and thus has no problems if the game unloads the DX library and load it back again later. Added some debug comments if logging mode is enabled. --- .gitattributes | 4 + uMod_DX10/uMod_DX10_dll.cpp | 86 +++-- uMod_DX10/uMod_DX10_dll.h | 9 +- uMod_DX10/uMod_IDXGISwapChain.cpp | 8 +- uMod_DX9/uMod_DX9_dll.cpp | 175 +++++----- uMod_DX9/uMod_DX9_dll.h | 17 +- uMod_DX9/uMod_IDirect3DDevice9.cpp | 4 +- uMod_DX9/uMod_IDirect3DSurface9.cpp | 23 +- uMod_DXMain/makefile.gcc | 6 + uMod_DXMain/makefile.vc | 6 + .../uMod_DX9_10_dll_DIRECT_INJECTION.def | 7 + uMod_DXMain/uMod_DXMain_dll.cpp | 2 + uMod_DXMain/uMod_Detour.cpp | 206 +++++++++++ uMod_DXMain/uMod_Detour.h | 72 ++++ uMod_DXMain/uMod_DetourEntry.h | 324 ++++++++++++++++++ uMod_DXMain/uMod_Main.h | 2 + uMod_GUI/uMod_Main.h | 2 +- 17 files changed, 793 insertions(+), 160 deletions(-) create mode 100644 uMod_DXMain/uMod_DX9_10_dll_DIRECT_INJECTION.def create mode 100644 uMod_DXMain/uMod_Detour.cpp create mode 100644 uMod_DXMain/uMod_Detour.h create mode 100644 uMod_DXMain/uMod_DetourEntry.h diff --git a/.gitattributes b/.gitattributes index 686a95d..655c714 100644 --- a/.gitattributes +++ b/.gitattributes @@ -44,12 +44,16 @@ uMod_DXMain/uMod_ArrayHandler.cpp -text uMod_DXMain/uMod_ArrayHandler.h -text uMod_DXMain/uMod_DX10_dll_DIRECT_INJECTION.def -text uMod_DXMain/uMod_DX10_dll_HOOK_INJECTION.def -text +uMod_DXMain/uMod_DX9_10_dll_DIRECT_INJECTION.def -text uMod_DXMain/uMod_DX9_dll_DIRECT_INJECTION.def -text uMod_DXMain/uMod_DX9_dll_HOOK_INJECTION.def -text uMod_DXMain/uMod_DX9_dll_NO_INJECTION.def -text uMod_DXMain/uMod_DXMain_dll.cpp -text uMod_DXMain/uMod_DXMain_dll.h -text uMod_DXMain/uMod_Defines.h -text +uMod_DXMain/uMod_Detour.cpp -text +uMod_DXMain/uMod_Detour.h -text +uMod_DXMain/uMod_DetourEntry.h -text uMod_DXMain/uMod_Main.h -text uMod_DXMain/uMod_TextureClient.cpp -text uMod_DXMain/uMod_TextureClient.h -text diff --git a/uMod_DX10/uMod_DX10_dll.cpp b/uMod_DX10/uMod_DX10_dll.cpp index d74572e..1405433 100644 --- a/uMod_DX10/uMod_DX10_dll.cpp +++ b/uMod_DX10/uMod_DX10_dll.cpp @@ -34,15 +34,17 @@ along with Universal Modding Engine. If not, see /* * global variable which are not linked external */ +#if INJECTION_METHOD==NO_INJECTION HINSTANCE gl_hOriginal_DX10_Dll = NULL; HINSTANCE gl_hOriginal_DX101_Dll = NULL; +#endif +#if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION typedef HRESULT (APIENTRY *D3D10CreateDeviceAndSwapChain_type)( IDXGIAdapter*, D3D10_DRIVER_TYPE, HMODULE, UINT, UINT, DXGI_SWAP_CHAIN_DESC*, IDXGISwapChain**, ID3D10Device**); typedef HRESULT (APIENTRY *D3D10CreateDeviceAndSwapChain1_type)( IDXGIAdapter*, D3D10_DRIVER_TYPE, HMODULE, UINT, D3D10_FEATURE_LEVEL1, UINT, DXGI_SWAP_CHAIN_DESC*, IDXGISwapChain**, ID3D10Device1**); -#if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION -D3D10CreateDeviceAndSwapChain_type D3D10CreateDeviceAndSwapChain_fn = NULL; -D3D10CreateDeviceAndSwapChain1_type D3D10CreateDeviceAndSwapChain1_fn = NULL; +uMod_Detour_Entry Detour_D3D10CreateDeviceAndSwapChain(5); +uMod_Detour_Entry Detour_D3D10CreateDeviceAndSwapChain1(5); #endif @@ -54,34 +56,46 @@ D3D10CreateDeviceAndSwapChain1_type D3D10CreateDeviceAndSwapChain1_fn = NULL; void InitDX10(void) { + +#if INJECTION_METHOD==NO_INJECTION LoadOriginal_DX10_Dll(); +#endif #if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION - // we detour the original D3D10CreateDeviceAndSwapChain to our uMod_D3D10CreateDeviceAndSwapChain - if (gl_hOriginal_DX10_Dll!=NULL) - { - D3D10CreateDeviceAndSwapChain_fn = (D3D10CreateDeviceAndSwapChain_type) GetProcAddress(gl_hOriginal_DX10_Dll, "D3D10CreateDeviceAndSwapChain"); - if (D3D10CreateDeviceAndSwapChain_fn!=NULL) - { - Message("Detour: D3D10CreateDeviceAndSwapChain\n"); - D3D10CreateDeviceAndSwapChain_fn = (D3D10CreateDeviceAndSwapChain_type)DetourFunc( (BYTE*)D3D10CreateDeviceAndSwapChain_fn, (BYTE*)uMod_D3D10CreateDeviceAndSwapChain, number_of_byte); - } - } - if (gl_hOriginal_DX101_Dll!=NULL) - { - D3D10CreateDeviceAndSwapChain1_fn = (D3D10CreateDeviceAndSwapChain1_type) GetProcAddress(gl_hOriginal_DX101_Dll, "D3D10CreateDeviceAndSwapChain1"); - if (D3D10CreateDeviceAndSwapChain1_fn!=NULL) - { - Message("Detour: D3D10CreateDeviceAndSwapChain1\n"); - D3D10CreateDeviceAndSwapChain1_fn = (D3D10CreateDeviceAndSwapChain1_type)DetourFunc( (BYTE*)D3D10CreateDeviceAndSwapChain1_fn, (BYTE*)uMod_D3D10CreateDeviceAndSwapChain1, 5); - } - } + char buffer[MAX_PATH]; + wchar_t buffer_w[MAX_PATH]; + GetSystemDirectory(buffer,MAX_PATH); //get the system directory, we need to open the original d3d9.dll + swprintf_s( buffer_w, MAX_PATH, L"%s\\d3d10.dll", buffer); + strcat_s( buffer, MAX_PATH,"\\d3d10.dll"); + + Detour_D3D10CreateDeviceAndSwapChain.SetFunctionName( "D3D10CreateDeviceAndSwapChain"); + Detour_D3D10CreateDeviceAndSwapChain.SetTargetFunction( uMod_D3D10CreateDeviceAndSwapChain); + Detour_D3D10CreateDeviceAndSwapChain.SetLibName( "d3d10.dll"); + Detour_D3D10CreateDeviceAndSwapChain.SetFullLibName( buffer); + Detour_D3D10CreateDeviceAndSwapChain.SetLibName( L"d3d10.dll"); // set also for wide character + Detour_D3D10CreateDeviceAndSwapChain.SetFullLibName( buffer_w); // set also for wide character + + GetSystemDirectory(buffer,MAX_PATH); //get the system directory, we need to open the original d3d9.dll + swprintf_s( buffer_w, MAX_PATH, L"%s\\d3d10_1.dll", buffer); + strcat_s( buffer, MAX_PATH,"\\d3d10_1.dll"); + + Detour_D3D10CreateDeviceAndSwapChain1.SetFunctionName( "D3D10CreateDeviceAndSwapChain1"); + Detour_D3D10CreateDeviceAndSwapChain1.SetTargetFunction( uMod_D3D10CreateDeviceAndSwapChain1); + Detour_D3D10CreateDeviceAndSwapChain1.SetLibName( "d3d10_1.dll"); + Detour_D3D10CreateDeviceAndSwapChain1.SetFullLibName( buffer); + Detour_D3D10CreateDeviceAndSwapChain1.SetLibName( L"d3d10_1.dll"); // set also for wide character + Detour_D3D10CreateDeviceAndSwapChain1.SetFullLibName( buffer_w); // set also for wide character + + GlobalDetour.AddEntry(&Detour_D3D10CreateDeviceAndSwapChain); + GlobalDetour.AddEntry(&Detour_D3D10CreateDeviceAndSwapChain1); + #endif } void ExitDX10(void) { +#if INJECTION_METHOD==NO_INJECTION // Release the system's d3d9.dll if (gl_hOriginal_DX10_Dll!=NULL) { @@ -94,7 +108,15 @@ void ExitDX10(void) FreeLibrary(gl_hOriginal_DX101_Dll); gl_hOriginal_DX101_Dll = NULL; } +#endif + +#if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION +#endif } + + + +#if INJECTION_METHOD==NO_INJECTION void LoadOriginal_DX10_Dll(void) { char buffer[MAX_PATH]; @@ -119,8 +141,6 @@ void LoadOriginal_DX10_Dll(void) } - -#if INJECTION_METHOD==NO_INJECTION /* * We do not inject, the game loads this dll by itself thus we must include the Direct3DCreate9 function */ @@ -254,10 +274,8 @@ HRESULT APIENTRY uMod_D3D10CreateDeviceAndSwapChain( ID3D10Device **ppDevice ) { - RetourFunc((BYTE*) GetProcAddress( gl_hOriginal_DX10_Dll, "D3D10CreateDeviceAndSwapChain"), (BYTE*)D3D10CreateDeviceAndSwapChain_fn, number_of_byte); - D3D10CreateDeviceAndSwapChain_fn = (D3D10CreateDeviceAndSwapChain_type) GetProcAddress( gl_hOriginal_DX10_Dll, "D3D10CreateDeviceAndSwapChain"); - - HRESULT ret = D3D10CreateDeviceAndSwapChain_fn(pAdapter,DriverType,Software,Flags,SDKVersion,pSwapChainDesc, ppSwapChain, ppDevice); + Detour_D3D10CreateDeviceAndSwapChain.Retour(); + HRESULT ret = Detour_D3D10CreateDeviceAndSwapChain.Function()(pAdapter,DriverType,Software,Flags,SDKVersion,pSwapChainDesc, ppSwapChain, ppDevice); if (ret==S_OK) { uMod_ID3D10Device *dev = new uMod_ID3D10Device( *ppDevice, gl_TextureServer); @@ -270,7 +288,7 @@ HRESULT APIENTRY uMod_D3D10CreateDeviceAndSwapChain( } } else Message("D3D10CreateDeviceAndSwapChain: Failed\n"); - D3D10CreateDeviceAndSwapChain_fn = (D3D10CreateDeviceAndSwapChain_type)DetourFunc( (BYTE*)D3D10CreateDeviceAndSwapChain_fn, (BYTE*)uMod_D3D10CreateDeviceAndSwapChain, number_of_byte); + Detour_D3D10CreateDeviceAndSwapChain.Detour(); return ret; } @@ -286,10 +304,8 @@ HRESULT APIENTRY uMod_D3D10CreateDeviceAndSwapChain1( ID3D10Device1 **ppDevice ) { - RetourFunc((BYTE*) GetProcAddress( gl_hOriginal_DX101_Dll, "D3D10CreateDeviceAndSwapChain1"), (BYTE*)D3D10CreateDeviceAndSwapChain1_fn, 5); - D3D10CreateDeviceAndSwapChain1_fn = (D3D10CreateDeviceAndSwapChain1_type) GetProcAddress( gl_hOriginal_DX101_Dll, "D3D10CreateDeviceAndSwapChain1"); - - HRESULT ret = D3D10CreateDeviceAndSwapChain1_fn(pAdapter,DriverType,Software,Flags,HardwareLevel,SDKVersion,pSwapChainDesc, ppSwapChain, ppDevice); + Detour_D3D10CreateDeviceAndSwapChain1.Retour(); + HRESULT ret = Detour_D3D10CreateDeviceAndSwapChain1.Function()(pAdapter,DriverType,Software,Flags,HardwareLevel,SDKVersion,pSwapChainDesc, ppSwapChain, ppDevice); if (ret==S_OK) { uMod_ID3D10Device1 *dev = new uMod_ID3D10Device1( *ppDevice, gl_TextureServer); @@ -302,9 +318,7 @@ HRESULT APIENTRY uMod_D3D10CreateDeviceAndSwapChain1( } } else Message("D3D10CreateDeviceAndSwapChain1: Failed\n"); - - D3D10CreateDeviceAndSwapChain1_fn = (D3D10CreateDeviceAndSwapChain1_type)DetourFunc( (BYTE*)D3D10CreateDeviceAndSwapChain1_fn, (BYTE*)uMod_D3D10CreateDeviceAndSwapChain1, 5); - + Detour_D3D10CreateDeviceAndSwapChain1.Detour(); return (ret); } diff --git a/uMod_DX10/uMod_DX10_dll.h b/uMod_DX10/uMod_DX10_dll.h index 14201cc..169b731 100644 --- a/uMod_DX10/uMod_DX10_dll.h +++ b/uMod_DX10/uMod_DX10_dll.h @@ -23,10 +23,17 @@ along with Universal Modding Engine. If not, see #include "../uMod_DXMain/uMod_Main.h" -void LoadOriginal_DX10_Dll(void); void InitDX10(); void ExitDX10(); +#if INJECTION_METHOD==NO_INJECTION +/** + * Load the official d3d10.dll from the system path. + */ +void LoadOriginal_DX10_Dll(void); +#endif + + #if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION HRESULT APIENTRY uMod_D3D10CreateDeviceAndSwapChain( diff --git a/uMod_DX10/uMod_IDXGISwapChain.cpp b/uMod_DX10/uMod_IDXGISwapChain.cpp index fd3c421..02fbdcd 100644 --- a/uMod_DX10/uMod_IDXGISwapChain.cpp +++ b/uMod_DX10/uMod_IDXGISwapChain.cpp @@ -23,7 +23,7 @@ along with Universal Modding Engine.If not, see . uMod_IDXGISwapChain::uMod_IDXGISwapChain(IDXGISwapChain *pOriginal, uMod_ID3D10Device *dev) { - Message( "IDXGISwapChain::IDXGISwapChain( %lu, %lu): %lu\n", pOriginal, dev, this); + Message( "uMod_IDXGISwapChain::uMod_IDXGISwapChain( %lu, %lu): %lu\n", pOriginal, dev, this); m_IDXGISwapChain = pOriginal; u_ID3D10Device = dev; RefCounter = 1; @@ -37,7 +37,7 @@ uMod_IDXGISwapChain::~uMod_IDXGISwapChain() HRESULT STDMETHODCALLTYPE uMod_IDXGISwapChain::QueryInterface( REFIID riid, void** ppvObject) { *ppvObject = NULL; - Message( "IDXGISwapChain::QueryInterface(): %lu\n", this); + Message( "uMod_IDXGISwapChain::QueryInterface(): %lu\n", this); HRESULT hRes = m_IDXGISwapChain->QueryInterface(riid, ppvObject); if (*ppvObject == m_IDXGISwapChain) @@ -51,12 +51,14 @@ HRESULT STDMETHODCALLTYPE uMod_IDXGISwapChain::QueryInterface( REFIID riid, void ULONG STDMETHODCALLTYPE uMod_IDXGISwapChain::AddRef(void) { + Message( "uMod_IDXGISwapChain::AddRef(): %lu\n", this); RefCounter++; return m_IDXGISwapChain->AddRef(); } ULONG STDMETHODCALLTYPE uMod_IDXGISwapChain::Release( void) { + Message( "uMod_IDXGISwapChain::Release(): %lu\n", this); if (--RefCounter==0) //if our counter drops to zero, the real device will be deleted, so we clean up before { // we must not release the fake textures, cause they are released if the target textures are released @@ -111,11 +113,13 @@ HRESULT STDMETHODCALLTYPE uMod_IDXGISwapChain::GetDevice( REFIID riid, void **pp HRESULT STDMETHODCALLTYPE uMod_IDXGISwapChain::Present( UINT SyncInterval, UINT Flags) { + Message( "uMod_IDXGISwapChain::Present(): %lu\n", this); return m_IDXGISwapChain->Present( SyncInterval, Flags); } HRESULT STDMETHODCALLTYPE uMod_IDXGISwapChain::GetBuffer( UINT Buffer, REFIID riid, void **ppSurface) { + Message( "uMod_IDXGISwapChain::GetBuffer(): %lu\n", this); return m_IDXGISwapChain->GetBuffer( Buffer, riid, ppSurface); } diff --git a/uMod_DX9/uMod_DX9_dll.cpp b/uMod_DX9/uMod_DX9_dll.cpp index fd34280..bf54f9f 100644 --- a/uMod_DX9/uMod_DX9_dll.cpp +++ b/uMod_DX9/uMod_DX9_dll.cpp @@ -33,58 +33,93 @@ along with Universal Modding Engine. If not, see /* * global variable which are not linked external */ +#if INJECTION_METHOD==NO_INJECTION HINSTANCE gl_hOriginal_DX9_Dll = NULL; +#endif + + +#if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION typedef IDirect3D9 *(APIENTRY *Direct3DCreate9_type)(UINT); typedef HRESULT (APIENTRY *Direct3DCreate9Ex_type)(UINT SDKVersion, IDirect3D9Ex **ppD3D); -#if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION -Direct3DCreate9_type Direct3DCreate9_fn = NULL; // we need to store the pointer to the original Direct3DCreate9 function after we have done a detour -Direct3DCreate9Ex_type Direct3DCreate9Ex_fn = NULL; // we need to store the pointer to the original Direct3DCreate9 function after we have done a detour +uMod_Detour_Entry Detour_Direct3DCreate9(5); +uMod_Detour_Entry Detour_Direct3DCreate9Ex(5); + #endif - -/* - * global variable which are linked external - */ - void InitDX9(void) { - LoadOriginal_DX9_Dll(); #if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION - // we detour the original Direct3DCreate9 to our MyDirect3DCreate9 - if (gl_hOriginal_DX9_Dll!=NULL) - { - Direct3DCreate9_fn = (Direct3DCreate9_type) GetProcAddress(gl_hOriginal_DX9_Dll, "Direct3DCreate9"); - if (Direct3DCreate9_fn!=NULL) - { - Message("Detour: Direct3DCreate9\n"); - Direct3DCreate9_fn = (Direct3DCreate9_type)DetourFunc( (BYTE*)Direct3DCreate9_fn, (BYTE*)uMod_Direct3DCreate9, 5); - } - Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type) GetProcAddress(gl_hOriginal_DX9_Dll, "Direct3DCreate9Ex"); - if (Direct3DCreate9Ex_fn!=NULL) - { - Message("Detour: Direct3DCreate9Ex\n"); - Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type)DetourFunc( (BYTE*)Direct3DCreate9Ex_fn, (BYTE*)uMod_Direct3DCreate9Ex, 7); - } + char buffer[MAX_PATH]; + wchar_t buffer_w[MAX_PATH]; + GetSystemDirectory(buffer,MAX_PATH); //get the system directory, we need to open the original d3d9.dll + + swprintf_s( buffer_w, MAX_PATH, L"%s\\d3d9.dll", buffer); + strcat_s( buffer, MAX_PATH,"\\d3d9.dll"); + + Detour_Direct3DCreate9.SetFunctionName( "Direct3DCreate9"); + Detour_Direct3DCreate9.SetTargetFunction( uMod_Direct3DCreate9); + Detour_Direct3DCreate9.SetLibName( "d3d9.dll"); + Detour_Direct3DCreate9.SetFullLibName( buffer); + Detour_Direct3DCreate9.SetLibName( L"d3d9.dll"); // set also for wide character + Detour_Direct3DCreate9.SetFullLibName( buffer_w); // set also for wide character + + Detour_Direct3DCreate9Ex.SetFunctionName( "Direct3DCreate9Ex"); + Detour_Direct3DCreate9Ex.SetTargetFunction( uMod_Direct3DCreate9Ex); + Detour_Direct3DCreate9Ex.SetLibName( "d3d9.dll"); + Detour_Direct3DCreate9Ex.SetFullLibName( buffer); + Detour_Direct3DCreate9Ex.SetLibName( L"d3d9.dll"); // set also for wide character + Detour_Direct3DCreate9Ex.SetFullLibName( buffer_w); // set also for wide character + + GlobalDetour.AddEntry(&Detour_Direct3DCreate9); + GlobalDetour.AddEntry(&Detour_Direct3DCreate9Ex); + //char buffer[MAX_PATH]; + //if (gl_hOriginal_DX9_Dll==NULL) + { + GetSystemDirectory(buffer,MAX_PATH); //get the system directory, we need to open the original d3d9.dll + + // Append dll name + strcat_s( buffer, MAX_PATH,"\\d3d9.dll"); + + // try to load the system's d3d9.dll + HANDLE gl_hOriginal_DX9_Dll = LoadLibrary(buffer); } #endif + +#if INJECTION_METHOD==NO_INJECTION + LoadOriginal_DX9_Dll(); +#endif } void ExitDX9(void) { // Release the system's d3d9.dll +#if INJECTION_METHOD==NO_INJECTION if (gl_hOriginal_DX9_Dll!=NULL) { FreeLibrary(gl_hOriginal_DX9_Dll); gl_hOriginal_DX9_Dll = NULL; } +#endif + + +#if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION +#endif + } + + + +#if INJECTION_METHOD==NO_INJECTION +/* + * We do not inject, the game loads this dll by itself thus we must include the Direct3DCreate9 function + */ void LoadOriginal_DX9_Dll(void) { char buffer[MAX_PATH]; @@ -100,12 +135,6 @@ void LoadOriginal_DX9_Dll(void) } } - -#if INJECTION_METHOD==NO_INJECTION -/* - * We do not inject, the game loads this dll by itself thus we must include the Direct3DCreate9 function - */ - IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) { Message("WINAPI Direct3DCreate9\n"); @@ -218,6 +247,9 @@ DWORD WINAPI D3DPERF_GetStatus( void ) #endif + + + #if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION /* @@ -226,95 +258,44 @@ DWORD WINAPI D3DPERF_GetStatus( void ) IDirect3D9 *APIENTRY uMod_Direct3DCreate9(UINT SDKVersion) { - Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Direct3DCreate9_fn, uMod_Direct3DCreate9); - - // in the Internet are many tutorials for detouring functions and all of them will work without the following 5 marked lines - // but somehow, for me it only works, if I retour the function and calling afterward the original function - - // BEGIN - - LoadOriginal_DX9_Dll(); - - RetourFunc((BYTE*) GetProcAddress( gl_hOriginal_DX9_Dll, "Direct3DCreate9"), (BYTE*)Direct3DCreate9_fn, 5); - Direct3DCreate9_fn = (Direct3DCreate9_type) GetProcAddress( gl_hOriginal_DX9_Dll, "Direct3DCreate9"); - -/* - if (Direct3DCreate9Ex_fn!=NULL) - { - RetourFunc((BYTE*) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9Ex"), (BYTE*)Direct3DCreate9Ex_fn, 7); - Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9Ex"); - } - */ - // END + Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Detour_Direct3DCreate9.Function(), uMod_Direct3DCreate9); IDirect3D9 *pIDirect3D9_orig = NULL; - if (Direct3DCreate9_fn) - { - pIDirect3D9_orig = Direct3DCreate9_fn(SDKVersion); //creating the original IDirect3D9 object - } - else return (NULL); - uMod_IDirect3D9 *pIDirect3D9; + uMod_IDirect3D9 *pIDirect3D9 = NULL; + + Detour_Direct3DCreate9.Retour(); + + pIDirect3D9_orig = Detour_Direct3DCreate9.Function()(SDKVersion); //creating the original IDirect3D9 object + if (pIDirect3D9_orig) { pIDirect3D9 = new uMod_IDirect3D9( pIDirect3D9_orig, gl_TextureServer); //creating our uMod_IDirect3D9 object } + Detour_Direct3DCreate9.Detour(); - // we detour again - Direct3DCreate9_fn = (Direct3DCreate9_type)DetourFunc( (BYTE*) Direct3DCreate9_fn, (BYTE*)uMod_Direct3DCreate9,5); - /* - if (Direct3DCreate9Ex_fn!=NULL) - { - Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type)DetourFunc( (BYTE*) Direct3DCreate9Ex_fn, (BYTE*)uMod_Direct3DCreate9Ex,7); - } -*/ return (pIDirect3D9); //return our object instead of the "real one" } + HRESULT APIENTRY uMod_Direct3DCreate9Ex( UINT SDKVersion, IDirect3D9Ex **ppD3D) { - Message( "uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Direct3DCreate9Ex_fn, uMod_Direct3DCreate9Ex); - - // in the Internet are many tutorials for detouring functions and all of them will work without the following 5 marked lines - // but somehow, for me it only works, if I retour the function and calling afterward the original function - - // BEGIN - - LoadOriginal_DX9_Dll(); - /* - if (Direct3DCreate9_fn!=NULL) - { - RetourFunc((BYTE*) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9"), (BYTE*)Direct3DCreate9_fn, 5); - Direct3DCreate9_fn = (Direct3DCreate9_type) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9"); - } -*/ - RetourFunc((BYTE*) GetProcAddress( gl_hOriginal_DX9_Dll, "Direct3DCreate9Ex"), (BYTE*)Direct3DCreate9Ex_fn, 7); - Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type) GetProcAddress( gl_hOriginal_DX9_Dll, "Direct3DCreate9Ex"); - // END + Message( "uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Detour_Direct3DCreate9Ex.Function(), uMod_Direct3DCreate9Ex); IDirect3D9Ex *pIDirect3D9Ex_orig = NULL; - HRESULT ret; - if (Direct3DCreate9Ex_fn) - { - ret = Direct3DCreate9Ex_fn(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object - } - else return (D3DERR_NOTAVAILABLE); + uMod_IDirect3D9Ex *pIDirect3D9Ex = NULL; + HRESULT ret = D3DERR_NOTAVAILABLE; + + Detour_Direct3DCreate9Ex.Retour(); + ret = Detour_Direct3DCreate9Ex.Function()(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object if (ret!=S_OK) return (ret); - uMod_IDirect3D9Ex *pIDirect3D9Ex; if (pIDirect3D9Ex_orig) { pIDirect3D9Ex = new uMod_IDirect3D9Ex( pIDirect3D9Ex_orig, gl_TextureServer); //creating our uMod_IDirect3D9 object } + Detour_Direct3DCreate9Ex.Detour(); - // we detour again -/* - if (Direct3DCreate9_fn!=NULL) - { - Direct3DCreate9_fn = (Direct3DCreate9_type)DetourFunc( (BYTE*) Direct3DCreate9_fn, (BYTE*)uMod_Direct3DCreate9,5); - } - */ - Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type)DetourFunc( (BYTE*) Direct3DCreate9Ex_fn, (BYTE*)uMod_Direct3DCreate9Ex,7); ppD3D = (IDirect3D9Ex**) &pIDirect3D9Ex; //return our object instead of the "real one" return (ret); } diff --git a/uMod_DX9/uMod_DX9_dll.h b/uMod_DX9/uMod_DX9_dll.h index 2175d64..8b627d5 100644 --- a/uMod_DX9/uMod_DX9_dll.h +++ b/uMod_DX9/uMod_DX9_dll.h @@ -23,20 +23,17 @@ along with Universal Modding Engine. If not, see #include "../uMod_DXMain/uMod_Main.h" + + +void InitDX9(); +void ExitDX9(); + +#if INJECTION_METHOD==NO_INJECTION /** * Load the official d3d9.dll from the system path. */ void LoadOriginal_DX9_Dll(void); - -/** - * Initialize dx9 -> loads d3d9.dll and set detour if this dll is compiled for "Direct Injection" or "Hook Injection" - */ -void InitDX9(); - -/** - * Unload the d3d9.dll - */ -void ExitDX9(); +#endif #if INJECTION_METHOD==DIRECT_INJECTION || INJECTION_METHOD==HOOK_INJECTION diff --git a/uMod_DX9/uMod_IDirect3DDevice9.cpp b/uMod_DX9/uMod_IDirect3DDevice9.cpp index 18734f7..8188ea5 100644 --- a/uMod_DX9/uMod_IDirect3DDevice9.cpp +++ b/uMod_DX9/uMod_IDirect3DDevice9.cpp @@ -491,11 +491,13 @@ BOOL uMod_IDirect3DDevice9::ShowCursor(BOOL bShow) HRESULT uMod_IDirect3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain) { + Message("uMod_IDirect3DDevice9::CreateAdditionalSwapChain() %p\n", this); return(m_pIDirect3DDevice9->CreateAdditionalSwapChain(pPresentationParameters,pSwapChain)); } HRESULT uMod_IDirect3DDevice9::GetSwapChain(UINT iSwapChain,IDirect3DSwapChain9** pSwapChain) { + Message("uMod_IDirect3DDevice9::GetSwapChain() %p\n", this); return(m_pIDirect3DDevice9->GetSwapChain(iSwapChain,pSwapChain)); } @@ -971,7 +973,7 @@ HRESULT uMod_IDirect3DDevice9::CreateOffscreenPlainSurface(UINT Width,UINT Heigh HRESULT uMod_IDirect3DDevice9::SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget) { - //Message( PRE_MESSAGE "::SetRenderTarget( %u, %p): %p\n", RenderTargetIndex, pRenderTarget, this); + Message( PRE_MESSAGE "::SetRenderTarget( %u, %p): %p\n", RenderTargetIndex, pRenderTarget, this); { IDirect3DSurface9 *back_buffer; NormalRendering = false; diff --git a/uMod_DX9/uMod_IDirect3DSurface9.cpp b/uMod_DX9/uMod_IDirect3DSurface9.cpp index 34de687..0c838d0 100644 --- a/uMod_DX9/uMod_IDirect3DSurface9.cpp +++ b/uMod_DX9/uMod_IDirect3DSurface9.cpp @@ -50,14 +50,14 @@ HRESULT uMod_IDirect3DSurface9::QueryInterface(REFIID riid, void** ppvObj) ULONG uMod_IDirect3DSurface9::AddRef() { - //Message( "uMod_IDirect3DSurface9::AddRef(): %p\n", this); + Message( "uMod_IDirect3DSurface9::AddRef(): %p\n", this); RefCounter++; return m_D3Dsurf->AddRef(); } ULONG uMod_IDirect3DSurface9::Release() { - //Message( "uMod_IDirect3DSurface9::Release(): %p\n", this); + Message( "uMod_IDirect3DSurface9::Release(): %p\n", this); // this object might be created by uMod_IDirect3DTexture9::GetSurfaceLevel // thus the RefCounter might be zero although m_D3Dsurf->Release() does not delete // the m_D3Dsurf object @@ -75,19 +75,19 @@ HRESULT uMod_IDirect3DSurface9::GetDevice( IDirect3DDevice9** ppDevice) HRESULT uMod_IDirect3DSurface9::SetPrivateData( REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) { - //Message( "uMod_IDirect3DSurface9::SetPrivateData(): %p\n", this); + Message( "uMod_IDirect3DSurface9::SetPrivateData(): %p\n", this); return m_D3Dsurf->SetPrivateData( refguid, pData, SizeOfData, Flags); } HRESULT uMod_IDirect3DSurface9::GetPrivateData( REFGUID refguid,void* pData,DWORD* pSizeOfData) { - //Message( "uMod_IDirect3DSurface9::GetPrivateData(): %p\n", this); + Message( "uMod_IDirect3DSurface9::GetPrivateData(): %p\n", this); return m_D3Dsurf->GetPrivateData( refguid, pData, pSizeOfData); } HRESULT uMod_IDirect3DSurface9::FreePrivateData( REFGUID refguid) { - //Message( "uMod_IDirect3DSurface9::FreePrivateData(): %p\n", this); + Message( "uMod_IDirect3DSurface9::FreePrivateData(): %p\n", this); return m_D3Dsurf->FreePrivateData( refguid); } @@ -116,7 +116,7 @@ D3DRESOURCETYPE uMod_IDirect3DSurface9::GetType() HRESULT uMod_IDirect3DSurface9::GetContainer( REFIID riid,void** ppContainer) { - //Message( "uMod_IDirect3DSurface9::GetContainer(): %p\n", this); + Message( "uMod_IDirect3DSurface9::GetContainer(): %p\n", this); HRESULT ret = m_D3Dsurf->GetContainer( riid, ppContainer); //return the uMod_IDirect3DTexture9 object @@ -136,38 +136,37 @@ HRESULT uMod_IDirect3DSurface9::GetContainer( REFIID riid,void** ppContainer) HRESULT uMod_IDirect3DSurface9::GetDesc( D3DSURFACE_DESC *pDesc) { - //Message( "uMod_IDirect3DSurface9::GetDesc(): %p\n", this); + Message( "uMod_IDirect3DSurface9::GetDesc(): %p\n", this); return m_D3Dsurf->GetDesc( pDesc); } HRESULT uMod_IDirect3DSurface9::LockRect( D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags) { - //Message( "uMod_IDirect3DSurface9::LockRect(): %p\n", this); + Message( "uMod_IDirect3DSurface9::LockRect(): %p\n", this); return m_D3Dsurf->LockRect( pLockedRect, pRect, Flags); } HRESULT uMod_IDirect3DSurface9::UnlockRect() { - //Message( "uMod_IDirect3DSurface9::UnlockRect(): %p\n", this); + Message( "uMod_IDirect3DSurface9::UnlockRect(): %p\n", this); HRESULT ret = m_D3Dsurf->UnlockRect(); if (m_D3DTex!=NULL && !m_D3DTex->FAKE) m_D3DTex->Dirty=1; else if (m_D3DCubeTex!=NULL && !m_D3DCubeTex->FAKE) m_D3DCubeTex->Dirty = 1; - return ret; } HRESULT uMod_IDirect3DSurface9::GetDC( HDC *phdc) { - //Message( "uMod_IDirect3DSurface9::GetDC(): %p\n", this); + Message( "uMod_IDirect3DSurface9::GetDC(): %p\n", this); return m_D3Dsurf->GetDC( phdc); } HRESULT uMod_IDirect3DSurface9::ReleaseDC( HDC hdc) { - //Message( "uMod_IDirect3DSurface9::ReleaseDC(): %p\n", this); + Message( "uMod_IDirect3DSurface9::ReleaseDC(): %p\n", this); HRESULT ret = m_D3Dsurf->ReleaseDC( hdc); if (m_D3DTex!=NULL && !m_D3DTex->FAKE) diff --git a/uMod_DXMain/makefile.gcc b/uMod_DXMain/makefile.gcc index 0647bb0..e3b8fde 100644 --- a/uMod_DXMain/makefile.gcc +++ b/uMod_DXMain/makefile.gcc @@ -79,6 +79,7 @@ objects = \ ${obj}\uMod_ArrayHandler.$(DX_XX_File).${obj_suff} \ ${obj}\uMod_TextureClient.$(DX_XX_File).${obj_suff} \ ${obj}\uMod_TextureServer.$(DX_XX_File).${obj_suff} \ + ${obj}\uMod_Detour.$(DX_XX_File).${obj_suff} \ ${obj}\uMod_DXMain_dll.$(DX_XX_File).${obj_suff} \ \ ${obj}\uMod_DX9_dll.${obj_suff} \ @@ -103,6 +104,8 @@ objects = \ headers = uMod_Main.h \ uMod_DXMain_dll.h \ + uMod_Detour.h \ + uMod_DetourEntry.h \ uMod_Defines.h \ uMod_TextureFunction.h \ uMod_ArrayHandler.h \ @@ -137,6 +140,9 @@ ${bin}\d3d9.dll: ${objects} ${obj}\uMod_DXMain_dll.$(DX_XX_File).${obj_suff}: uMod_DXMain_dll.cpp ${headers} ${CXX} ${CFLAGS} /c $< /Fo$@ +${obj}\uMod_Detour.$(DX_XX_File).${obj_suff}: uMod_Detour.cpp ${headers} + ${CXX} ${CFLAGS} /c $< /Fo$@ + ${obj}\uMod_ArrayHandler.$(DX_XX_File).${obj_suff}: uMod_ArrayHandler.cpp ${headers} ${CXX} ${CFLAGS} /c $< /Fo$@ diff --git a/uMod_DXMain/makefile.vc b/uMod_DXMain/makefile.vc index 3711d7e..ee011ef 100644 --- a/uMod_DXMain/makefile.vc +++ b/uMod_DXMain/makefile.vc @@ -79,6 +79,7 @@ objects = \ $(obj)\uMod_ArrayHandler.$(DX_XX_File).$(obj_suff) \ $(obj)\uMod_TextureClient.$(DX_XX_File).$(obj_suff) \ $(obj)\uMod_TextureServer.$(DX_XX_File).$(obj_suff) \ + $(obj)\uMod_Detour.$(DX_XX_File).$(obj_suff) \ $(obj)\uMod_DXMain_dll.$(DX_XX_File).$(obj_suff) \ \ $(obj)\uMod_DX9_dll.$(obj_suff) \ @@ -103,6 +104,8 @@ objects = \ headers = uMod_Main.h \ uMod_DXMain_dll.h \ + uMod_Detour.h \ + uMod_DetourEntry.h \ uMod_Defines.h \ uMod_TextureFunction.h \ uMod_ArrayHandler.h \ @@ -137,6 +140,9 @@ $(bin)\d3d9.dll: $(objects) $(obj)\uMod_DXMain_dll.$(DX_XX_File).$(obj_suff): uMod_DXMain_dll.cpp $(headers) $(CXX) $(CFLAGS) /c uMod_DXMain_dll.cpp /Fo$@ +$(obj)\uMod_Detour.$(DX_XX_File).$(obj_suff): uMod_Detour.cpp $(headers) + $(CXX) $(CFLAGS) /c uMod_Detour.cpp /Fo$@ + $(obj)\uMod_ArrayHandler.$(DX_XX_File).$(obj_suff): uMod_ArrayHandler.cpp $(headers) $(CXX) $(CFLAGS) /c uMod_ArrayHandler.cpp /Fo$@ diff --git a/uMod_DXMain/uMod_DX9_10_dll_DIRECT_INJECTION.def b/uMod_DXMain/uMod_DX9_10_dll_DIRECT_INJECTION.def new file mode 100644 index 0000000..65c1d46 --- /dev/null +++ b/uMod_DXMain/uMod_DX9_10_dll_DIRECT_INJECTION.def @@ -0,0 +1,7 @@ +LIBRARY "uMod_d3d9_DI" +EXPORTS + uMod_Direct3DCreate9 @1 + uMod_Direct3DCreate9Ex @2 + uMod_D3D10CreateDeviceAndSwapChain @3 + uMod_D3D10CreateDeviceAndSwapChain1 @4 + Nothing @5 \ No newline at end of file diff --git a/uMod_DXMain/uMod_DXMain_dll.cpp b/uMod_DXMain/uMod_DXMain_dll.cpp index 7e4c710..f3e9e9d 100644 --- a/uMod_DXMain/uMod_DXMain_dll.cpp +++ b/uMod_DXMain/uMod_DXMain_dll.cpp @@ -102,6 +102,7 @@ void InitInstance(HINSTANCE hModule) gl_TextureServer = new uMod_TextureServer(game); //create the server which listen on the pipe and prepare the update for the texture clients + GlobalDetour.Init(); #ifdef DEF_USE_DX9 InitDX9(); #endif @@ -146,6 +147,7 @@ void ExitInstance() ExitDX10(); #endif + GlobalDetour.Exit(); CloseMessage(); } diff --git a/uMod_DXMain/uMod_Detour.cpp b/uMod_DXMain/uMod_Detour.cpp new file mode 100644 index 0000000..3b846dd --- /dev/null +++ b/uMod_DXMain/uMod_Detour.cpp @@ -0,0 +1,206 @@ +/* +This file is part of Universal Modding Engine. + + +Universal Modding Engine is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Universal Modding Engine is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Universal Modding Engine. If not, see . +*/ + +#include "uMod_Detour.h" +#include "uMod_Main.h" + + + +uMod_Detour::uMod_Detour() : NumOfEntries(0), Entries(NULL), + Detour_FreeLibrary(5), + Detour_LoadLibraryA(5), + Detour_LoadLibraryW(5), + Detour_LoadLibraryExA(5), + Detour_LoadLibraryExW(5) +{ + +} + +uMod_Detour::~uMod_Detour() +{ + if (Entries!=NULL) delete [] Entries; +} + + +void uMod_Detour::Init(void) +{ + Detour_FreeLibrary.SetOrigFunction(FreeLibrary); + Detour_FreeLibrary.SetTargetFunction(uMod_FreeLibrary); + Detour_FreeLibrary.Detour(); + + Detour_LoadLibraryA.SetOrigFunction(LoadLibraryA); + Detour_LoadLibraryA.SetTargetFunction(uMod_LoadLibraryA); + Detour_LoadLibraryA.Detour(); + + Detour_LoadLibraryW.SetOrigFunction(LoadLibraryW); + Detour_LoadLibraryW.SetTargetFunction(uMod_LoadLibraryW); + Detour_LoadLibraryW.Detour(); + + Detour_LoadLibraryExA.SetOrigFunction(LoadLibraryExA); + Detour_LoadLibraryExA.SetTargetFunction(uMod_LoadLibraryExA); + Detour_LoadLibraryExA.Detour(); + + Detour_LoadLibraryExW.SetOrigFunction(LoadLibraryExW); + Detour_LoadLibraryExW.SetTargetFunction(uMod_LoadLibraryExW); + Detour_LoadLibraryExW.Detour(); + + + //for (int i=0; iDetour(); +} + +void uMod_Detour::Exit(void) +{ + Detour_FreeLibrary.Retour(); + Detour_LoadLibraryA.Retour(); + Detour_LoadLibraryW.Retour(); + Detour_LoadLibraryExA.Retour(); + Detour_LoadLibraryExW.Retour(); + + //for (int i=0; iRetour(); +} + +int uMod_Detour::AddEntry( uMod_Detour_Entry_Base* entry) +{ + uMod_Detour_Entry_Base** temp = new uMod_Detour_Entry_Base*[NumOfEntries+1]; + + if (Entries!=NULL) + { + for (int i=0; iFreeLib( plib); +} + +void uMod_Detour::TestLib(const char* lib_name, HMODULE plib) +{ + Message("uMod_Detour::TestLib( %s, %p )\n", lib_name, plib); + if (lib_name==NULL) return; + if (plib==NULL) return; + + for (int i=0; iTestLib( lib_name, plib); +} + +void uMod_Detour::TestLib(const wchar_t* lib_name, HMODULE plib) +{ + Message("uMod_Detour::TestLib( %ls, %p )\n", lib_name, plib); + if (lib_name==NULL) return; + if (plib==NULL) return; + + for (int i=0; iTestLib( lib_name, plib); +} + + +uMod_Detour GlobalDetour; + + +BOOL WINAPI uMod_FreeLibrary( HMODULE hModule) +{ + GlobalDetour.Detour_FreeLibrary.Retour(); //retour the FreeLibrary function + + BOOL ret = FreeLibrary( hModule); // now call the original function + Message("%d = uMod_FreeLibrary( %p )\n", ret, hModule); + + GlobalDetour.FreeLib(hModule); // notify all detoured function, that this library was once more freed + + GlobalDetour.Detour_FreeLibrary.Detour(); // detour again the FreeLibrary function + + return ret; +} + +HMODULE WINAPI uMod_LoadLibraryA( LPCSTR lpFileName) +{ + GlobalDetour.Detour_LoadLibraryA.Retour(); //retour the LoadLibraryA function + + HMODULE ret = LoadLibraryA( lpFileName); // now call the original function + Message("%p = uMod_LoadLibraryA( %s )\n", ret, lpFileName); + + GlobalDetour.TestLib( lpFileName, ret); // notify all detoured function, that this library was once more loaded + + GlobalDetour.Detour_LoadLibraryA.Detour(); // detour again the LoadLibraryA function + + return ret; +} + +HMODULE WINAPI uMod_LoadLibraryW( LPCWSTR lpFileName) +{ + GlobalDetour.Detour_LoadLibraryW.Retour(); //retour the LoadLibraryW function + + HMODULE ret = LoadLibraryW( lpFileName); // now call the original function + GlobalDetour.TestLib( lpFileName, ret); // notify all detoured function, that this library was once more loaded + Message("%p = uMod_LoadLibraryW( %ls )\n", ret, lpFileName); + + GlobalDetour.Detour_LoadLibraryW.Detour(); // detour again the LoadLibraryW function + + return ret; +} + +HMODULE WINAPI uMod_LoadLibraryExA( LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags) +{ + GlobalDetour.Detour_LoadLibraryExA.Retour(); //retour the LoadLibraryExA function + + HMODULE ret = LoadLibraryExA( lpFileName, hFile, dwFlags); // now call the original function + Message("%p = uMod_LoadLibraryExA( %s, %p, %d)\n", ret, lpFileName, hFile, dwFlags); + + if (dwFlags==0) + { + GlobalDetour.TestLib( lpFileName, ret); // notify all detoured function, that this library was once more loaded + } + + GlobalDetour.Detour_LoadLibraryExA.Detour(); // detour again the LoadLibraryExA function + + return ret; +} + +HMODULE WINAPI uMod_LoadLibraryExW( LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) +{ + GlobalDetour.Detour_LoadLibraryExW.Retour(); //retour the LoadLibraryExA function + + HMODULE ret = LoadLibraryExW( lpFileName, hFile, dwFlags); // now call the original function + Message("%p = uMod_LoadLibraryExW( %ls, %p, %d)\n", ret, lpFileName, hFile, dwFlags); + + if (dwFlags==0) + { + GlobalDetour.TestLib( lpFileName, ret); // notify all detoured function, that this library was once more loaded + } + + GlobalDetour.Detour_LoadLibraryExW.Detour(); // detour again the LoadLibraryExA function + + return ret; +} + diff --git a/uMod_DXMain/uMod_Detour.h b/uMod_DXMain/uMod_Detour.h new file mode 100644 index 0000000..1f1bb69 --- /dev/null +++ b/uMod_DXMain/uMod_Detour.h @@ -0,0 +1,72 @@ +/* +This file is part of Universal Modding Engine. + + +Universal Modding Engine is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Universal Modding Engine is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Universal Modding Engine. If not, see . +*/ + +#ifndef UMOD_DETOUR_H_ +#define UMOD_DETOUR_H_ + +#include "uMod_DetourEntry.h" +#include + +#ifdef __CDT_PARSER__ +#define NULL 0 +#endif + +typedef BOOL (WINAPI *FreeLibrary_type)( HMODULE hModule); +typedef HMODULE (WINAPI *LoadLibraryA_type)( LPCSTR lpFileName); +typedef HMODULE (WINAPI *LoadLibraryW_type)( LPCWSTR lpFileName); +typedef HMODULE (WINAPI *LoadLibraryExA_type)( LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags); +typedef HMODULE (WINAPI *LoadLibraryExW_type)( LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags); + +BOOL WINAPI uMod_FreeLibrary( HMODULE hModule); +HMODULE WINAPI uMod_LoadLibraryA( LPCSTR lpFileName); +HMODULE WINAPI uMod_LoadLibraryW( LPCWSTR lpFileName); +HMODULE WINAPI uMod_LoadLibraryExA( LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags); +HMODULE WINAPI uMod_LoadLibraryExW( LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags); + +class uMod_Detour +{ +public: + uMod_Detour(); + ~uMod_Detour(); + + + void Init(); + void Exit(); + + int AddEntry( uMod_Detour_Entry_Base* entry); + + + void FreeLib( HMODULE plib); + void TestLib(const char* lib_name, HMODULE plib); + void TestLib(const wchar_t* lib_name, HMODULE plib); + + + uMod_Detour_Entry Detour_FreeLibrary; + uMod_Detour_Entry Detour_LoadLibraryA; + uMod_Detour_Entry Detour_LoadLibraryW; + uMod_Detour_Entry Detour_LoadLibraryExA; + uMod_Detour_Entry Detour_LoadLibraryExW; + +private: + int NumOfEntries; + uMod_Detour_Entry_Base** Entries; +}; + +extern uMod_Detour GlobalDetour; + +#endif /* UMOD_DETOUR_H_ */ diff --git a/uMod_DXMain/uMod_DetourEntry.h b/uMod_DXMain/uMod_DetourEntry.h new file mode 100644 index 0000000..04e34b2 --- /dev/null +++ b/uMod_DXMain/uMod_DetourEntry.h @@ -0,0 +1,324 @@ +/* + * uMod_DetourEntry.h + * + * Created on: 13.01.2013 + * Author: marts + */ + +#ifndef UMOD_DETOURENTRY_H_ +#define UMOD_DETOURENTRY_H_ + +#include "uMod_Main.h" + +#ifdef __CDT_PARSER__ +#define NULL 0 +#endif + +class uMod_Detour_Entry_Base +{ +public: + uMod_Detour_Entry_Base() {} + virtual ~uMod_Detour_Entry_Base() {} + + virtual void TestLib(const char* lib_name, HMODULE plib) = 0; + virtual void TestLib(const wchar_t* lib_name, HMODULE plib) = 0; + virtual void FreeLib(HMODULE plib) = 0; + + + virtual void Detour(void) = 0; + virtual void Retour(void) = 0; +}; + + + + +template +class uMod_Detour_Entry : public uMod_Detour_Entry_Base +{ +public: + uMod_Detour_Entry(const int num_bytes); + virtual ~uMod_Detour_Entry(); + + + virtual void TestLib(const char* lib_name, HMODULE plib); + virtual void TestLib(const wchar_t* lib_name, HMODULE plib); + virtual void FreeLib(HMODULE plib); + + virtual void Detour(void); + virtual void Retour(void); + bool CheckForDetour(); + + int SetFunctionName( const char* name) {return SetName( FunctionName, name);} + int SetLibName( const char* name) {return SetName( LibName, name);} + int SetFullLibName( const char* name) {return SetName( FullLibName, name);} + + int SetLibName( const wchar_t* name) {return SetName( LibNameW, name);} + int SetFullLibName( const wchar_t* name) {return SetName( FullLibNameW, name);} + + void SetOrigFunction(T func) {OrigFunction = func;} + void SetTargetFunction(T func) {TargetFunction = func;} + + T Function(void) const {return OrigFunction;} + +private: + + + int SetName( char* &member_var, const char* name); + int SetName( wchar_t* &member_var, const wchar_t* name); + + char* FunctionName; + char* LibName; + char* FullLibName; + + wchar_t* LibNameW; + wchar_t* FullLibNameW; + + HMODULE PLibrary; + int RefCounter; + + + + const int NumBytes; + T OrigFunction; + T TargetFunction; + + BYTE* DetourFunction; + bool IsDetoured; + bool IsFailed; +}; + + + +template +uMod_Detour_Entry::uMod_Detour_Entry(const int num_bytes) : FunctionName(NULL), LibName(NULL), FullLibName(NULL), + LibNameW(NULL), FullLibNameW(NULL), PLibrary(NULL), + NumBytes(num_bytes), OrigFunction(NULL), TargetFunction(NULL), DetourFunction(NULL), IsDetoured(false), IsFailed(false) +{ +} + + +template +uMod_Detour_Entry::~uMod_Detour_Entry() +{ + if (FunctionName!=NULL) delete [] FunctionName; + if (LibName!=NULL) delete [] LibName; + if (FullLibName!=NULL) delete [] FullLibName; + if (LibNameW!=NULL) delete [] LibNameW; + if (FullLibNameW!=NULL) delete [] FullLibNameW; + if (DetourFunction!=NULL) delete [] DetourFunction; +} + + +template +void uMod_Detour_Entry::TestLib(const char* lib_name, HMODULE plib) +{ + if (lib_name==NULL) return; + if (plib==NULL) return; + if (FunctionName==NULL) return; + if (LibName==NULL) return; + + if (PLibrary==plib) + { + RefCounter++; + //return; + } + + int len=0; + while (lib_name[len]) len++; + while (len>=0 && (lib_name[len]!='/' && lib_name[len]!='\\')) len--; + len++; + + if (_stricmp( &lib_name[len], LibName)==0) + { + bool set_detour = true; + if (FullLibName!=NULL) + { + set_detour = false; + GlobalDetour.Detour_LoadLibraryA.Retour(); + GlobalDetour.Detour_FreeLibrary.Retour(); + HMODULE test_handle = LoadLibraryA( FullLibName); //get handle of original library + if (test_handle==NULL || test_handle==plib) set_detour = true; // test if library (loaded by the game) is the original one or a fake one + //if (test_handle!=NULL) FreeLibrary( test_handle); // free the library (we don't want top disturb our own RefCounter) + GlobalDetour.Detour_LoadLibraryA.Detour(); + GlobalDetour.Detour_FreeLibrary.Detour(); + } + + if (!set_detour) return; // it is not the official library (or FullLibName is not set) + if (CheckForDetour()) return; + + OrigFunction = (T) GetProcAddress(plib, FunctionName); + if (OrigFunction==NULL) return; // this library does not contain the function we want to detour + + + Message("uMod_Detour_Entry::TestLib( %s, %p ) set detour -> %s \n", lib_name, plib, FunctionName); + + RefCounter = 1; + PLibrary = plib; + + IsDetoured = false; + IsFailed = false; + Detour(); + } +} + +template +void uMod_Detour_Entry::TestLib(const wchar_t* lib_name, HMODULE plib) +{ + if (lib_name==NULL) return; + if (plib==NULL) return; + if (FunctionName==NULL) return; + if (LibNameW==NULL) return; + + if (PLibrary==plib) + { + RefCounter++; +// return; + } + + int len=0; + while (lib_name[len]) len++; + while (len>=0 && (lib_name[len]!='/' && lib_name[len]!='\\' )) len--; + len++; + + if (_wcsicmp( &lib_name[len], LibNameW)==0) + { + bool set_detour = true; + if (FullLibNameW!=NULL) + { + set_detour = false; + + GlobalDetour.Detour_LoadLibraryW.Retour(); + GlobalDetour.Detour_FreeLibrary.Retour(); + HMODULE test_handle = LoadLibraryW( FullLibNameW); //get handle of original library + if (test_handle==NULL || test_handle==plib) set_detour = true; // test if library (loaded by the game) is the original one or a fake one + if (test_handle!=NULL) FreeLibrary( test_handle); // free the library (we don't want top disturb our own RefCounter) + + GlobalDetour.Detour_LoadLibraryW.Detour(); + GlobalDetour.Detour_FreeLibrary.Detour(); + } + + if (!set_detour) return; // it is not the official library (or FullLibName is not set) + if (CheckForDetour()) return; + + OrigFunction = (T) GetProcAddress(plib, FunctionName); + if (OrigFunction==NULL) return; // this library does not contain the function we want to detour + + + Message("uMod_Detour_Entry::TestLib( %ls, %p ) set detour -> %s \n", lib_name, plib, FunctionName); + + RefCounter = 1; + PLibrary = plib; + + IsDetoured = false; + IsFailed = false; + Detour(); + } +} + +template +void uMod_Detour_Entry::FreeLib(HMODULE plib) +{ + if (plib==NULL) return; + if (plib==PLibrary) RefCounter--; + if (RefCounter<=0) PLibrary = NULL; +} + +template +void uMod_Detour_Entry::Detour(void) +{ + if (IsDetoured || IsFailed) return; + if (DetourFunction==NULL) + { + DetourFunction = new BYTE[NumBytes+5]; + } + BYTE *jmp = DetourFunction; + BYTE *src = (BYTE*) OrigFunction; + const BYTE *dst = (BYTE*) TargetFunction; + const int len = NumBytes; + + DWORD dwback = 0; + //(jmp, len+5, PAGE_EXECUTE_READWRITE, &dwback); //This is the addition needed for Windows 7 RC + if(!VirtualProtect(src, NumBytes, PAGE_READWRITE, &dwback)) IsFailed = true; + if(!memcpy(jmp, src, len)) IsFailed = true; + jmp += len; + jmp[0] = 0xE9; + *(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5; + //memset(src, 0x90, len); + src[0] = 0xE9; + *(DWORD*)(src+1) = (DWORD)(dst - src) - 5; + if(!VirtualProtect(src, len, dwback, &dwback)) IsFailed = true; + + IsDetoured = true; +} + +template +void uMod_Detour_Entry::Retour(void) +{ + if (!IsDetoured || IsFailed) return; + + BYTE *src = (BYTE*) OrigFunction; + BYTE *restore = DetourFunction; + const int len = NumBytes; + DWORD dwback; + if(!VirtualProtect(src, len, PAGE_READWRITE, &dwback)) IsFailed = true; + if(!memcpy(src, restore, len)) IsFailed = true; + restore[0] = 0xE9; + *(DWORD*)(restore+1) = (DWORD)(src - restore) - 5; + + if(!VirtualProtect(src, len, dwback, &dwback)) IsFailed = true; + + IsDetoured = false; +} + + +template +bool uMod_Detour_Entry::CheckForDetour() +{ + if (DetourFunction==NULL) return false; + + //BYTE *jmp = DetourFunction; + BYTE *src = (BYTE*) OrigFunction; + const BYTE *dst = (BYTE*) TargetFunction; + //const int len = NumBytes; + + if (src[0] != 0xE9) return false; + if ( *(DWORD*)(src+1) != (DWORD)(dst - src) - 5) return false; + + return true; +} + +template +int uMod_Detour_Entry::SetName( char* &member_var, const char* name) +{ + if (member_var!=NULL) delete [] member_var; + member_var = NULL; + int len=0; + while (name[len]) len++; + len++; + + member_var = new char[len]; + len = 0; + + while (name[len]) {member_var[len] = name[len]; len++;} + member_var[len] = 0; + return 0; +} + +template +int uMod_Detour_Entry::SetName( wchar_t* &member_var, const wchar_t* name) +{ + if (member_var!=NULL) delete [] member_var; + member_var = NULL; + int len=0; + while (name[len]) len++; + len++; + + member_var = new wchar_t[len]; + len = 0; + + while (name[len]) {member_var[len] = name[len]; len++;} + member_var[len] = 0; + return 0; +} + +#endif /* UMOD_DETOURENTRY_H_ */ diff --git a/uMod_DXMain/uMod_Main.h b/uMod_DXMain/uMod_Main.h index 7a136f0..41535d2 100644 --- a/uMod_DXMain/uMod_Main.h +++ b/uMod_DXMain/uMod_Main.h @@ -52,6 +52,8 @@ along with Universal Modding Engine. If not, see #include "uMod_TextureFunction.h" +#include "uMod_DetourEntry.h" +#include "uMod_Detour.h" #include "uMod_DXMain_dll.h" diff --git a/uMod_GUI/uMod_Main.h b/uMod_GUI/uMod_Main.h index 8bd3b06..be386fa 100644 --- a/uMod_GUI/uMod_Main.h +++ b/uMod_GUI/uMod_Main.h @@ -140,7 +140,7 @@ enum #define ABORT_SERVER L"uMod_Abort_Server" #define uMod_d3d9_Hook_dll L"uMod_d3d9_HI.dll" -#define uMod_d3d9_DI_dll L"uMod_d3d9_DI.dll" +#define uMod_d3d9_DI_dll L"uMod_d3d9_10_DI.dll" #include "uMod_Settings.h" #include "uMod_ModElement.h"