From 920d97606b258aba18c336f3b85b544a05383a1c Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sun, 28 Jan 2024 16:22:14 +0100 Subject: [PATCH] FileStream: Fix opening long paths on Windows (#1216) 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 --- taglib/toolkit/tfilestream.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/taglib/toolkit/tfilestream.cpp b/taglib/toolkit/tfilestream.cpp index f1233436..9ace7c85 100644 --- a/taglib/toolkit/tfilestream.cpp +++ b/taglib/toolkit/tfilestream.cpp @@ -56,7 +56,21 @@ 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); + constexpr wchar_t LongLocalPathPrefix[] = L"\\\\?\\"; + constexpr wchar_t UNCPathPrefix[] = L"\\\\"; + constexpr wchar_t LongUNCPathPrefix[] = L"\\\\?\\UNC\\"; + std::wstring pathWStr = path.wstr(); + if(pathWStr.length() > MAX_PATH && + pathWStr.compare(0, std::size(LongLocalPathPrefix) - 1, LongLocalPathPrefix) != 0 && + pathWStr.compare(0, std::size(LongUNCPathPrefix) - 1, LongUNCPathPrefix) != 0) { + if(pathWStr.compare(0, std::size(UNCPathPrefix) - 1, UNCPathPrefix) == 0) { + pathWStr = LongUNCPathPrefix + pathWStr.substr(2); + } + else { + pathWStr = LongLocalPathPrefix + pathWStr; + } + } + return CreateFileW(pathWStr.c_str(), access, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); #endif }