Reputation: 10037
In this post it is suggested to use GetFileAttributes()
to check if a directory exists. But apparently, GetFileAttributes()
can succeed even if it is passed an invalid path.
For example, let's assume the current directory is D:/test
but doing the following still doesn't return INVALID_FILE_ATTRIBUTES
although the path passed to GetFileAttributes()
clearly doesn't exist because there are way too many levels of ..
:
DWORD attrs = GetFileAttributes("../../../../../../..");
So how can I detect if a path actually exists?
Upvotes: 1
Views: 668
Reputation: 33706
But apparently,
GetFileAttributes()
can succeed even if it is passed an invalid path.
this is wrong. if path really invalid - GetFileAttributes
return appropriate error (ERROR_INVALID_NAME
or ERROR_FILE_NOT_FOUND
usually). not also that need check for ERROR_SHARING_VIOLATION
and ERROR_ACCESS_DENIED
in case GetFileAttributes
return INVALID_FILE_ATTRIBUTES
. because win32 convert to ERROR_ACCESS_DENIED
not only STATUS_ACCESS_DENIED
but many other unrelated status - more correct use NtQueryAttributesFile
. also exist undocumented
extern "C" NTSYSAPI BOOLEAN NTAPI RtlDoesFileExists_U( _In_ PWSTR FileName );
which do this job (internal it call NtQueryAttributesFile
and check also for STATUS_SHARING_VIOLATION
AND STATUS_ACCESS_DENIED
)
also after api return - file already can be deleted (or created) - as result returned value can be already wrong. so usual if we need some file/folder - need not try check but create or open it. or get error in this operation
but really your problem not in GetFileAttributes
but in win32 to nt path conversion.
you assume that path D:/test../../../../../../..
is wrong. but system think that not. the RtlDosPathNameToNtPathName_U_WithStatus
(or related) used by system for convert win32 path to nt. if test this api with your path, this give:
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:\
and \??\<X>:\
so system convert this to root folder on drive. and this folder exist.
Upvotes: 2