在原生應用程式中

Mark Russinovich 已發佈:2006年11月1日

簡介

如果您熟悉 NT 的架構,您可能會發現 Win32 應用程式所使用的 API 不是「真正的」 NT API。 NT 的作業環境(包括 POSIX、OS/2 和 Win32)會透過自己的 Api 與用戶端應用程式通訊,但使用 NT 「原生」 API 來與 NT 交談。 原生 API 大部分是未記載的,只有大約25個250函式 Windows NT 設備磁碟機套件中所述。

不過,大部分的人都不知道,「原生」應用程式是存在於不是任何作業環境用戶端的 NT 上。 這些程式會說出原生 NT API,而且無法使用 Win32 之類的作業環境 Api。 為什麼需要這種程式,在 Win32 子系統啟動之前必須執行的任何程式 (在登入方塊出現時) 必須是原生應用程式。 原生應用程式的最明顯範例是「autochk」程式,它會在初始化藍色畫面期間執行 chkdsk (它是列印 "." ' 的程式。畫面上的) 。 當然,Win32 作業環境伺服器 CSRSS.EXE (用戶端-伺服器執行時間子系統) )也必須是原生應用程式。

在本文中,我將說明如何建立原生應用程式,以及它們的運作方式。

執行 Autochk 的方式

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

Autocheck Autochk *

會話管理員 會在 winnt > \system32 目錄中查看此值所列的可執行檔。 當 Autochk 執行時,沒有開啟的檔案,所以 Autochk 可以開啟原始模式中的任何磁片區,包括開機磁片磁碟機,以及操作其磁片上的資料結構。 在任何時候,都不可能發生這種情況。

建立原生應用程式

Microsoft 不會記載它,但是 NT DDK Build 公用程式知道如何 (原生應用程式,以及它可能用來編譯 Autochk) 。 您可以在定義應用程式的來源檔案中指定資訊,就像是針對設備磁碟機所做的一樣。 不過,您可以告訴它您想要原生 applicationin 原始程式檔,如下所示:

TARGETTYPE=PROGRAM

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

如果您在 DDK 的「已檢查組建」環境下執行 組建 ,則會產生原生應用程式,並在%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 匯出程式庫所提供。 原生應用程式必須建立自己的堆積,以使用 RtlCreateHeap(ntdll.dll 函數)來配置儲存區。 記憶體是從具有 RtlAllocateHeap 的堆積配置,並使用 RtlFreeHeap釋放。 如果原生應用程式希望將某個內容列印到螢幕上,它必須使用函式 NtDisplayString,它會輸出到初始化藍色畫面。

原生應用程式不會直接從其啟動函式傳回,例如 Win32 程式,因為沒有任何執行時間程式碼可返回。 相反地,它們必須藉由呼叫 NtProcessTerminate來自行終止。

NTDLL.DLL 執行時間包含數以百計的函式,可讓原生應用程式執行檔案 i/o、與設備磁碟機互動,以及執行進程間的通訊。 可惜的是,如前所述,大部分的函式都未記載。