寫(xiě)這篇文章的起因是這么一個(gè)問(wèn)題:我們?cè)谑褂煤桶惭bWindows程序時(shí),有時(shí)會(huì)看到以“2052”、“1033”這些數(shù)字為名的文件夾,這些數(shù)字似乎和字符集有關(guān),但它們究竟是什么意思呢?
研究這個(gè)問(wèn)題的同時(shí),又會(huì)遇到其它問(wèn)題。我們會(huì)談到Windows的內(nèi)部架構(gòu)、Win32 API的A/W函數(shù)、Locale、ANSI代碼頁(yè)、與字符編碼有關(guān)的編譯參數(shù)、MBCS和Unicode程序、資源和亂碼等,一起經(jīng)歷這段瑣碎細(xì)節(jié)為主,間或樂(lè)趣點(diǎn)綴的旅程。
0 Where is Win32 API
Windows程序有用戶態(tài)和核心態(tài)的說(shuō)法。在32位地址空間中,0x80000000以下屬于用戶態(tài),0x80000000以上屬于核心態(tài)。所有硬件管理都在核心態(tài)。用戶態(tài)程序的不能直接使用核心態(tài)的任何代碼。所謂核心態(tài)其實(shí)只是CPU的一種保護(hù)模式。在x86 CPU上,用戶態(tài)處于ring 3,核心態(tài)處于ring 0。
從用戶態(tài)進(jìn)入核心態(tài)的最常用的方法是在寄存器eax填一個(gè)功能碼,然后執(zhí)行int 2e。這有點(diǎn)像DOS時(shí)代的DOS和BIOS系統(tǒng)調(diào)用。在NT架構(gòu)中這種機(jī)制被稱作system service。
在核心態(tài)提供system service的有兩個(gè)家伙:ntoskrnl.exe和win32k.sys。ntoskrnl.exe是Windows的大腦,它的上層被稱為Executive,下層被稱作Kernel。Win32k.sys提供與顯示有關(guān)的system service。
在用戶態(tài)一側(cè),有一個(gè)重要的角色叫作ntdll.dll,大多數(shù)system service都是它調(diào)用的。它封裝這些system service,然后提供一個(gè)API接口。這個(gè)接口被稱作native API。 native API的用戶是各個(gè)子系統(tǒng)(subsystem),包括Win32子系統(tǒng)、OS/2子系統(tǒng)、POSIX子系統(tǒng)。各個(gè)子系統(tǒng)為Win32、OS2、POSIX程序提供了運(yùn)行平臺(tái)。
ntdll.dll由于提供了平臺(tái)無(wú)關(guān)的API接口,所以被看作是NT系統(tǒng)的原生接口,由之得到了“native API”的匪號(hào)。其實(shí)它的主要工作是將調(diào)用傳遞到核心態(tài)。
Win32、OS/2、POSIX,聽(tīng)起來(lái)很龐大。其實(shí)真正做好的只有Win32子系統(tǒng)。OS2、POSIX都是Console UI,即只有字符界面。提供OS/2子系統(tǒng),只因?yàn)樵?988年,NT的主要設(shè)計(jì)目標(biāo)就是與OS/2兼容,后來(lái)由于Windows 3.0賣得很好,所以設(shè)計(jì)目標(biāo)被變更為與Windows兼容。提供POSIX子系統(tǒng),是為了應(yīng)付美國(guó)政府的一個(gè)編號(hào)為FIPS 151-2的標(biāo)準(zhǔn)。
Win32子系統(tǒng)的管理員是一個(gè)叫作csrss.exe的弟兄,它的全名是:Client/Server Run-Time Subsystem。它剛上任時(shí),本來(lái)要分管所有的子系統(tǒng),但后來(lái)POSIX和OS/2都被分別處理了,所以只管了一個(gè)Win32。即使這樣也很了不起,所有的Win32程序的進(jìn)程、線程們都要向它登記。
不過(guò)Win32程序用得最多的還是Win32子系統(tǒng)的DLL們,最核心的DLL包括:kernel32.dll、User32.dll、Gdi32.dll、Advapi32.dll。這些DLL包裝了ntdll.dll的native API。其中Gdi32.dll比較特殊,它與核心態(tài)的win32k.sys直接保持聯(lián)系,以提高NT系統(tǒng)的圖形處理能力。Win32子系統(tǒng)的DLL們提供的接口函數(shù)在MSDN文檔中被詳細(xì)介紹,它們就是Win32 API。
研究這個(gè)問(wèn)題的同時(shí),又會(huì)遇到其它問(wèn)題。我們會(huì)談到Windows的內(nèi)部架構(gòu)、Win32 API的A/W函數(shù)、Locale、ANSI代碼頁(yè)、與字符編碼有關(guān)的編譯參數(shù)、MBCS和Unicode程序、資源和亂碼等,一起經(jīng)歷這段瑣碎細(xì)節(jié)為主,間或樂(lè)趣點(diǎn)綴的旅程。
0 Where is Win32 API
Windows程序有用戶態(tài)和核心態(tài)的說(shuō)法。在32位地址空間中,0x80000000以下屬于用戶態(tài),0x80000000以上屬于核心態(tài)。所有硬件管理都在核心態(tài)。用戶態(tài)程序的不能直接使用核心態(tài)的任何代碼。所謂核心態(tài)其實(shí)只是CPU的一種保護(hù)模式。在x86 CPU上,用戶態(tài)處于ring 3,核心態(tài)處于ring 0。
從用戶態(tài)進(jìn)入核心態(tài)的最常用的方法是在寄存器eax填一個(gè)功能碼,然后執(zhí)行int 2e。這有點(diǎn)像DOS時(shí)代的DOS和BIOS系統(tǒng)調(diào)用。在NT架構(gòu)中這種機(jī)制被稱作system service。
在核心態(tài)提供system service的有兩個(gè)家伙:ntoskrnl.exe和win32k.sys。ntoskrnl.exe是Windows的大腦,它的上層被稱為Executive,下層被稱作Kernel。Win32k.sys提供與顯示有關(guān)的system service。
在用戶態(tài)一側(cè),有一個(gè)重要的角色叫作ntdll.dll,大多數(shù)system service都是它調(diào)用的。它封裝這些system service,然后提供一個(gè)API接口。這個(gè)接口被稱作native API。 native API的用戶是各個(gè)子系統(tǒng)(subsystem),包括Win32子系統(tǒng)、OS/2子系統(tǒng)、POSIX子系統(tǒng)。各個(gè)子系統(tǒng)為Win32、OS2、POSIX程序提供了運(yùn)行平臺(tái)。
ntdll.dll由于提供了平臺(tái)無(wú)關(guān)的API接口,所以被看作是NT系統(tǒng)的原生接口,由之得到了“native API”的匪號(hào)。其實(shí)它的主要工作是將調(diào)用傳遞到核心態(tài)。
Win32、OS/2、POSIX,聽(tīng)起來(lái)很龐大。其實(shí)真正做好的只有Win32子系統(tǒng)。OS2、POSIX都是Console UI,即只有字符界面。提供OS/2子系統(tǒng),只因?yàn)樵?988年,NT的主要設(shè)計(jì)目標(biāo)就是與OS/2兼容,后來(lái)由于Windows 3.0賣得很好,所以設(shè)計(jì)目標(biāo)被變更為與Windows兼容。提供POSIX子系統(tǒng),是為了應(yīng)付美國(guó)政府的一個(gè)編號(hào)為FIPS 151-2的標(biāo)準(zhǔn)。
Win32子系統(tǒng)的管理員是一個(gè)叫作csrss.exe的弟兄,它的全名是:Client/Server Run-Time Subsystem。它剛上任時(shí),本來(lái)要分管所有的子系統(tǒng),但后來(lái)POSIX和OS/2都被分別處理了,所以只管了一個(gè)Win32。即使這樣也很了不起,所有的Win32程序的進(jìn)程、線程們都要向它登記。
不過(guò)Win32程序用得最多的還是Win32子系統(tǒng)的DLL們,最核心的DLL包括:kernel32.dll、User32.dll、Gdi32.dll、Advapi32.dll。這些DLL包裝了ntdll.dll的native API。其中Gdi32.dll比較特殊,它與核心態(tài)的win32k.sys直接保持聯(lián)系,以提高NT系統(tǒng)的圖形處理能力。Win32子系統(tǒng)的DLL們提供的接口函數(shù)在MSDN文檔中被詳細(xì)介紹,它們就是Win32 API。