mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-24 03:56:34 +00:00
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.
This commit is contained in:
@@ -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$@
|
||||
|
||||
|
||||
@@ -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$@
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LIBRARY "uMod_d3d9_DI"
|
||||
EXPORTS
|
||||
uMod_Direct3DCreate9 @1
|
||||
uMod_Direct3DCreate9Ex @2
|
||||
uMod_D3D10CreateDeviceAndSwapChain @3
|
||||
uMod_D3D10CreateDeviceAndSwapChain1 @4
|
||||
Nothing @5
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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; i<NumOfEntries; i++)
|
||||
// Entries[i]->Detour();
|
||||
}
|
||||
|
||||
void uMod_Detour::Exit(void)
|
||||
{
|
||||
Detour_FreeLibrary.Retour();
|
||||
Detour_LoadLibraryA.Retour();
|
||||
Detour_LoadLibraryW.Retour();
|
||||
Detour_LoadLibraryExA.Retour();
|
||||
Detour_LoadLibraryExW.Retour();
|
||||
|
||||
//for (int i=0; i<NumOfEntries; i++)
|
||||
// Entries[i]->Retour();
|
||||
}
|
||||
|
||||
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; i<NumOfEntries; i++)
|
||||
temp[i] = Entries[i];
|
||||
delete [] Entries;
|
||||
}
|
||||
Entries = temp;
|
||||
|
||||
Entries[NumOfEntries] = entry;
|
||||
|
||||
NumOfEntries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uMod_Detour::FreeLib( HMODULE plib)
|
||||
{
|
||||
Message("uMod_Detour::FreeLib( %p )\n", plib);
|
||||
if (plib==NULL) return;
|
||||
|
||||
for (int i=0; i<NumOfEntries; i++)
|
||||
Entries[i]->FreeLib( 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; i<NumOfEntries; i++)
|
||||
Entries[i]->TestLib( 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; i<NumOfEntries; i++)
|
||||
Entries[i]->TestLib( 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;
|
||||
}
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UMOD_DETOUR_H_
|
||||
#define UMOD_DETOUR_H_
|
||||
|
||||
#include "uMod_DetourEntry.h"
|
||||
#include <windows.h>
|
||||
|
||||
#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<FreeLibrary_type> Detour_FreeLibrary;
|
||||
uMod_Detour_Entry<LoadLibraryA_type> Detour_LoadLibraryA;
|
||||
uMod_Detour_Entry<LoadLibraryW_type> Detour_LoadLibraryW;
|
||||
uMod_Detour_Entry<LoadLibraryExA_type> Detour_LoadLibraryExA;
|
||||
uMod_Detour_Entry<LoadLibraryExW_type> Detour_LoadLibraryExW;
|
||||
|
||||
private:
|
||||
int NumOfEntries;
|
||||
uMod_Detour_Entry_Base** Entries;
|
||||
};
|
||||
|
||||
extern uMod_Detour GlobalDetour;
|
||||
|
||||
#endif /* UMOD_DETOUR_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 T>
|
||||
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 <class T>
|
||||
uMod_Detour_Entry<T>::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 <class T>
|
||||
uMod_Detour_Entry<T>::~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 <class T>
|
||||
void uMod_Detour_Entry<T>::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<T>::TestLib( %s, %p ) set detour -> %s \n", lib_name, plib, FunctionName);
|
||||
|
||||
RefCounter = 1;
|
||||
PLibrary = plib;
|
||||
|
||||
IsDetoured = false;
|
||||
IsFailed = false;
|
||||
Detour();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void uMod_Detour_Entry<T>::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<T>::TestLib( %ls, %p ) set detour -> %s \n", lib_name, plib, FunctionName);
|
||||
|
||||
RefCounter = 1;
|
||||
PLibrary = plib;
|
||||
|
||||
IsDetoured = false;
|
||||
IsFailed = false;
|
||||
Detour();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void uMod_Detour_Entry<T>::FreeLib(HMODULE plib)
|
||||
{
|
||||
if (plib==NULL) return;
|
||||
if (plib==PLibrary) RefCounter--;
|
||||
if (RefCounter<=0) PLibrary = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void uMod_Detour_Entry<T>::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 <class T>
|
||||
void uMod_Detour_Entry<T>::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 <class T>
|
||||
bool uMod_Detour_Entry<T>::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 <class T>
|
||||
int uMod_Detour_Entry<T>::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 <class T>
|
||||
int uMod_Detour_Entry<T>::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_ */
|
||||
@@ -52,6 +52,8 @@ along with Universal Modding Engine. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include "uMod_TextureFunction.h"
|
||||
|
||||
#include "uMod_DetourEntry.h"
|
||||
#include "uMod_Detour.h"
|
||||
#include "uMod_DXMain_dll.h"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user