日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

消息机制学习笔记(四)—— 内核回调机制

發(fā)布時(shí)間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 消息机制学习笔记(四)—— 内核回调机制 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

消息機(jī)制學(xué)習(xí)筆記(四)—— 內(nèi)核回調(diào)機(jī)制

    • 要點(diǎn)回顧
    • 內(nèi)核調(diào)用
      • 實(shí)驗(yàn)1:理解內(nèi)核調(diào)用
        • 第一步:編譯并運(yùn)行以下代碼
        • 第二步:修改窗口過(guò)程函數(shù),重新運(yùn)行
    • KeUserModeCallback
      • 實(shí)驗(yàn)2:在OD中查看回調(diào)函數(shù)地址表
        • 第一步:加載程序
        • 第二步:在內(nèi)存中查看TEB
        • 第三步:查看PEB數(shù)據(jù)
        • 第四步:查看回調(diào)地址表
    • 總結(jié)

要點(diǎn)回顧

1)GetMessage不僅能夠取出消息,還能處理SentMessagesListHead隊(duì)列中的消息
2)DispatchMessage用于處理其它隊(duì)列中的消息。

內(nèi)核調(diào)用

描述:窗口過(guò)程函數(shù)除了會(huì)在消息循環(huán)中被調(diào)用,一些0環(huán)的代碼也可以直接發(fā)起調(diào)用。

例如:窗口初始化時(shí)、窗口創(chuàng)建時(shí)、窗口顯示時(shí)。

目的:使窗口在被初始化、被創(chuàng)建、被顯示時(shí),用戶能夠有機(jī)會(huì)做一些事情。

實(shí)驗(yàn)1:理解內(nèi)核調(diào)用

第一步:編譯并運(yùn)行以下代碼

注意:運(yùn)行前在while(GetMessage(&msg, NULL, 0, 0))這行設(shè)置斷點(diǎn)。

#include <stdio.h> #include <windows.h>#define DPRINTF_BUF_SZ 1024void OutputDebugStringf(char *fmt, ...) { #ifdef _DEBUGva_list args;char buf[DPRINTF_BUF_SZ];va_start(args, fmt);vsprintf(buf, fmt, args);OutputDebugString(buf); #endif }LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){switch(uMsg){case WM_DESTROY:{ExitProcess(0);return 0;}}OutputDebugStringf("消息類型:%x \n", uMsg);return DefWindowProc(hwnd, uMsg, wParam, lParam); }int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd ){//窗口的類名TCHAR className[] = "My First Window";//創(chuàng)建一個(gè)自己的窗口WNDCLASS wndclass = {0};wndclass.hbrBackground = (HBRUSH)COLOR_MENU;wndclass.lpfnWndProc = WindowProc;wndclass.lpszClassName = className;wndclass.hInstance = hInstance;//注冊(cè)RegisterClass(&wndclass);//創(chuàng)建窗口HWND hwnd = CreateWindow(className,TEXT("測(cè)試窗口"),WS_OVERLAPPEDWINDOW,10,10,600,300,NULL,NULL,hInstance,NULL);if(hwnd == NULL)return 0;//顯示窗口ShowWindow(hwnd, SW_SHOW);//消息循環(huán)MSG msg;while(GetMessage(&msg, NULL, 0, 0)){//TranslateMessage(&msg);DispatchMessage(&msg);}return 0; }

運(yùn)行結(jié)果

第二步:修改窗口過(guò)程函數(shù),重新運(yùn)行

注意:仍然在while(GetMessage(&msg, NULL, 0, 0))這行設(shè)置斷點(diǎn)。

新窗口過(guò)程函數(shù)

LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){switch(uMsg){case WM_CREATE:{MessageBoxA(NULL, "窗口被創(chuàng)建了", "CREATE", MB_OK);return 0;}case WM_DESTROY:{ExitProcess(0);return 0;}}OutputDebugStringf("消息類型:%x \n", uMsg);return DefWindowProc(hwnd, uMsg, wParam, lParam); }

運(yùn)行結(jié)果

不難發(fā)現(xiàn),程序并未進(jìn)入消息循環(huán),卻調(diào)用了窗口過(guò)程函數(shù),輸出了消息與彈窗,說(shuō)明消息不是只有當(dāng)調(diào)用GetMessage與DispatchMessage時(shí)才處理。

KeUserModeCallback

描述
1)從0環(huán)調(diào)用3環(huán)函數(shù)的幾種方式

  • APC
  • 異常
  • 內(nèi)核回調(diào)

APC異常回三環(huán)的落腳點(diǎn)比較單一,而消息機(jī)制需要處理的情況較多,不能使用同一個(gè)邏輯進(jìn)行處理,因此消息機(jī)制使用內(nèi)核回調(diào)調(diào)用三環(huán)函數(shù)。

2)回到3環(huán)的落腳點(diǎn)

  • APC:ntdll!KiUserApcDispatcher
  • 異常:ntdll!KiUserExceptionDispatcher

3)內(nèi)核回調(diào)在3環(huán)的落腳點(diǎn):KeUserModeCallback

PEB+0x2C指向回調(diào)函數(shù)地址表。

4)凡是有窗口的程序就有可能0環(huán)直接調(diào)用3環(huán)的程序。


聲明

NTSTATUS NTAPI KeUserModeCallback(IN ULONG FunctionID, //索引,指向三環(huán)落腳點(diǎn)IN PVOID InputBuffer, //包含窗口回調(diào)函數(shù)與相關(guān)重要信息IN ULONG InputLength,OUT PVOID *OutputBuffer,OUT PULONG OutputLength );

FunctionID索引列表

#define USER32_CALLBACK_WINDOWPROC (0) #define USER32_CALLBACK_SENDASYNCPROC (1) #define USER32_CALLBACK_LOADSYSMENUTEMPLATE (2) #define USER32_CALLBACK_LOADDEFAULTCURSORS (3) #define USER32_CALLBACK_HOOKPROC (4) #define USER32_CALLBACK_EVENTPROC (5) #define USER32_CALLBACK_LOADMENU (6) #define USER32_CALLBACK_CLIENTTHREADSTARTUP (7) #define USER32_CALLBACK_MAXIMUM (7)

實(shí)驗(yàn)2:在OD中查看回調(diào)函數(shù)地址表

第一步:加載程序

第二步:在內(nèi)存中查看TEB


第三步:查看PEB數(shù)據(jù)

PEB位于TIB+0x30位置

第四步:查看回調(diào)地址表

回調(diào)地址表位于PEB+0x2C位置

總結(jié)

  • 不是所有消息都是在進(jìn)入消息循環(huán)后由GetMessageDispatchMessage進(jìn)行處理的,部分內(nèi)核代碼也能夠調(diào)用窗口處理函數(shù)。
  • 內(nèi)核代碼通過(guò)KeUserModeCallback調(diào)用窗口處理函數(shù),由第一個(gè)參數(shù)FunctionID決定回到三環(huán)時(shí)的落腳點(diǎn)。
  • FunctionID的值為回調(diào)地址表的索引,回調(diào)地址表位于PEB+0x2C位置,每個(gè)值為一個(gè)函數(shù)地址。
  • 總結(jié)

    以上是生活随笔為你收集整理的消息机制学习笔记(四)—— 内核回调机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。