使用TRUNCATE_EXISTING调用Windows的CreateFile并使用OPEN_EXISTING调用它然后调用SetEndOfFile有什么区别?
前者被记录为需要GENERIC_WRITE访问权限,如果我只询问FILE_WRITE_DATA,则CreateFile会因ERROR_ACCESS_DENIED而失败。
对于后者,FILE_WRITE_DATA就足够了,CreateFile和SetEndOfFile都成功。
答案 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_ATTRIBUTES
,FILE_WRITE_EA
,FILE_APPEND_DATA
和READ_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
(The
调用者必须在设置FILE_WRITE_DATA
标志的情况下打开文件
在 DesiredAccess 参数中)或者
FileAllocationInformation
- 这项工作适用于所有窗口 SetFileInformationByHandle
- 非常瘦的win32 shell
NtSetInformationFile
但仅限vista。同
FileEndOfFileInfo
或FileAllocationInfo
。请注意,如果我们设置
AllocationSize
到0 - 文件也将被截断为0大小。
文件的文件结尾(EOF)位置必须始终小于或 等于文件分配大小。如果分配大小设置为a 小于EOF的值,EOF位置是自动的 调整以匹配文件分配大小。
SetEndOfFile
第一次致电ZwQueryInformationFile
FilePositionInformation
(文件句柄打开后设置为0)
然后使用它(FILE_POSITION_INFORMATION
)进行两次调用
NtSetInformationFile
FileEndOfFileInformation
和FileAllocationInformation
CreateFile
。在这种情况下我们有2个没有
需要额外调用内核。所以这个效率比较不如前2
方式。TRUNCATE_EXISTING
FileAllocationInformation
首次打开文件而不是
使用FILE_GENERIC_WRITE
设置来调用NtSetInformationFile
为了这个电话,您如何查看需要额外的访问权限 -
FILE_WRITE_DATA
真的不需要。只需要
FILE_OVERWRITE
。所以这种方式很糟糕NtCreateFile
与TRUNCATE_EXISTING
一起使用
CreateDisposition - 它在单个调用打开文件中并将EOF设置为0.感觉FILE_OVERWRITE
必须这样做(使用FILE_OPEN
配置)。但由于未知原因(我认为这是错误),它使用
通过额外调用FileAllocationInformation
访问
NtSetInformationFile
与FILE_OVERWRITE_IF
CREATE_ALWAYS
选项或它对应{{1}} - 这也是开放的
在对内核的单次调用中截断文件。或创建新文件