CreateFile2 函数 (fileapi.h)

创建或打开文件或 I/O 设备。 最常用的 I/O 设备如下所示:文件、文件流、目录、物理磁盘、卷、控制台缓冲区、磁带驱动器、通信资源、mailslot 和管道。 该函数返回一个句柄,该句柄可用于访问各种类型的 I/O 的文件或设备,具体取决于文件或设备以及指定的标志和属性。

从 Windows 应用商店应用调用时,CreateFile2 简化。 只能打开 ApplicationData.LocalFolderPackage.InstalledLocation 目录中的文件或目录。 无法打开命名管道或 mailslot 或创建加密文件(FILE_ATTRIBUTE_ENCRYPTED)。

注意 此处我们指的是应用的本地文件夹和包的已安装位置,而不是包图中的其他包,如资源包。 CreateFile2 不支持在包图中的其他包中打开文件。 例如,假设应用依赖于 WinJS。 应用可以调用 CreateFile2,以在其包中打开文件,但不能在 WinJS 包中打开文件。
 
若要将此操作作为事务处理操作执行,这会导致可用于事务处理 I/O 的句柄,请使用 CreateFileTransacted 函数。

语法

HANDLE CreateFile2(
  [in]           LPCWSTR                           lpFileName,
  [in]           DWORD                             dwDesiredAccess,
  [in]           DWORD                             dwShareMode,
  [in]           DWORD                             dwCreationDisposition,
  [in, optional] LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams
);

参数

[in] lpFileName

要创建或打开的文件或设备的名称。

有关特殊设备名称的信息,请参阅 定义 MS-DOS 设备名称

若要创建文件流,请指定文件的名称、冒号,然后指定流的名称。 有关详细信息,请参阅 文件流

提示 从 Windows 10 版本 1607 开始,你可以选择加入以删除 MAX_PATH 限制,而无需追加“\\?\”。 有关详细信息,请参阅 命名文件、路径和命名空间 的“最大路径长度限制”部分。
 

[in] dwDesiredAccess

请求对文件或设备的访问权限,可以汇总为读取、写入或两者均未进行零访问。

最常用的值是 GENERIC_READGENERIC_WRITE或两者(GENERIC_READ | GENERIC_WRITE)。 有关详细信息,请参阅 通用访问权限文件安全性和访问权限文件访问权限常量ACCESS_MASK

如果此参数为零,则应用程序可以在不访问该文件或设备的情况下查询某些元数据(如文件、目录或设备属性),即使拒绝 GENERIC_READ 访问也是如此。

不能请求与共享模式冲突的访问模式,该模式由 dwShareMode 参数指定的打开请求中已具有打开句柄。

有关详细信息,请参阅本主题的“备注”部分,创建和打开文件

[in] dwShareMode

请求的文件或设备的共享模式,可以读取、写入、删除、所有这些或无(请参阅下表)。 对属性或扩展属性的访问请求不受此标志的影响。

如果此参数为零且 CreateFile2 成功,则文件或设备无法共享,并且无法在文件或设备的句柄关闭之前再次打开。 有关详细信息,请参阅“备注”部分。

无法请求与具有打开句柄的现有请求中指定的访问模式冲突的共享模式。 CreateFile2 将失败,GetLastError 函数将返回 ERROR_SHARING_VIOLATION

若要使进程能够在另一个进程打开文件或设备时共享文件或设备,请使用以下一个或多个值的兼容组合。 有关此参数与 dwDesiredAccess 参数的有效组合的详细信息,请参阅 创建和打开文件

注意 每个打开句柄的共享选项一直有效,直到该句柄关闭,而不考虑进程上下文。
 
价值 意义
0
0x00000000
如果其他进程请求删除、读取或写入访问权限,则阻止其他进程打开文件或设备。 仅当应用程序对文件具有写入访问权限时,才授予对文件或目录的独占访问权限。
FILE_SHARE_DELETE
0x00000004
启用对文件或设备上的后续打开操作以请求删除访问权限。

否则,如果进程请求删除访问权限,则无法打开文件或设备。

如果未指定此标志,但文件或设备已打开以删除访问权限,则函数将失败。

注释 删除访问权限允许删除和重命名操作。
 
FILE_SHARE_READ
0x00000001
允许对文件或设备执行后续打开操作以请求读取访问权限。

否则,如果进程请求读取访问权限,则其他进程无法打开文件或设备。

如果未指定此标志,但已打开文件或设备进行读取访问,则函数将失败。

