|
|
(莫名春秋发表)
在看vc知识库38期的com部分《atl布幔之下的秘密》一文中,开始的时候对thunk非常的不理解,在跟一位学长探讨之后,呵呵,主要是学到了vc下如何得到察看程序的汇编代码。终于明白了是怎么一回事。
开始对mov dword ptr [esp+0x4], pThis中[esp+0x4]指向WindowProc函数的hwnd参数非常的不理解,似乎按照函数的入栈规则,[esp+0x4]是不可能指向WindowProc函数的hwnd参数。懂得察看汇编代码后,发现在窗口建立过程只运行一次的StartWndProc中对thunk初始化(init函数)后,得到了WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);(注意这里typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);)
改变窗口过程为pProc后,然后就是调用pProc,首先将4个参数压入栈中,这段汇编代码如下:
004014FF mov esi,esp
00401501 mov ecx,dword ptr [ebp+14h]
00401504 push ecx
00401505 mov edx,dword ptr [ebp+10h]
00401508 push edx
00401509 mov eax,dword ptr [ebp+0Ch]
0040150C push eax
0040150D mov ecx,dword ptr [ebp+8]
00401510 push ecx
00401511 call dword ptr [ebp-8] ;调用thunk代码
前面push就是把参数入栈,call调用要保存返回地址,所以相当push一次。所以这个时候[esp+4]刚好就是hwnd的堆栈地址。然后通过call调用thunk代码。
Thunk代码如下:
0012FED0 mov dword ptr [esp+4],12FEC8h
0012FED8 jmp @ILT+95(ZWindow::WindowProc) (00401064)
下面就是进入了windowProc的处理过程之中。
所以这个thunk就是在 windowProc执行之前,将hwnd指向正确的地方,因为每一个window都包含一个WndProcThunk变量,所以可以保持唯一性。WNDPROC的声明形式也能保证参数的准确入栈操作。
|
|