gpt4 book ai didi

c++ - Windows 文件系统 API 不同的输出

转载 作者:行者123 更新时间:2023-11-30 05:00:30 30 4
gpt4 key购买 nike

在我的工作场所,我们有一个封装在 Win32 文件系统 API 上的接口(interface),它允许我们执行大量文件操作。因为我们有一个操作,它本质上调用 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!!!\n\n" ;
}

}

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!!!\n\n" ;
}
}

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:\TEMP\Dir1\Dir2 : Dir1 has permissions denied for current user
C:\TEMP\DIRX\DIRY\DIRZ : 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:\TEMP\Dir1

This is all good in GetFileAttributesExW!!!

This is all good in FindFirstFileExW!!!


B:\testfun>.\testfun.exe C:\TEMP\Dir1\Dir2 <-------- This

This is all good in GetFileAttributesExW!!!

Error occurred in FindFirstFileExW : 5


B:\testfun>.\testfun.exe C:\TEMP\DIRX

This is all good in GetFileAttributesExW!!!

This is all good in FindFirstFileExW!!!


B:\testfun>.\testfun.exe C:\TEMP\DIRX\DIRY
Error occurred in GetFileAttributesExW : 5
Error occurred in FindFirstFileExW : 5


B:\testfun>.\testfun.exe C:\TEMP\DIRX\DIRY\DIRZ <-------- This

This is all good in GetFileAttributesExW!!!

Error occurred in FindFirstFileExW : 5

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

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

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

最佳答案

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

例如,如果您调用 FindFirstFileExW(L"C:\\TEMP\\Dir1\\Dir2", ..) C:\TEMP\Dir1\Dir2 拆分为 C:\TEMP\Dir1Dir2。系统尝试打开 C:\TEMP\Dir1(并在此处访问被拒绝)然后(如果打开正常)将在文件夹中搜索 Dir2(准确)文件 - 不是意义重大 - 通常我们使用通配符,例如 C:\TEMP\Dir1\*

对面GetFileAttributesEx使用 lpFileName 作为文件的确切名称。

所以当你打电话

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

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

C:\TEMP\Dir1(对于第一行)和 C:\TEMP\Dir1\Dir2(对于第二行)- 结果并不奇怪访问权限可能不同。其次 - 此 api 使用不同 访问文件夹 - FindFirstFileExW 需要 FILE_READ_DATAGetFileAttributesEx 需要 FILE_READ_ATTRIBUTES 仅限访问。所以由此也可以得到不同的结果。另请注意,FILE_READ_ATTRIBUTES 是文件系统的特殊访问权限。在 2 种情况下,ntfs(例如)授予调用者 FILE_READ_ATTRIBUTES 访问权限 - 如果调用者直接对文件具有 FILE_READ_ATTRIBUTES 访问权限,或者如果调用者具有 FILE_LIST_DIRECTORY 访问 parent 文件夹(如旁注 - 与 DELETE 访问相同的情况 - 如果明确有文件或(如果没有)如果我们有 我们可以获得它FILE_DELETE_CHILD 对父文件夹的访问权限)。

如果 case 调用 C:\TEMP\Dir1 - GetFileAttributesEx 没有失败,因为您可以访问父 C 上的 FILE_LIST_DIRECTORY :\TEMP 文件夹。FindFirstFileExW 不会失败,因为它确实打开了 C:\TEMP,您可以访问 FILE_READ_DATA(还要注意 FILE_READ_DATA == FILE_LIST_DIRECTORY = = 1 )


C:\TEMP\DIRX

GetFileAttributesExWFindFirstFileExW 正常,因为用户在 C 上有 FILE_READ_DATA(与 FILE_LIST_DIRECTORY 相同):\温度

C:\TEMP\DIRX\DIRY

GetFileAttributesExW 失败,因为用户在 DirY 上没有FILE_READ_ATTRIBUTES 并且在 DirX< 上没有FILE_LIST_DIRECTORY/FindFirstFileExW 失败,因为用户在 DirX

上没有 FILE_READ_DATA

C:\TEMP\DIRX\DIRY\DIRZ

GetFileAttributesExW 正常 - 用户对 DirZ 具有 FILE_READ_ATTRIBUTES 访问权限。 FindFirstFileExW 失败,因为用户在 DirY

上没有 FILE_READ_DATA

关于c++ - Windows 文件系统 API 不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50740108/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com