TRUNCATE_EXISTING与OPEN_EXISTING + SetEndOFile

时间:2018-03-23 20:26:16

标签: winapi createfile

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

前者被记录为需要GENERIC_WRITE访问权限,如果我只询问FILE_WRITE_DATA,则CreateFile会因ERROR_ACCESS_DENIED而失败。

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

1 个答案:

答案 0 :(得分:2)

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_ATTRIBUTESFILE_WRITE_EAFILE_APPEND_DATAREAD_CONTROL==STANDARD_RIGHTS_WRITE。 (CreateFile始终隐含需要SYNCHRONIZE

如果您ERROR_ACCESS_DENIED GENERIC_WRITEFILE_WRITE_DATA正常,则表示您FILE_WRITE_DATA访问了该文件,但FILE_GENERIC_WRITE没有其他访问权限}。这种情况很少见,但可能。

但实际上截断文件所需要的只是FILE_WRITE_DATA访问权限。这是win32 api CreateFile的错误和非常糟糕的设计。

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

  • NtSetInformationFileFileEndOfFileInformation(The 调用者必须在设置FILE_WRITE_DATA标志的情况下打开文件 在 DesiredAccess 参数中)或者 FileAllocationInformation - 这项工作适用于所有窗口
  • SetFileInformationByHandle - 非常瘦的win32 shell NtSetInformationFile但仅限vista。同 FileEndOfFileInfoFileAllocationInfo。请注意,如果我们设置 AllocationSize到0 - 文件也将被截断为0大小。

      

    文件的文件结尾(EOF)位置必须始终小于或   等于文件分配大小。如果分配大小设置为a   小于EOF的值,EOF位置是自动的   调整以匹配文件分配大小。

  • SetEndOfFile第一次致电ZwQueryInformationFile FilePositionInformation(文件句柄打开后设置为0) 然后使用它(FILE_POSITION_INFORMATION)进行两次调用 NtSetInformationFile FileEndOfFileInformationFileAllocationInformation CreateFile。在这种情况下我们有2个没有 需要额外调用内核。所以这个效率比较不如前2 方式。
  • TRUNCATE_EXISTING FileAllocationInformation首次打开文件而不是 使用FILE_GENERIC_WRITE设置来调用NtSetInformationFile 为了这个电话,您如何查看需要额外的访问权限 - FILE_WRITE_DATA真的不需要。只需要 FILE_OVERWRITE。所以这种方式很糟糕
  • NtCreateFileTRUNCATE_EXISTING一起使用 CreateDisposition - 它在单个调用打开文件中并将EOF设置为0.感觉FILE_OVERWRITE必须这样做(使用FILE_OPEN 配置)。但由于未知原因(我认为这是错误),它使用 通过额外调用FileAllocationInformation访问 NtSetInformationFileFILE_OVERWRITE_IF
  • 如果我们不仅需要截断现有的文件,还需要创建新文件 空文件,如果它还不存在 - 最好用CREATE_ALWAYS 选项或它对应{{1}} - 这也是开放的 在对内核的单次调用中截断文件。或创建新文件