-
001_函数的不同版本
- HANDLE : CreateFile()函数返回一个内核对象的句柄
- WINAPI : 一种调用约定,调用方式。
- _In_ 与 _In_opt_ : 本身没有意义,一个说明宏,来标明这个参数的性质。
- _In_ 说明此参数是“输入型”参数
- _In_Opt_ 说明此参数是“输入指针型”参数
- _Out_ 说明此参数是“输出型”参数
- VS2015中,CreateFile()是一个宏:
WINBASEAPI HANDLE WINAPI CreateFileA(
_In_ LPCSTR lpFileName,
……
);
WINBASEAPI HANDLE WINAPI CreateFileW(
_In_ LPCWSTR lpFileName,
……
);
#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE
- windows平台编程,关于字符的处理,需要区分两大阵营:1 宽字符集 与 2 窄字符集
- “宽”与“窄”两种不同的字节集,会导致类型的不同; 最初CreateFile函数支持的是窄字节,后来发现窄字节在多国语言环境中,是不够用的,windows的设计者们,把CreateFile函数变成一个宏,这个宏使得CreateFile有了CreateFileA()与 CreateFileW()两个版本。CreateFileA()兼容窄字节,CreateFileW()推广宽字节。
- 实际使用过程中,造成了很多的不方便 :
- 示例1:
wchar_t *filename = L"d:\\1.txt";
CreateFile(filename,……);
- 看示例代码,此时程序员以宽字节设定 filename,但是当外部变换为“窄”字节集时,CreateFile这个宏,能变换成CreateFileW这个版本,而wchar_t * filename不能自动兼容“窄”字节。所以就出现了“TCHAR”这个宏,而右边也出现了“TEXT()”这个宏。
- TEXT()这个宏,作用是:当环境为UNICODE时,在字符串前面加“L”;否则不加“L”。
- 以上整套处理方案,不能移植到linux上,需要完全的重写。
-
002_CreateFile参数详解
- 参见下面中文翻译
- 事务型操作:
- 把一个操作分成“读”“写”“修改”“完成”4个部分,中间123任意部分失败,则操作无效,“回滚”到操作进行之前的状态。
- 比如程序安装,可以做成一个“事务型”操作,只有当整体完成,这个事务型操作,才算真正的完成,否则“回滚”至安装之前的状态。
- 只有在同步时,会考虑事务型操作;当异步时,事务型操作是不适用的。
- lpFileName 文件名称
- ANSI版本中MAX_PATH 宏 代替 260;Unicode版本中,没有限制长度。
- dwDesiredAccess 权限:以何种权限打开文件
- 可以多个权限叠加使用
- 如置为0,则设备不具有读和写的权限。比如我们只要访问一文件的创建时间,不需要对文件读和写时,这个设置就非常的合适。
- dwShareMode 共享模式
- 一系列共享给别人的模式。
- 如置为0,别的程序占用了这个文件,那么无法再次被打开。
- 当访问模式冲突时,有GetLastError返回ERROR_SHARING_VIOLATION
- 内核对象打开之后,需要关闭。否则此项设置的权限一直生效。
- lpSecurityAttributes 安全描述符
- dwCreationDisposition 当文件存在与否时,针对存在与否,展开何种操作
- CREATE_ALWAYS 问题创建一个新文件
- 文件被重写成功时,将last-error code设置为ERROR_ALREADY_EXISTS
- 文件不存在,创建成功时,将last-error code 设置为0。
- CREATE_NEW 仅文件不存在时,才创建一个新文件
- 如文件存在,执行失败,将last-error code设置为ERROR_FILE_EXISTS
- OPEN_ALWAYS 总是打开一个文件
- 文件存在,执行成功,置为ERROR_ALREADY_EXISTS
- 文件不存在,路径名合法且可写时,创建一个新文件,last-error code置为0 。
- OPEN_EXISTING 仅在文件存在时,打开它
- 文件不存在,则置为ERROR_FILE_NOT_FOUND
- TRUNCATE_EXISTING 测试一个文件是否存在
- 仅当文件存在时,才打开一个文件并且,将其大小截取到0字节
- 文件不存在,函数执行失败,last-error code置为ERROR_FILE_NOT_FOUND
- dwFlagsAndAttributes
-
003_CreateFile完成
- dwFlagsAndAttributes 属性与标记位
- 对于文件 FILE_ATTRIBUTE_NORMAL是最常用 默认值
- 设置文件的属性值的组合,所有属性值是: FILE_ATTRIBUTE_NORMAL
- FILE_FLAG_BACKUP_SEMANTICS
- FILE_FLAG_NO_BUFFERING
- FILE_FLAG_WRITE_THROUGH
- hTemplateFile 内核相同的对象
- 一般为NULL
- 当不为NULL时,上一参数dwFlagsAndAttributes所有设置无效,将继承此参数,也就是新给出的内核对象,继承此对象的所有Flags.
- 返回值
- 返回文件句柄
- 如果失败,返回last-error code 为 INVALID_HANDLE_VALUE
- 备注 具体查看MSDN 历史问题,疑难问题,在出问题时查看
-
CreateFile中文翻译:
- 函数功能
- CreateFile 函数用于创建或打开一个文件或者 I/O 设备。最常使用的 I/O 设备如下:
- 文件
- 文件流
- 文件夹
- 物理磁盘
- 逻辑磁盘驱动器
- 控制台程序缓冲区
- 磁带
- 通信资源
- 邮槽
- 管道
- 此函数返回一个指向用于访问来自不同类型I/O的文件或设备的句柄,其访问权限取决于它所访问的文件、设备和我们所指定的标记位、属性。
- 为了使之可以处理事务型 I/O,请使用 CreateFileTransacted 函数。
- 函数原型
- 参数解析
- lpFileName
- 1 指定要打开、创建的文件或设备的名字。你可以在名字中使用斜杠(/)或者反斜杠(\)
- 2 在此函数的 ANSI 版本中,名字长度被限制为 MAX_PATH 个字符。为了将此限制扩展到 32767 个宽字符,需要调用此函数的 Unicode 版本,并且在添加在路径名中添加 “\?\” 前缀。获取更多的信息,参见 Naming Files, Paths, and Namespaces
- 3 想获取关于特殊设备的名字,参见 Defining an MS-DOS Device Name
- 4 为了创建一个文件流,需要指定文件名,一个冒号加上流文件的名字。获取更多信息,参见 File Streams
- dwDesiredAccess
- 指定以何种权限打开文件或设备,可以归纳为:读访问权、写访问权、读写访问权、非读非写访问权
- 最常使用的值为 GENERIC_READ, GENERIC_WRITE, 或者二者都用(GENERIC_READ | GENERIC_WRITE)。获取更多信息,参见 Generic Access Rights, File Security and Access Rights, File Access Rights Constants 和 ACCESS_MASK
- 如果参数值为 0,那么程序可以在不访问文件或设备情况下,询问某些元数据,如文件、目录或者设备属性。此外,即使 GENERIC_READ 请求,也会被拒绝
- 你无法请求一个与共享模式冲突的访问权限。共享模式是在参数 dwShareMode 中设置的
- 获取更多信息,参见本文备注以及 Creating and Opening Files
- dwShareMode
- 设置文件或者设备的共享模式,包括读、写、读写、删除、全部权限或者以上什么权限都没有(参考下面的表格)。此参数不影响对属性和扩展属性的访问请求
- 如果此参数为 0 且 CreateFile 函数执行成功,那么此文件或设备无法被共享,且在其句柄被关闭前,无法被再次打开。更多信息,参见本文备注。
- 你无法设置一个与访问模式相冲突的共享模式。此时如果 CreateFile 函数执行失败,那么 GetLastError 函数会返回 ERROR_SHARING_VIOLATION
- 为了允许进程去共享一个已经在另一个进程中打开的文件或句柄,那么可对以下一个或多个取值进行组合,且各取值间需要可互相兼容。更多有关此参数与 dwDesiredAccess 参数的合法取值组合的信息,参见 Creating and Opening Files
- 注意:在句柄被关闭之前,每个句柄的共享选项都会一直生效,且与进程的运行上下文(process context)无关。
- lpSecurityAttributes
- 指向 SECURITY_ATTRIBUTES 结构体的指针。此结构体拥有两个分开但是相关的数据成员:一个是可选的安全描述符,另一个是决定返回的句柄是否可以被子进程继承的 Boolean 值
- 此参数可以设置为 NULL
- 如果参数为 NULL,那么 CreateFile 函数返回的句柄无法被任意此进程的子进程所继承,且与返回的句柄所对应的文件或句柄拥有一个默认的安全描述符
- 该结构体的 lpSecurityDescriptor 成员为文件或设备指定一个安全描述符(SECURITY_DESCRIPTOR)。如果此成员取值为 NULL,那么与返回的句柄所对应的文件或句柄拥有一个默认的安全描述符
- 当打开一个已经存在的文件或设备时,CreateFile 函数忽略 lpSecurityDescriptor 成员,但是 bInheritHandle 成员仍然可以使用
- 结构体的 bInheritHandle 成员用于设置返回的句柄是否可以被继承
- 更多信息,参见本文备注
- dwCreationDisposition
- 用于设置当文件存在或不存在时,要对文件或设备执行何种操作
- 对于设备来说,此参数通常设置为 OPEN_EXISTING
- 更多信息,参见本文备注
- 这个参数的值必须为以下值之一,且只能选择一个而不能组合多个:
- dwFlagsAndAttributes
- 文件或设备的属性值和标记位,对于文件来说,FILE_ATTRIBUTE_NORMAL 是最常用的默认值
- 此参数可以是任意文件属性值(FILE_ATTRIBUTE_*)的组合。所有其他的文件属性值会覆盖 FILE_ATTRIBUTE_NORMAL
- 此参数也可以包含任意标记位(FILE_FLAG_*)的组合以控制文件或设备的行为、权限设置和其他目的。此外,还可以与任意 FILE_ATTRIBUTE_* 进行组合
- 这个参数还可以通过指定 SECURITY_SQOS_PRESENT 标记来包含 Security Quality of Service (SQOS) 信息。与SQOS相关的标记位信息见属性与标记位表格下面的表格中
- 注意:当CreateFile 打开一个已存在的文件时,它通常将文件属性和文件标记位组合在一起,并且忽略在 dwFlagsAndAttributes 中定义的属性值。详细例子见 Creating and Opening Files
- 以下的属性和标记位可能只适用于文件的打开,而并非支持所有其他 CreateFile 函数可以打开的设备。想了解更多信息,参见本文备注部分和 Creating and Opening Files。想进一步了解文件属性相关信息,参见 SetFileAttributes 函数。你还可以在 File Attribute Constants 中看到完整的介绍所有文件属性的值和对应描述信息
- hTemplateFile
- 指向一个拥有 GENERIC_READ 访问权限的的模板文件的合法句柄
- 此模板文件为即将创建的文件提供属性和扩展属性
- 参数值可以为 NULL
- 如果打开一个已存在的文件,则 CreateFile 函数忽略这个参数
- 如果打开一个新的被加密文件,此函数从其父目录中继承自由存取控制列表。更多信息,见 File Encryption