如前所述,
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
內核等技術綜合應用在一起,配合單詞查找算法和詞組分析算法就可以實現鼠標隨動翻譯功能。