template<typename CallFunctionType,typename ClassFunctionType>class Thunk
{
//BYTE:unsigned char
//DWORD:unsigned long
BYTE*m_thunk=0;
public:
operator CallFunctionType()
{
return (CallFunctionType)m_thunk;
}
public:
Thunk(void*_this, ClassFunctionType callBack)
{
DWORD FuncAddr;
DWORD addr1, addr2;
GetMemberFuncAddr_VC6(FuncAddr, callBack);
ThunkTemplate(addr1, addr2, 0);
m_thunk = (BYTE *)VirtualAlloc(NULL, sizeof(BYTE[100]), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(m_thunk, (void*)addr1, addr2 - addr1);
ReplaceCodeBuf(m_thunk, addr2 - addr1, -1, (DWORD)((void*)_this));
ReplaceCodeBuf(m_thunk, addr2 - addr1, -2, FuncAddr);
}
~Thunk()
{
VirtualFree(m_thunk, sizeof(BYTE[100]), MEM_RELEASE);
}
template <class ToType, class FromType>void GetMemberFuncAddr_VC6(ToType& addr, FromType f)
{
union
{
FromType _f;
ToType _t;
}ut;
ut._f = f;
addr = ut._t;
}
void ThunkTemplate(DWORD& addr1, DWORD& addr2, int calltype = 0)
{
int flag = 0;
DWORD x1, x2;
if (flag)
{
__asm //__thiscall
{
thiscall_1: mov ecx, -1; //-1占位符,运行时将被替换为this指针.
mov eax, -2; //-2占位符,运行时将被替换为CTimer::CallBcak的地址.
jmp eax;
thiscall_2:;
}
__asm //__stdcall
{
stdcall_1: push dword ptr[esp]; //保存(复制)返回地址到当前栈中
mov dword ptr[esp + 4], -1; //将this指针送入栈中,即原来的返回地址处
mov eax, -2;
jmp eax; //跳转至目标消息处理函数(类成员函数)
stdcall_2:;
}
}
if (calltype == 0)//this_call
{
__asm
{
mov x1, offset thiscall_1; //取 Thunk代码段 的地址范围.
mov x2, offset thiscall_2;
}
}
else
{
__asm
{
mov x1, offset stdcall_1;
mov x2, offset stdcall_2;
}
}
addr1 = x1;
addr2 = x2;
}
void ReplaceCodeBuf(BYTE *code, int len, DWORD old, DWORD x)
{
int i = 0;
for (i = 0; i<len - 4; ++i)
{
if (*((DWORD *)&code[i]) == old)
{
*((DWORD *)&code[i]) = x;
return;
}
}
}
};
使用例子:
class CTimer
{
private:
int m_uElapse;
int m_handle;
typedef Thunk<TIMERPROC, void (CTimer::*)(HWND hwnd, UINT uMsg, unsigned int idEvent, DWORD dwTime)>TimerCallBackThunk;
TimerCallBackThunk*m_timerCallbackFun = 0;
public:
CTimer() :m_uElapse(20), m_handle(1), m_timerCallbackFun(new TimerCallBackThunk(this, &CTimer::TimerProc)){}
~CTimer(){ delete m_timerCallbackFun; }
void SetInterval(int uElapse)
{
m_uElapse = uElapse;
}
void Begin()
{
m_handle = SetTimer(NULL, 0, m_uElapse, *m_timerCallbackFun);
}
void End()
{
KillTimer(NULL, m_handle);
}
void TimerProc(HWND hwnd, UINT uMsg, unsigned int idEvent, DWORD dwTime)
{
printf("回调转换成功!当前时间计数:dwTime=%d\n",dwTime);
}
};
int main(int argc, char* argv[])
{
CTimer timer;
timer.SetInterval(400);
timer.Begin();
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}