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 parameter.)
FILE_READ_EA 读取文件的扩展属性 (CA) 。 此标志与设备和中间驱动程序无关。
FILE_WRITE_DATA 将数据写入文件。
FILE_WRITE_ATTRIBUTES 写入文件的属性。 (有关详细信息,请参阅 FileAttributes parameter.)
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的指针,其中包含创建或覆盖的文件的初始分配大小(以字节为单位)。 如果 AllocationSizeNULL,则不指定分配大小。 如果未创建或覆盖任何文件,则忽略 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 为此文件创建树连接,以便通过网络打开它。 设备和中间驱动程序不使用此标志。
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 创建或打开的文件的名称:

  1. 作为完全限定的路径名,在输入 ObjectAttributesObjectName 成员中提供。

  2. 作为相对于输入 ObjectAttributesRootDirectory 成员中的句柄表示的目录文件的路径名。

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 标志必须与尚未通过 释放的所有先前打开操作的 DesiredAccessShareAccess 标志兼容。 也就是说,指定给给定文件的 ZwCreateFileDesiredAccess 不得与该文件的其他打开程序禁止的访问发生冲突。

CreateDisposition 值FILE_SUPERSEDE要求调用方对现有文件对象具有 DELETE 访问权限。 如果是这样,如果成功调用 ZwCreateFile 并FILE_SUPERSEDE现有文件,则会有效地删除该文件,然后重新创建该文件。 这意味着,如果文件已被另一个线程打开,则它通过指定一个 ShareAccess 参数来打开文件,并设置了FILE_SHARE_DELETE标志。 请注意,这种类型的处置与覆盖文件的 POSIX 样式一致。

CreateDisposition 值FILE_OVERWRITE_IF和FILE_SUPERSEDE相似。 如果 ZwCreateFile 是使用现有文件以及其中任一 CreateDisposition 值调用的,则将替换该文件。

覆盖文件在语义上等效于取代操作,但以下情况除外:

  • 调用方必须对文件具有写入访问权限,而不是删除访问权限。 这意味着,如果文件已由另一个线程打开,它将在输入 ShareAccess 中设置FILE_SHARE_WRITE标志打开文件。

  • 指定的文件属性在逻辑上与文件上已有的属性一起为 ORed。 这意味着,如果文件已被另一个线程打开, ZwCreateFile 的后续调用方无法禁用现有的 FileAttributes 标志,但可以为同一文件启用其他标志。

FILE_DIRECTORY_FILE CreateOptions 值指定要创建或打开的文件是目录。 创建目录文件时,文件系统会在磁盘上创建适当的结构,以表示该特定文件系统的磁盘上结构的空目录。 如果指定了此选项,并且要打开的给定文件不是目录文件,或者调用方指定的 CreateOptionsCreateDisposition 值不一致,则对 ZwCreateFile 的调用将失败。

FILE_NO_INTERMEDIATE_BUFFERING CreateOptions 标志阻止文件系统代表调用方执行任何中间缓冲。 指定此标志会将调用方参数的以下限制置于其他 ZwXxx文件 例程:

  • 传递给 ZwReadFile 或 ZwWriteFile 的任何可选 ByteOffset 必须是扇区大小的倍数。

  • 传递给 ZwReadFileZwWriteFileLength 必须是扇区大小的整数。 请注意,如果在传输过程中到达文件的末尾,则指定对长度正好为扇区大小的缓冲区的读取操作可能会导致传输到该缓冲区的重要字节数减少。

  • 缓冲区必须根据基础设备的对齐要求进行对齐。 若要获取此信息,请调用 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 管理器会跟踪当前文件位置偏移量,你可以将偏移量传递给 ZwReadFileZwWriteFile。 调用 ZwQueryInformationFileZwSetInformationFile 获取或设置此位置。

如果未指定 CreateOptions FILE_OPEN_REPARSE_POINT 标志,并且 ZwCreateFile 尝试使用重新分析点打开文件,则文件将进行正常的重新分析点处理。 另一方面,如果指定了FILE_OPEN_REPARSE_POINT标志,则不会进行正常的重新分析处理, 并且 ZwCreateFile 会尝试直接打开重新分析点文件。 在任一情况下,如果打开操作成功, ZwCreateFile 将返回STATUS_SUCCESS;否则,例程将返回 NTSTATUS 错误代码。 ZwCreateFile 从不返回STATUS_REPARSE。

CreateOptions FILE_OPEN_REQUIRING_OPLOCK 标志消除了打开该文件和请求 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、Batch 或 Filter oplock,以防止其他应用程序发生共享冲突。 但是,FILE_RESERVE_OPFILTER实际上只对 Filter oplock 有用。 若要使用它,必须完成以下步骤:

  1. 使用 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失败。

  2. 如果创建请求成功,请请求 oplock。

  3. 打开文件的另一个句柄以执行 I/O。

步骤 3 使此功能仅适用于 Filter oplock。 步骤 3 中打开的句柄可以包含最多FILE_READ_ATTRIBUTES的 DesiredAccess |FILE_WRITE_ATTRIBUTES |FILE_READ_DATA |FILE_READ_EA |FILE_EXECUTE |SYNCHRONIZE |READ_CONTROL,但仍未中断 Filter oplock。 但是,任何大于 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 本机系统服务例程的 NtXxxZwXxx 版本在处理和解释输入参数的方式上的行为可能有所不同。 有关例程的 NtXxxZwXxx 版本之间的关系的详细信息,请参阅 使用本机系统服务例程的 Nt 和 Zw 版本

要求

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

另请参阅

ACCESS_MASK

DEVICE_OBJECT

IO_STATUS_BLOCK

InitializeObjectAttributes

使用本机系统服务例程的 Nt 和 Zw 版本

ZwClose

ZwOpenFile

ZwQueryInformationFile

ZwReadFile

ZwSetInformationFile

ZwWriteFile

 机会锁

重分析点