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