THUNK mechanism learning in ATL

zhaozj2021-02-17  78

ATL uses a series of classes to manage windows. In order to make the code as compact, ATL uses an interesting technique to implement the HWnd associated with the window message and the map responsible for the THIS pointer responsible for processing the message. The specific process is as follows:

The window process declared when the window registration is a static member function startWindowProc corresponding to the window class of this window. When the first message reaches this function:

Template

LResult Callback CWindowImplbaset :: StartWindowProc (HWND HWND, UINT UMSG, WPARAM WPARAM, LPARAM LPARAM)

{

CWindowImplbaset * PTHIS =

(CWindowImplbaset *) _ Module.extractCreateWnddata ();

Atlassert (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 _Debug

// 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);

}

It first acquires the THIS pointer of the window class corresponding to this window in the global variable _module, and then uses the M_Thunk to use the assembly instruction to transform the window process member function of this window class. M_thunk is an instance of CWndProCThunk, each having one of the window classes. It is defined as follows:

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 = (dword) 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 >> 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);

}

}

Its INIT () function completes the initialization of the WndPROCTHUNK structure. The WndProcThunk structure is defined for the X86 system as follows:

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

}

Structural members saved a set of assembly instructions. In the x86 system, this set of assembly instructions in the init () function is initialized to the following instructions:

Mov DWORD PTR [ESP 0x4], PTHIS

JMP (int) proc - ((int) this sizeof (_wndprocthun))

Its completion is that the pointer PTHIS with a window class is replaced by the window handle HWnd (ESP 0x4 is hwnd), then jumps to the incoming PROC function ((int) proc - ((int) THIS SIZEOF (_WndProctHunk)) is the distance between Proc and Thunk).

After calling the M_thunk.init () function, it is actually a transformed window process (m_thunk.thunk). This window process is a member function of the window class. Its first parameter definition is hwnd, but In fact, it is the THIS pointer of its class. Finally, use setWindowlong () with this new window process to replace the original window process (that is, StartWindowProc), all of the subsequent messages will be routed to the new window process.

转载请注明原文地址:https://www.9cbs.com/read-31504.html

New Post(0)