Browse Source

[Windows] Fall back on FindFirstFile if PathFileExistsW encounters an unexpected error code

mpqfs
staphen 2 days ago
parent
commit
17c7088bf3
No known key found for this signature in database
GPG Key ID: E6D757EEF0CE235F
  1. 89
      Source/utils/file_util.cpp

89
Source/utils/file_util.cpp

@ -87,75 +87,100 @@ std::string_view Dirname(std::string_view path)
return std::string_view { path.data(), sep };
}
bool FileExists(const char *path)
{
#ifdef _WIN32
namespace {
DWORD WindowsGetFileAttributes(const char *path)
{
#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR
const bool exists = ::GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
const DWORD attr = ::GetFileAttributesA(path);
#else
const auto pathUtf16 = ToWideChar(path);
if (pathUtf16 == nullptr) {
LogError("UTF-8 -> UTF-16 conversion error code {}", ::GetLastError());
return false;
}
const bool exists = ::PathFileExistsW(&pathUtf16[0]);
const DWORD attr = ::GetFileAttributesW(&pathUtf16[0]);
#endif
if (!exists) {
if (attr == INVALID_FILE_ATTRIBUTES) {
if (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) {
::SetLastError(ERROR_SUCCESS);
} else {
#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR
LogError("GetFileAttributesA({}): error code {}", path, ::GetLastError());
LogError("GetFileAttributesA: error code {}", ::GetLastError());
#else
LogError("PathFileExistsW({}): error code {}", path, ::GetLastError());
LogError("GetFileAttributesW: error code {}", ::GetLastError());
#endif
}
return false;
}
return true;
#elif defined(DVL_HAS_POSIX_2001) && !defined(__ANDROID__)
return ::access(path, F_OK) == 0;
#elif defined(DVL_HAS_FILESYSTEM)
std::error_code ec;
return std::filesystem::exists(reinterpret_cast<const char8_t *>(path), ec);
return attr;
}
#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR
bool WindowsFindFile(const char *path)
#else
SDL_IOStream *file = SDL_IOFromFile(path, "rb");
if (file == nullptr) return false;
SDL_CloseIO(file);
return true;
bool WindowsFindFile(const wchar_t *path)
#endif
{
#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR
WIN32_FIND_DATAA findFileData;
HANDLE hFind = FindFirstFileA(path, &findFileData);
#else
WIN32_FIND_DATAW findFileData;
HANDLE hFind = FindFirstFileW(path, &findFileData);
#endif
if (hFind == INVALID_HANDLE_VALUE) {
return false;
}
FindClose(hFind);
return true;
}
#ifdef _WIN32
namespace {
DWORD WindowsGetFileAttributes(const char *path)
bool WindowsFileExists(const char *path)
{
#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR
const DWORD attr = ::GetFileAttributesA(path);
const bool exists = ::GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
#else
const auto pathUtf16 = ToWideChar(path);
if (pathUtf16 == nullptr) {
LogError("UTF-8 -> UTF-16 conversion error code {}", ::GetLastError());
return false;
}
const DWORD attr = ::GetFileAttributesW(&pathUtf16[0]);
const bool exists = ::PathFileExistsW(&pathUtf16[0]);
#endif
if (attr == INVALID_FILE_ATTRIBUTES) {
if (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) {
::SetLastError(ERROR_SUCCESS);
} else {
if (exists) {
return true;
}
if (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) {
::SetLastError(ERROR_SUCCESS);
return false;
}
#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR
LogError("GetFileAttributesA: error code {}", ::GetLastError());
LogError("GetFileAttributesA({}): error code {}", path, ::GetLastError());
return WindowsFindFile(path);
#else
LogError("GetFileAttributesW: error code {}", ::GetLastError());
LogError("PathFileExistsW({}): error code {}", path, ::GetLastError());
return WindowsFindFile(pathUtf16.get());
#endif
}
}
return attr;
}
} // namespace
#endif
bool FileExists(const char *path)
{
#ifdef _WIN32
return WindowsFileExists(path);
#elif defined(DVL_HAS_POSIX_2001) && !defined(__ANDROID__) && !defined(_WIN32)
return ::access(path, F_OK) == 0;
#elif defined(DVL_HAS_FILESYSTEM) && !defined(_WIN32)
std::error_code ec;
return std::filesystem::exists(reinterpret_cast<const char8_t *>(path), ec);
#else
SDL_IOStream *file = SDL_IOFromFile(path, "rb");
if (file == nullptr) return false;
SDL_CloseIO(file);
return true;
#endif
}
bool DirectoryExists(const char *path)
{

Loading…
Cancel
Save