Windows 文件系统 API 不同的输出
Windows filesystem API different outputs
在我的工作场所,我们有一个封装在 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!!!\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
似乎尊重目录上设置的权限?
我正在使用 Windows 10 Build 16299 和 VS 2017 编译器。
首先让我们看看 FindFirstFileExW
use first parameter lpFileName
- this is not final and exactly path to file which used to open. api is parse and split this string. it search for last trailing backslash \
in this string and split it to 2 strings. then it the first part of lpFileName
(before last trailing backslash) if used as path to folder which system is try open with FILE_READ_DATA | SYNCHRONIZE
access. and second part of lpFileName
used (after wrap to UNICODE_STRING
) in call NtQueryDirectoryFile
如何放置 FileName
参数 - 指向包含一个文件(或多个文件)名称的调用者分配的 Unicode 字符串的可选指针, 如果使用通配符) 在 FileHandle 指定的目录中。
例如,如果您调用 FindFirstFileExW(L"C:\TEMP\Dir1\Dir2", ..)
,则 C:\TEMP\Dir1\Dir2
拆分为 C:\TEMP\Dir1
和 Dir2
。系统尝试打开 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
(第 1 行)和 C:\TEMP\Dir1\Dir2
(第 2 行)- 访问结果可能不同并不奇怪。其次 - 此 api 使用 不同的 访问文件夹 - FindFirstFileExW
需要 FILE_READ_DATA
而 GetFileAttributesEx
仅需要 FILE_READ_ATTRIBUTES
访问.所以由此也可以得到不同的结果。另请注意 FILE_READ_ATTRIBUTES
是文件系统的特殊访问权限。 ntfs(例如)在两种情况下授予调用者 FILE_READ_ATTRIBUTES
访问权限 - 如果调用者直接对文件具有 FILE_READ_ATTRIBUTES
访问权限,或者如果调用者对 父级具有 FILE_LIST_DIRECTORY
访问权限 文件夹(作为附注 - 与 DELETE
访问权限相同的情况 - 如果明确具有文件或(如果没有)如果我们对父文件夹具有 FILE_DELETE_CHILD
访问权限,我们可以获得它)。
if case 调用 C:\TEMP\Dir1
- GetFileAttributesEx
不会失败,因为您可以访问 FILE_LIST_DIRECTORY
父文件夹 C:\TEMP
。
FindFirstFileExW
不会失败,因为它确实打开了您具有 FILE_READ_DATA
访问权限的 C:\TEMP
(另请注意 FILE_READ_DATA == FILE_LIST_DIRECTORY == 1
)
C:\TEMP\DIRX
GetFileAttributesExW
和 FindFirstFileExW
可以,因为用户在 C:\TEMP
上有 FILE_READ_DATA
(与 FILE_LIST_DIRECTORY
相同)
C:\TEMP\DIRX\DIRY
GetFileAttributesExW
失败,因为用户在 DirY
上没有 FILE_READ_ATTRIBUTES
并且在 DirX
上没有 FILE_LIST_DIRECTORY
。 FindFirstFileExW
失败,因为用户没有 FILE_READ_DATA
DirX
C:\TEMP\DIRX\DIRY\DIRZ
GetFileAttributesExW
正常 - 用户拥有 DirZ
的 FILE_READ_ATTRIBUTES
访问权限。 FindFirstFileExW
失败,因为用户没有 FILE_READ_DATA
DirY
在我的工作场所,我们有一个封装在 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!!!\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
似乎尊重目录上设置的权限?
我正在使用 Windows 10 Build 16299 和 VS 2017 编译器。
首先让我们看看 FindFirstFileExW
use first parameter lpFileName
- this is not final and exactly path to file which used to open. api is parse and split this string. it search for last trailing backslash \
in this string and split it to 2 strings. then it the first part of lpFileName
(before last trailing backslash) if used as path to folder which system is try open with FILE_READ_DATA | SYNCHRONIZE
access. and second part of lpFileName
used (after wrap to UNICODE_STRING
) in call NtQueryDirectoryFile
如何放置 FileName
参数 - 指向包含一个文件(或多个文件)名称的调用者分配的 Unicode 字符串的可选指针, 如果使用通配符) 在 FileHandle 指定的目录中。
例如,如果您调用 FindFirstFileExW(L"C:\TEMP\Dir1\Dir2", ..)
,则 C:\TEMP\Dir1\Dir2
拆分为 C:\TEMP\Dir1
和 Dir2
。系统尝试打开 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
(第 1 行)和 C:\TEMP\Dir1\Dir2
(第 2 行)- 访问结果可能不同并不奇怪。其次 - 此 api 使用 不同的 访问文件夹 - FindFirstFileExW
需要 FILE_READ_DATA
而 GetFileAttributesEx
仅需要 FILE_READ_ATTRIBUTES
访问.所以由此也可以得到不同的结果。另请注意 FILE_READ_ATTRIBUTES
是文件系统的特殊访问权限。 ntfs(例如)在两种情况下授予调用者 FILE_READ_ATTRIBUTES
访问权限 - 如果调用者直接对文件具有 FILE_READ_ATTRIBUTES
访问权限,或者如果调用者对 父级具有 FILE_LIST_DIRECTORY
访问权限 文件夹(作为附注 - 与 DELETE
访问权限相同的情况 - 如果明确具有文件或(如果没有)如果我们对父文件夹具有 FILE_DELETE_CHILD
访问权限,我们可以获得它)。
if case 调用 C:\TEMP\Dir1
- GetFileAttributesEx
不会失败,因为您可以访问 FILE_LIST_DIRECTORY
父文件夹 C:\TEMP
。
FindFirstFileExW
不会失败,因为它确实打开了您具有 FILE_READ_DATA
访问权限的 C:\TEMP
(另请注意 FILE_READ_DATA == FILE_LIST_DIRECTORY == 1
)
C:\TEMP\DIRX
GetFileAttributesExW
和 FindFirstFileExW
可以,因为用户在 C:\TEMP
FILE_READ_DATA
(与 FILE_LIST_DIRECTORY
相同)
C:\TEMP\DIRX\DIRY
GetFileAttributesExW
失败,因为用户在 DirY
上没有 FILE_READ_ATTRIBUTES
并且在 DirX
上没有 FILE_LIST_DIRECTORY
。 FindFirstFileExW
失败,因为用户没有 FILE_READ_DATA
DirX
C:\TEMP\DIRX\DIRY\DIRZ
GetFileAttributesExW
正常 - 用户拥有 DirZ
的 FILE_READ_ATTRIBUTES
访问权限。 FindFirstFileExW
失败,因为用户没有 FILE_READ_DATA
DirY