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 时可能遇到的各种问题。 仅当专门引用存储在文件系统上实际文件中的数据时,文本才会尝试使用单词 file 。 但是, 文件 的某些用途可能更一般地引用支持类似文件的机制的 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)
群集共享卷文件系统 (CSV)
弹性文件系统 (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 标志指定为 pCreateExParams 参数中传递的 CREATEFILE2_EXTENDED_PARAMETERS 结构的 dwFileFlags 成员的一部分。 在没有 SE_BACKUP_NAMESE_RESTORE_NAME 特权的情况下使用此标志时,仍适用适当的安全检查。

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

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

物理磁盘和卷

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

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

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

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

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

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

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

String 含义
“\\.\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++ 编写的应用程序中打开更换设备零,请使用以下文件名:“\\\\.\Changer0”。

磁带驱动器

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

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

通信资源

CreateFile2 函数可以创建通信资源的句柄,例如串行端口 COM1。 对于通信资源,dwCreationDisposition 参数必须是OPEN_EXISTING,dwShareMode 参数必须是零 (独占访问 ) ,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 之前尝试打开本地 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 应用]
目标平台 Windows
标头 fileapi.h (包括 Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

另请参阅

关于目录管理

关于卷管理

备份

CloseHandle

通信

CreateDirectory

CreateDirectoryEx

CreateFile

CreateFileTransacted

CreateMailSlot

CreateNamedPipe

创建、删除和维护文件

DeleteFile

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

DeviceIoControl

文件压缩和解压缩

文件加密

文件管理函数

文件安全和访问权限

文件流

函数

GetLastError

I/O 完成端口

I/O 概念

Mailslots

获取和设置文件信息

概述主题

管道

ReadFile

ReadFileEx

使用特殊权限运行

SetFileAttributes

WriteFile

WriteFileEx