ZwCreateFile 函数 (wdm.h)
ZwCreateFile 例程创建新文件或打开现有文件。
语法
NTSYSAPI NTSTATUS ZwCreateFile(
[out] PHANDLE FileHandle,
[in] ACCESS_MASK DesiredAccess,
[in] POBJECT_ATTRIBUTES ObjectAttributes,
[out] PIO_STATUS_BLOCK IoStatusBlock,
[in, optional] PLARGE_INTEGER AllocationSize,
[in] ULONG FileAttributes,
[in] ULONG ShareAccess,
[in] ULONG CreateDisposition,
[in] ULONG CreateOptions,
[in, optional] PVOID EaBuffer,
[in] ULONG EaLength
);
参数
[out] FileHandle
指向 HANDLE 变量的指针,该变量接收文件的句柄。
[in] DesiredAccess
指定一个 ACCESS_MASK 值,该值确定对 对象的请求访问权限。 除了为所有类型的对象定义的访问权限外,调用方还可以指定以下任何特定于文件的访问权限。
ACCESS_MASK标志 | 允许调用方执行此操作 |
---|---|
FILE_READ_DATA | 从文件读取数据。 |
FILE_READ_ATTRIBUTES | 读取文件的属性。 (有关详细信息,请参阅 FileAttributes 参数的说明。) |
FILE_READ_EA | 读取文件的扩展属性 (CA) 。 此标志与设备和中间驱动程序无关。 |
FILE_WRITE_DATA | 将数据写入文件。 |
FILE_WRITE_ATTRIBUTES | 写入文件的属性。 (有关详细信息,请参阅 FileAttributes 参数的说明。) |
FILE_WRITE_EA | (文件的 CA) 更改扩展属性。 此标志与设备和中间驱动程序无关。 |
FILE_APPEND_DATA | 将数据追加到文件。 |
FILE_EXECUTE | 使用系统分页 I/O 将数据从文件读取到内存中。 此标志与设备和中间驱动程序无关。 |
创建或打开目录时,请勿指定FILE_READ_DATA、FILE_WRITE_DATA、FILE_APPEND_DATA或FILE_EXECUTE。
调用方只能为文件指定泛型访问权限(GENERIC_XXX),不能指定目录。 一般访问权限对应于特定访问权限,如下表所示。
通用访问权限 | 特定访问权限集 |
---|---|
GENERIC_READ | STANDARD_RIGHTS_READ、FILE_READ_DATA、FILE_READ_ATTRIBUTES、FILE_READ_EA和 SYNCHRONIZE。 |
GENERIC_WRITE | STANDARD_RIGHTS_WRITE、FILE_WRITE_DATA、FILE_WRITE_ATTRIBUTES、FILE_WRITE_EA、FILE_APPEND_DATA和 SYNCHRONIZE。 |
GENERIC_EXECUTE | STANDARD_RIGHTS_EXECUTE、FILE_EXECUTE、FILE_READ_ATTRIBUTES和 SYNCHRONIZE。 此值与设备和中间驱动程序无关。 |
GENERIC_ALL | FILE_ALL_ACCESS。 |
例如,如果为文件对象指定GENERIC_READ,则例程会将此值映射到特定访问权限FILE_GENERIC_READ位掩码。 在上表中,为 GENERIC_READ列出的特定访问权限对应于FILE_GENERIC_READ位掩码中包含的访问标志。
如果文件实际上是一个目录,则调用方还可以指定以下通用访问权限。
DesiredAccess 标志 | 允许调用方执行此操作 |
---|---|
FILE_LIST_DIRECTORY | 列出目录中的文件。 |
FILE_TRAVERSE | 遍历目录,换言之,将目录包含在文件的路径中。 |
有关访问权限的详细信息,请参阅 ACCESS_MASK。
[in] ObjectAttributes
指向 OBJECT_ATTRIBUTES 结构的指针,该结构指定对象名称和其他属性。 使用 InitializeObjectAttributes 初始化此结构。 如果调用方未在系统线程上下文中运行,则必须在调用 InitializeObjectAttributes 时设置 OBJ_KERNEL_HANDLE 属性。
[out] IoStatusBlock
指向 IO_STATUS_BLOCK 结构的指针,该结构接收最终完成状态和有关所请求操作的其他信息。 特别是, Information 成员接收以下值之一:
FILE_CREATED
FILE_OPENED
FILE_OVERWRITTEN
FILE_SUPERSEDED
FILE_EXISTS
FILE_DOES_NOT_EXIST
[in, optional] AllocationSize
指向LARGE_INTEGER的指针,其中包含创建或覆盖的文件的初始分配大小(以字节为单位)。 如果 AllocationSize 为 NULL,则不指定任何分配大小。 如果未创建或覆盖任何文件,则忽略 AllocationSize 。
[in] FileAttributes
指定一个或多个 FILE_ATTRIBUTE_XXX 标志,这些标志表示在创建或覆盖文件时要设置的文件属性。 调用方通常指定FILE_ATTRIBUTE_NORMAL,用于设置默认属性。 有关有效 FILE_ATTRIBUTE_XXX 标志的列表,请参阅 CreateFile 例程。 如果未创建或覆盖任何文件,则忽略 FileAttributes 。
[in] ShareAccess
共享访问的类型,指定为零或以下标志的任意组合。
ShareAccess 标志 | 允许其他线程执行此操作 |
---|---|
FILE_SHARE_READ | 读取文件 |
FILE_SHARE_WRITE | 写入文件 |
FILE_SHARE_DELETE | 删除文件 |
设备和中间驱动程序通常将 ShareAccess 设置为零,这为调用方提供了对打开的文件的独占访问权限。
[in] CreateDisposition
指定在文件存在或不存在时要执行的操作。 CreateDisposition 可以是下表中的值之一。
CreateDisposition 值 | 如果文件存在,则执行操作 | 如果文件不存在,则执行操作 |
---|---|---|
FILE_SUPERSEDE | 替换 文件。 | 创建文件。 |
FILE_CREATE | 返回错误。 | 创建文件。 |
FILE_OPEN | 打开 文件。 | 返回错误。 |
FILE_OPEN_IF | 打开 文件。 | 创建文件。 |
FILE_OVERWRITE | 打开文件并覆盖它。 | 返回错误。 |
FILE_OVERWRITE_IF | 打开文件并覆盖它。 | 创建文件。 |
[in] CreateOptions
指定驱动程序创建或打开文件时要应用的选项。 使用下表中的一个或多个标志。
CreateOptions 标志 | 含义 |
---|---|
FILE_DIRECTORY_FILE | 此文件是一个目录。 兼容的 CreateOptions 标志包括FILE_SYNCHRONOUS_IO_ALERT、FILE_SYNCHRONOUS_IO_NONALERT、FILE_WRITE_THROUGH、FILE_OPEN_FOR_BACKUP_INTENT和FILE_OPEN_BY_FILE_ID。 CreateDisposition 参数必须设置为 FILE_CREATE、FILE_OPEN 或 FILE_OPEN_IF。 |
FILE_NON_DIRECTORY_FILE | 该文件不是目录。 要打开的文件对象可以表示数据文件;逻辑、虚拟或物理设备;或卷。 |
FILE_WRITE_THROUGH | 在将任何请求的写入操作视为完成之前,系统服务、文件系统驱动程序和将数据写入文件的驱动程序必须实际将数据传输到文件。 |
FILE_SEQUENTIAL_ONLY | 对文件的所有访问都是按顺序进行的。 |
FILE_RANDOM_ACCESS | 对文件的访问可以是随机的,因此文件系统驱动程序或系统不应执行顺序预读操作。 |
FILE_NO_INTERMEDIATE_BUFFERING | 不能在驱动程序的内部缓冲区中缓存或缓冲该文件。 此标志与 DesiredAccess 参数的 FILE_APPEND_DATA 标志不兼容。 |
FILE_SYNCHRONOUS_IO_ALERT | 对文件执行的所有操作都是同步执行的。 代表调用方的任何等待都可能会提前终止警报。 此标志还会导致 I/O 系统维护文件位置指针。 如果设置了此标志,则必须在 DesiredAccess 参数中设置 SYNCHRONIZE 标志。 |
FILE_SYNCHRONOUS_IO_NONALERT | 对文件执行的所有操作都是同步执行的。 系统中同步 I/O 队列和完成的等待不受警报约束。 此标志还会导致 I/O 系统维护文件位置上下文。 如果设置了此标志,则必须在 DesiredAccess 参数中设置 SYNCHRONIZE 标志。 |
FILE_CREATE_TREE_CONNECTION | Create此文件的树连接,以便通过网络打开它。 设备和中间驱动程序不使用此标志。 |
FILE_COMPLETE_IF_OPLOCKED | 如果目标文件是机会锁定 (oplock) ,而不是阻止调用方线程,请立即使用备用成功代码STATUS_OPLOCK_BREAK_IN_PROGRESS完成此操作。 如果文件已锁定,则另一个调用方已有权访问该文件。 设备和中间驱动程序不使用此标志。 有关 oplock 的信息,请参阅 机会锁。 |
FILE_NO_EA_KNOWLEDGE | 如果扩展属性 (为打开的现有文件) 的 CA 指示调用方必须了解 CA 才能正确解释文件, 则 ZwCreateFile 应返回错误。 此标志与设备和中间驱动程序无关。 |
FILE_OPEN_REPARSE_POINT | 打开具有重分析点的文件,并绕过该文件的正常重分析点处理。 有关更多信息,请参见下面的“备注”部分。 有关重新分析点的信息,请参阅 重新分析点。 |
FILE_DELETE_ON_CLOSE | 当文件的最后一个句柄传递给 ZwClose 时,系统会删除该文件。 如果设置了此标志,则必须在 DesiredAccess 参数中设置 DELETE 标志。 |
FILE_OPEN_BY_FILE_ID | ObjectAttributes 参数指定的文件名包括文件的二进制 8 字节或 16 字节文件引用编号或对象 ID,具体取决于如下所示的文件系统。 (可选)后跟反斜杠字符的设备名称可以继续这些二进制值。 例如,设备名称将采用以下格式: ??\C:\FileID \device\HardDiskVolume1\ObjectID 其中 ,FileID 为 8 字节, ObjectID 为 16 字节。 在 NTFS 上,这可以是 8 字节或 16 字节引用编号或对象 ID。 16 字节引用编号与用零填充的 8 字节数字相同。 在 ReFS 上,这可以是 8 字节或 16 字节的引用编号。 16 字节数字与 8 字节数字无关。 不支持对象 ID。 FAT、ExFAT、UDFS 和 CDFS 文件系统不支持此标志。 此编号由 特定文件系统分配,并特定于特定文件系统。 由于文件名字段将部分包含二进制 blob,因此假定这是有效的 Unicode 字符串是不正确的,更重要的是,它可能不是以 null 结尾的字符串。 |
FILE_OPEN_FOR_BACKUP_INTENT | 正在为备份意向打开文件。 因此,在根据文件的安全描述符检查 DesiredAccess 参数之前,系统应检查某些访问权限,并授予调用方对文件的适当访问权限。 设备和中间驱动程序不使用此标志。 |
FILE_RESERVE_OPFILTER | 此标志允许应用程序请求 filter 机会锁 (oplock) ,以防止其他应用程序发生共享冲突。 如果已有打开的句柄,则创建请求将失败并STATUS_OPLOCK_NOT_GRANTED。 有关更多信息,请参见下面的“备注”部分。 有关 oplock 的信息,请参阅 机会锁。 |
FILE_OPEN_REQUIRING_OPLOCK | 正在打开文件,并且正在以单个原子操作的形式请求对文件 (oplock) 的机会锁。 文件系统在执行创建操作之前会检查 oplock,如果结果将中断现有 oplock,则会使创建失败并返回STATUS_CANNOT_BREAK_OPLOCK代码。 FILE_OPEN_REQUIRING_OPLOCK标志在 Windows 7、Windows Server 2008 R2 及更高版本的 Windows 操作系统中可用。 |
FILE_SESSION_AWARE | 打开文件或设备的客户端是会话感知的,并在必要时验证每个会话的访问权限。 FILE_SESSION_AWARE标志从 Windows 8 开始可用。 |
[in, optional] EaBuffer
对于设备和中间驱动程序,此参数必须是 NULL 指针。
[in] EaLength
对于设备和中间驱动程序,此参数必须为零。
返回值
ZwCreateFile 在成功时返回STATUS_SUCCESS或在失败时返回相应的 NTSTATUS 错误代码。 在后一种情况下,调用方可以通过检查 IoStatusBlock 参数来确定失败的原因。
ZwCreateFile 可能会返回STATUS_FILE_LOCK_CONFLICT作为返回值,或者在 IoStatusBlock 参数指向的 IO_STATUS_BLOCK 结构的 Status 成员中返回。 仅当 NTFS 日志文件已满并且 ZwCreateFile 尝试处理这种情况时发生错误时,才会发生这种情况。
注解
ZwCreateFile 提供调用方可用于操作文件数据或文件对象的状态和属性的句柄。 有关详细信息,请参阅 在驱动程序中使用文件。
不再使用 FileHandle 指向的句柄后,驱动程序必须调用 ZwClose 以将其关闭。
如果调用方未在系统线程上下文中运行,则必须确保它创建的任何句柄都是专用句柄。 否则,运行驱动程序的上下文中的进程可以访问句柄。 有关详细信息,请参阅 对象句柄。
有两种替代方法可以指定要使用 ZwCreateFile 创建或打开的文件的名称:
作为完全限定的路径名,在输入 ObjectAttributes 的 ObjectName 成员中提供。
作为相对于输入 ObjectAttributes 的 RootDirectory 成员中的句柄所表示的目录文件的路径名。
在 DesiredAccess 参数中设置某些标志会导致以下效果:
要使调用方通过等待返回 的 FileHandle 来同步 I/O 完成,必须设置 SYNCHRONIZE 标志。 否则,作为设备或中间驱动程序的调用方必须使用事件对象同步 I/O 完成。
如果调用方仅设置FILE_APPEND_DATA和 SYNCHRONIZE 标志,则它只能写入文件末尾,并且将忽略有关写入文件操作的任何偏移信息。 对于这种类型的操作,文件将根据需要自动扩展。
为文件设置FILE_WRITE_DATA标志还允许调用方写入文件末尾之外的内容。 同样,文件会根据需要自动扩展。
如果调用方仅设置FILE_EXECUTE和 SYNCHRONIZE 标志,则无法使用返回的 FileHandle 直接读取或写入文件的任何数据。 也就是说,针对文件的所有操作都通过系统寻呼程序进行,以响应指令和数据访问操作。 设备和中间驱动程序不应设置FILE_EXECUTE标志。
ShareAccess 参数确定单独的线程是否可以同时访问同一文件。 如果两个调用方都具有适当的访问特权,则可以成功打开和共享该文件。 如果 ZwCreateFile 的原始调用方未指定FILE_SHARE_READ、FILE_SHARE_WRITE或FILE_SHARE_DELETE,则其他调用方都不能打开该文件,即向原始调用方授予独占访问权限。
若要成功打开共享文件, DesiredAccess 标志必须与之前尚未通过 释放的所有打开操作的 DesiredAccess 和 ShareAccess 标志兼容。 也就是说,为给定文件指定给 ZwCreateFile 的 DesiredAccess 不得与文件的其他打开程序禁止的访问冲突。
CreateDisposition 值FILE_SUPERSEDE要求调用方对现有文件对象具有 DELETE 访问权限。 如果是这样,对现有文件使用 FILE_SUPERSEDE 成功调用 ZwCreateFile 会有效地删除该文件,然后重新创建该文件。 这意味着,如果文件已被另一个线程打开,则它通过指定 ShareAccess 参数来打开该文件,并设置了FILE_SHARE_DELETE标志。 请注意,这种类型的处置与覆盖文件的 POSIX 样式一致。
createDisposition 值FILE_OVERWRITE_IF和FILE_SUPERSEDE相似。 如果使用现有文件和任一 CreateDisposition 值调用 ZwCreateFile,则将替换该文件。
覆盖文件在语义上等效于取代操作,但以下操作除外:
调用方必须具有对文件的写入访问权限,而不是删除访问权限。 这意味着,如果文件已由另一个线程打开,则它打开文件时在输入 ShareAccess 中设置了FILE_SHARE_WRITE标志。
指定的文件属性在逻辑上是 ORed,文件中已有的属性。 这意味着,如果文件已由另一个线程打开, 则 ZwCreateFile 的后续调用方无法禁用现有的 FileAttributes 标志,但可以为同一文件启用其他标志。
FILE_DIRECTORY_FILE CreateOptions 值指定要创建或打开的文件是目录。 创建目录文件时,文件系统会在磁盘上创建适当的结构,以表示该特定文件系统的磁盘上结构的空目录。 如果指定了此选项,并且要打开的给定文件不是目录文件,或者调用方指定的 CreateOptions 或 CreateDisposition 值不一致,则对 ZwCreateFile 的调用将失败。
FILE_NO_INTERMEDIATE_BUFFERING CreateOptions 标志阻止文件系统代表调用方执行任何中间缓冲。 指定此标志会将以下限制用于其他 ZwXxx文件 例程的调用方参数:
传递给 ZwReadFile 或 ZwWriteFile 的任何可选 ByteOffset 必须是扇区大小的倍数。
传递给 ZwReadFile 或 ZwWriteFile 的 Length 必须是扇区大小的整数。 请注意,如果向长度正好为扇区大小的缓冲区指定读取操作,则如果在传输过程中到达文件末尾,则可能会减少传输到该缓冲区的重要字节数。
缓冲区必须根据基础设备的对齐要求进行对齐。 若要获取此信息,请调用 ZwCreateFile 以获取表示物理设备的文件对象的句柄,并将该句柄传递给 ZwQueryInformationFile。 有关系统FILE_XXX_ALIGNMENT值的列表,请参阅 DEVICE_OBJECT。
在 FileInformationClass 参数设置为 FilePositionInformation 的情况下调用 ZwSetInformationFile 时,必须指定扇区大小的倍数的偏移量。
FILE_SYNCHRONOUS_IO_ALERT 和 FILE_SYNCHRONOUS_IO_NONALERT CreateOptions 标志(顾名思义,它们互斥)指定对文件执行的所有 I/O 操作都是同步的, 只要它们通过返回的 FileHandle 引用的文件对象进行。 使用返回的句柄跨所有线程序列化此类文件上的所有 I/O。 如果设置了上述任一 CreateOptions 标志,还必须设置 SYNCHRONIZE DesiredAccess 标志,以强制 I/O 管理器将文件对象用作同步对象。 在这些情况下,I/O 管理器会跟踪当前文件位置偏移量,你可以将偏移量传递给 ZwReadFile 和 ZwWriteFile。 调用 ZwQueryInformationFile 或 ZwSetInformationFile 获取或设置此位置。
如果未指定 CreateOptions FILE_OPEN_REPARSE_POINT 标志,并且 ZwCreateFile 尝试打开具有重新分析点的文件,则该文件将进行正常的重新分析点处理。 另一方面,如果指定了FILE_OPEN_REPARSE_POINT标志,则不会进行正常的重新分析处理,并且 ZwCreateFile 会尝试直接打开重新分析点文件。 在任一情况下,如果打开操作成功, 则 ZwCreateFile 将返回STATUS_SUCCESS;否则,例程将返回 NTSTATUS 错误代码。 ZwCreateFile 从不返回STATUS_REPARSE。
CreateOptions FILE_OPEN_REQUIRING_OPLOCK 标志消除了打开文件和请求可能允许第三方打开文件并发生共享冲突的 oplock 之间的时间。 应用程序可以使用 ZwCreateFile 上的 FILE_OPEN_REQUIRING_OPLOCK 标志,然后请求任何 oplock。 这可确保 oplock 所有者收到导致共享冲突的任何后续打开请求的通知。
在 Windows 7 中,如果应用程序使用 FILE_OPEN_REQUIRING_OPLOCK 标志时文件上存在其他句柄,则创建操作将失败并显示STATUS_OPLOCK_NOT_GRANTED。 从Windows 8开始,此限制不再存在。
如果此创建操作会中断文件上已存在的 oplock,则设置FILE_OPEN_REQUIRING_OPLOCK标志将导致创建操作失败并STATUS_CANNOT_BREAK_OPLOCK。 此创建操作不会破坏现有的 oplock。
使用 FILE_OPEN_REQUIRING_OPLOCK 标志的应用程序必须在此调用成功后请求 oplock,否则所有后续打开该文件的尝试都将被阻止,而没有正常 oplock 处理的好处。 同样,如果此调用成功,但后续的 oplock 请求失败,则使用此标志的应用程序必须在检测到 oplock 请求失败后关闭其句柄。
FILE_OPEN_REQUIRING_OPLOCK标志在 Windows 7、Windows Server 2008 R2 及更高版本的 Windows 操作系统中可用。 在 Windows 7 中实现此标志的 Microsoft 文件系统是 NTFS、FAT 和 exFAT。
CreateOptions 标志FILE_RESERVE_OPFILTER允许应用程序请求级别 1、批处理或筛选器操作锁,以防止其他应用程序发生共享冲突。 但是,FILE_RESERVE_OPFILTER实际上仅适用于 Filter oplock。 若要使用它,必须完成以下步骤:
使用 createOptions 为 FILE_RESERVE_OPFILTER、DesiredAccess 为 exactly FILE_READ_ATTRIBUTES,ShareAccess 为 exactly FILE_SHARE_READ 发出创建请求 |FILE_SHARE_WRITE |FILE_SHARE_DELETE。
如果已有打开的句柄,则创建请求会失败并STATUS_OPLOCK_NOT_GRANTED,下一个请求的 oplock 也会失败。
如果使用更多访问权限或更少的共享打开也会导致STATUS_OPLOCK_NOT_GRANTED失败。
如果创建请求成功,则请求 oplock。
打开文件的另一个句柄以执行 I/O。
步骤 3 使此功能仅适用于筛选操作锁。 步骤 3 中打开的句柄可以包含最多FILE_READ_ATTRIBUTES的 DesiredAccess |FILE_WRITE_ATTRIBUTES |FILE_READ_DATA |FILE_READ_EA |FILE_EXECUTE |SYNCHRONIZE |READ_CONTROL,但仍不中断筛选器操作锁。 但是,任何大于 FILE_READ_ATTRIBUTES 的 DesiredAccess |FILE_WRITE_ATTRIBUTES |SYNCHRONIZE 将中断级别 1 或 Batch oplock,并使FILE_RESERVE_OPFILTER标志对这些 oplock 类型毫无用。
NTFS 是唯一实现FILE_RESERVE_OPFILTER的 Microsoft 文件系统。
ZwCreateFile 的调用方必须在 IRQL = PASSIVE_LEVEL 且启用了特殊内核 APC 的情况下运行。
如果在用户模式下调用此函数,则应使用名称“NtCreateFile”而不是“ZwCreateFile”。
对于来自内核模式驱动程序的调用,Windows Native System Services 例程的 NtXxx 和 ZwXxx 版本在处理和解释输入参数的方式上的行为可能有所不同。 有关例程的 NtXxx 和 ZwXxx 版本之间的关系的详细信息,请参阅 使用本机系统服务例程的 Nt 和 Zw 版本。
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
标头 | wdm.h(包括 Wdm.h、Ntddk.h、Ntifs.h) |
Library | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | PASSIVE_LEVEL (请参阅“备注”部分) |
DDI 符合性规则 | HwStorPortProhibitedDDI (storport) , PowerIrpDDis (wdm) |