当前位置: 首页 > news >正文

WTL 之trunk技术学习

相比于MFC的消息机制,WTL/ATL的实现更加优雅。后者将win32 API与面向对象技术完美地结合起来,去掉了庞杂的MFC依赖,生成的软件体积更小,运行速度更快。在其中,如何将窗口函数转变为对窗口对象成员函数的调用,是WTL/ATL消息机制的核心。以下利用trunk技术模拟了这一过程,仅供参考:

#include <Windows.h>
#include <assert.h>
#include <tchar.h>
thread_local void* pWnd = nullptr;#pragma pack(push,1)
struct _StdCallThunk32//x86
{DWORD		m_mov;ULONG_PTR   m_this;BYTE		m_jmp;ULONG_PTR   m_relproc;void Init(ULONG_PTR wPtr, ULONG_PTR proc){m_mov = 0x042444C7;//mov dword ptr [esp+4], pThism_this = wPtr;m_jmp = 0xe9;//jmp pRelFuncm_relproc = proc;}
};struct _StdCallThunk64//x64
{unsigned char mov_rax_1[2];unsigned char object[sizeof(ULONG_PTR)];unsigned char mov_rax_to_rcx[3];unsigned char mov_rax_2[2];unsigned char procedure[sizeof(ULONG_PTR)];unsigned char jump_rax[3];void Init(ULONG_PTR wPtr, ULONG_PTR proc){mov_rax_1[0] = 0x48;//mov rax, pThismov_rax_1[1] = 0xb8;memcpy(object, &wPtr, sizeof(ULONG_PTR));mov_rax_to_rcx[0] = 0x48;//mov rcx,raxmov_rax_to_rcx[1] = 0x89;mov_rax_to_rcx[2] = 0xc1;mov_rax_2[0] = 0x48;//mov rax, pFuncmov_rax_2[1] = 0xb8;memcpy(procedure, &proc, sizeof(ULONG_PTR));jump_rax[0] = 0x48;//jmp raxjump_rax[1] = 0xff;jump_rax[2] = 0xe0;}
};#pragma pack(pop)#if defined(_WIN64)
typedef struct _StdCallThunk64 StdCallThunk;
#elif defined(_WIN32)
typedef struct _StdCallThunk32 StdCallThunk;
#endif
class Window
{
public:Window();~Window();public:BOOL Create();protected:LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam);protected:HWND          m_hWnd;StdCallThunk* m_pThunk;protected:static LRESULT CALLBACK TempWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};Window::Window():m_hWnd(NULL),m_pThunk(nullptr)
{}Window::~Window()
{if(m_pThunk != nullptr)VirtualFree(m_pThunk, sizeof(StdCallThunk), MEM_RELEASE);
}BOOL Window::Create()
{LPCTSTR lpszClassName = _T("ClassName");HINSTANCE hInstance = GetModuleHandle(NULL);WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };wcex.lpfnWndProc = TempWndProc;wcex.hInstance = hInstance;wcex.lpszClassName = lpszClassName;wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);ATOM regRes = RegisterClassEx(&wcex);pWnd = this;m_pThunk = (StdCallThunk*)VirtualAlloc(NULL, sizeof(StdCallThunk), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);m_hWnd = CreateWindow(lpszClassName, NULL, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);if (m_hWnd == NULL){return FALSE;}ShowWindow(m_hWnd, SW_SHOW);UpdateWindow(m_hWnd);return TRUE;
}LRESULT Window::WndProc(UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_LBUTTONUP:MessageBox(m_hWnd, _T("LButtonUp"), _T("Message"), MB_OK | MB_ICONINFORMATION);break;case WM_RBUTTONUP:MessageBox(m_hWnd, _T("RButtonUp"), _T("Message"), MB_OK | MB_ICONINFORMATION);break;case WM_DESTROY:PostQuitMessage(0);break;default:break;}return DefWindowProc(m_hWnd, message, wParam, lParam);
}LRESULT CALLBACK Window::TempWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{Window* pThis = (Window*)pWnd;assert(pThis != nullptr);WNDPROC pWndProc = (WNDPROC)pThis->m_pThunk;
#if defined(_WIN64)ULONG_PTR rel = (LONG_PTR)&Window::StaticWndProc;auto ret = SetWindowLongPtr(hWnd, GWLP_WNDPROC, (ULONG_PTR)pWndProc);
#elif defined(_WIN32)ULONG_PTR rel = (DWORD)&Window::StaticWndProc - ((DWORD)pThis->m_pThunk + sizeof(StdCallThunk));auto ret = SetWindowLong(hWnd, GWLP_WNDPROC, (ULONG)pWndProc);
#endifpThis->m_pThunk->Init((ULONG_PTR)pThis, rel);//FlushInstructionCache(GetCurrentProcess(), pThis->m_pThunk, sizeof(StdCallThunk));pThis->m_hWnd = hWnd;return pWndProc(hWnd, message, wParam, lParam);
}LRESULT CALLBACK Window::StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{return ((Window*)hWnd)->WndProc(message, wParam, lParam);
}int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{Window wnd;wnd.Create();MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return (int)msg.wParam;
}

http://www.dtcms.com/a/263195.html

相关文章:

  • Compose入门1 - 高仿抖音 上下滑动播放视频
  • 深入解析JADX:专业Android逆向工程的利器
  • Oracle 进阶语法实战:从多维分析到数据清洗的深度应用​(第四课)
  • 大模型在多发性硬化预测及治疗方案制定中的应用研究
  • Stable Diffusion 项目实战落地:从0到1 掌握ControlNet 第三篇: 打造光影字形的创意秘技-文字与自然共舞
  • Java:Json反序列化自定义类
  • 计算机网络(一)层
  • 【基于Nest.js+React的全栈项目-00篇】开篇目录:25年新开系列文章,望多多支持~
  • 06_Americanas精益管理项目_数据分析
  • 卡片跳转到应用页面(router事件)
  • 阿里云-Docker的使用
  • 手动续期证书后自动上传到阿里云
  • 9.6 视觉专家模块+1536超清解析!智谱CogVLM-9B多模态模型中文场景实战评测,性能炸裂吊打LLaVA
  • 笨方法学python -练习6
  • MySQL 慢查询日志详解
  • Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
  • 第81题:搜索旋转排序数组Ⅱ
  • PHP:历经岁月沉淀的Web开发利器
  • 如何查看服务器的运行日志?
  • mysql 分组后时间没有按照最新时间倒序
  • PHP安装使用教程
  • 气候智能体:AI如何重构人类应对气候危机的决策体系?
  • FastAPI 学习(二)
  • 三态门Multisim电路仿真——硬件工程师笔记
  • 重构老项目不再“踩雷”:飞算JavaAI的本地化智能合并实战
  • react setstate
  • 【Java面试】10GB,1GB内存,如何排序?
  • 筑牢医疗AI安全防线:四重防护体系全解析
  • kubernetes(k8s)控制器与案例详解
  • 华为云Flexus+DeepSeek征文|​​华为云ModelArts Studio大模型 + WPS:AI智能PPT生成解决方案​