如果打开文件或目录,并且未指定此标志,并且调用方没有对文件或目录的写入访问权限,则函数将失败。

FILE_SHARE_WRITE
0x00000002
允许对文件或设备执行后续打开操作以请求写入访问权限。

否则,如果进程请求写入访问权限,则其他进程无法打开文件或设备。

如果未指定此标志,但已打开文件或设备进行写入访问或具有写入访问权限的文件映射,则函数将失败。

[in] dwCreationDisposition

对存在或不存在的文件或设备执行的操作。

对于文件以外的设备,此参数通常设置为 OPEN_EXISTING

有关详细信息,请参阅“备注”部分。

此参数必须是以下值之一,不能组合这些值:

价值 意义
CREATE_ALWAYS
2
始终创建新文件。

如果指定的文件存在且可写,则函数将截断文件、函数成功,最后错误代码设置为 ERROR_ALREADY_EXISTS(183)。

如果指定的文件不存在且路径有效,则会创建一个新文件,该函数会成功,最后一个错误代码设置为零。

有关详细信息,请参阅本主题的“备注”部分。

CREATE_NEW
1
仅当该文件尚不存在时,才会创建一个新文件。

如果指定的文件存在,函数将失败,最后一个错误代码设置为 ERROR_FILE_EXISTS(80)。

如果指定的文件不存在,并且是可写位置的有效路径,则会创建一个新文件。

OPEN_ALWAYS
4
始终打开文件。

如果指定文件存在,则函数成功,最后一个错误代码设置为 ERROR_ALREADY_EXISTS(183)。

如果指定的文件不存在并且是可写位置的有效路径,该函数将创建一个文件,最后一个错误代码设置为零。

OPEN_EXISTING
3
仅当文件或设备存在时才打开该文件或设备。

如果指定的文件或设备不存在,该函数将失败,最后一个错误代码设置为 ERROR_FILE_NOT_FOUND(2)。

有关设备的详细信息,请参阅“备注”部分。

TRUNCATE_EXISTING
5
打开一个文件并截断它,使其大小为零字节,仅当它存在时。

如果指定的文件不存在,该函数将失败,最后一个错误代码设置为 ERROR_FILE_NOT_FOUND(2)。

调用过程必须打开文件,并将 GENERIC_WRITE 位设置为 dwDesiredAccess 参数的一部分。

[in, optional] pCreateExParams

指向可选 CREATEFILE2_EXTENDED_PARAMETERS 结构的指针。

返回值

如果函数成功,则返回值是指定文件、设备、命名管道或邮件槽的打开句柄。

如果函数失败,则返回值 INVALID_HANDLE_VALUE。 若要获取扩展的错误信息,请调用 GetLastError

言论

若要编译使用 CreateFile2 函数的应用程序,请将 _WIN32_WINNT 宏定义为0x0602或更高版本。 有关详细信息,请参阅 使用 Windows 标头

CreateFile2 支持文件交互以及 Windows 开发人员可用的大多数其他类型的 I/O 设备和机制。 本部分尝试介绍开发人员在不同上下文和不同 I/O 类型中使用 CreateFile2 时可能会遇到的各种问题。 仅当专门引用存储在文件系统上实际文件中的数据时,文本才会尝试使用单词 文件。 但是,文件的一些用法 可能更普遍地引用支持类似文件的机制的 I/O 对象。 由于前面提到的历史原因,此术语 文件 在常量名称和参数名称中特别普遍。

使用 CreateFile2返回的对象句柄完成应用程序后,请使用 CloseHandle 函数关闭句柄。 这不仅释放了系统资源,还可以对共享文件或设备以及将数据提交到磁盘等内容产生更广泛的影响。 本主题中会相应地说明具体内容。

某些文件系统(如 NTFS 文件系统)支持单个文件和目录的压缩或加密。 在具有具有此支持的装载文件系统的卷上,新文件继承其目录的压缩和加密属性。

不能使用 CreateFile2 来控制文件或目录上的压缩、解压缩或解密。 有关详细信息,请参阅 创建和打开文件文件压缩和解压缩,以及 文件加密

