zwReadFile 函数 (wdm.h)

ZwReadFile 例程从打开的文件读取数据。

语法

NTSYSAPI NTSTATUS ZwReadFile(
  [in]           HANDLE           FileHandle,
  [in, optional] HANDLE           Event,
  [in, optional] PIO_APC_ROUTINE  ApcRoutine,
  [in, optional] PVOID            ApcContext,
  [out]          PIO_STATUS_BLOCK IoStatusBlock,
  [out]          PVOID            Buffer,
  [in]           ULONG            Length,
  [in, optional] PLARGE_INTEGER   ByteOffset,
  [in, optional] PULONG           Key
);

参数

[in] FileHandle

文件对象的句柄。 此句柄是通过成功调用 ZwCreateFileZwOpenFile 创建的。

[in, optional] Event

(可选)在读取操作完成后设置为信号状态的事件对象的句柄。 设备和中间驱动程序应将此参数设置为 NULL

[in, optional] ApcRoutine

此参数为保留参数。 设备和中间驱动程序应将此指针设置为 NULL

[in, optional] ApcContext

此参数为保留参数。 设备和中间驱动程序应将此指针设置为 NULL

[out] IoStatusBlock

指向 IO_STATUS_BLOCK 结构的指针,该结构接收最终完成状态和有关请求的读取操作的信息。 Information 成员接收实际从文件读取的字节数。

[out] Buffer

指向调用方分配的缓冲区的指针,该缓冲区接收从文件读取的数据。

[in] Length

Buffer 指向的缓冲区的大小(以字节为单位)。

[in, optional] ByteOffset

指向变量的指针,该变量指定将开始读取操作的文件中起始字节偏移量。 如果尝试读取文件末尾以外的内容, ZwReadFile 将返回错误。

如果对 ZwCreateFile 的调用设置 CreateOptions 标志FILE_SYNCHRONOUS_IO_ALERT或FILE_SYNCHRONOUS_IO_NONALERT,则 I/O 管理器将保留当前文件位置。 如果是这样, ZwReadFile 的调用方可以指定使用当前文件位置偏移量而不是显式 ByteOffset 值。 可以使用以下方法之一进行此规范:

  • 指定指向LARGE_INTEGER值的指针,其中 HighPart 成员设置为 - 1,LowPart 成员设置为系统定义的值FILE_USE_FILE_POINTER_POSITION。

  • 传递 ByteOffsetNULL 指针。

如果 ZwReadFile 使用由 I/O 管理器维护的当前文件位置,则 ZwReadFile 会通过添加在完成读取操作时读取的字节数来更新当前文件位置。

即使 I/O 管理器维护当前文件位置,调用方也可以通过将显式 ByteOffset 值传递给 ZwReadFile 来重置此位置。 执行此操作会自动将当前文件位置更改为该 ByteOffset 值,执行读取操作,然后根据实际读取的字节数更新位置。 此方法为调用方提供原子查找和读取服务。

[in, optional] Key

设备和中间驱动程序应将此指针设置为 NULL

返回值

ZwReadFile 返回STATUS_SUCCESS或相应的 NTSTATUS 错误代码。

注解

ZwReadFile 的调用方必须已使用 desiredAccess 参数中设置FILE_READ_DATA或GENERIC_READ值调用 ZwCreateFile

如果前面对 ZwCreateFile 的调用将 CreateOptions 参数中的 FILE_NO_INTERMEDIATE_BUFFERING 标志设置为 ZwCreateFile,则 ZwReadFileLengthByteOffset 参数必须是扇区大小的倍数。 有关详细信息,请参阅 ZwCreateFile

ZwReadFile 开始从给定的 ByteOffset 或当前文件位置读取到给定 的 Buffer。 它会在以下条件之一下终止读取操作:

  • 缓冲区已满,因为已读取 Length 参数指定的字节数。 因此,在未发生溢出的情况下,无法将更多数据放入缓冲区中。

  • 读取操作期间会到达文件末尾,因此文件中没有更多要传输到缓冲区中的数据。

如果调用方在 DesiredAccess 中设置了 SYNCHRONIZE 标志打开文件,则调用线程可以通过等待文件句柄 FileHandle 来同步到读取操作的完成。 每次在句柄上发出的 I/O 操作完成时,都会发出句柄的信号。 但是,调用方不得等待为同步文件访问打开的句柄 (FILE_SYNCHRONOUS_IO_NONALERT 或FILE_SYNCHRONOUS_IO_ALERT) 。 在这种情况下, ZwReadFile 代表调用方等待,在读取操作完成之前不会返回。 仅当满足以下所有三个条件时,调用方才能安全地等待文件句柄:

  • 为异步访问打开了句柄, (,即) 未指定FILE_SYNCHRONOUS_IO_XXX 标志。

  • 句柄一次只用于一个 I/O 操作。

  • ZwReadFile 返回STATUS_PENDING。

如果存在以下任何条件,驱动程序应在系统进程的上下文中调用 ZwReadFile

  • 驱动程序创建了传递给 ZwReadFile 的文件句柄。

  • ZwReadFile 将通过驱动程序创建的事件通知驱动程序 I/O 完成。

  • ZwReadFile 将通过驱动程序传递给 ZwReadFile 的 APC 回调例程通知驱动程序 I/O 完成。

文件和事件句柄仅在创建句柄的进程上下文中有效。 因此,为了避免安全漏洞,驱动程序应在系统进程的上下文而不是驱动程序所处的进程上下文中创建传递给 ZwReadFile 的任何文件或事件句柄。

同样,如果 ZwReadFile 通过 APC 通知驱动程序 I/O 完成,则应在系统进程的上下文中调用,因为 APC 始终在发出 I/O 请求的线程上下文中触发。 如果驱动程序在非系统进程上下文中调用 ZwReadFile ,则 APC 可能会无限期延迟,或者根本无法触发。

有关使用文件的详细信息,请参阅 在驱动程序中使用文件

ZwReadFile 的调用方必须在 IRQL = PASSIVE_LEVEL 且启用了特殊内核 APC 的情况下运行。

如果在用户模式下调用此函数,则应使用名称“NtReadFile”而不是“ZwReadFile”。

要求

要求
目标平台 通用
标头 wdm.h(包括 Wdm.h、Ntddk.h、Ntifs.h)
Library NtosKrnl.lib
DLL NtosKrnl.exe
IRQL PASSIVE_LEVEL (请参阅“备注”部分)
DDI 符合性规则 BufAfterReqCompletedIntIoctlA (kmdf) BufAfterReqCompletedIoctlA (kmdf) BufAfterReqCompletedReadA (kmdf) (BufAfterReqCompletedWriteA (kmdf) HwStorPortProhibitedDIs (storport) PowerIrpDDis (wdm)

另请参阅

KeInitializeEvent

ZwCreateFile

ZwQueryInformationFile

ZwSetInformationFile

ZwWriteFile