API файловой системы Windows разные выходы - PullRequest
0 голосов
/ 07 июня 2018

На моем рабочем месте у нас есть интерфейс, обернутый поверх API файловой системы Win32, который позволяет нам выполнять кучу операций с файлами.В этом у нас есть одна операция, которая по существу вызывает 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.

1 Ответ

0 голосов
/ 07 июня 2018

Прежде всего давайте посмотрим, как FindFirstFileExW использует первый параметр lpFileName - это не окончательный, а именно путь к файлу, который использовался для открытия.api - это разбор и разбиение этой строки.он ищет последнюю косую черту \ в этой строке и разделяет ее на 2 строки.затем это первая часть lpFileName (до последней обратной косой черты), если она используется как путь к папке, которую система пытается открыть с доступом FILE_READ_DATA | SYNCHRONIZE.и вторая часть lpFileName используется (после переноса в UNICODE_STRING) при вызове 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 (для второй строки) - неудивительно, что результаты доступа могут отличаться.во-вторых - этот API использует другой доступ к папкам - FindFirstFileExW требуют FILE_READ_DATA, когда GetFileAttributesEx требуют только FILE_READ_ATTRIBUTES доступа.поэтому к этому также могут быть разные результаты.Также обратите внимание, что FILE_READ_ATTRIBUTES - это специальный доступ для файловых систем.ntfs (например) предоставляет FILE_READ_ATTRIBUTES доступ к вызывающей стороне в 2 случаях - если у прямой вызывающей стороны есть FILE_READ_ATTRIBUTES доступ к файлу, или если у вызывающей стороны есть FILE_LIST_DIRECTORY доступ к папке parent (как примечание стороны)- та же ситуация с доступом DELETE - мы можем получить его, если у нас есть явный доступ к файлу или (если нет), если у нас есть FILE_DELETE_CHILD доступ к родительской папке).

, если case вызывает C:\TEMP\Dir1 - GetFileAttributesEx не ошибка, потому что у вас есть доступ FILE_LIST_DIRECTORY к родительской папке C:\TEMP.FindFirstFileExW не сбой, потому что он действительно открывает C:\TEMP, к которому у вас есть FILE_READ_DATA доступ (также обратите внимание, что FILE_READ_DATA == FILE_LIST_DIRECTORY == 1)


C:\TEMP\DIRX

GetFileAttributesExW иFindFirstFileExW хорошо, потому что у пользователя FILE_READ_DATA (так же, как FILE_LIST_DIRECTORY) на C:\TEMP

C:\TEMP\DIRX\DIRY

GetFileAttributesExW сбой, потому что у пользователя нет FILE_READ_ATTRIBUTES на DirY и не FILE_LIST_DIRECTORY на DirX.FindFirstFileExW ошибка, потому что у пользователя нет FILE_READ_DATA в DirX

C:\TEMP\DIRX\DIRY\DIRZ

GetFileAttributesExW нормально - у пользователя есть FILE_READ_ATTRIBUTES доступ для DirZ.FindFirstFileExW сбой, потому что у пользователя нет FILE_READ_DATA на DirY

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...