如果传入 pCreateExParams 参数的 CREATEFILE2_EXTENDED_PARAMETERS 结构的 lpSecurityAttributes 成员 NULL,则 CreateFile2 返回的句柄不能由应用程序可能创建的任何子进程继承。 有关此成员的以下信息也适用:

  • 如果 bInheritHandle 成员变量未 FALSE(任何非零值),则可以继承句柄。 因此,如果不希望句柄可继承,则必须将此结构成员正确初始化为 FALSE
  • 文件或目录的默认安全描述符中的访问控制列表(ACL)继承自其父目录。
  • 目标文件系统必须支持 lpSecurityDescriptor 成员对文件和目录的安全性,才能对其产生影响,这可以通过使用 GetVolumeInformation来确定。
在 Windows 8 和 Windows Server 2012 中,以下技术支持此函数。
科技 支持
服务器消息块 (SMB) 3.0 协议 是的
SMB 3.0 透明故障转移 (TFO)
具有横向扩展文件共享的 SMB 3.0 (SO)
群集共享卷文件系统 (CsvFS) 是的
可复原文件系统 (ReFS) 是的
 

符号链接行为

如果对此函数的调用创建文件,则行为没有变化。 此外,请考虑以下有关在 pCreateExParams 参数 中传递的 CREATEFILE2_EXTENDED_PARAMETERS 结构的 dwFileFlags 成员 FILE_FLAG_OPEN_REPARSE_POINT 标志的信息:
  • 如果指定了 FILE_FLAG_OPEN_REPARSE_POINT
    • 如果打开现有文件并且它是符号链接,则返回的句柄是符号链接的句柄。
    • 如果指定了 TRUNCATE_EXISTINGFILE_FLAG_DELETE_ON_CLOSE,受影响的文件是符号链接。
  • 如果未指定 FILE_FLAG_OPEN_REPARSE_POINT
    • 如果打开现有文件并且它是符号链接,则返回的句柄是目标的句柄。
    • 如果指定了 CREATE_ALWAYSTRUNCATE_EXISTINGFILE_FLAG_DELETE_ON_CLOSE,受影响的文件就是目标。

文件

如果重命名或删除文件,然后在不久后还原该文件,系统会在缓存中搜索要还原的文件信息。 缓存信息包括其短/长名称对和创建时间。

如果由于对 DeleteFile的上一次调用而挂起删除的文件调用 CreateFile2,该函数将失败。 操作系统会延迟文件删除,直到文件的所有句柄都关闭。 GetLastError 返回 ERROR_ACCESS_DENIED

dwDesiredAccess 参数可以为零,允许应用程序在没有使用足够安全设置的情况下访问文件属性来查询文件属性。 这可用于测试文件是否存在,而无需打开该文件进行读取和/或写入访问,或获取有关文件或目录的其他统计信息。 请参阅 获取和设置文件信息GetFileInformationByHandle

当应用程序跨网络创建文件时,最好将 GENERIC_READ | GENERIC_WRITE 用于 dwDesiredAccess,而不是单独使用 GENERIC_WRITE。 生成的代码速度更快,因为重定向程序可以使用缓存管理器,并发送更少的 SMB 和更多数据。 这种组合还避免了跨网络写入文件偶尔会返回 ERROR_ACCESS_DENIED的问题。

有关详细信息,请参阅 创建和打开文件

文件流

在 NTFS 文件系统上,可以使用 CreateFile2 在文件中创建单独的流。 有关详细信息,请参阅 文件流

目录

应用程序无法使用 CreateFile2创建目录,因此,对于此用例,只有 OPEN_EXISTING 值对 dwCreationDisposition 有效。 若要创建目录,应用程序必须调用 CreateDirectoryCreateDirectoryEx

若要使用 CreateFile2打开目录,请将 FILE_FLAG_BACKUP_SEMANTICS 标志指定为 dwFileFlagspCreateExParams 参数中传递 CREATEFILE2_EXTENDED_PARAMETERS 结构的一部分。 在没有 SE_BACKUP_NAMESE_RESTORE_NAME 特权的情况下使用此标志时,仍适用适当的安全检查。

使用 CreateFile2 在对 FAT 或 FAT32 文件系统卷进行碎片整理期间打开目录时,请不要指定 MAXIMUM_ALLOWED 访问权限。 如果这样做,则拒绝对目录的访问。 请改为指定 GENERIC_READ 访问权限。

有关详细信息,请参阅 关于目录管理

物理磁盘和卷

对磁盘或卷的直接访问受到限制。

