Skip to content

Commit 3defe99

Browse files
committed
Merge pull request #3361 from roggiezhang-nv/improve_arch_get_file_name
Improve `ArchGetFileName` for windows to return full path (Internal change: 2350905)
2 parents dbe196b + 19201b2 commit 3defe99

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

pxr/base/arch/fileSystem.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <cstdio>
2222
#include <cstdlib>
2323
#include <cerrno>
24+
#include <filesystem>
2425
#include <memory>
2526
#include <utility>
2627

@@ -532,24 +533,35 @@ ArchGetFileName(FILE *file)
532533
}
533534
return result;
534535
#elif defined (ARCH_OS_WINDOWS)
535-
static constexpr DWORD bufSize =
536-
sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * 4096;
537-
HANDLE hfile = _FileToWinHANDLE(file);
538-
auto fileNameInfo = reinterpret_cast<PFILE_NAME_INFO>(malloc(bufSize));
539536
string result;
540-
if (GetFileInformationByHandleEx(
541-
hfile, FileNameInfo, static_cast<void *>(fileNameInfo), bufSize)) {
537+
std::vector<WCHAR> filePath(MAX_PATH);
538+
HANDLE hfile = _FileToWinHANDLE(file);
539+
DWORD dwSize = GetFinalPathNameByHandleW(hfile, filePath.data(), MAX_PATH, VOLUME_NAME_DOS);
540+
// * dwSize == 0. Fail.
541+
// * dwSize < MAX_PATH. Success, and dwSize returns the size without null terminator.
542+
// * dwSize >= MAX_PATH. Buffer is too small, and dwSize returns the size with null terminator.
543+
if (dwSize >= MAX_PATH) {
544+
filePath.resize(dwSize);
545+
dwSize = GetFinalPathNameByHandleW(hfile, filePath.data(), dwSize, VOLUME_NAME_DOS);
546+
}
547+
548+
if (dwSize != 0) {
542549
size_t outSize = WideCharToMultiByte(
543-
CP_UTF8, 0, fileNameInfo->FileName,
544-
fileNameInfo->FileNameLength/sizeof(WCHAR),
550+
CP_UTF8, 0, filePath.data(),
551+
dwSize,
545552
NULL, 0, NULL, NULL);
546553
result.resize(outSize);
547554
WideCharToMultiByte(
548-
CP_UTF8, 0, fileNameInfo->FileName,
549-
fileNameInfo->FileNameLength/sizeof(WCHAR),
555+
CP_UTF8, 0, filePath.data(),
556+
-1,
550557
&result.front(), outSize, NULL, NULL);
558+
559+
// Strip path prefix if necessary.
560+
// See https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
561+
// for format of DOS device paths.
562+
auto canonicalPath = std::filesystem::canonical(result);
563+
result = canonicalPath.string();
551564
}
552-
free(fileNameInfo);
553565
return result;
554566
#else
555567
#error Unknown system architecture

pxr/base/arch/testenv/testFileSystem.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <cstdio>
1515
#include <cstdlib>
1616
#include <cstring>
17+
#include <filesystem>
1718

1819
PXR_NAMESPACE_USING_DIRECTIVE
1920

@@ -92,6 +93,12 @@ int main()
9293
fclose(firstFile);
9394
ARCH_AXIOM(ArchGetFileLength(firstName.c_str()) == strlen(testContent));
9495

96+
// Open a file, check that the file path from FILE* handle is matched.
97+
ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "rb")) != NULL);
98+
std::string filePath = ArchGetFileName(firstFile);
99+
ARCH_AXIOM(std::filesystem::equivalent(filePath, firstName));
100+
fclose(firstFile);
101+
95102
// Map the file and assert the bytes are what we expect they are.
96103
ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "rb")) != NULL);
97104
ArchConstFileMapping cfm = ArchMapFileReadOnly(firstFile);

0 commit comments

Comments
 (0)