ZwReadFile routine
ZwReadFile 从一个打开的文件中读取内容
Syntax
NTSTATUS ZwReadFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_ PVOID Buffer,
_In_ ULONG Length,
_In_opt_ PLARGE_INTEGER ByteOffset,
_In_opt_ PULONG Key
);
Parameters
FileHandle [in]
ZwCreateFile or ZwOpenFile调用成功后返回的句柄
Event [in, optional]
可选的一个事件对象的句柄,用于当读文件操作完成后设置这个句柄的信号状态设备和中间层驱动应当设置这个参数为NULL。
ApcRoutine [in, optional]
保留,设备和中间层驱动应当设置这个参数为NULL。
ApcContext [in, optional]
保留,设备和中间层驱动应当设置这个参数为NULL。
IoStatusBlock [out]
指向IO_STATUS_BLOCK 结构体的指针用于接收最终完成状态和与读请求有关的信息。 Information 成员接收从文件中读取的实际大小。
Buffer [out]
指向调用者申请的用于接收从文件中所读取数据的缓冲区。
Length [in]
以字节为单位的Buffer指向的缓冲区的大小。
ByteOffset [in, optional]
指向一个变量的指针,该指针指定文件读操作在文件中的开始位置。如果试图在文件结尾之后读取数据ZwReadFile 返回一个错误。
如果 ZwCreateFile 设置了CreateOptions 参数为FILE_SYNCHRONOUS_IO_ALERT 或是 FILE_SYNCHRONOUS_IO_NONALERT之一, I/O管理器保管当前的文件位置,如果这样,ZwReadFile 的调用者可以指定当前使用的文件位置而不通过显式传入一个ByteOffset值。这个规范设置可以使用下列方法之一:
·
1、指定一个指向LARGE_INTEGER值得指针,其HighPart 设置为-1,LowPart 设置为系统定义的值FILE_USE_FILE_POINTER_POSITION。
·
·
2、传递一个NULL 指针给 ByteOffset参数。
·
如果I/O管理器保管着当前文件位置,ZwReadFile 通过在完成读取操作时增加读取的字节数更新当前文件的位置。即使I/O管理器保管着当前的文件位置,调用者亦可通过调用ZwReadFile并传递一个显式的ByteOffset值重设这个位置。通过这样子做自动改变当前的文件位置到ByteOffset值 ,执行读操作,然后根据实际读取的字节数更新文件位置。这种技术授予调用着自动的seek-and-read服务。
Key [in, optional]
设备和中间层驱动应设置这个指针为NULL。
Return value
ZwReadFile 返回STATUS_SUCCESS 或是一个合适的NTSTATUS 错误码。
Remarks
ZwReadFile 的调用者必须已经设置调用ZwCreateFile 的参数DesiredAccessparameter为FILE_READ_DATA 或者 GENERIC_READ。如果之前的ZwCreateFile 调用设置了CreateOptions 包括FILE_NO_INTERMEDIATE_BUFFERING ,ZwReadFile 的Length 和ByteOffset 参数必须是sector size的整数倍。更多信息详见 ZwCreateFile。
ZwReadFile 从给定的ByteOffset 参数或者是当前文件位置开始读取文件到指定的缓冲区。读操作在以下条件下将被结束:
·
由于已经读取了Length 参数指定大小的字节数,导致目标缓冲区已经满了。因此无法在不溢出的情况下继续放入更多数据到缓冲区中。
·
读操作已经到了文件的结尾处,因此没有更多的文件数据可以被传输的缓冲区中。
·
如果调用者打开文件时在DesiredAccess参数中指定了SYNCHRONIZE标志 ,调用线程可以通过在文件句柄FileHandle上等待来同步一个读操作的完成。句柄每次在发布的I/O操作完成后变成signaled,然而调用者不可以在一个为同步文件访问(FILE_SYNCHRONOUS_IO_NONALERT or FILE_SYNCHRONOUS_IO_ALERT)而打开的句柄上等待 ,在这种情况下, ZwReadFile waits on behalf of the caller 并且直到读操作完成才返回。调用者只有在满足以下三种条件后才能安全地等待一个文件句柄:
·
句柄为异步访问打开。 (指定FILE_SYNCHRONOUS_IO_XXX)。
·
句柄一次只执行一个I/O操作。
·
ZwReadFile 返回 STATUS_PENDING.
在以下任意情况下,驱动文件应当在系统进程的上下文中调用 ZwReadFile :
·
是驱动创建了传给ZwReadFile的文件句柄
·
ZwReadFile 将通过一个驱动创建的事件通知驱动I/O的完成。
·
ZwReadFile 将通过驱动传递给ZwReadFile的一个APC回调同事驱动I/O的完成。
·
文件和事件句柄仅在创建它们的进程上下文中有效。因此为了避免安全漏洞驱动应当在系统进程的上下文中创建文件或者事件句柄而不是驱动所在的进程上下文中。
同样 ZwReadFile 如果通过APC来通知驱动I/O的完成,ZwReadFile 应当在系统进程的上下文中调用。这是因为APC们中是在发布I/O请求的线程上下文中被引发。如果驱动在不是系统进程的进程的上下文中调用了 ZwReadFile , APC可能被无限期延迟,或者根本不会引发这个APC调用。
对于文件操作的更多内容见: Using Files in a Driver.
ZwReadFile 调用者必须在 IRQL = PASSIVE_LEVEL 上并且 with special kernel APCs enabled.
Note 如果这个函数在用户模式下调用当使用名字"NtReadFile" 代替"ZwReadFile".
Requirements
Target platform | |
Version | Available starting with Windows 2000. |
Header | Wdm.h (include Wdm.h, Ntddk.h, or Ntifs.h) |
Library | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | PASSIVE_LEVEL (see Remarks section) |
DDI compliance rules | PowerIrpDDis, BufAfterReqCompletedIntIoctlA, BufAfterReqCompletedIoctlA, BufAfterReqCompletedReadA,BufAfterReqCompletedWriteA, HwStorPortProhibitedDDIs |