起初在DECLARE_WND_CLASS宏中可以知道,窗口类的窗口过程是CWindowImplBaseT< TBase, TWinTraits >的静态成员函数StartWindowProc,
在StartWindowProc第一次被调用的时候,它把CWindowImplBaseT< TBase, TWinTraits >的非静态成员函数通过thunk机制设置为窗口过程。
template <class TBase, class TWinTraits>
LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_AtlWinModule.ExtractCreateWndData();
ATLASSERT(pThis != NULL);
if(!pThis)
{
return 0;
}
pThis->m_hWnd = hWnd;
// Initialize the thunk. This is allocated in CWindowImplBaseT::Create,
// so failure is unexpected here.
pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);// 初始化thunk
WNDPROC pProc = pThis->m_thunk.GetWNDPROC(); //
WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
#ifdef _DEBUG
// check if somebody has subclassed us already since we discard it
if(pOldProc != StartWindowProc)
ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded./n"));
#else
(pOldProc); // avoid unused warning
#endif
return pProc(hWnd, uMsg, wParam, lParam);
}
struct _stdcallthunk
{
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
BOOL Init(DWORD_PTR proc, void* pThis) /*pThis指向CWindowImplBaseT< TBase, TWinTraits > 的对象*/
{
m_mov = 0x042444C7; //C7 44 24 0C
m_this = PtrToUlong(pThis);
m_jmp = 0xe9;
m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk)));
// write block from data cache and
// flush from instruction cache
FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
return TRUE;
}
//some thunks will dynamically allocate the memory for the code
void* GetCodeAddress()
{
return this;
}
void* operator new(size_t)
{
return __AllocStdCallThunk();
}
void operator delete(void* pThunk)
{
__FreeStdCallThunk(pThunk);
}
};
class CDynamicStdCallThunk
{
public:
_stdcallthunk *pThunk;
...
};
typedef CDynamicStdCallThunk CStdCallThunk;
/////////////////////////////////////////////////////////////////////////////
// WindowProc thunks
class CWndProcThunk
{
public:
_AtlCreateWndData cd;
CStdCallThunk thunk;
BOOL Init(WNDPROC proc, void* pThis)
{
return thunk.Init((DWORD_PTR)proc, pThis);
}
WNDPROC GetWNDPROC()
{
return (WNDPROC)thunk.GetCodeAddress();
}
};