Thunk 封装 Windows Timer Api

      以前看过李维老师写的<inside vcl>,delphi就是通过这种技术实现对窗口函数封装的,当时水平菜没看明白。后来

自己在打算用c++来重写QQ ip时候发现无法继续写下去来,主要是回调和hookapi时候,不知道怎么解决这个用类

封装的问题。后来看雪论坛一高数指点要我用thunk解决。后来搜索了下thunk才知道就是当年vcl的那技术,只是我

不知道它叫这个名字。呵呵。今天来尝试下自己实现,参照了前辈(不知道名字)的结构和思路,做了个最简化的例子。

/*
描叙:Thunk技术学习
作者:debug

时间:2008/8/20

 

环境:VC8

*/
#include 
"stdafx.h"

#include 
<Windows.h>

#include 
<conio.h>

#pragma pack(push, 1)


//由于没有虚方法所以this地址就是m_mov成员的地址
class Thunk
{
    unsigned 
char    m_mov;         
    unsigned int    m_this;         
    unsigned int    m_xchg_push;      
    unsigned char   m_jmp;         
    unsigned int    m_relproc;      
public:
    typedef 
void (_stdcall Thunk::*TMFP)();

    
void start()
    {
        Init((TMFP)
&Thunk::TimerProc,this);
        ::SetTimer(
0,0,500,(TIMERPROC )this);//用构造的假数据欺骗回调函数
    }
    
void Init(TMFP method, const Thunk *pThis)
    {
        
//用union的特点巧取成员地址
        union {
            unsigned 
int func;
            TMFP method;
        } addr;

        addr.method 
= method;
        m_jmp       
= 0xE9;
        m_mov       
= 0xB8;
        m_this       
= (unsigned int)(void *) pThis;
        m_xchg_push    
= 0x50240487;
        m_relproc    
= addr.func - (unsigned int)(void *)(this + 1);
        
//this指针是Thunk类型的,所以this+1就
        
//对象地址+所有成员大小= 对象数据结束的地址
        
//e9进行跳转的距离 = 成员函数的地址-对象数据结束的地址
    }

    VOID CALLBACK TimerProc(
        HWND hwnd,         
// handle to window
        UINT uMsg,         // WM_TIMER message
        UINT_PTR idEvent,  // timer identifier
        DWORD dwTime       // current system time
        )
    {
        printf(
"test timer!\n");
    }

};

#pragma pack(pop)

int _tmain(int argc, _TCHAR* argv[])
{
    Thunk myThunk;
    MSG msg;
    myThunk.start();
    
while (GetMessage(&msg, NULL, 00)) {
        
if (kbhit()) {
            
break;
        }
        DispatchMessage(
&msg);
    }
    
return 0;
}

posted @ 2008-08-20 15:01  debugzhu  阅读(806)  评论(1编辑  收藏  举报