ATL thunk机制

来源:互联网 发布:布莱克书店知乎 编辑:程序博客网 时间:2024/05/17 08:11

起初在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();
  }
};

 

 

 

原创粉丝点击