winapi - TRUNCATE_EXISTING 与 OPEN_EXISTING+SetEndOFile

标签 winapi createfile

使用 TRUNCATE_EXISTING 调用 Windows 的 CreateFile 和使用 OPEN_EXISTING 调用然后调用 SetEndOfFile 有什么区别?

前者被记录为需要 GENERIC_WRITE 访问权限,如果我只要求 FILE_WRITE_DATA,CreateFile 将失败并显示 ERROR_ACCESS_DENIED。

对于后者,FILE_WRITE_DATA 就足够了,CreateFile 和 SetEndOfFile 都成功。

最佳答案

FILE_WRITE_DATA是单存取位(2)。当GENERIC_WRITE是通用访问,映射到 FILE_GENERIC_WRITE 中的案例文件中你可以查看它的定义:

#define FILE_GENERIC_WRITE        (STANDARD_RIGHTS_WRITE    |\
                                   FILE_WRITE_DATA          |\
                                   FILE_WRITE_ATTRIBUTES    |\
                                   FILE_WRITE_EA            |\
                                   FILE_APPEND_DATA         |\
                                   SYNCHRONIZE)

所以除了FILE_WRITE_DATA还包括FILE_WRITE_ATTRIBUTES , FILE_WRITE_EA , FILE_APPEND_DATAREAD_CONTROL==STANDARD_RIGHTS_WRITE 。 ( CreateFile 始终隐式要求 SYNCHRONIZE )

如果你有ERROR_ACCESS_DENIED对于 GENERIC_WRITE但对于 FILE_WRITE_DATA 来说还可以这意味着您有 FILE_WRITE_DATA访问文件,但没有来自 FILE_GENERIC_WRITE 的一些额外访问权限。这种情况很少见,但也有可能发生。

但实际上截断文件所需的只是 FILE_WRITE_DATA使用权。这是错误,而且 win32 api 的设计非常糟糕 CreateFile .

要将文件截断为零大小,我们可以使用或:

  • NtSetInformationFile FileEndOfFileInformation (这 调用者必须使用 FILE_WRITE_DATA 打开文件标志设置 在 DesiredAccess 参数中)或 FileAllocationInformation - 这适用于所有窗口
  • SetFileInformationByHandle - 非常薄的win32 shell NtSetInformationFile 但仅适用于 Vista。和 FileEndOfFileInfoFileAllocationInfo 。请注意,如果我们设置 AllocationSize to 0 -- 文件也将被截断为 0 大小。

    The end-of-file (EOF) position for a file must always be less than or equal to the file allocation size. If the allocation size is set to a value that is less than EOF, the EOF position is automatically adjusted to match the file allocation size.

  • SetEndOfFile第一次调用 ZwQueryInformationFile FilePositionInformation (文件句柄打开后立即设置为 0) 然后使用它( FILE_POSITION_INFORMATION )进行两次调用 NtSetInformationFile 两者都有 FileEndOfFileInformationFileAllocationInformation 。显然在这种情况下我们有 2 个不 需要对内核进行额外的调用。所以这比较前2效率不高 方法。
  • CreateFileTRUNCATE_EXISTING首先打开文件然后 调用 NtSetInformationFile FileAllocationInformation放 到 0。但是这个调用,你如何查看需要额外的访问权限 - FILE_GENERIC_WRITE这确实不需要。只需要 FILE_WRITE_DATA 。所以这种方式不好
  • 使用 NtCreateFile FILE_OVERWRITE CreateDisposition - 它在单个调用中打开文件并将 EOF 设置为 0。根据感觉 TRUNCATE_EXISTING必须这样做(使用 FILE_OVERWRITE 处置)。但由于未知的原因(我认为这是错误)它使用 FILE_OPEN通过额外的调用来访问 NtSetInformationFile FileAllocationInformation
  • 如果我们不仅需要截断现有文件,还需要创建新文件 空文件,如果尚不存在 - 最好使用 FILE_OVERWRITE_IF 选项或对应的CREATE_ALWAYS - 这也开放和 在对内核的单次调用中截断文件。或创建新文件

关于winapi - TRUNCATE_EXISTING 与 OPEN_EXISTING+SetEndOFile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49457814/

相关文章:

java - 所以我偶然发现了一些东西......文件扫描媒体扫描仪连接

c++ - 使用 CreateFile 打开套接字

c - 使用 native Win32 读取 'C' 中的文本文件 (Unicode)

c++ - 我可以在不引发 C++ 异常的情况下检查内存块是否可读吗?

c - ReadFile COM 全批

c++ - 使用来自 CreateFile 的有效句柄来自 ReadFileEx 的无效句柄错误

winapi - 如何在Windows编辑控件上下文菜单中禁用复制/粘贴命令?

c++ - 查找文本的宽度

c++ - 位于字符串加密密码中的断点

python - 使用 wxpython 传递参数来创建窗口?