网站导航免费论文 原创论文 论文搜索 原创论文 网学软件 学术大家 资料中心 会员中心 问题解答 原创论文 论文素材 设计下载 最新论文 下载排行 论文上传 在线投稿 联系我们
返回网学首页
网学联系
最新论文 推荐专题 热门论文 素材专题
当前位置: 网学 > 编程文档 > VC++ > 正文
thunk技术实现窗口类的封装
来源:Http://myeducs.cn 联系QQ:点击这里给我发消息 作者: 用户投稿 来源: 网络 发布时间: 12/10/15
下载{$ArticleTitle}原创论文样式
替换掉就行了。这时thunk技术就有用武之地了,我们先定义一个结构:

#pragma pack(push,1) //该结构必须以字节对齐
struct Thunk {
BYTE    Call;
int    Offset;
WNDPROC   Proc;
BYTE    Code;
CMyWnd*   Window;
BYTE    Jmp;
BYTE    ECX;
};
#pragma pack(pop)

类定义:
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 = 0xC7;  // mov
thunk->Code = 0x44;  // dword ptr
thunk->Code = 0x24;  // disp8[esp]
thunk->Code = 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;
}

这样m_thunk虽然是一个结构,但其数据是一段可执行的代码,而其类型又是WNDPROC,系统就会忠实地按窗口过程规则调用这段代码,m_thunk就把Window字段里记录的this指针替换掉堆栈中的hWnd参数,然后跳转到静态的stdProc:

//本回调函数的HWND调用之前已由m_thunk替换为对象指针
LRESULT WINAPI CMyWnd::stdProc(HWND hWnd,UINT uMsg,UINT wParam,LONG lParam)
{
CMyWnd* w = (CMyWnd*)hWnd;

  return w->WindowProc(uMsg,wParam,lParam);
}

这样就把窗口过程转向到了类成员函数WindowProc,当然这样还有一个问题,就是窗口句柄hWnd还没来得及记录,因此一开始的窗口过程应该先定位

网学推荐

免费论文

原创论文

浏览:
设为首页 | 加入收藏 | 论文首页 | 论文专题 | 设计下载 | 网学软件 | 论文模板 | 论文资源 | 程序设计 | 关于网学 | 站内搜索 | 网学留言 | 友情链接 | 资料中心
版权所有 QQ:3710167 邮箱:3710167@qq.com 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2015 myeducs.Cn www.myeducs.Cn All Rights Reserved
湘ICP备09003080号