Thunk 技术的一个改进
2008-03-27 21:40:28 来源:WEB开发网至于替换占位数的功能是很简单的,直接替换就好。
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 ;
}
}
} DWORD addr1,addr2;
ThunkTemplate(addr1,addr2);
memset(m_thunk,0,100);//m_thunk是一个数组: char m_thunk[100];
memcpy(m_thunk,(void*)addr1,addr2-addr1);//将代码拷贝到m_thunk中。
ReplaceCodeBuf(m_thunk,addr2-addr1,-1,(DWORD)((void*)this));//将m_thunk中的-1替换为this指针的值。
原理部分到此为止。下面举一个完整的,有实际意义的例子。在windows中,回调函数的使用是很常见的。比如窗口过程,又比如定时器回调函数。这些函数,你写好代码,但是却从不直接调用。相反,你把函数地址传递给系统,当系统检测到某些事件发生的时候,系统来调用这些函数。这样当然很好,不过如果你想做一个封装,将所有相关部分写成一个类,那问题就来了。
问题是,这些回调函数的形式事先已经定义好了,你无法让一个类的成员函数成为一个回调函数,因为类型不可能匹配。这不能怪微软,微软不可能将回调函数定义为一个类成员函数(该定义为什么类?),而只能将回调函数定义为一个全局的函数。并且微软其实很多时候也提供了补救措施,在回调函数中增加了一个void *的参数。这个参数一般都用来传递类的this指针。这样一来,可以这样解决:给系统提供一个全局函数作为回调函数,在该函数中通过额外的那个void *参数访问到类的对象,从而直接调用到类成员函数。如此,你的封装一样可以完成,不过多了一次函数调用而已。
更多精彩
赞助商链接