使用本机系统服务例程的 Nt 和 Zw 版本
Windows 本机操作系统服务 API 作为一组在内核模式下运行的例程实现。 这些例程的名称以前缀 Nt 或 Zw 开头。 内核模式驱动程序可以直接调用这些例程。 用户模式应用程序可以使用系统调用访问这些例程。
除了少数例外,每个本机系统服务例程都有两个略有不同的版本,它们名称相似,但前缀不同。 例如,对 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 结构描述的工作队列项的类型。
本节包括下列主题: