From 0eea7ca90bbf1ee44e836ab8ab3b6aab41dc82a1 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 4 Dec 2013 07:37:07 +0100 Subject: Utils: Fix getting a case sensitive path on windows. Until now we used GetShortPathName which relies on having 8.3 paths. This short path names are converted into long names which also corrects the case. The 8.3 paths can be manually deactivated via the fsutil. When this is done GetShortPathName does not return a convertible path string. If the case isn't corrected on windows we are opening multiple editors for the same file. For example, when reaching a breakpoint when using cdb or opening an entry from the issue panel generated by the msvc compile. Task-number: QTCREATORBUG-11199 Change-Id: Ic04055685e0e9bbe0d45cde20563929b7370695d Reviewed-by: Orgad Shaneh Reviewed-by: Eike Ziller Reviewed-by: Friedemann Kleint --- src/libs/utils/fileutils.cpp | 51 ++++++++------------------------------------ 1 file changed, 9 insertions(+), 42 deletions(-) (limited to 'src/libs/utils/fileutils.cpp') diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 4d7756b293..d5dc5b7a0b 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -40,6 +40,7 @@ #ifdef Q_OS_WIN #include +#include #endif namespace Utils { @@ -241,55 +242,21 @@ bool FileUtils::makeWritable(const FileName &path) return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser); } -#ifdef Q_OS_WIN -static QString getShortPathName(const QString &name) -{ - if (name.isEmpty()) - return name; - - // Determine length, then convert. - const LPCTSTR nameC = reinterpret_cast(name.utf16()); // MinGW - const DWORD length = GetShortPathNameW(nameC, NULL, 0); - if (length == 0) - return name; - QScopedArrayPointer buffer(new TCHAR[length]); - GetShortPathNameW(nameC, buffer.data(), length); - const QString rc = QString::fromUtf16(reinterpret_cast(buffer.data()), length - 1); - return rc; -} - -static QString getLongPathName(const QString &name) -{ - if (name.isEmpty()) - return name; - - // Determine length, then convert. - const LPCTSTR nameC = reinterpret_cast(name.utf16()); // MinGW - const DWORD length = GetLongPathNameW(nameC, NULL, 0); - if (length == 0) - return name; - QScopedArrayPointer buffer(new TCHAR[length]); - GetLongPathNameW(nameC, buffer.data(), length); - const QString rc = QString::fromUtf16(reinterpret_cast(buffer.data()), length - 1); - return rc; -} -#endif // Q_OS_WIN - // makes sure that capitalization of directories is canonical on Windows. // This mimics the logic in QDeclarative_isFileCaseCorrect QString FileUtils::normalizePathName(const QString &name) { #ifdef Q_OS_WIN - QString canonicalName = getShortPathName(name); - if (canonicalName.isEmpty()) + const QString nativeSeparatorName(QDir::toNativeSeparators(name)); + const LPCTSTR nameC = reinterpret_cast(nativeSeparatorName.utf16()); // MinGW + PIDLIST_ABSOLUTE file; + HRESULT hr = SHParseDisplayName(nameC, NULL, &file, 0, NULL); + if (FAILED(hr)) return name; - canonicalName = getLongPathName(canonicalName); - if (canonicalName.isEmpty()) + TCHAR buffer[MAX_PATH]; + if (!SHGetPathFromIDList(file, buffer)) return name; - // Upper case drive letter - if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':')) - canonicalName[0] = canonicalName.at(0).toUpper(); - return canonicalName; + return QDir::fromNativeSeparators(QString::fromUtf16(reinterpret_cast(buffer))); #else // Filesystem is case-insensitive only on Windows return name; #endif -- cgit v1.2.1