MFC:thunk技术实现窗口类的封装[图](2)
类定义:
class CMyWnd
{
public:
BOOL Create(...);
LRESULT WINAPI WindowProc(UINT,WPARAM,LPARAM);
static LRESULT WINAPI InitProc(HWND,UINT,WPARAM,LPARAM);
static LRESULT WINAPI stdProc(HWND,UINT,WPARAM,LPARAM);
WNDPROC CreateThunk();
WNDPROC GetThunk(){return m_thunk}
...
private:
WNDPROC m_thunk
}
在创建窗口的时候把窗口过程设定为this->m_thunk,m_thunk的类型是WNDPROC,因此是完全合法的,当然这个m_thunk还没有初始化,在创建窗口前必须初始化:
WNDPROC CMyWnd::CreateThunk()
{
Thunk* thunk = new Thunk;
///////////////////////////////////////////////
//
//系统调用m_thunk时的堆栈:
//ret HWND MSG WPARAM LPARAM
//-------------------------------------------
//栈顶 栈底
///////////////////////////////////////////////
//call Offset
//调用code[0],call执行时会把下一条指令压栈,即把Proc压栈
thunk->Call = 0xE8; // call [rel]32
thunk->Offset = (size_t)&(((Thunk*)0)->Code)-(size_t)&(((Thunk*)0)->Proc); // 偏移量,跳过Proc到Code[0]
thunk->Proc = CMyWnd::stdProc; //静态窗口过程
//pop ecx,Proc已压栈,弹出Proc到ecx
thunk->Code[0] = 0x59; //pop ecx
//mov dword ptr [esp+0x4],this
//Proc已弹出,栈顶是返回地址,紧接着就是HWND了。
//[esp+0x4]就是HWND
thunk->Code[1] = 0xC7; // mov
thunk->Code[2] = 0x44; // dword ptr
thunk->Code[3] = 0x24; // disp8[esp]
thunk->Code[4] = 0x04; // +4
thunk->Window = this;
//偷梁换柱成功!跳转到Proc
//jmp [ecx]
thunk->Jmp = 0xFF; // jmp [r/m]32
thunk->ECX = 0x21; // [ecx]
m_thunk = (WNDPROC)thunk;
return m_thunk;
}
- 上一篇:在一个程序中打开其它应用程序
- 下一篇:MFC的子类化技术