Но, очевидно, 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>:\
, поэтому система преобразует это в корневую папку на диске. и эта папка существует.