Thank you for the information!
Still I'll go with detours. I already wrote my virtual-method detouring macros.
#ifndef VIRTUALMEMBER_H
#define VIRTUALMEMBER_H
#include "detours.h"
//############## Converts a virtual member-function's pointer to a member-function pointer. Thank you Jinto for helping me out with this @Jinto, aVoN
template<typename T>
union VirtualPointer_t{
size_t* m_pointer;
T m_function;
};
//############## Sets up entries in your Detour-Class @aVoN
#define VDETOUR_SETUP(_type_,_class_,_method_,...)\
typedef _type_ (T##_method_)(##__VA_ARGS__);\
typedef _type_ (_class_::*T__##_method_)(##__VA_ARGS__);\
T##_method_ _method_;\
static T__##_method_ __##_method_;
//############## Creates your hook @aVoN
#define VDETOUR_HOOK(_type_,_class_,_method_,...)\
_class_::T__##_method_ _class_::__##_method_ = NULL;\
_type_ _class_::_method_(##__VA_ARGS__)
//############## Starts detouring your method, giving the object as argument @aVoN
#define VDETOUR_FROM_OBJECT(_object_,_vtableindex_,_class_,_method_)\
{\
size_t** vtable = *reinterpret_cast<size_t***>(_object_);\
VirtualPointer_t<_class_::T__##_method_> wrapper;\
wrapper.m_pointer = vtable[_vtableindex_];\
_class_::__##_method_ = reinterpret_cast<_class_::T__##_method_>(wrapper.m_function);\
}\
DetourAttach(&(PVOID&) _class_::__##_method_,(PVOID)(&(PVOID&) _class_::_method_));
//############## Same as above but for passing classes (Creates momentary overhead - but frees memory again - Does not work if no non-generic constructor is available) @aVoN
#define VDETOUR_FROM_CLASS(_target_class_,_vtableindex_,_class_,_method_)\
{\
_target_class_* object = new _target_class_;\
VDETOUR_FROM_OBJECT(object,_vtableindex_,_class_,_method_);\
delete object;\
}
//############## Removes/Detaches a hook @aVoN
#define VDETOUR_REMOVE(_class_,_method_)\
DetourDetach(&(PVOID&) _class_::__##_method_,(PVOID)(&(PVOID&) _class_::_method_));
/*
############## Example usage!
//Let's assume you want to detour the virtual method "int Read(bool b)" from IFileSystem.
class IFileSystem{
public:
virtual int Read(bool b); //VTable index: 0
virtual void Write(char c); //VTable index: 1
bool Delete(int d); //This has NO VTable index
virtual void Read(char e); //VTable index: 2
//Overloaded functions are getting added in opposite order!
virtual Size(int a);//VTable index: 5!!!!!
virtual Size(bool b);//VTable index: 4!!!!!
virtual Size(char c);//VTable index: 3!!!!!
//VTable indexing is straight forward ... (Just with multiple-inherited classes, it's not that easy though)
};
//Then this class can (but hasn't be necessarily) initialized (You see why in code later - Two ways of detouring using VDETOUR_FROM_OBJECT or VDETOUR_FROM_CLASS)
IFileSystem* FILESYSTEM = new IFileSystem;
//To prepare detouring, create a class like this
class CDetour{
public:
VDETOUR_SETUP(int,CDetour,Read,bool b);
//The above macro does simply this
// int Read(bool b); //This is your hook
// static int (CDetour::*__Read)(bool b);
}
//Then define your actual hook "int CDetour::Read(bool b)" with this
VDETOUR_HOOK(int,CDetour,Read,bool b){ //This defines CDetour::Read(bool b);
(this->*__Read)(b); //With this, you can call the original method again
}
//Later in code: Start detouring. Make sure, you use the correct VTable index (here, it is 0)
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
//Now if your class already has an initialized object or has no generic constructor, use the already initialized object
VDETOUR_FROM_OBJECT(FILESYSTEM,0,CDetour,Read);
//Or if you want to, simply supply the classname with this method below (but be warned: This macro initializes the class and creates an object for the time it detours. It will destroy the object later)
VDETOUR_FROM_CLASS(IFileSystem,0,CDetour,Read);
DetourTransactionCommit();
//Unloading hooks
//Just run
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
VDETOUR_REMOVE(CDetour,Read);
DetourTransactionCommit();
*/
#endif //VIRTUALMEMBER_H