原文地址:http://www.zdexe.com/program/201004/576.htmlhtml
比較專業的對鉤子的技術性理解函數
鉤子(Hook),是Windows消息處理機制的一個平臺,應用程序能夠在上面設置子程以監視指定窗口的某種消息,並且所監視的窗口能夠是其餘進程所創 建的。當消息到達後,在目標窗口處理函數以前處理它。鉤子機制容許應用程序截獲處理window消息或特定事件。spa
Windows系統是創建在事件驅動的機制上的,說穿了就是整個系統都是經過消息的傳遞來實現的。而鉤子是Windows系統中很是重要的系統接 口,用它能夠截獲並處理送給其餘應用程序的消息,來完成普通應用程序難以實現的功能。鉤子能夠監視系統或進程中的各類事件消息,截獲發往目標窗口的消息並 進行處理。這樣,咱們就能夠在系統中安裝自定義的鉤子,監視系統中特定事件的發生,完成特定的功能,好比截獲鍵盤、鼠標的輸入,屏幕取詞,日誌監視等等。 可見,利用鉤子能夠實現許多特殊而有用的功能。線程
鉤子其實是一個處理消息的程序段,經過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得 到控制權。這時鉤子函數便可以加工處理(改變)該消息,也能夠不做處理而繼續傳遞該消息,還能夠強制結束消息的傳遞。指針
一個Hook都有一個與之相關聯的指針列表,稱之爲鉤子鏈表,由系統來維護。這個列表的指針指向指定的,應用程序定義的,被Hook子程調用的回調函 數,也就是該鉤子的各個處理子程。當與指定的Hook類型關聯的消息發生時,系統就把這個消息傳遞到Hook子程。一些Hook子程能夠只監視消息,或者 修改消息,或者中止消息的前進,避免這些消息傳遞到下一個Hook子程或者目的窗口。最近安裝的鉤子放在鏈的開始,而最先安裝的鉤子放在最後,也就是後加 入的先得到控制權。日誌
Windows 並不要求鉤子子程的卸載順序必定得和安裝順序相反。每當有一個鉤子被卸載,Windows 便釋放其佔用的內存,並更新整個Hook鏈表。若是程序安裝了鉤子,可是在還沒有卸載鉤子以前就結束了,那麼系統會自動爲它作卸載鉤子的操做。htm
大多數人或者網上文章認爲全局鉤子都要依賴於一個DLL才能正常工做的,經常會看到不少人在論壇上長期爭論一個話題:「全局鉤子必定要在DLL裏面嗎?」。實際上這裏有一個概念的問題,究竟上面提到的全局鉤子是指什麼。經過對上面各類鉤子的做用域的理解就會發現這個問題的答案。進程
上面一共提到了15種鉤子,他們的做用域請看下錶:事件
Hook內存 |
Scope |
WH_CALLWNDPROC |
Thread or global |
WH_CALLWNDPROCRET |
Thread or global |
WH_CBT |
Thread or global |
WH_DEBUG |
Thread or global |
WH_FOREGROUNDIDLE |
Thread or global |
WH_GETMESSAGE |
Thread or global |
WH_JOURNALPLAYBACK |
Global only |
WH_JOURNALRECORD |
Global only |
WH_KEYBOARD |
Thread or global |
WH_KEYBOARD_LL |
Global only |
WH_MOUSE |
Thread or global |
WH_MOUSE_LL |
Global only |
WH_MSGFILTER |
Thread or global |
WH_SHELL |
Thread or global |
WH_SYSMSGFILTER |
Global only |
表一:鉤子做用域
WH_JOURNALPLAYBACK,WH_JOURNALRECORD,WH_KEYBOARD_LL,WH_MOUSE_LL、WH_SYSMSGFILTER這5種鉤子自己的做用域就是全局的,無論鉤子是直接寫在應用程序的代碼裏仍是放在DLL中,他們都可以鉤住系統的消息。剩下的10種鉤子,他們的做用域既能夠是線程的又能夠是全局的,當將相應的鉤子直接寫在應用程序的代碼中時,他們只能捕獲當前線程上下文的消息。那麼他們如何實現捕獲全局消息的功能呢?當把鉤子寫入到一個單獨的DLL中再引用後,系統自動將該DLL映射到受鉤子函數影響的全部進程的地址空間中,即將這個DLL注入了那些進程,從而達到捕獲全局消息的目的。相對來講,前面5種鉤子自己就是全局的,是不須要注入的。
所以,對於前面問題的答案就是:要實現捕獲全局消息功能的鉤子,是否要寫在單獨的DLL裏面,取決於鉤子的類型以及相應的做用域。
若是對於同一事件既安裝了線程勾子又安裝了全局勾子,那麼系統會自動先調用線程勾子,而後調用全局勾子。