ntWriteFile 函数 (ntifs.h)
ZwWriteFile 例程将数据写入打开的文件。
语法
__kernel_entry NTSYSCALLAPI NTSTATUS NtWriteFile(
[in] HANDLE FileHandle,
[in, optional] HANDLE Event,
[in, optional] PIO_APC_ROUTINE ApcRoutine,
[in, optional] PVOID ApcContext,
[out] PIO_STATUS_BLOCK IoStatusBlock,
[in] PVOID Buffer,
[in] ULONG Length,
[in, optional] PLARGE_INTEGER ByteOffset,
[in, optional] PULONG Key
);
参数
[in] FileHandle
文件对象的句柄。 此句柄是通过成功调用 NtCreateFile 或 NtOpenFile 创建的。
[in, optional] Event
(可选)将事件对象的句柄设置为写入操作完成后的信号状态。 设备和中间驱动程序应将此参数设置为 NULL。
[in, optional] ApcRoutine
此参数为保留参数。 设备和中间驱动程序应将此指针设置为 NULL。
[in, optional] ApcContext
此参数为保留参数。 设备和中间驱动程序应将此指针设置为 NULL。
[out] IoStatusBlock
指向 IO_STATUS_BLOCK 结构的指针,该结构接收请求的写入操作的最终完成状态和信息。 Information 成员接收实际写入文件的字节数。
[in] Buffer
指向调用方分配的缓冲区的指针,该缓冲区包含要写入文件的数据。
[in] Length
Buffer 指向的缓冲区的大小(以字节为单位)。
[in, optional] ByteOffset
指向变量的指针,该变量指定文件中用于开始写入操作的起始字节偏移量。 如果 Length 和 ByteOffset 指定超过当前文件结束标记的写入操作, 则 NtWriteFile 会自动扩展文件并更新文件结束标记;在此类旧标记和新文件结束标记之间未显式写入的任何字节都定义为零。
如果对 NtCreateFile 的调用仅设置 DesiredAccess 标志FILE_APPEND_DATA,则忽略 ByteOffset 。 给定 缓冲区中的数据( 长度 字节)从文件的当前末尾开始写入。
如果对 NtCreateFile 的调用设置了 CreateOptions 标志、FILE_SYNCHRONOUS_IO_ALERT或FILE_SYNCHRONOUS_IO_NONALERT,则 I/O 管理器将保留当前文件位置。 如果是这样, NtWriteFile 的调用方可以指定使用当前文件位置偏移量而不是显式 ByteOffset 值。 可以使用以下方法之一进行此规范:
- *指定指向LARGE_INTEGER值的指针,其中 HighPart 成员设置为 - 1,LowPart 成员设置为系统定义的值FILE_USE_FILE_POINTER_POSITION。
- 传递 ByteOffset 的 NULL 指针。
NtWriteFile 通过使用 I/O 管理器维护的当前文件位置,则通过添加完成写入操作时写入的字节数来更新当前文件位置。
即使 I/O 管理器维护当前文件位置,调用方也可以通过将显式 ByteOffset 值传递给 NtWriteFile 来重置此位置。 执行此操作会自动将当前文件位置更改为该 ByteOffset值,执行写入操作,然后根据实际写入的字节数更新位置。 此方法为调用方提供原子查找和写入服务。
还可以通过在 HighPart 设置为 -1 且 LowPart 设置为 FILE_WRITE_TO_END_OF_FILE 的情况下,为 ByteOffset 指定指向LARGE_INTEGER值的指针,使写入操作在文件的当前末尾开始。 无论 I/O 管理器是否维护当前文件位置,这都有效。
[in, optional] Key
设备和中间驱动程序应将此指针设置为 NULL。
返回值
NtWriteFile 在成功时返回STATUS_SUCCESS或在失败时返回相应的 NTSTATUS 错误代码。
注解
NtWriteFile 的调用方必须已调用 NtCreateFile,并在 DesiredAccess 参数中设置了FILE_WRITE_DATA、FILE_APPEND_DATA或GENERIC_WRITE标志。 请注意,仅FILE_APPEND_DATA访问文件不允许调用方在文件中的任意位置写入,除非当前文件结束标记处,而对文件具有FILE_WRITE_DATA访问权限并不阻止调用方写入文件末尾或超出文件末尾。
如果前面对 NtCreateFile 的调用FILE_NO_INTERMEDIATE_BUFFERING设置了 CreateOptions 标志,则为 NtWriteFile 的 Length 和 ByteOffset 参数必须是扇区大小的整数。 有关详细信息,请参阅 NtCreateFile。
NtWriteFile 在 ByteOffset、当前文件位置或文件结尾标记处开始对文件的写入操作。 当已从 Buffer 写入长度字节时,它将终止写入操作。 如有必要,它会扩展文件的长度并重置文件结束标记。
如果调用方打开了设置了 DesiredAccess SYNCHRONIZE 标志的文件,则调用方可以等待此例程将给定 的 FileHandle 设置为信号状态。
在三种情况下,驱动程序应在系统进程的上下文中调用 NtWriteFile :
- 驱动程序创建传递给 NtWriteFile 的文件句柄。
- NtWriteFile 通过驱动程序创建的事件通知驱动程序 I/O 完成。
- NtWriteFile 通过驱动程序传递给 NtWriteFile 的 APC 回调例程通知驱动程序 I/O 完成。
文件和事件句柄仅在创建句柄的进程上下文中有效。 因此,为了避免安全漏洞,驱动程序应在系统进程的上下文而不是驱动程序所处的进程上下文中创建传递给 NtWriteFile 的任何文件或事件句柄。
同样,如果 NtWriteFile 通过 APC 通知驱动程序 I/O 完成,则应在系统进程的上下文中调用,因为 APC 始终在发出 I/O 请求的线程上下文中触发。 如果驱动程序在系统进程以外的其他进程的上下文中调用 NtWriteFile ,则 APC 可能会无限期延迟,或者它可能根本不触发,因为原始线程可能永远不会进入可警报的等待状态。
有关使用文件的详细信息,请参阅 在驱动程序中使用文件。
NtWriteFile 的调用方必须在 IRQL = PASSIVE_LEVEL 且启用了特殊内核 APC 的情况下运行。
如果在用户模式下调用此函数,则应使用名称“NtWriteFile”而不是“ZwWriteFile”。
对于来自内核模式驱动程序的调用,Windows Native System Services 例程的 NtXxx 和 ZwXxx 版本在处理和解释输入参数的方式上的行为可能有所不同。 有关例程的 NtXxx 和 ZwXxx 版本之间的关系的详细信息,请参阅 使用本机系统服务例程的 Nt 和 Zw 版本。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 2000 |
目标平台 | 通用 |
标头 | ntifs.h(包括 Wdm.h、Ntddk.h、Ntifs.h) |
Library | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | PASSIVE_LEVEL (请参阅“备注”部分) |
DDI 符合性规则 | HwStorPortProhibitedDDI、PowerIrpDDis |