可以使用 CreateFile2 函数打开物理磁盘驱动器或卷,该驱动器返回可与 DeviceIoControl 函数一起使用的直接访问存储设备 (DASD) 句柄。 这样,便可以直接访问磁盘或卷,例如分区表等磁盘元数据。 但是,这种类型的访问还会向潜在的数据丢失公开磁盘驱动器或卷,因为使用此机制对磁盘进行不正确的写入可能会使其内容无法访问操作系统。 为了确保数据完整性,请务必熟悉 DeviceIoControl,以及其他 API 与直接访问句柄(而不是文件系统句柄)的行为方式不同。

必须满足以下要求才能成功进行此类调用:

  • 调用方必须具有管理权限。 有关详细信息,请参阅 使用特殊特权运行。
  • dwCreationDisposition 参数必须具有 OPEN_EXISTING 标志。
  • 打开卷或软盘时,dwShareMode 参数必须具有 FILE_SHARE_WRITE 标志。
注释 dwDesiredAccess 参数 可以为零,允许应用程序在不访问设备的情况下查询设备属性。 这适用于应用程序来确定软盘驱动器的大小及其支持的格式,而无需驱动器中的软盘,例如。 它还可用于读取统计信息,而无需更高级别的数据读取/写入权限。
 
x:打开物理驱动器时,lpFileName 字符串应采用以下格式:“\\.\PhysicalDriveX”。 硬盘编号从零开始。 下表显示了物理驱动器字符串的一些示例。
字符串 意义
“\\.\PhysicalDrive0” 打开第一个物理驱动器。
“\\.\PhysicalDrive2” 打开第三个物理驱动器。
 

若要获取卷的物理驱动器标识符,请打开卷的句柄,并使用 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS调用 DeviceIoControl 函数。 此控制代码返回每个卷的一个或多个盘区的磁盘编号和偏移量;卷可以跨越多个物理磁盘。

有关打开物理驱动器的示例,请参阅 调用 DeviceIoControl

打开卷或可移动媒体驱动器(例如软盘驱动器或闪存内存拇指驱动器)时,lpFileName 字符串应采用以下格式:“\\.\X:”。 不要使用尾随反斜杠(\),指示驱动器的根目录。 下表显示了驱动器字符串的一些示例。

字符串 意义
“\\.\A:” 打开软盘驱动器 A。
“\\.\C:” 打开 C: 卷。
“\\.\C:\” 打开 C: 卷的文件系统。
 

还可以通过引用卷名称来打开卷。 有关详细信息,请参阅 命名卷

卷包含一个或多个装载的文件系统。 即使 CreateFile2中未指定非缓存选项,也可以以非缓存方式打开卷句柄。 应假定所有Microsoft文件系统都以非缓存的形式打开卷句柄。 对文件的非缓存 I/O 的限制也适用于卷。

即使数据未缓存,文件系统也可能不需要缓冲区对齐。 但是,如果在打开卷时指定了非缓存选项,则会强制实施缓冲区对齐方式,而不考虑卷上的文件系统。 建议在所有文件系统上以非缓存方式打开卷句柄,并遵循非缓存 I/O 限制。

注意 若要读取或写入卷的最后几个扇区,必须调用 DeviceIoControl 并指定 FSCTL_ALLOW_EXTENDED_DASD_IO。 这表示文件系统驱动程序不会对分区读取或写入调用执行任何 I/O 边界检查。 相反,边界检查由设备驱动程序执行。
 

变更程序设备

DeviceIoControl 的 IOCTL_CHANGER_* 控制代码 接受变更器设备的句柄。 若要打开更改器设备,请使用以下形式的文件名:“\\.\Changerx”,其中 x 是一个数字,指示要打开的设备,从零开始。 若要在用 C 或 C++ 编写的应用程序中打开 changer 设备零,请使用以下文件名:“\\.\Changer0”。

磁带驱动器

可以使用以下格式的文件名打开磁带驱动器:“\\.\TAPEx”,其中 x 是指示要打开的驱动器的数字,从磁带驱动器零开始。 若要在用 C 或C++编写的应用程序中打开磁带驱动器零,请使用以下文件名:“\\\\.\TAPE0”。

有关详细信息,请参阅 备份

通信资源

CreateFile2 函数可以创建通信资源的句柄,例如串行端口 COM1。 对于通信资源,dwCreationDisposition 参数必须 OPEN_EXISTINGdwShareMode 参数必须为零(独占访问),hTemplateFile 参数必须 NULL。 可以指定读取、写入或读/写访问权限,并且可以为重叠 I/O 打开句柄。

