Windows 文件系统 API 不同的输出

Windows filesystem API different outputs

本文关键字:输出 文件系统 API Windows      更新时间:2023-10-16

在我的工作场所,我们有一个包装在Win32文件系统API上的接口,它允许我们做一堆文件操作。我们有一个操作,它基本上调用GetFileAttributesExW后跟FindFirstFileExW

这是一个简单的独立用例。

#include <Windows.h>
#include <string>
#include <iostream>
#include <errno.h>
#include <memory>
struct file_handle_close
{
void operator()(void *handle) const
{
if (static_cast<HANDLE>(handle) != INVALID_HANDLE_VALUE)
{
CloseHandle(static_cast<HANDLE>(handle));
}
}
};
typedef std::unique_ptr<void, file_handle_close>  file_handle_uptr;
void function2(const std::wstring& path)
{
WIN32_FILE_ATTRIBUTE_DATA attr_ctx;
if (GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &attr_ctx) == 0)
{    
DWORD  error_code(GetLastError());
std::cout << "Error occurred in GetFileAttributesExW : "<< error_code << std::endl;
}
else
{     
std::cout << "This is all good in GetFileAttributesExW!!!nn" ;
}
}
void function3(const std::wstring& path)
{
file_handle_uptr                         handle_uptr;
WIN32_FIND_DATAW                     file_attr;
DWORD                                error_code = ERROR_SUCCESS;
handle_uptr.reset(FindFirstFileExW(path.c_str(), FindExInfoBasic, &file_attr, FindExSearchNameMatch, nullptr, 0));
if (static_cast<HANDLE>(handle_uptr.get()) == INVALID_HANDLE_VALUE)
{
DWORD  error_code(GetLastError());
std::cout << "Error occurred in FindFirstFileExW : "<< error_code << std::endl; 
}
else
{
std::cout << "This is all good in FindFirstFileExW!!!nn" ;
}
}
int main(int argc,char** argv)
{
if(argc < 2)
{
std::cout << "Please enter a path!!!"<<std::endl;
}
else
{
const std::string str = argv[1];
const std::wstring wstr(str.begin(),str.end());
function2(wstr);
function3(wstr);
}
return 0;
}

我有两条具有混合权限的路径。

C:TEMPDir1Dir2 : Dir1 has permissions denied for current user
C:TEMPDIRXDIRYDIRZ : DIRX and DIRY have permissions denied for current user

我使用以下命令拒绝了权限

%icacls directoryname /deny username:(RX)

我使用这些路径作为上述代码创建的.exe文件的输入。我得到以下输出。

B:testfun>.testfun.exe C:TEMP
This is all good in GetFileAttributesExW!!!
This is all good in FindFirstFileExW!!!

B:testfun>.testfun.exe C:TEMPDir1
This is all good in GetFileAttributesExW!!!
This is all good in FindFirstFileExW!!!

B:testfun>.testfun.exe C:TEMPDir1Dir2  <-------- This
This is all good in GetFileAttributesExW!!!
Error occurred in FindFirstFileExW : 5

B:testfun>.testfun.exe C:TEMPDIRX
This is all good in GetFileAttributesExW!!!
This is all good in FindFirstFileExW!!!

B:testfun>.testfun.exe C:TEMPDIRXDIRY
Error occurred in GetFileAttributesExW : 5
Error occurred in FindFirstFileExW : 5

B:testfun>.testfun.exe C:TEMPDIRXDIRYDIRZ   <-------- This
This is all good in GetFileAttributesExW!!!
Error occurred in FindFirstFileExW : 5

我想了解的是这些函数行为的差异。

为什么GetFileAttributesExW给出不同的输出,而不是似乎尊重目录上设置的权限的FindFirstFileExW

我正在使用带有VS 10编译器的Windows 16299 Build 2017。

首先让我们看看FindFirstFileExW如何使用第一个参数lpFileName- 这不是最终的,确切地说是用于打开的文件的路径。 API 解析并拆分此字符串。 它在此字符串中搜索最后一个尾随反斜杠并将其拆分为 2 个字符串。 然后它是lpFileName的第一部分(在最后一个尾随反斜杠之前(,如果用作文件夹的路径,则尝试使用CC_打开系统9 访问。lpFileName的第二部分(换行到UNICODE_STRING后(在调用中使用NtQueryDirectoryFileFileName参数 -指向调用方分配的 Unicode 字符串的可选指针,其中包含 FileHandle 指定的目录中的文件(如果使用通配符,则为多个文件(的名称。

例如,如果您调用FindFirstFileExW(L"C:\TEMP\Dir1\Dir2", ..)C:TEMPDir1Dir2拆分为C:TEMPDir1Dir2. 和系统尝试打开C:TEMPDir1(并到达此处访问被拒绝(,然后(如果打开确定(将在文件夹中搜索Dir2(确切(文件 - 一点意义都不大 - 通常我们使用通配符,例如C:TEMPDir1*.

相反GetFileAttributesEx使用lpFileName作为文件的确切名称。

所以当你打电话

FindFirstFileExW(L"C:\TEMP\Dir1\Dir2", ..);
GetFileAttributesEx(L"C:\TEMP\Dir1\Dir2", ..);

您测试 2 个不同的文件夹:

C:TEMPDir1(1 行(和C:TEMPDir1Dir2(第二行( - 访问的结果可能不同也就不足为奇了。 第二 - 此 API 对文件夹使用不同的访问权限 - 当GetFileAttributesEx仅需要FILE_READ_ATTRIBUTES访问权限时,FindFirstFileExW需要FILE_READ_DATA。 因此,这也可能是不同的结果。 另请注意,FILE_READ_ATTRIBUTES是文件系统的特殊访问权限。 NTFS(例如(授予FILE_READ_ATTRIBUTES对调用方的访问权限2 种情况 - 如果调用方直接对文件具有FILE_READ_ATTRIBUTES访问权限,或者如果调用方对父文件夹具有FILE_LIST_DIRECTORY访问权限(作为旁注 - 与DELETE访问权限相同 - 如果明确拥有文件或(如果没有(如果我们对文件夹具有FILE_DELETE_CHILD访问权限,我们可以获得它(。

如果对C:TEMPDir1- 的案例调用不会失败,GetFileAttributesEx,因为您在父文件夹上具有访问权限C:TEMPFILE_LIST_DIRECTORYFindFirstFileExW不会失败,因为它确实打开了您可以FILE_READ_DATA访问的C:TEMP(另请注意FILE_READ_DATA == FILE_LIST_DIRECTORY == 1(

<小时 />

C:TEMPDIRX

GetFileAttributesExWFindFirstFileExW正常,因为用户FILE_READ_DATA(与FILE_LIST_DIRECTORY相同(C:TEMP

C:TEMPDIRXDIRY

GetFileAttributesExW失败,因为用户尚未FILE_READ_ATTRIBUTESDirY,也没有FILE_LIST_DIRECTORYDirXFindFirstFileExW失败,因为用户尚未FILE_READ_DATADirX

C:TEMPDIRXDIRYDIRZ

GetFileAttributesExW好的 - 用户对DirZ具有FILE_READ_ATTRIBUTES访问权限。FindFirstFileExW失败,因为用户尚未FILE_READ_DATADirY