From 42b96187e3a58229be7c39f0e3a65a825c6cf100 Mon Sep 17 00:00:00 2001 From: Roggie Zhang Date: Wed, 4 Dec 2024 14:21:35 +0800 Subject: [PATCH] Handle long paths for windows --- pxr/base/arch/fileSystem.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/pxr/base/arch/fileSystem.cpp b/pxr/base/arch/fileSystem.cpp index c36aa49503..008caced1f 100644 --- a/pxr/base/arch/fileSystem.cpp +++ b/pxr/base/arch/fileSystem.cpp @@ -533,22 +533,34 @@ ArchGetFileName(FILE *file) return result; #elif defined (ARCH_OS_WINDOWS) string result; - WCHAR filePath[MAX_PATH]; + std::vector filePath(MAX_PATH); HANDLE hfile = _FileToWinHANDLE(file); - if (GetFinalPathNameByHandleW(hfile, filePath, MAX_PATH, VOLUME_NAME_DOS)) { + DWORD dwSize = GetFinalPathNameByHandleW(hfile, filePath.data(), MAX_PATH, VOLUME_NAME_DOS); + // * dwSize == 0. Fail. + // * dwSize < MAX_PATH. Success, and dwSize returns the size without null terminator. + // * dwSize >= MAX_PATH. Buffer is too small, and dwSize returns the size with null terminator. + if (dwSize >= MAX_PATH) { + filePath.resize(dwSize); + dwSize = GetFinalPathNameByHandleW(hfile, filePath.data(), dwSize, VOLUME_NAME_DOS); + } + + if (dwSize != 0) { size_t outSize = WideCharToMultiByte( - CP_UTF8, 0, filePath, - wcslen(filePath), + CP_UTF8, 0, filePath.data(), + dwSize, NULL, 0, NULL, NULL); result.resize(outSize); WideCharToMultiByte( - CP_UTF8, 0, filePath, + CP_UTF8, 0, filePath.data(), -1, &result.front(), outSize, NULL, NULL); - if (result.length() > 4) + // See https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats + // for format of DOS device paths. For UNC paths, it's returned as untouched. + if (result.length() > 4 && + result.compare(0, 8, "\\\\?\\UNC\\") != 0) { - // It needs to strip the path prefix as + // Otherwise, It needs to strip the path prefix as // the path returned is DOS device path, and the // syntax is one of: // \\.\C:\Test\Foo.txt