65,210
社区成员
发帖
与我相关
我的任务
分享// newThunk.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
//////////////////////////////////////////////////////////////////////////
//取类成员函数的地址.vc6版本.
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
{
public:
CTimer();
void set(int uElapse);
void begin();
void end();
void /*__stdcall*/ CallBcak(HWND hwnd, UINT uMsg, unsigned int idEvent, DWORD dwTime);
private:
int m_uElapse;
int m_TimerID;
BYTE m_thunk[100];
};
CTimer::CTimer()
{
m_uElapse = 20;
m_TimerID = 30;
DWORD FuncAddr;
GetMemberFuncAddr_VC6(FuncAddr,&CTimer::CallBcak);
DWORD addr1,addr2;
ThunkTemplate(addr1,addr2,0);
memset(m_thunk,0,100);
memcpy(m_thunk,(void*)addr1,addr2-addr1);
ReplaceCodeBuf(m_thunk,addr2-addr1,-1,(DWORD)((void*)this));
ReplaceCodeBuf(m_thunk,addr2-addr1,-2,FuncAddr);
}
void CTimer::set(int uElapse)
{
m_uElapse = uElapse;
}
void CTimer::begin()
{
m_TimerID = SetTimer(NULL,0,m_uElapse,(TIMERPROC)&m_thunk[0]);
}
void CTimer::end()
{
KillTimer(NULL,m_TimerID);
}
void CTimer::CallBcak(HWND hwnd, UINT uMsg, unsigned int idEvent, DWORD dwTime)
{
printf("\n CTimer::CallBcak,ID=%d, Elapse=%d\n",m_TimerID,m_uElapse);
printf("hwnd=%x, nMsg=%d, idEvent=%d, dwTime=%d\n",hwnd, uMsg,idEvent,dwTime);
}
int main(int argc, char* argv[])
{
CTimer xx;
xx.set(400);
xx.begin();
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}