ATL中的Thunk機制學習 (轉)
ATL利用一系列的類來管理視窗。為了使程式碼儘量緊湊而高效,ATL使用了一種有趣的技術來實現與視窗訊息相關聯的HWND和負責處理訊息的的this指標之間的對映。具體過程如下:
:namespace prefix = o ns = "urn:schemas--com::office" />
在視窗註冊時宣告的視窗過程為此視窗對應的視窗類的靜態成員StartWindowProc,當第一條訊息到達此函式時,其處理如下:
template
LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowImplBaseT< TBase, TWinTraits >* pThis =
(CWindowImplBaseT< TBase, TWinTraits >*)_Module.ExtractCreateWndData();
SERT(pThis != NULL);
pThis->m_hWnd = hWnd;
pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
#ifdef _DE
// check if somebody has subclassed us already since we discard it
if(pOldProc != StartWindowProc)
ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.n"));
#else
pOldProc; // avoid unused warning
#endif
return pProc(hWnd, uMsg, wParam, lParam);
}
它先由全域性變數_Module中取得此視窗對應的視窗類的this指標,然後透過m_thunk運用指令改造此視窗類的視窗過程成員函式。m_thunk是CWndProcThunk的例項,每個視窗類各有一個。它的定義如下:
class CWndProcThunk
{
public:
union
{
_AtlCreateWndData cd;
_WndProcThunk thunk;
};
void Init(WNDPROC proc, void* pThis)
{
#if defined (_M_IX86)
thunk.m_mov = 0x042444C7; //C7 44 24 0C
thunk.m_this = (D)pThis;
thunk.m_jmp = 0xe9;
thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
#elif defined (_M_ALPHA)
thunk.ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15);
thunk.ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15);
thunk.lda_at = 0x239c0000 | LOWORD(proc);
thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
thunk.jmp = 0x6bfc0000;
#endif
// write block from data cache and
// flush from instruction cache
FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
}
};
其Init()函式完成對WndProcThunk結構的初始化工作。WndProcThunk結構針對X86體系的定義如下:
struct _WndProcThunk
{
DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
DWORD m_this; //
BYTE m_jmp; // jmp WndProc
DWORD m_relproc; // relative jmp
};
結構成員中儲存的是一組彙編指令。在X86體系下,在Init()函式中這組彙編指令被初始化為下面的指令:
mov dword ptr [esp+0x4], pThis
jmp (int)proc - ((int)this+sizeof(_WndProcThunk))
它完成的功能是,用視窗類的指標pThis代替視窗控制程式碼hWnd(esp+0x4中放的就是hWnd),然後跳轉到傳入的proc函式處((int)proc - ((int)this+sizeof(_WndProcThunk))是proc與thunk之間的距離)。
在完m_thunk.Init()函式之後,實際上就得到了經過改造的視窗過程(m_thunk.thunk),此視窗過程是視窗類的一個成員函式,它的第一個引數定義雖然是HWND,但實際上是它的類的this指標。最後使用SetWindowLong()用這個新的視窗過程替換掉原有的視窗過程(也就是StartWindowProc),以後的所有訊息都會被給新的視窗過程。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-982219/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ATL Thunk機制深入分析
- 《深入解析ATL》學習手札 -- 第一天 (ATL #1) (轉)
- 深度學習中的注意力機制(Attention Model)深度學習
- java反射機制的學習心得Java反射
- Qt 事件機制 學習QT事件
- 透過原始碼學習TComponent類的機制(1) (轉)原始碼
- Redis學習之管道機制Redis
- 跟著GPT學習Java執行緒中斷機制GPTJava執行緒
- 學習筆記(2)IPC機制筆記
- 淘寶 rem 機制入門學習REM
- 學習資料庫索引機制資料庫索引
- attention注意力機制學習
- MFC學習(四) 訊息機制
- Binder學習(二)Binder機制解析
- Java 反射機制學習資料Java反射
- 對epoll機制的學習理解v1
- 我對C++中THUNK一種實現技術的分析 (轉)C++
- React 原始碼學習(五):事件機制React原始碼事件
- JVM學習(三)——類載入機制JVM
- JVM學習(二)——GC垃圾回收機制JVMGC
- 07.初步學習redis哨兵機制Redis
- MySQL 學習筆記(二)MVCC 機制MySql筆記MVC
- OS學習筆記四:同步機制筆記
- C#反射機制學習總結C#反射
- IOS學習之NSNotificationCenter訊息機制iOS
- 計算機中進位制轉換計算機
- 不使用ATL嚮導,建立一個簡單的ATL對話方塊程式. (轉)
- 【讀書筆記】Android的Ashmem機制學習筆記Android
- object-c 記憶體管理機制的學習Object記憶體
- JVM學習-虛擬機器類載入機制JVM虛擬機
- 從各種注意力機制窺探深度學習在NLP中的神威深度學習
- Seq2Seq那些事:詳解深度學習中的“注意力機制”深度學習
- JVM學習筆記——類載入機制JVM筆記
- 深度學習中的序列模型演變及學習筆記(含RNN/LSTM/GRU/Seq2Seq/Attention機制)深度學習模型筆記RNN
- ICML 2024 | 揭示非線形Transformer在上下文學習中學習和泛化的機制ORM
- 遊戲中的牛頓力學,簡析遊戲物理機制遊戲
- 淺談深度學習中的機率深度學習
- 物聯網學習教程—多型的實現機制多型