From 3a0f90c77b5e011485b0194455b6b7b1795ab7c8 Mon Sep 17 00:00:00 2001
From: Dongmei Wang <dongmei.wang@qt.io>
Date: Wed, 2 Nov 2016 22:38:17 -0700
Subject: [PATCH] QFileDialog() displays mapped network drives on Windows

Use WNet APIs to detect mapped network drives and connection
status of mapped network drives. Mapped network drives are
reported on Windows via QDir::drives(). When QFileDialog opens,
don't call blocking APIs such as GetFileAttributesEx on
disconnected mapped network drives.

Change-Id: I10f2353c8d0237ea2cf18920e71c4a35426a19ff
---
 src/corelib/io/qfileinfo.cpp              |  13 +++
 src/corelib/io/qfileinfo.h                |   2 +
 src/corelib/io/qfileinfo_p.h              |  32 +++++-
 src/corelib/io/qfilesystemengine.cpp      |  19 ++++
 src/corelib/io/qfilesystemengine_p.h      |   9 ++
 src/corelib/io/qfilesystemengine_win.cpp  | 162 +++++++++++++++++++++++++++++-
 src/corelib/io/qfsfileengine_win.cpp      |  13 ++-
 src/widgets/dialogs/qfileinfogatherer.cpp |  27 +++++
 src/widgets/dialogs/qfileinfogatherer_p.h |   3 +
 src/widgets/dialogs/qfilesystemmodel.cpp  |   5 +
 src/widgets/dialogs/qfilesystemmodel_p.h  |   6 +-
 11 files changed, 282 insertions(+), 9 deletions(-)

diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index dd19459..4536b31 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -197,6 +197,19 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
     return fileTimes[request];
 }
 
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+bool QFileInfoPrivate::isConnected() const {
+    if (mappedDrive) {
+        QString driveName = fileEntry.path();
+        if (driveName.endsWith(QLatin1Char('/')))
+            driveName.chop(1);
+        connected = QFileSystemEngine::mappedDriveConnectStatus(driveName, smb);
+        return connected;
+    }
+    return true;
+}
+#endif
+
 //************* QFileInfo
 
 /*!
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index 59d12c3..f8597bb 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -139,6 +139,8 @@ private:
     {
         return d_ptr.constData();
     }
+
+    friend class QFileInfoPrivate;
 };
 
 Q_DECLARE_SHARED(QFileInfo)
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index 73f9236..ea8d8ba 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -58,7 +58,7 @@
 
 QT_BEGIN_NAMESPACE
 
-class QFileInfoPrivate : public QSharedData
+class Q_CORE_EXPORT QFileInfoPrivate : public QSharedData
 {
 public:
     enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
@@ -70,6 +70,9 @@ public:
         cachedFlags(0),
         isDefaultConstructed(true),
         cache_enabled(true), fileFlags(0), fileSize(0)
+#if defined(Q_OS_WIN)  && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+        ,mappedDrive(false), connected(false), smb(false)
+#endif
     {}
     inline QFileInfoPrivate(const QFileInfoPrivate &copy)
         : QSharedData(copy),
@@ -83,6 +86,9 @@ public:
         isDefaultConstructed(!fileEngine),
 #endif
         cache_enabled(copy.cache_enabled), fileFlags(0), fileSize(0)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+        ,mappedDrive(copy.mappedDrive), connected(copy.connected), mappedDriveRemoteName(copy.mappedDriveRemoteName), smb(copy.smb)
+#endif
     {}
     inline QFileInfoPrivate(const QString &file)
         : fileEntry(QDir::fromNativeSeparators(file)),
@@ -94,8 +100,10 @@ public:
         isDefaultConstructed(!fileEngine),
 #endif
         cache_enabled(true), fileFlags(0), fileSize(0)
-    {
-    }
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+        ,mappedDrive(false), connected(false), smb(false)
+#endif
+    {}
 
     inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data)
         : QSharedData(),
@@ -105,6 +113,9 @@ public:
         cachedFlags(0),
         isDefaultConstructed(false),
         cache_enabled(true), fileFlags(0), fileSize(0)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+        ,mappedDrive(false), connected(false), smb(false)
+#endif
     {
         //If the file engine is not null, this maybe a "mount point" for a custom file engine
         //in which case we can't trust the metadata
@@ -123,6 +134,9 @@ public:
         isDefaultConstructed(!fileEngine),
 #endif
         cache_enabled(true), fileFlags(0), fileSize(0)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+         ,mappedDrive(false), connected(false), smb(false)
+#endif
     {
     }
 
@@ -141,6 +155,10 @@ public:
         fileOwners[0].clear();
     }
 
+    static const QFileInfoPrivate *get(const QFileInfo *o) {
+        return o->d_func();
+    }
+
     uint getFileFlags(QAbstractFileEngine::FileFlags) const;
     QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
     QString getFileName(QAbstractFileEngine::FileName) const;
@@ -170,6 +188,14 @@ public:
     inline void setCachedFlag(uint c) const
     { if (cache_enabled) cachedFlags |= c; }
 
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+    //mapped network drive support
+    mutable bool mappedDrive;
+    mutable bool connected;
+    mutable QString mappedDriveRemoteName;
+    mutable bool smb;
+    bool isConnected() const;
+#endif
 };
 
 QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index 02aa2ff..3e7dda5 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -425,4 +425,23 @@ QString QFileSystemEngine::resolveGroupName(const QFileSystemEntry &entry, QFile
 #endif
 }
 
+QFileInfoList QFileSystemEngine::getMappedDrives()
+{
+    QFileInfoList infoList;
+#if defined(Q_OS_WIN)
+    getMappedNetworkDrives(RESOURCE_CONNECTED, infoList);
+    getMappedNetworkDrives(RESOURCE_REMEMBERED, infoList);
+#endif
+    return infoList;
+}
+
+bool QFileSystemEngine::mappedDriveConnectStatus(const QString &name, bool smb)
+{
+#if defined(Q_OS_WIN)
+    return mappedNetworkDriveConnectStatus(name, smb);
+#endif
+    // not supported yet for other OSes
+    return false;
+}
+
 QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index 6db9319..628bdaa 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -46,6 +46,7 @@
 //
 
 #include "qfile.h"
+#include "qfileinfo.h"
 #include "qfilesystementry_p.h"
 #include "qfilesystemmetadata_p.h"
 #include <QtCore/private/qsystemerror_p.h>
@@ -84,6 +85,10 @@ public:
 
     static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
                              QFileSystemMetaData::MetaDataFlags what);
+
+    static QFileInfoList getMappedDrives();
+    static bool mappedDriveConnectStatus(const QString &name, bool smb);
+
 #if defined(Q_OS_UNIX)
     static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
 #endif
@@ -98,7 +103,10 @@ public:
                                 QFileSystemMetaData::MetaDataFlags what);
     static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
     static QString nativeAbsoluteFilePath(const QString &path);
+    static bool getMappedNetworkDrives(DWORD dwScope, QFileInfoList &list);
+    static bool mappedNetworkDriveConnectStatus(const QString &name, bool smb);
 #endif
+
     //homePath, rootPath and tempPath shall return clean paths
     static QString homePath();
     static QString rootPath();
@@ -121,6 +129,7 @@ public:
 
     static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
                                                                   QFileSystemMetaData &data);
+
 private:
     static QString slowCanonicalized(const QString &path);
 #if defined(Q_OS_WIN)
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index e55ab0b..0cd5a81 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -41,6 +41,7 @@
 #include <qdebug.h>
 
 #include "qfile.h"
+#include "qfileinfo_p.h"
 #include "qdir.h"
 #include "private/qmutexpool_p.h"
 #include "qvarlengtharray.h"
@@ -291,6 +292,25 @@ typedef struct _SHARE_INFO_1 {
     LPWSTR shi1_remark;
 } SHARE_INFO_1;
 
+#if defined( _WIN32_WINNT ) || defined( WINNT ) || defined( __midl ) \
+    || defined( FORCE_UNICODE )
+#define LMSTR   LPWSTR
+#define LMCSTR  LPCWSTR
+#else
+#define LMSTR   LPSTR
+#define LMCSTR  LPCSTR
+#endif
+typedef DWORD (WINAPI *PtrNetUseGetInfo)(LMSTR, LMSTR, DWORD, LPBYTE*);
+static PtrNetUseGetInfo ptrNetUseGetInfo = 0;
+typedef struct _USE_INFO_1 {
+    LMSTR ui1_local;
+    LMSTR ui1_remote;
+    LMSTR ui1_password;
+    DWORD ui1_status;
+    DWORD ui1_asg_type;
+    DWORD ui1_refcount;
+    DWORD ui1_usecount;
+} USE_INFO_1, *LPUSE_INFO_1;
 
 static bool resolveUNCLibs()
 {
@@ -299,7 +319,7 @@ static bool resolveUNCLibs()
 #ifndef QT_NO_THREAD
         QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
         if (triedResolve) {
-            return ptrNetShareEnum && ptrNetApiBufferFree;
+            return ptrNetShareEnum && ptrNetApiBufferFree && ptrNetUseGetInfo;
         }
 #endif
         triedResolve = true;
@@ -309,10 +329,12 @@ static bool resolveUNCLibs()
             ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum");
             if (ptrNetShareEnum)
                 ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree");
+            if (ptrNetApiBufferFree)
+                ptrNetUseGetInfo = (PtrNetUseGetInfo)GetProcAddress(hLib, "NetUseGetInfo");
         }
 #endif // !Q_OS_WINCE && !Q_OS_WINRT
     }
-    return ptrNetShareEnum && ptrNetApiBufferFree;
+    return ptrNetShareEnum && ptrNetApiBufferFree && ptrNetUseGetInfo;
 }
 
 static QString readSymLink(const QFileSystemEntry &link)
@@ -921,7 +943,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa
     }
 #endif
     if (entryExists)
-        data.fillFromFileAttribute(fileAttrib);
+        data.fillFromFileAttribute(fileAttrib, fname.isDriveRoot());
     return entryExists;
 }
 
@@ -1470,6 +1492,140 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
     return ret;
 }
 
+typedef DWORD (WINAPI *PtrWNetOpenEnumW) (DWORD, DWORD, DWORD, LPNETRESOURCEW, LPHANDLE);
+static PtrWNetOpenEnumW ptrWNetOpenEnumW = 0;
+typedef DWORD (WINAPI *PtrWNetEnumResourceW) (HANDLE, LPDWORD, LPVOID, LPDWORD);
+static PtrWNetEnumResourceW ptrWNetEnumResourceW = 0;
+typedef DWORD (WINAPI *PtrWNetCloseEnum) (HANDLE);
+static PtrWNetCloseEnum ptrWNetCloseEnum = 0;
+typedef DWORD (WINAPI *PtrWNetGetConnection) (LPCTSTR, LPTSTR, LPDWORD);
+static PtrWNetGetConnection ptrWNetGetConnection = 0;
+#define USE_SESSLOST 2
+#define USE_DISCONN 3
+#define USE_NETERR 4
+
+static bool resolveMprLibrary()
+{
+    static bool triedResolve = false;
+
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+#endif
+    if (!triedResolve) {
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+        HINSTANCE hLib = QSystemLibrary::load(L"Mpr");
+        if (hLib) {
+            if (ptrWNetOpenEnumW = (PtrWNetOpenEnumW)GetProcAddress(hLib, "WNetOpenEnumW"))
+                if (ptrWNetEnumResourceW = (PtrWNetEnumResourceW)GetProcAddress(hLib, "WNetEnumResourceW"))
+                    if (ptrWNetCloseEnum = (PtrWNetCloseEnum)GetProcAddress(hLib, "WNetCloseEnum"))
+                        if (ptrWNetGetConnection = (PtrWNetGetConnection)GetProcAddress(hLib, "WNetGetConnectionW"))
+                            triedResolve = true;
+        }
+#endif // !Q_OS_WINCE && !Q_OS_WINRT
+    }
+    return ptrWNetOpenEnumW && ptrWNetEnumResourceW && ptrWNetCloseEnum && ptrWNetGetConnection;
+}
+
+bool QFileSystemEngine::getMappedNetworkDrives(DWORD dwScope, QFileInfoList &list)
+{
+    if (!resolveMprLibrary())
+        return false;
+
+    DWORD ret;
+    HANDLE hEnum;
+    DWORD bufferSize = 16384;
+    DWORD entryCount = -1;
+    LPNETRESOURCE lpnr;
+
+    lpnr = NULL;
+    ret = ptrWNetOpenEnumW(dwScope, RESOURCETYPE_DISK, 0, NULL, &hEnum);
+
+    if (ret != NO_ERROR) {
+        qWarning() << "WNetOpenEnum failed with error" << ret;
+        return FALSE;
+    }
+
+    lpnr = (LPNETRESOURCE) GlobalAlloc(GPTR, bufferSize);
+    if (!lpnr) {
+        qWarning() << "WNetOpenEnum failed with error" << ret;
+        return FALSE;
+    }
+
+    do {
+        ZeroMemory(lpnr, bufferSize);
+        ret = ptrWNetEnumResourceW(hEnum, &entryCount, lpnr, &bufferSize);
+        if (ret == NO_ERROR) {
+           for (DWORD i = 0; i < entryCount; i++) {
+               if (!(lpnr[i].dwType == RESOURCETYPE_DISK
+                     && lpnr[i].dwDisplayType == RESOURCEDISPLAYTYPE_SHARE
+                     && lpnr[i].lpLocalName))
+                   continue;
+               QString localName = QString::fromWCharArray(lpnr[i].lpLocalName) + QLatin1Char('/');
+               QFileInfo info(localName);
+               const QFileInfoPrivate *priv = QFileInfoPrivate::get(&info);
+               priv->metaData.size_ = 0;
+               priv->metaData.knownFlagsMask = QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType
+                                                | QFileSystemMetaData::SizeAttribute;
+               priv->metaData.entryFlags = QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType;
+               priv->mappedDrive = true;
+               priv->mappedDriveRemoteName = QString::fromWCharArray(lpnr[i].lpRemoteName);
+               QString str = QString::fromWCharArray(lpnr[i].lpProvider);
+               priv->smb = (str == QLatin1String("Microsoft Windows Network"));
+               priv->connected = mappedNetworkDriveConnectStatus(localName, priv->smb);
+               // for disconnected mapped drives, set knowFlagsMask to 0xFFFFFFFF since the attributes other than
+               //QFileSystemMetaData::ExistsAttribute and QFileSystemMetaData::DirectoryType don't seem to be valid.
+               if (!priv->connected)
+                   priv->metaData.knownFlagsMask = (QFileSystemMetaData::MetaDataFlags)0xFFFFFFFF;
+               bool found = false;
+               for (int i = 0; i < list.size(); i++) {
+                   if (localName == list.at(i).filePath())
+                       found = true;
+               }
+               if (!found)
+                    list.append(info);
+            }
+        }
+        else if (ret != ERROR_NO_MORE_ITEMS) {
+            qWarning() << "WNetEnumResource failed with error" << ret;
+
+            break;
+        }
+    } while (ret != ERROR_NO_MORE_ITEMS);
+
+    GlobalFree((HGLOBAL) lpnr);
+    lpnr = NULL;
+
+    ret = ptrWNetCloseEnum(hEnum);
+
+    if (ret != NO_ERROR) {
+        qWarning() << "WNetCloseEnum failed with error" << ret;
+        return false;
+    }
+    return true;
+}
+
+bool QFileSystemEngine::mappedNetworkDriveConnectStatus(const QString &name, bool smb)
+{
+    bool connect = false;
+    if ( smb && resolveUNCLibs()) {
+        LPUSE_INFO_1 pUse_Info = NULL;
+        if (!ptrNetUseGetInfo(NULL, (wchar_t *)name.utf16(), 1, (LPBYTE *)&pUse_Info)) {
+            if (pUse_Info)
+                connect = !(pUse_Info->ui1_status==USE_SESSLOST || pUse_Info->ui1_status==USE_DISCONN
+                            || pUse_Info->ui1_status==USE_NETERR);
+        }
+        ptrNetApiBufferFree(pUse_Info);
+    }
+    else {
+        wchar_t buffer[256];
+        DWORD bufferLength = 256;
+        DWORD res = ptrWNetGetConnection((wchar_t *)name.utf16(), buffer, &bufferLength);
+        if (res == NO_ERROR)
+            connect = true;
+    }
+    return connect;
+}
+
 static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
 {
     QDateTime ret;
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 886d526..79a7c67 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -625,17 +625,26 @@ QFileInfoList QFSFileEngine::drives()
 {
     QFileInfoList ret;
 #if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+    QFileInfoList mappedDrives = QFileSystemEngine::getMappedDrives();
 #if defined(Q_OS_WIN32)
     quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff;
 #endif
     char driveName[] = "A:/";
 
     while (driveBits) {
-        if (driveBits & 1)
-            ret.append(QFileInfo(QLatin1String(driveName)));
+        if (driveBits & 1) {
+            int i;
+            for (i = 0; i < mappedDrives.size(); i++) {
+                if (mappedDrives.at(i).filePath() == QLatin1String(driveName))
+                    break;
+            }
+            if (i == mappedDrives.size())
+                ret.append(QFileInfo(QLatin1String(driveName)));
+        }
         driveName[0]++;
         driveBits = driveBits >> 1;
     }
+    ret.append(mappedDrives);
     return ret;
 #else // !Q_OS_WINCE && !Q_OS_WINRT
     ret.append(QFileInfo(QLatin1String("/")));
diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp
index be96b4c..18d6283 100644
--- a/src/widgets/dialogs/qfileinfogatherer.cpp
+++ b/src/widgets/dialogs/qfileinfogatherer.cpp
@@ -221,10 +221,27 @@ void QFileInfoGatherer::run()
     }
 }
 
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+static QString mappedDriveType(const QFileInfoPrivate *fileInfo)
+{
+    if (!fileInfo)
+        return QLatin1String("");
+
+    return fileInfo->isConnected() ? QObject::tr("Network Drive")
+                                   : QObject::tr("Disconnected Network Drive");
+}
+#endif
+
 QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
 {
     QExtendedInformation info(fileInfo);
     info.icon = m_iconProvider->icon(fileInfo);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+    const QFileInfoPrivate *priv = QFileInfoPrivate::get(&fileInfo);
+    if (priv->mappedDrive)
+        info.displayType = mappedDriveType(priv);
+    else
+#endif
     info.displayType = m_iconProvider->type(fileInfo);
 #ifndef QT_NO_FILESYSTEMWATCHER
     // ### Not ready to listen all modifications
@@ -336,6 +353,16 @@ void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bo
     }
 }
 
+QString QExtendedInformation::displayFileType() const
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+    const QFileInfoPrivate *priv = QFileInfoPrivate::get(&mFileInfo);
+    if (priv->mappedDrive)
+        return mappedDriveType(priv);
+#endif
+    return displayType;
+}
+
 #endif // QT_NO_FILESYSTEMMODEL
 
 QT_END_NAMESPACE
diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h
index 03f87fd..3481444 100644
--- a/src/widgets/dialogs/qfileinfogatherer_p.h
+++ b/src/widgets/dialogs/qfileinfogatherer_p.h
@@ -57,6 +57,7 @@
 #include <qelapsedtimer.h>
 
 #include <private/qfilesystemengine_p.h>
+#include <private/qfileinfo_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -133,6 +134,8 @@ public:
         return size;
     }
 
+    QString displayFileType() const;
+
     QString displayType;
     QIcon icon;
 
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index 0e2eee3..cb123d2 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -1677,10 +1677,15 @@ QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFile
         wchar_t name[MAX_PATH + 1];
         //GetVolumeInformation requires to add trailing backslash
         const QString nodeName = fileName + QLatin1String("\\");
+        const QFileInfoPrivate *priv = QFileInfoPrivate::get(&info);
+        if (!priv->mappedDrive) {
         BOOL success = ::GetVolumeInformation((wchar_t *)(nodeName.utf16()),
                 name, MAX_PATH + 1, NULL, 0, NULL, NULL, 0);
         if (success && name[0])
             node->volumeName = QString::fromWCharArray(name);
+        }
+        else
+            node->volumeName = priv->mappedDriveRemoteName;
     }
 #endif
     parentNode->children.insert(fileName, node);
diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h
index d2a40a1..9e8c0e2 100644
--- a/src/widgets/dialogs/qfilesystemmodel_p.h
+++ b/src/widgets/dialogs/qfilesystemmodel_p.h
@@ -50,6 +50,7 @@
 #ifndef QT_NO_FILESYSTEMMODEL
 
 #include <private/qabstractitemmodel_p.h>
+#include <private/qfileinfo_p.h>
 #include <qabstractitemmodel.h>
 #include "qfileinfogatherer_p.h"
 #include <qpair.h>
@@ -94,7 +95,10 @@ public:
 #endif
 
         inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; }
-        inline QString type() const { if (info) return info->displayType; return QLatin1String(""); }
+        inline QString type() const {
+            if (info) return info->displayFileType();
+            return QLatin1String("");
+        }
         inline QDateTime lastModified() const { if (info) return info->lastModified(); return QDateTime(); }
         inline QFile::Permissions permissions() const { if (info) return info->permissions(); return 0; }
         inline bool isReadable() const { return ((permissions() & QFile::ReadUser) != 0); }
-- 
2.8.1.windows.1

