Share via


原生應用程式內部

作者:Mark Russinovich,發佈日期:2006 年 11 月 1 日

簡介

如果您已熟悉 NT 的架構,您可能知道 Win32 應用程式使用的 API 不是「真正的」NT API。 NT 的作業環境,包括 POSIX、OS/2 和 Win32,會透過自己的 API 與用戶端應用程式交談,但使用 NT「原生」API 與 NT 通訊。 原生 API 大多未記載,Windows NT 裝置驅動程式套件中所述的 250 個函式中只有大約 25 個。

不過,大多數人不知道的是,NT 上存在「原生」應用程式,不是任何作業環境的用戶端。 這些程式使用原生 NT API,無法使用 Win32 等操作環境 API。 為什麼需要這類程式」必須在 Win32 子系統啟動之前執行的任何程式 (在登入方塊出現前後) 必須是原生應用程式。 原生應用程式的最明顯範例是 “autochk” 程式,會在初始化 Blue Screen 期間執行 chkdsk(它是列印 “” 的程式。在畫面上。 當然,Win32 作業環境伺服器 CSRSS.EXE (Client-Server Runtime Subsystem) 也必須是原生應用程式。

在本文中,我將說明原生應用程式的建置方式,以及其運作方式。

Autochk 如何執行

Autochk 會在 NT 開機和系統啟動驅動程式載入,以及開啟分頁時執行。 此時,開機順序工作階段管理員 (smss.exe) 正在關閉 NT 的使用者模式環境,而且沒有其他程式處於作用中狀態。 HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute 值 MULTI_SZ 包含工作階段管理員所執行之程式的名稱和引數,以及指定 Autochk 的位置。 以下是您查看此值時通常會發現的內容,其中 "Autochk" 會傳遞 "*" 作為引數:

Autocheck Autochk *

工作階段管理員會在 <winnt>\system32 目錄中尋找此值中列出的可執行檔。 當 Autochk 執行時,沒有開啟任何檔案,因此 Autochk 可以在原始模式中開啟任何磁碟區,包括開機磁碟機,以及操作其磁碟上的資料結構。 這不可能在稍後的任何時間點。

建置原生應用程式

Microsoft 不會記錄它,但 NT DDK 組建公用程式知道如何建立原生應用程式 (及其可能用來編譯 Autochk)。 您可以在定義應用程式的 SOURCES 檔案中指定資訊,與裝置驅動程式相同。 不過,您不要指示要建置驅動程式,而是告訴它您想要SOURCES檔案中的原生應用程式,如下所示:

TARGETTYPE=PROGRAM

Build 公用程式會使用標準 makefile 來引導它 ,\ddk\inc\makefile.def,它會在編譯原生應用程式時尋找名為 nt.lib 的執行時間程式庫。 不幸的是,Microsoft 不會將此檔案隨附於 DDK (其包含在 Server 2003 DDK 中,但我懷疑如果您與該版本連結,原生應用程式將不會在 XP 或 Windows 2000 上執行)。 不過,您可以藉由在 makefile.def 中包含一行,藉由指定 Visual C++的執行時間程式庫 msvcrt.lib 來覆寫 nt.lib 的選取範圍,以解決此問題。

如果您在 DDK 的「核取組建」環境中執行 Build,它會在 %BASEDIR%\lib%CPU%\Checked 下 (例如 c:\ddk\lib\i386\checked\native.exe) 產生具有完整偵錯資訊的原生應用程式,而且如果您在「免費組建」環境中叫用它,程式的版本最終會以 %BASEDIR%\lib%CPU%\Free 結束。 這些是組建放置裝置驅動程式映射的相同位置。

原生應用程式具有 ".exe" 副檔名,但您無法像 Win32 .exe 一樣執行它們。 如果您嘗試收到下列訊息:

應用程式無法在 Windows NT 模式中執行。

原生應用程式內部

原生應用程式的進入點是 NtProcessStartup,而不是 winmainmain。 與其他 Win32 進入點不同,原生應用程式必須觸達作為唯一參數傳遞的資料結構,才能尋找命令列引數。

大部分原生應用程式的執行時間環境是由 NTDLL.DLL 提供,這是 NT 的原生 API 匯出程式庫。 原生應用程式必須建立自己的堆積,才能使用 NTDLL 函式 RtlCreateHeap 來配置儲存空間。 記憶體是從具有 RtlAllocateHeap 的堆積配置,並使用 RtlFreeHeap 釋出。 如果原生應用程式想要將某內容列印到畫面,它必須使用 NtDisplayString 函式,這會輸出至初始化藍色畫面。

原生應用程式不會直接從 Win32 程式之類的啟動函式傳回,因為沒有要傳回的執行時間程式碼。 相反地,他們必須藉由呼叫 NtProcessTerminate 來終止自己。

NTDLL 執行時間包含數百個函式,可讓原生應用程式執行檔案 I/O、與裝置驅動程式互動,以及執行處理序間通訊。 不幸的是,正如我稍早所述,大部分的函式都是未記載的。