如前所述, Windows95 不是一個“純” 32 位操作系統,其內核模塊中的 USER 和 GDI 均是用 16 位代碼實現的。 USER32.DLL 和 GDI32.DLL 只是 16 位的 USER.EXE 和 GDI.EXE 的 32 位調用接口。因此,如果屏幕截獲程序用 32 位代碼實現,則只能截獲 32 位應用程序對 USER32.DLL 和 GDI32.DLL 的調用,無法截獲 16 位應用程序對 USER.EXE 和 GDI.EXE 的調用,所以如果想截獲所有應用程序(包括 Windows95 的桌面程序 Explorer )中有關屏幕輸出的系統調用,則應該用 16 位代碼實現屏幕截獲功能。這就是 LTW32 為什么不是“純” 32 位應用程序的原因。 LTW32 主要截獲兩個系統調用 TextOut() 和 ExtTextOut() ,方法很簡單,把這兩個函數的頭五個字節修改為一個 JMP FAR 指令,使得對這兩個函數的調用均轉向屏幕截獲程序。這就涉及到一個關鍵問題:動態修改 Windows 的代碼。
在傳統的 DOS 程序中,動態修改程序代碼無任何困難,但在 Windows 中則不然,因為在 Windows 中,代碼可被同一程序的多個實例(進程)共享,所以系統不允許應用程序動態的修改代碼。在 16 位側,內存的可讀、寫屬性是與段選擇符聯系在一起的。段選擇符基本上可分為兩類:數據段選擇符和代碼段選擇符。前者可讀、可寫、不可執行;后者可讀、可執行、不可寫。 Windows 提供了這兩類段選擇符相轉換的系統調用。未公開的 16 位系統調用 AllocCStoDSAlias() 為給定的代碼段選擇符分配一個具有相同線性基址和尺寸的數據段別名( DS Alias )。通過 DS 別名可以對給定的代碼段進行修改。 AllocCStoDSAlias() 的使用方法如下:
WORD (FAR PASCAL *AllocCStoDSAlias)(WORD);
AllocCStoDSAlias = GetProcAddress(
GetModuleHandle(“KERNEL”), ”ALLOCCSTODSALIAS”);
調用參數為給定的代碼選擇符,調用成功時返回一個線性基址和尺寸均與原代碼選擇符相同的 DS 別名。當不再使用此 DS 別名時,要用系統調用 FreeSelector() 把 DS 別名釋放掉。
使用上述技術,就可實現動態修改 Windows 代碼,從而改變 GDI 的系統調用 TextOut() 和 ExtTextOut() 的執行動作,實時地截獲屏幕輸出,為實現鼠標隨動翻譯提供可能。
把上述的 32 位到 16 位的形式替換、 32 位代碼與 16 位代碼的數據交換、動態修改 Windows 內核等技術綜合應用在一起,配合單詞查找算法和詞組分析算法就可以實現鼠標隨動翻譯功能。