IoCreateFile 函数 (wdm.h)
IoCreateFile 例程会导致创建新文件或目录,或者打开现有文件、设备、目录或卷,为调用方提供文件对象的句柄。
语法
NTSTATUS IoCreateFile(
[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 Disposition,
[in] ULONG CreateOptions,
[in, optional] PVOID EaBuffer,
[in] ULONG EaLength,
[in] CREATE_FILE_TYPE CreateFileType,
[in, optional] PVOID InternalParameters,
[in] ULONG Options
);
参数
[out] FileHandle
指向一个变量的指针,该变量接收文件句柄(如果调用成功)。 在句柄不再使用后,驱动程序必须使用 ZwClose 关闭该句柄。
[in] DesiredAccess
标志的位掩码,指定对调用方所需的文件或目录的访问类型。 有关此参数和标志值列表的详细信息,请参阅 IoCreateFileEx 的 DesiredAccess 参数。
[in] ObjectAttributes
指向已使用 InitializeObjectAttributes 初始化的不透明OBJECT_ATTRIBUTES结构的指针。 有关详细信息和每个结构成员的说明,请参阅 IoCreateFileEx 的 ObjectAttributes 参数。
[out] IoStatusBlock
指向 IO_STATUS_BLOCK 结构的指针,该结构接收最终完成状态和有关所请求操作的信息。 请参阅 IoCreateFileEx 的 IoStatusBlock 参数。
[in, optional] AllocationSize
(可选)指定文件的初始分配大小(以字节为单位)。 除非正在创建、覆盖或取代文件,否则非零值不起作用。
[in] FileAttributes
仅当创建、取代文件或在某些情况下被覆盖时,才会应用显式指定的属性。 默认情况下,此值为FILE_ATTRIBUTE_NORMAL,可由 Wdm.h 中定义的一个或多个 FILE_ATTRIBUTE_XXX 标志的 ORed 组合重写。 有关可与 IoCreateFile 一起使用的标志列表,请参阅 CreateFile。
[in] ShareAccess
指定调用方所需的文件的共享访问类型,为零个或一个,或者标志的组合。 有关更多详细信息和标志列表,请参阅 IoCreateFileEx 的 ShareAccess 参数。
[in] Disposition
指定一个值,该值确定要执行的操作,具体取决于文件是否已存在。 有关可能值的列表,请参阅 IoCreateFileEx 的 Disposition 参数。
[in] CreateOptions
指定要在创建或打开文件时应用的选项。 此参数是 IoCreateFileEx 的 CreateOptions 参数中列出和描述的标志的兼容组合。
[in, optional] EaBuffer
对于设备和中间驱动程序,此参数必须是 NULL 指针。
[in] EaLength
对于设备和中间驱动程序,此参数必须为零。
[in] CreateFileType
驱动程序必须将此参数设置为 CreateFileTypeNone。
[in, optional] InternalParameters
驱动程序必须将此参数设置为 NULL。
[in] Options
指定要在创建请求期间使用的选项。 有关可能选项的列表,请参阅 IoCreateFileEx 的 Options 参数。
返回值
IoCreateFile 返回STATUS_SUCCESS或适当的错误状态。 NTSTATUS 值。 有关可能的 返回 代码的列表,请参阅 IoCreateFileEx 的返回值部分。
注解
IoCreateFileEx 例程类似于 IoCreateFile 例程,但提供了比 IoCreateFile 例程更大的功能,包括访问额外的创建参数 (ECP) 、设备对象和事务信息。
IoCreateFile 获取的句柄可由后续调用使用,以操作文件中的数据或文件对象的状态或属性。
可通过两种替代方法指定要使用 IoCreateFile 创建或打开的文件的名称:
作为完全限定的路径名,在输入 ObjectAttributes 的 ObjectName 成员中提供
作为相对于输入 ObjectAttributes 的 RootDirectory 成员中的句柄表示的目录文件的路径名
某些 DesiredAccess 标志和标志组合具有以下效果:
对于调用方通过等待返回 的 FileHandle 来同步 I/O 完成,必须设置 SYNCHRONIZE 标志。 否则,作为设备或中间驱动程序的调用方必须使用事件对象同步 I/O 完成。
如果只设置了FILE_APPEND_DATA和 SYNCHRONIZE 标志,则调用方只能写入文件末尾,并且有关写入文件的任何偏移量信息将被忽略。 但是,对于这种类型的写入操作,文件将自动扩展。
为文件设置FILE_WRITE_DATA标志还允许写入文件末尾以外的操作。 文件也会自动扩展为此类写入。
如果只设置了FILE_EXECUTE和 SYNCHRONIZE 标志,则调用方无法使用返回的 FileHandle 直接读取或写入文件中的任何数据:也就是说,对文件执行的所有操作都通过系统寻呼程序进行,以响应指令和数据访问。 设备和中间驱动程序不应在 DesiredAccess 中设置FILE_EXECUTE标志。
ShareAccess 参数确定单独的线程是否可以同时访问同一文件。 如果两个文件打开程序都具有以指定方式访问文件的权限,则可以成功打开和共享该文件。 如果 IoCreateFile 的原始调用方未指定FILE_SHARE_READ、FILE_SHARE_WRITE或FILE_SHARE_DELETE,则无法对文件执行其他打开操作:即向原始调用方授予对该文件的独占访问权限。
若要成功打开共享文件,文件请求的 DesiredAccess 必须与之前尚未使用 ZwClose 发布的所有打开的 DesiredAccess 和 ShareAccess 规范兼容。 也就是说,为给定文件指定的 IoCreateFile的 DesiredAccess 不得与文件的其他打开程序禁止的访问发生冲突。
处置值FILE_SUPERSEDE要求调用方对现有文件对象具有 DELETE 访问权限。 如果是这样,如果成功调用 IoCreateFile 并FILE_SUPERSEDE现有文件,则会有效地删除该文件,然后重新创建该文件。 这意味着,如果文件已由另一个线程打开,则它通过指定 ShareAccess参数来打开文件,并设置了FILE_SHARE_DELETE标志。 请注意,这种类型的处置与覆盖文件的 POSIX 样式一致。
处置值FILE_OVERWRITE_IF和FILE_SUPERSEDE相似。 如果 IoCreateFile 是使用现有文件调用的,并且其中任一 处置 值,则将替换该文件。
覆盖文件在语义上等效于取代操作,但以下情况除外:
调用方必须对文件具有写入访问权限,而不是删除访问权限。 这意味着,如果文件已由另一个线程打开,它将在输入 ShareAccess 中设置FILE_SHARE_WRITE标志打开文件。
指定的文件属性在逻辑上与文件上已有的属性一起为 ORed。 这意味着,如果文件已被另一个线程打开, IoCreateFile 的后续调用方无法禁用现有的 FileAttributes 标志,但可以为同一文件启用其他标志。
CreateOptions FILE_DIRECTORY_FILE 值指定要创建或打开的文件是目录文件。 创建目录文件时,文件系统会在磁盘上创建适当的结构,以表示该特定文件系统的磁盘上结构的空目录。 如果指定了此选项,并且要打开的给定文件不是目录文件,或者调用方指定的 CreateOptions 或 Disposition 值不一致,则对 IoCreateFile 的调用将失败。
CreateOptions FILE_NO_INTERMEDIATE_BUFFERING 标志阻止文件系统代表调用方执行任何中间缓冲。 指定此值会对 ZwXxx文件 例程的调用方参数进行某些限制,包括:
传递给 ZwReadFile 或 ZwWriteFile 的任何可选 ByteOffset 都必须是扇区大小的整数。
传递给 ZwReadFile 或 ZwWriteFile 的 Length 必须是扇区大小的整数。 请注意,如果在传输过程中到达文件的末尾,则指定对长度正好为扇区大小的缓冲区的读取操作可能会导致传输到该缓冲区的重要字节数减少。
缓冲区必须根据基础设备的对齐要求进行对齐。 可以通过调用 IoCreateFile 获取表示物理设备的文件对象的句柄,然后使用该句柄调用 ZwQueryInformationFile 来获取此信息。 有关系统FILE_XXX_ALIGNMENT值的列表,请参阅 DEVICE_OBJECT。
对 FileInformationClass 参数设置为 FilePositionInformation 的 ZwSetInformationFile 的调用必须指定作为扇区大小的整数的偏移量。
CreateOptions FILE_SYNCHRONOUS_IO_ALERT 和 FILE_SYNCHRONOUS_IO_NONALERT(顾名思义)指定,只要通过返回的 FileHandle 引用的文件对象发生,文件上的所有 I/O 操作都将同步。 使用返回的句柄跨所有线程序列化此类文件上的所有 I/O。 对于上述任一 CreateOptions,必须设置 DesiredAccess SYNCHRONIZE 标志,以便 I/O 管理器将文件对象用作同步对象。 设置上述任一 CreateOptions 后,I/O 管理器将维护文件对象的“文件位置上下文”,即内部的当前文件位置偏移量。 此偏移量可用于对 ZwReadFile 和 ZwWriteFile 的调用。 也可以使用 ZwQueryInformationFile 和 ZwSetInformationFile 查询或设置其位置。
如果未指定 CreateOptions FILE_OPEN_REPARSE_POINT 标志,并且 IoCreateFile 尝试使用重新分析点打开文件,则会对该文件进行正常的重新分析点处理。 另一方面,如果指定了FILE_OPEN_REPARSE_POINT标志,则不会进行正常的重新分析处理, 并且 IoCreateFile 会尝试直接打开重新分析点文件。 在任一情况下,如果打开操作成功, IoCreateFile 将返回STATUS_SUCCESS;否则,例程将返回 NTSTATUS 错误代码。 IoCreateFile 从不返回STATUS_REPARSE。
CreateOptions FILE_OPEN_REQUIRING_OPLOCK 标志消除了打开文件和请求 oplock 之间的时间,oplock 可能会使第三方打开文件并发生共享冲突。 应用程序可以使用 IoCreateFile 上的 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、批处理或筛选器 oplock,以防止其他应用程序发生共享冲突。 但是,FILE_RESERVE_OPFILTER仅适用于筛选器 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 使此功能仅适用于筛选器 oplock。 步骤 3 中打开的句柄可以包含最多FILE_READ_ATTRIBUTES的 DesiredAccess |FILE_WRITE_ATTRIBUTES |FILE_READ_DATA |FILE_READ_EA |FILE_EXECUTE |SYNCHRONIZE |READ_CONTROL,但仍未中断筛选器 oplock。 但是,任何大于 FILE_READ_ATTRIBUTES 的 DesiredAccess |FILE_WRITE_ATTRIBUTES |SYNCHRONIZE 会中断级别 1 或批处理 oplock,并使FILE_RESERVE_OPFILTER标志对这些 oplock 类型无用。
如果驱动程序代表用户模式应用程序启动的操作发出内核模式创建请求, 则 Options IO_NO_PARAMETER_CHECKING 标志非常有用。 由于请求发生在用户模式上下文中,因此 I/O 管理器默认探测提供的参数值,如果参数是内核模式地址,这可能会导致访问冲突。 此标志使调用方能够替代此默认行为并避免访问冲突。
对于源自用户模式的创建请求,如果驱动程序在 IoCreateFile 的 Options 参数中同时设置IO_NO_PARAMETER_CHECKING和IO_FORCE_ACCESS_CHECK,则它还应在 ObjectAttributes 参数中设置OBJ_FORCE_ACCESS_CHECK。 有关此标志的信息,请参阅 OBJECT_ATTRIBUTES 的 Attributes 成员。
NTFS 是唯一实现FILE_RESERVE_OPFILTER的 Microsoft 文件系统。
在系统进程上下文以外的进程上下文中运行的驱动程序例程必须为 IoCreateFile 的 ObjectAttributes 参数设置 OBJ_KERNEL_HANDLE 属性。 这会将 IoCreateFile 返回的句柄的使用限制为仅在内核模式下运行的进程。 否则,运行驱动程序的上下文的进程可以访问句柄。 驱动程序可以调用 InitializeObjectAttributes 来设置 OBJ_KERNEL_HANDLE 属性,如下所示。
InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
标头 | wdm.h(包括 Wdm.h、Ntddk.h、Ntifs.h) |
Library | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | PASSIVE_LEVEL |
DDI 符合性规则 | HwStorPortProhibitedDDI (storport) 、 IrqlIoPassive4 (wdm) 、 PowerIrpDDis (wdm) |
另请参阅
IoCreateFileEx (DesiredAccess 参数)