Windows内核编程
上QQ阅读APP看书,第一时间看更新

3.3 内核API

内核驱动程序使用的是从内核的组件输出的函数。这些函数被视为内核的API。大多数函数则在内核本身模块(NtOskrnl.exe)里实现,但还有些在别的模块中实现,比如在HAL(hal.dll)中。

内核API是大量C函数的集合,其中多数的名称含有一个前缀,这个前缀指示了实现该函数的模块。表3-2显示了一些常见的前缀和它们的含义。

表3-2 常见的内核API前缀

000

如果看一下NtOsKrnl.exe输出的函数列表,会发现有很多函数在WDK中没有文档。这只是内核开发者生活中的事实而已—并非所有东西都是有文档的。

这里有一组函数值得讨论一下—以Zw开头的函数。这组函数作为NTDLL.dll中的原生API的镜像,是从原生API到位于执行体中的实现之间的网关。当用户模式调用了Nt函数,比如NtCreateFile时,最终将到达执行体中实际的NtCreateFile实现。此时,基于原始调用来自用户模式这个事实,NtCreateFile可能会做各种合法性检查。这里调用者的信息以线程为基础保存在每个线程对应的KTHREAD结构中未公开的PreviousMode字段里。

另一方面,如果内核驱动程序要调用某个系统服务,它就没必要做跟用户模式一样的检查以及接受用户模式调用者所受的限制。这就是为什么要有Zw系列函数。调用Zw函数会将PreviousMode设置成KernelMode(0),然后调用原生函数。举个例子,调用ZwCreateFile会将前一个调用者的模式设置为KernelMode,然后调用NtCreateFile,这使得NtCreateFile绕过一些安全性和缓冲区的检查。底线是,驱动程序必须调用Zw系列函数,除非它们有令人信服的理由不这么做。