Windows本地操做系統服務API由一系列以Nt或Zw爲前綴的函數實現的,這些函數之內核模式運行,內核驅動能夠直接調用這些函數,而用戶層程序只能經過系統進行調用。一般狀況下用戶層應用程序不會直接調用Nt和Zw系函數,更多的是經過直接調用Win32函數,這些Win32函數內部會調用Nt和Zw系函數,但也僅限於一般狀況下,當Win32函數不支持一些操做時,用戶層也會直接調用這些本地系統服務函數。windows
Nt前綴是Windows NT的縮寫,但Zw前綴並無任何意義,使用Zw只是避免跟其餘已存在和將來可能出現的API有命名衝突而已。不少Windows驅動支持函數都以兩到三個特定的簡稱字母爲前綴進行命名,以此來表示這些例程都是由哪些內核系統組件實現的,好比CmRegisterCallbackEx
中的Cm就表示配置管理器(Configuration manager)緩存
每一個本地系統服務例程都有兩個有着不一樣前綴的類似名稱的函數版本,好比NtCreateFile
和ZwCreateFile
,二者執行相同的操做,而且事實上二者也都服務於相同的內核模式系統例程。對於用戶層的系統調用,Nt和Zw系函數是沒有什麼區別的,但對於來自於內核驅動的調用,Nt和Zw系函數對傳入參數的處理方式有些不同。函數
若是傳入參數是來自於可信任的內核層,那麼內核模式驅動則調用Zw版本的本地系統服務例程來通知其餘例程,在這種狀況下,例程都是不通過驗證就直接使用這些參數。反而,若是這些參數可能來自用戶層或者內核層,那麼驅動則調用Nt版本的例程,這取決於調用線程的歷程——這些參數是從用戶層仍是內核層發起的,線程對象中有個PreviousMode的屬性可用於判斷參數是否從用戶層過來的,關於例程如何判斷參數是來自用戶層仍是內核層,詳細內容請參見預先模式操作系統
當一個用戶層應用程序調用Nt或Zw系函數,這些本地系統服務函數始終會認爲它接收到的參數來自於不可信任的用戶層,在使用前必先驗證參數的有效性。特別是對於由調用者提供的緩存區,這些函數將會探測其內存地址是否有效而且是否正常對齊。線程
本地系統服務例程對於接收到參數值還會作額外的設定。若是一個例程接收到一個由指向由內核驅動分配的緩存區指針,它會認爲這緩存區是從系統內存而不是從用戶層內存分配的,若是例程接收到一個由用戶層應用程序打開的句柄類型參數,那麼例程就會從用戶層句柄表中查找句柄而不是從內核層。指針
在一些狀況下,從用戶層調用仍是從內核層調用對傳入參數的意義和後續的使用影響重要。好比說ZwNotifyChangeKey
(或說NtNotifyChangeKey
)這個函數,其中有兩個輸入參數ApcRoutine
和APCContext
,從用戶層和從內核層傳過來分別表明不一樣的意義。若是其從用戶層被調用,ApcRoutine
指向一個APC例程,ApcContext
則指向一個由操做系統在調用APC例程時分配的上下文;若是其從內核層被調用,ApcRoutine
指向一個WORK_QUEUE_ITEM
結構,而ApcContext
則表示WORK_QUEUE_ITEM
隊列項的類型。code
用戶層不支持調用Zw系函數,而在內核層調用Zw系函數時,上面也稍微提到過,系統不檢測調用者的訪問權限,調用以前必須檢測從用戶模式下傳來的參數的有效性對象
大多數Zw 系函數的聲明在Wdm.h中能夠找獲得,少部分散落在其餘頭文件裏如Ntddk.h和Ntifs.h接口
用戶層可經過引用Ntdll.lib靜態庫(在WDK中能夠找到)來調用這些本地系統服務例程,大多數文檔化的Nt系函數聲明在Windows SDK的Winternl.h頭文件中,對於未文檔化的Nt系函數,微軟一直不建議開發者進行調用,由於在將來的Windows版本中這些函數接口可能會有所改動或者直接被廢除,這對使用了這些未文檔化函數的應用程序的穩定運行形成必定的影響,但每每是這些未文檔化的函數和結構體可以獲取更多的系統權限,這也是衆多的Windows應用開發者不聽勸告反而樂此不疲地去挖掘的緣由。隊列
內核驅動可經過調用Nt和Zw在Ntoskrnl.exe的動態連接庫的入口點(entry points)來使用這些本地系統服務例程的,該DLL(動態連接庫)包含這些服務例程的具體實現,要訪問這些入口點,驅動程序須要靜態連接到Ntoskrnl.lib(在WDK中也能夠找到)
對於Nt*Xxx* and Zw*Xxx* 的具體函數列表可查看此處