aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Kvinge <jonas@jkvinge.net>2024-01-28 16:22:14 +0100
committerGitHub <noreply@github.com>2024-01-28 16:22:14 +0100
commit920d97606b258aba18c336f3b85b544a05383a1c (patch)
tree202a9d432d371b6268106a62a23c6584232fd619
parent0d2c31b10210cbf94a7bd3b86f4e89e111e1add0 (diff)
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
-rw-r--r--taglib/toolkit/tfilestream.cpp16
1 files changed, 15 insertions, 1 deletions
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
}