Как проверить, существует ли относительный путь - PullRequest
0 голосов
/ 03 ноября 2019

В этой записи предлагается использовать GetFileAttributes(), чтобы проверить, существует ли каталог. Но, очевидно, GetFileAttributes() может быть успешным, даже если ему передан неправильный путь.

Например, предположим, что текущим каталогом является D:/test, но выполнение следующих действий по-прежнему не возвращает INVALID_FILE_ATTRIBUTES, хотя путьпереданный в GetFileAttributes() явно не существует, потому что существует слишком много уровней ..:

DWORD attrs = GetFileAttributes("../../../../../../..");

Итак, как я могу определить, существует ли путь на самом деле?

1 Ответ

1 голос
/ 03 ноября 2019

Но, очевидно, GetFileAttributes() может быть успешным, даже если ему передан неверный путь.

это неправильно. если путь действительно неверен - GetFileAttributes возвращает соответствующую ошибку (обычно ERROR_INVALID_NAME или ERROR_FILE_NOT_FOUND). также не нужно проверять ERROR_SHARING_VIOLATION и ERROR_ACCESS_DENIED в случае GetFileAttributes return INVALID_FILE_ATTRIBUTES. потому что win32 конвертирует в ERROR_ACCESS_DENIED не только STATUS_ACCESS_DENIED, но и многие другие несвязанные состояния - более правильное использование NtQueryAttributesFile. также существуют недокументированные

extern "C" NTSYSAPI BOOLEAN NTAPI RtlDoesFileExists_U( _In_ PWSTR FileName );

, которые выполняют эту работу (внутренний вызов NtQueryAttributesFile и проверяют также на STATUS_SHARING_VIOLATION AND STATUS_ACCESS_DENIED)

также после APIreturn - файл уже может быть удален (или создан) - в результате возвращаемое значение может быть уже неправильным. так обычно, если нам нужен какой-то файл / папка - не нужно пытаться проверить, а создать или открыть его. или получите ошибку в этой операции


, но на самом деле ваша проблема не в GetFileAttributes, а в преобразовании пути win32 в nt.

вы предполагаете, что путь D:/test../../../../../../.. неверен. но система думает, что нет. RtlDosPathNameToNtPathName_U_WithStatus (или связанный), используемый системой для преобразования пути win32 в nt. если проверить этот API с вашим путем, это даст:

UNICODE_STRING us;
if (0 <= RtlDosPathNameToNtPathName_U_WithStatus(L"D:/test../../../../../../..", &us, 0, 0))
{
    DbgPrint("%wZ\n", &us);
    RtlFreeUnicodeString(&us);
}
if (0 <= RtlDosPathNameToNtPathName_U_WithStatus(L"../../../../../../..", &us, 0, 0))
{
    DbgPrint("%wZ\n", &us);
    RtlFreeUnicodeString(&us);
}

\??\D:\ и \??\<X>:\, поэтому система преобразует это в корневую папку на диске. и эта папка существует.

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