FileStream: Fix opening long paths on Windows

To make sure paths longer than MAX_PATH (260) can be opened, prefix local paths with `\\?\`, and UNC paths with `\\?\UNC\`.

I've tested on Windows 10 22H2 (Build 19045.3930), even when setting LongPathsEnabled to 1 in the registry, it still won't open files with long paths without prefixing them.

For more information see.: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
This commit is contained in:
Jonas Kvinge
2024-01-27 23:27:15 +01:00
committed by Urs Fleisch
parent 0d2c31b102
commit e08d0395c6

View File

@ -49,6 +49,10 @@ namespace
const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE;
const std::wstring LongLocalPathPrefix = L"\\\\?\\";
const std::wstring UNCPathPrefix = L"\\\\";
const std::wstring LongUNCPathPrefix = L"\\\\?\\UNC\\";
FileHandle openFile(const FileName &path, bool readOnly)
{
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
@ -56,7 +60,25 @@ namespace
#if defined (PLATFORM_WINRT)
return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#else
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
std::wstring fixed_path;
if (path.wstr().length() > MAX_PATH && path.wstr().compare(0, LongLocalPathPrefix.length(), LongLocalPathPrefix) != 0 && path.wstr().compare(0, LongUNCPathPrefix.length(), LongUNCPathPrefix) != 0)
{
if (path.wstr().compare(0, UNCPathPrefix.length(), UNCPathPrefix) == 0)
{
fixed_path.append(LongUNCPathPrefix);
fixed_path.append(path.wstr().substr(2));
}
else
{
fixed_path.append(LongLocalPathPrefix);
fixed_path.append(path.wstr());
}
}
else
{
fixed_path = path.wstr();
}
return CreateFileW(fixed_path.c_str(), access, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
#endif
}