為什么 SetWindowsHookEx 采用 HINSTANCE 參數?
有開發者問了這樣一個問題:既然 SetWindowsHookEx 的第一個參數總是會被轉換為一個文件名,那為什么它的傳參類型是 HINSTANCE 呢?這豈不是多此一舉?
原因是這樣的:在 16 位 Windows 系統上,它不是這樣工作的。16 位 Windows 上根本就沒有 “鉤子注入” 的概念。
所有 16 位 Windows 應用程序都是運行在同一個地址空間,所以就沒有必要將代碼注入到其他程序中。所以,就沒有必要將實例句柄轉換為一個文件名來注入代碼。
實際的工作原理是這樣的:實例句柄將會被用來增加引用計數,從而鉤子函數就不會被意外釋放掉。當鉤子被卸載的時候,模塊的引用計數會自動減一。
即使到了 32 位 Windows,窗口管理器需要實例句柄才能將函數指針轉換回 RVA,以便在將模塊加載到另一個進程時可以找到函數。
如果你傳遞了帶有模塊路徑的 LPCWSTR,則窗口管理器無論如何都必須執行 GetModuleHandle 來恢復實例句柄。
由于大多數程序的實例句柄都隨時可用,因此這是更自然的選擇。(更不用說它將保持與 16 位 Windows 的源代碼兼容性,這是試圖讓人們有興趣將他們的代碼移植到 Win32 時的一個重要標準。)
總結
做 Windows 世界的良好公民,不要隨意使用鉤子。除非迫不得已。