2.内核回调机制

有谁调用了窗口过程?

  1. GetMessage()在处理SentMessagesListHead中消息时
  2. DispatchMessage(&msg)在处理其他队列中的消息时
  3. CreateWindow() 0环的一些代码也会调用窗口过程,但它没有发消息给队列而是直接调用窗口过程(KeUserModeCallback)

NtUserCreateWindowEx()这样设计是因为,如果你程序需要在窗口创建就做一些事情但窗口没创建出来它接收不了消息,它刚好就能帮你解决,WM_CREATE就是它在你创建窗口出来之前就会被调用

KeUserModeCallback的执行流程

  1. 从0环调用3环函数的几种方式:
    APC、异常、内核回调

  2. 凡是有窗口的程序就有可能0环直接调用3环的程序。回调机制中0环调用3环的的代码是函数:KeUserModeCallback

  3. 回到3环的落脚点:
    APC:ntdll!KiUserApcDispatcher
    异常:ntdll!KiUserExceptionDispatcher

  4. 内核回调在3环的落脚点:
    KeUserModeCallback()

所有的消息机制都是通过这个函数回3环

NTSTATUS KeUserModeCallback (
      IN ULONG ApiNumber,     //索引
      IN PVOID   InputBuffer, //当前窗口过程 函数 参数 等等
      IN ULONG InputLength,   //InputBuffer的大小
      OUT PVOID *OutputBuffer,
      IN PULONG OutputLength  
      //后面两个参数似乎并没有被使用,只要传入有效的值就可以了
      );

ApiNumber的索引:
PEB
+0x2C   KernelCallbackTable 内核回调函数地址表
找到3环KernelCallbackTable表,如果你填的索引为0就取这张表的第1个函数,1就取第2个函数,以此类推...

KernelCallbackTable 里面包含了一堆函数的地址,这堆函数由user32.dll提供

fs[0]->TEB-> PEB(+0x30)->KernelCallbackTable(0x2c)

2.内核回调机制_第1张图片
这里面的函数再负责调用我们的窗口过程函数,窗口过程函数已经被压入3环的堆栈中。

LPARAM lParam
WPARAM wParam
UINT mge
HWND hWnd
lpWindowProc()     <-InputBuffer

你可能感兴趣的:(消息机制)