ZwCreateFile routine
ZwCreateFile 创建一个新的文件或者打开一个已经存在的文件。
Syntax
C++
NTSTATUS ZwCreateFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_opt_ PLARGE_INTEGER AllocationSize,
_In_ ULONG FileAttributes,
_In_ ULONG ShareAccess,
_In_ ULONG CreateDisposition,
_In_ ULONG CreateOptions,
_In_opt_ PVOID EaBuffer,
_In_ ULONG EaLength
);
Parameters
FileHandle [out]
用于接收文件句柄的指针。
DesiredAccess [in]
指定一个 ACCESS_MASK 值,决定打开文件后期望的访问方式 。 此外这些访问权限的定义能被所有类型的对象使用。 调用者可以指定以下列表中(对象类型相关的)任意访问权限。
ACCESS_MASK flag | Allows caller to do this |
FILE_READ_DATA | 从文件中读取内容 |
FILE_READ_ATTRIBUTES | 读取文件的属性。 (详见FileAttributes参数的描述) |
FILE_READ_EA | 读取文件的拓展属性。 设备和中间层驱动不适用 |
FILE_WRITE_DATA | 写入数据到文件 |
FILE_WRITE_ATTRIBUTES | 写文件属性。 (详见FileAttributes参数的描述) |
FILE_WRITE_EA | 改变文件的拓展属性,设备和中间层驱动不适用 |
FILE_APPEND_DATA | 追加文件数据 |
FILE_EXECUTE | 使用系统页面IO(system paging I/O)读取文件到内存,设备和中间层驱动不适用 |
Note 当创建或者打开一个目录时不能指定 FILE_READ_DATA, FILE_WRITE_DATA, FILE_APPEND_DATA, or FILE_EXECUTE。
调用者可为一个文件(不能是目录)指定一个通用访问权限(generic access right), GENERIC_XXX, 和通用访问权限对应的权限列在下表中。
通用权限 | 指定权限集合 |
GENERIC_READ | STANDARD_RIGHTS_READ, FILE_READ_DATA, FILE_READ_ATTRIBUTES, FILE_READ_EA, and SYNCHRONIZE. |
GENERIC_WRITE | STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA, FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, FILE_APPEND_DATA, and SYNCHRONIZE. |
GENERIC_EXECUTE | STANDARD_RIGHTS_EXECUTE, FILE_EXECUTE, FILE_READ_ATTRIBUTES, and SYNCHRONIZE. This value is irrelevant for device and intermediate drivers. |
GENERIC_ALL | FILE_ALL_ACCESS. |
例如,当为一个文件对象指定GENERIC_READ时, 例程将这个值映射为FILE_GENERIC_READ访问权限的位掩码。在之前的表中, GENERIC_READ指定的访问权限对应FILE_GENERIC_READ包含的位掩码中。如果文件事实上是一个路径,那么调用者可以使用以下的通用访问权限。
DesiredAccess flag | Allows caller to do this |
FILE_LIST_DIRECTORY | 列出目录中的文件 |
FILE_TRAVERSE | 遍历目录,也包括子目录 |
有关访问权限的更多信息详见: ACCESS_MASK.
ObjectAttributes [in]
一个指向 OBJECT_ATTRIBUTES 结构的指针,指定对象名称和其他属性。使用 InitializeObjectAttributes 来初始化这个结构. 如果调用者不在系统线程上下文中,那么必须在调用InitializeObjectAttributes时设置OBJ_KERNEL_HANDLE属性。
IoStatusBlock [out]
指向IO_STATUS_BLOCK结构体的指针,用于接收所请求操作的最后完成状态和其他信息。它的Information 成员被设置为以下值中的一个:
· FILE_CREATED
· FILE_OPENED
· FILE_OVERWRITTEN
· FILE_SUPERSEDED
· FILE_EXISTS
· FILE_DOES_NOT_EXIST
AllocationSize [in, optional]
指向LARGE_INTEGER的指针,包含了初始分配内存大小,以字节为单位。 它用于当一个文件被创建或者被覆盖重写时。如果 AllocationSize 为NULL,那么不指定一个分配的大小,如果没有文件别创建或者重新,此参数被忽略。
FileAttributes [in]
指定一个或者多个 FILE_ATTRIBUTE_XXX 标志, 用于表示当创建或者重写文件时设置的文件属性。调用者一般指定该值为FILE_ATTRIBUTE_NORMAL以设定一个默认的属性。关于FILE_ATTRIBUTE_XXX 标志列表的详细信息见Microsoft Windows SDK documentation中的CreateFile例程。 如果没有文件被创建或者重写, FileAttributes将被忽略。
ShareAccess [in]
共享访问的类型。可以是0或者是以下列表中的标志的任意组合。
ShareAccess flag | 允许其他线程做的事情 |
FILE_SHARE_READ | 读文件 |
FILE_SHARE_WRITE | 写文件 |
FILE_SHARE_DELETE | 删除文件 |
设备和中间层驱动一般设置ShareAccess 为0,表示调用者以独占访问方式打开文件。
CreateDisposition [in]
指定如果文件存在或者不存在时所做的操作。 CreateDisposition 可以是以下列表中的任意一个值。
CreateDisposition value | 文件存在时的操作 | 文件不存在时的操作 |
FILE_SUPERSEDE | 替换文件 | 创建文件 |
FILE_CREATE | 返回一个错误 | 创建文件 |
FILE_OPEN | 打开文件 | 返回一个错误 |
FILE_OPEN_IF | 打开文件 | 创建文件 |
FILE_OVERWRITE | 打开文件并重写 | 返回错误 |
FILE_OVERWRITE_IF | 打开文件并重写 | 创建文件 |
CreateOptions [in]
指定驱动创建或者打开文件时需要应用的选项,使用一个或者多个以下列表中的标志。
CreateOptions flag | Meaning |
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 | 系统服务,文件系统驱动和其他写入数据到文件的驱动必须在任何请求的写操作被认为完成前实际传输数据到文件。(System services, file-system drivers, and drivers that write data to the file must actually transfer the data to the file before any requested write operation is considered complete.) |
FILE_SEQUENTIAL_ONLY | 对文件的任何操作必须是顺序操作。(禁止随即访问) |
FILE_RANDOM_ACCESS | 允许随即访问文件, 因此文件系统驱动或者系统不应当对该文件执行预读(read-ahead)操作。 |
FILE_NO_INTERMEDIATE_BUFFERING | 文件无法在驱动的内部缓冲区中被缓存。此标志无法与DesiredAccess的FILE_APPEND_DATA一起使用。 |
FILE_SYNCHRONOUS_IO_ALERT | 所有在此文件上执行的操作都是同步的。 Any wait on behalf of the caller is subject to premature termination from alerts. 此标志同样也导致了I/O系统保持文件位置的上下文。如果此标志被设置,那么DesiredAccess必须设置为SYNCHRONIZE。 |
FILE_SYNCHRONOUS_IO_NONALERT | 在文件上执行的任何操作都是同步的, Waits in the system that synchronize I/O queuing and completion are not subject to alerts. 此符号同样导致I/O系统保持一个文件位置的上下文。如果此标志被设置,那么DesiredAccess必须设置为SYNCHRONIZE。 |
FILE_CREATE_TREE_CONNECTION | Create a tree connection for this file in order to open it over the network. 此符号不能用于设备或者中间层驱动。 |
FILE_COMPLETE_IF_OPLOCKED | 如果目标文件被机会锁锁定,不阻塞调用者的线程直接完成操作并返回一个STATUS_OPLOCK_BREAK_IN_PROGRESS。 如果文件被机会锁锁定另外的调用者已经对这个文件进行访问。此符号不能再设备和中间层驱动上使用。 |
FILE_NO_EA_KNOWLEDGE | If the extended attributes (EAs) for an existing file being opened indicate that the caller must understand EAs to properly interpret the file, ZwCreateFile should return an error. 此符号不能再设备和中间层驱动上使用。 |
FILE_OPEN_REPARSE_POINT | Open a file with a reparse point and bypass normal reparse point processing for the file.详见Remarks 一节 |
FILE_DELETE_ON_CLOSE | 当此文件的所有句柄都被ZwClose关闭时删除此文件。如果被设置,那么DesiredAccess必须包含DELETE标志。 |
FILE_OPEN_BY_FILE_ID | ObjectAttributes参数指定的文件名包含一个二进制8字节或者16字节参考数字或者对象ID,这取决于如下所示的文件系统。在此之前可以有任意的一个设备名称(在反斜杠之后)。例如一个设备名可能是如下格式: \??\C:\<8 bytes of binary FileID> \device\HardDiskVolume1\<16 bytes of binary ObjectID> · 在NTFS上,这可以是8字节或者16直接参考数字或者对象ID. 一个16-byte 参考数字和追加了一些0的8-byte 参考数字被视为一样。 · · On ReFS, 可以是一个8-byte 或者是16-byte 参考数字. 一个16-byte 数值和一个8-byte数字没有什么关联. 不支持对象ID。 · · FAT, ExFAT, UDFS, and CDFS文件系统不支持这个标志。 · 文件数字为特定的特殊文件系统分配。 Note 文件名域可能部分包含一个二进制块,因此不可以假设它是一个有效的Unicode字符串,更重要的是不能假设它是一个NULL结尾的字符串。
|
FILE_OPEN_FOR_BACKUP_INTENT | 为备份而打开文件。因此系统应为调用者检查必要的访问权限和授予调用核实的权限以访问该文件--在对DesiredAccess和文件安全描述符检查直线。 此符号不能再设备和中间层驱动上使用。 |
FILE_RESERVE_OPFILTER | 此标志允许一个应用程序请求一个过滤器机会锁 (oplock)以防止其他应用程序共享违例,如果它们已经打开了句柄,那么创建请求将以STATUS_OPLOCK_NOT_GRANTED失败返回,更多信息见Remarks节. |
FILE_OPEN_REQUIRING_OPLOCK | The file is being opened and an opportunistic lock (oplock) on the file is being requested as a single atomic operation. The file system checks for oplocks before it performs the create operation, and will fail the create with a return code of STATUS_CANNOT_BREAK_OPLOCK if the result would be to break an existing oplock. Note The FILE_OPEN_REQUIRING_OPLOCK 在Windows 7, Windows Server 2008 R2 和之后的 Windows 系统中有效.
|
FILE_SESSION_AWARE | The client opening the file or device is session aware and per session access is validated if necessary. Note The FILE_SESSION_AWARE 对Windows 8之后的系统有效.
|
EaBuffer [in, optional]
设备和中间层驱动必须设置此参数为NULL
EaLength [in]
设备和中间层驱动必须设置此参数为0
Return value
ZwCreateFile 成功时返回 STATUS_SUCCESS ,失败时返回一个合适的NTSTATUS 错误码。在后面一情况中可以通过IoStatusBlock 参数的值检查错误原因。
Note ZwCreateFile 可能返回 STATUS_FILE_LOCK_CONFLICT ,或者在IO_STATUS_BLOCK 的Status 成员中,这只可能发生在NTFS日志文件已满而ZwCreateFile试图处理这个问题的情况下。
Remarks
ZwCreateFile 提供了一个句柄,调用者可以利用它去操作一个文件的数据或者是文件对象的状态和属性。更多信息见 Using Files in a Driver。
一旦FileHandle指向的文件句柄代表的文件不在被使用,驱动必须调用函数ZwClose 关闭它。
如果调用者不在系统线程的上下文中运行,必须保证任何它创建的句柄为私有的。否则其他在驱动中运行的进程上下文可以访问它。更多信息见: Object Handles.
有两种不同的方法指定将要被ZwCreateFile创建或者打开的文件的文件名。
1.
一个合法的全路径, 在ObjectAttributes的ObjectName 中提供。
2.
以RootDirectory 句柄代表的目录文件对象的路径为相对路径
为DesiredAccess 设置合适的参数将有如下效果:
·
调用者同步一个在FileHandle文件上的I/O, 必须设置SYNCHRONIZE,否则(设备和中间层驱动)调用者必须通过一个等待时间同步一个I/O的结束。
·
如果调用者仅设置了FILE_APPEND_DATA 和SYNCHRONIZE 标志, 它只能王文件的结尾写入数据。任何写入操作的文件偏移信息都被忽略。文件将为这个类型的操作自动扩展。
·
为一个文件设置FILE_WRITE_DATA 标志同样允许调用者往文件的接卸写入数据,同样的,文件在必要的情况下也将自动扩展。
·
如果调用者仅设置了FILE_EXECUTE 和 SYNCHRONIZE 标志,它将不能在返回的FileHandle上直接读写任何数据。也就是说,所有在文件上的操作都将通过系统页面管理器执行。(That is, all operations on the file occur through the system pager in response to instruction and data-access operations)设备和中间层驱动不能使用 FILE_EXECUTE 标志。
·
ShareAccess 参数决定了不同的线程是否能够同时访问同一文件, 通过提供不同的调用者合适的访问权限文件能被成功打开并且共享。如果第一个ZwCreateFile 的调用者没有设置FILE_SHARE_READ, FILE_SHARE_WRITE, 或 FILE_SHARE_DELETE, 其他调用者无法打开这个文件,也就是说第一个调用者被授予了独占访问的权限。为了打开一个能共享打开的文件DesiredAccess 参数必须设置为和之前所有未释放的打开操作兼容的值。也就是说ZwCreateFile 的DesiredAccess 参数不能和这个文件其他打开者的访问权限冲突。
CreateDisposition 参数 FILE_SUPERSEDE 要求调用者具有一个已经存在的文件对象的DELETE 访问权限. 如果是这样,一个CreateDisposition参数为FILE_SUPERSEDE 的ZwCreateFile 成功打开一个已经存在的文件并删除它,然后重新生成它。这意味着, 如果这个文件已经被其他线程打开,那么其他线程打开的参数ShareAccess 被指定为FILE_SHARE_DELETE, Note that this type of disposition is consistent with the POSIX style of overwriting files.
CreateDisposition 值为FILE_OVERWRITE_IF 和FILE_SUPERSEDE 类似。如果 ZwCreateFile 创建一个已经存在的文件,那么文件将被替换。
重写一个文件和取代一个文件在语意上是一致的,但除了以下不同。
·
调用者必须具有对文件的写权限而不是删除权限,这意味着,如果文件已经被其他线程打开,其他线程打开这个文件时设置了ShareAccess中的FILE_SHARE_WRITE标志。
·
指定的文件属性和已经存在的文件属性是逻辑与的关系,这意味着如果文件已经被其他线程打开,一个之后的ZwCreateFile 调用者不能禁用/删除已经存在的文件属性标志但是可以为同一个文件增加额外的标志。 注意这种覆盖文件的风格和MS-DOS, Microsoft Windows 3.1, and OS/2是一致的。
·
CreateOptions 参数设置为FILE_DIRECTORY_FILE 需要创建或者打开的文件是一个目录,当一个目录文件被创建,文件系统在硬盘上创建一个合适的(特定文件系统相关的on-disk)结构用于表示一个空的目录。如果此参数被指定而将要打开的文件不是一个目录文件,或者是调用者提供了与之不匹配的CreateOptions 或CreateDisposition 参数, ZwCreateFile 将失败。.
CreateOptions 参数设定为FILE_NO_INTERMEDIATE_BUFFERING 标志时将组织文件系统指定任何该调用者的中间层缓冲。指定这个标志将限定调用者使用其他ZwXxxFile 例程的参数。
·
任何传递给ZwReadFile or ZwWriteFile 的可选参数ByteOffset必须是sector size的整数倍。
·
传递给ZwReadFile or ZwWriteFile 的Length 参数必须是一个完整的 sector size. Note that specifying a read operation to a buffer whose length is exactly the sector size might result in a lesser number of significant bytes being transferred to that buffer if the end of the file was reached during the transfer.
·
缓冲区必须按照底层设备的对齐要求进行对齐. 想要获取这些信息,调用ZwCreateFile 以获取代表物理设备的文件对象,然后传递这个句柄给ZwQueryInformationFile. 想获取系统FILE_XXX_ALIGNMENT的值,请见: DEVICE_OBJECT。
·
调用 ZwSetInformationFile 时如果 FileInformationClass设置为FilePositionInformation 必须指定一个sector size整数倍的偏移值.
·
CreateOptions 标志: FILE_SYNCHRONOUS_IO_ALERT 和FILE_SYNCHRONOUS_IO_NONALERT 顾名思义,它们是互斥的一对标志。 指定它们将使得在FileHandle指定的文件设备上的所有I/O操作被设置为同步,所有线程在这个文件上的I/O操作都将被序列化,如果任意一个标志被设定DesiredAccess 必须设定为SYNCHRONIZE — 用以迫使I/O manager作为一个同步对象使用这个文件对象. 在种情况下,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 标志消除了你获取一个机会锁打开文件和可能允许第三放打开文件并得到一个共享违例错误之间的时间。 应用程序可以使用FILE_OPEN_REQUIRING_OPLOCK 调用 ZwCreateFile 然后获得一个机会锁. 这保证了一个机会锁拥有者将在接下来的导致共享违例的打开请求中收到通知。
在Window7中,这个文件的其他句柄存在时应用程序使用了FILE_OPEN_REQUIRING_OPLOCK 标志, 这个创建操作将以错误号 STATUS_OPLOCK_NOT_GRANTED失败,这个限制从Windows 8开始被取消。
如果文件创建操作会打断一个存在文件上的机会锁, 那么设置 FILE_OPEN_REQUIRING_OPLOCK flag 将导致创建操作以STATUS_CANNOT_BREAK_OPLOCK失败。已经存在的机会锁不会被这个创建操作打断。
使用FILE_OPEN_REQUIRING_OPLOCK 标志的应用程序必须在这个调用成功后获取一个机会锁 否则所有接下来试图打开这个文件的操作将被阻塞而失去正常机会锁操作的好处。类似的如果这个文件成功但是接下来的机会锁请示失败了,使用这个标志的应用程序在检测到机会锁请求失败后必须关闭这个句柄
Note The FILE_OPEN_REQUIRING_OPLOCK 标志在 Windows 7, Windows Server 2008 R2 和之后的 Windows 操作系统有效. 应用了此标志的Windows 7文件系统包括NTFS, FAT, 和 exFAT.
CreateOptions 标志FILE_RESERVE_OPFILTER 允许一个应用程序申请一个Level 1, Batch, 或Filter oplock 用以防止其他应用程序发生一个共享违例错误。然而, FILE_RESERVE_OPFILTER 仅对过滤器机会锁特别有效,要使用它,你必须完成以下步骤:
以CreateOptions 为 FILE_RESERVE_OPFILTER发布一个创建请求时, DesiredAccess 设置为 FILE_READ_ATTRIBUTES, ShareAccess 设置为 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE.
·
如果有文件已经被打开的其他句柄,创建请求以STATUS_OPLOCK_NOT_GRANTED失败, 接下来获取机会锁也会失败。
·
如果打开时使用了更多的访问参数或者更少的共享限定同样导致以STATUS_OPLOCK_NOT_GRANTED失败。
·
如果创建文件成功,请求一个机会锁。
打开文件的其他句柄进行I/O.
第三步使得这仅对过滤器机会锁实用。第三步中打开的句柄的DesiredAccess 最多可以是FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE | SYNCHRONIZE | READ_CONTROL,且依然不会打断过滤机会锁,然而任何超过FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE的DesiredAccess将导致打断一个Level 1 或者是 Batch 机会锁。并且将导致FILE_RESERVE_OPFILTER 在这些机会锁类型上失效。
NTFS 是唯一一种实现了FILE_RESERVE_OPFILTER的文件系统。
ZwCreateFile 的调用者必须在IRQL = PASSIVE_LEVEL的级别上 并且 with special kernel APCs enabled.
Note 如果这个函数在用户模式下被调用,您当使用 "NtCreateFile" 代替 "ZwCreateFile".
Requirements
Target platform | |
Version | 自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 |
See also
窗体底端