若要指定大于 9 的 COM 端口号,请使用以下语法:“\.\COM10”。 此语法适用于允许指定 COM 端口号的所有端口号和硬件。

有关通信的详细信息,请参阅 通信

控制台

CreateFile2 函数可以创建控制台输入的句柄(CONIN$)。 如果进程由于继承或重复而具有打开的句柄,则它还可以为活动屏幕缓冲区(CONOUT$)创建句柄。 调用进程必须附加到继承的控制台或由 AllocConsole 函数分配的控制台。 对于控制台句柄,请按如下所示设置 CreateFile2 参数。
参数 价值
lpFileName 使用 CONIN$ 值指定控制台输入。

使用 CONOUT$ 值指定控制台输出。

CONIN$ 获取控制台输入缓冲区的句柄,即使 SetStdHandle 函数也会重定向标准输入句柄。 若要获取标准输入句柄,请使用 GetStdHandle 函数。

CONOUT$ 获取活动屏幕缓冲区的句柄,即使 SetStdHandle 重定向标准输出句柄也是如此。 若要获取标准输出句柄,请使用 GetStdHandle

dwDesiredAccess 首选 GENERIC_READ | GENERIC_WRITE,但任一限制访问。
dwShareMode 打开 CONIN$时,请指定 FILE_SHARE_READ。 打开 CONOUT$时,请指定 FILE_SHARE_WRITE

如果调用进程继承控制台,或者子进程应能够访问控制台,则必须 FILE_SHARE_READ | FILE_SHARE_WRITE此参数。

dwCreationDisposition 使用 createFile2 打开控制台时,应指定 OPEN_EXISTING
 

设置 pCreateExParams 参数中传递的 CREATEFILE2_EXTENDED_PARAMETERS 结构的成员,如下所示。

成员 价值
lpSecurityAttributes 如果希望继承控制台,SECURITY_ATTRIBUTES 结构的 bInheritHandle 成员必须 TRUE
dwFileAttributes

dwFileFlags

dwSecurityQosFlags

hTemplateFile

忽视。
 

下表显示了 dwDesiredAccesslpFileName的各种设置。

lpFileName dwDesiredAccess 结果
“CON” GENERIC_READ 打开控制台进行输入。
“CON” GENERIC_WRITE 打开控制台进行输出。
“CON” GENERIC_READ | GENERIC_WRITE 导致 CreateFile2 失败;GetLastError 返回 ERROR_FILE_NOT_FOUND
 

Mailslots

如果 CreateFile2 打开 mailslot 的客户端端,则如果 mailslot 客户端尝试在 mailslot 服务器使用 CreateMailSlot 函数创建本地 mailslot 之前,该函数将返回 INVALID_HANDLE_VALUE

有关详细信息,请参阅 Mailslots

管道

如果 CreateFile2 打开命名管道的客户端端,该函数将使用处于侦听状态的命名管道的任何实例。 打开过程可以根据需要多次复制句柄,但在打开句柄后,命名管道实例无法由另一个客户端打开。 打开管道时指定的访问必须与 createNamedPipe 函数的 dwOpenMode 参数中指定的访问兼容。

如果在此操作之前未在服务器上成功调用 CreateNamedPipe 函数,则管道将不存在,并且 CreateFile2 失败,ERROR_FILE_NOT_FOUND

如果至少有一个活动管道实例,但服务器上没有可用的侦听器管道,这意味着所有管道实例当前都已连接,CreateFile2 失败,ERROR_PIPE_BUSY

有关详细信息,请参阅 管道

要求

要求 价值
最低支持的客户端 Windows 8 [桌面应用 |UWP 应用]
支持的最低服务器 Windows Server 2012 [桌面应用 |UWP 应用]
目标平台 窗户
标头 fileapi.h (包括 Windows.h)
Kernel32.lib
DLL Kernel32.dll

另请参阅

关于目录管理

关于卷管理 的

备份

CloseHandle

通信

CreateDirectory

CreateDirectoryEx

CreateFile

CreateFileTransacted

CreateMailSlot

CreateNamedPipe

创建、删除和维护文件

DeleteFile

设备输入和输出控制(IOCTL)

DeviceIoControl

文件压缩和解压缩

文件加密

文件管理功能

文件安全性和访问权限

文件流

Functions

GetLastError

I/O 完成端口

I/O 概念

Mailslots

获取和设置文件信息

概述主题

管道

ReadFile

ReadFileEx

使用特殊特权运行的

SetFileAttributes

WriteFile

WriteFileEx