]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/filename.cpp
Add white outline to bulls eye cursor used under MSW.
[wxWidgets.git] / src / common / filename.cpp
index 130d42951006eb9adb1202bae00dbe310f94e3fd..917c89de0f7c5927c1ac7ad8cb5e4f35957a2c77 100644 (file)
                 drive:\dir1\dir2\...\dirN\filename.ext where drive is a single
                 letter. "." and ".." as for Unix but no "~".
 
-                There are also UNC names of the form \\share\fullpath
+                There are also UNC names of the form \\share\fullpath and
+                MSW unique volume names of the form \\?\Volume{GUID}\fullpath.
+
+                The latter provide a uniform way to access a volume regardless of
+                its current mount point, i.e. you can change a volume's mount
+                point from D: to E:, or even remove it, and still be able to
+                access it through its unique volume name. More on the subject can
+                be found in MSDN's article "Naming a Volume" that is currently at
+                http://msdn.microsoft.com/en-us/library/aa365248(VS.85).aspx.
+
 
    wxPATH_MAC:  Mac OS 8/9 and Mac OS X under CodeWarrior 7 format, absolute file
                 names have the form
 extern const wxULongLong wxInvalidSize = (unsigned)-1;
 #endif // wxUSE_LONGLONG
 
+#ifdef __WIN32__
+    // this define is missing from VC6 headers
+    #ifndef INVALID_FILE_ATTRIBUTES
+        #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+    #endif
+#endif // __WIN32__
+
 namespace
 {
 
@@ -289,7 +305,18 @@ static wxString wxGetVolumeString(const wxString& volume, wxPathFormat format)
         // although I didn't find any authoritative docs on this)
         if ( format == wxPATH_DOS && volume.length() > 1 )
         {
-            path << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << volume;
+            // We also have to check for Windows unique volume names here and
+            // return it with '\\?\' prepended to it
+            if ( wxFileName::IsMSWUniqueVolumeNamePath("\\\\?\\" + volume + "\\",
+                                                       format) )
+            {
+                path << "\\\\?\\" << volume;
+            }
+            else
+            {
+                // it must be a UNC path
+                path << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << volume;
+            }
         }
         else if  ( format == wxPATH_DOS || format == wxPATH_VMS )
         {
@@ -319,6 +346,13 @@ static bool IsUNCPath(const wxString& path, wxPathFormat format)
                             !IsDOSPathSep(path[2u]);
 }
 
+// ----------------------------------------------------------------------------
+// private constants
+// ----------------------------------------------------------------------------
+
+// length of \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\ string
+static const size_t wxMSWUniqueVolumePrefixLength = 49;
+
 } // anonymous namespace
 
 // ============================================================================
@@ -574,7 +608,7 @@ bool wxFileName::FileExists() const
 /* static */
 bool wxFileName::FileExists( const wxString &filePath )
 {
-    #if defined(__WXPALMOS__)
+#if defined(__WXPALMOS__)
     return false;
 #elif defined(__WIN32__) && !defined(__WXMICROWIN__)
     // we must use GetFileAttributes() instead of the ANSI C functions because
@@ -587,16 +621,13 @@ bool wxFileName::FileExists( const wxString &filePath )
         #define S_ISREG(mode) ((mode) & S_IFREG)
     #endif
     wxStructStat st;
-#ifndef wxNEED_WX_UNISTD_H
-    return (wxStat( filePath.fn_str() , &st) == 0 && S_ISREG(st.st_mode))
+
+    return (wxStat( filePath, &st) == 0 && S_ISREG(st.st_mode))
 #ifdef __OS2__
       || (errno == EACCES) // if access is denied something with that name
                             // exists and is opened in exclusive mode.
 #endif
       ;
-#else
-    return wxStat( filePath , &st) == 0 && S_ISREG(st.st_mode);
-#endif
 #endif // __WIN32__/!__WIN32__
 }
 
@@ -613,12 +644,17 @@ bool wxFileName::DirExists( const wxString &dirPath )
 #if defined(__WINDOWS__) || defined(__OS2__)
     // Windows fails to find directory named "c:\dir\" even if "c:\dir" exists,
     // so remove all trailing backslashes from the path - but don't do this for
-    // the paths "d:\" (which are different from "d:") nor for just "\"
+    // the paths "d:\" (which are different from "d:"), for just "\" or for
+    // windows unique volume names ("\\?\Volume{GUID}\")
     while ( wxEndsWithPathSeparator(strPath) )
     {
         size_t len = strPath.length();
-        if ( len == 1 || (len == 3 && strPath[len - 2] == wxT(':')) )
+        if ( len == 1 || (len == 3 && strPath[len - 2] == wxT(':')) ||
+            (len == wxMSWUniqueVolumePrefixLength &&
+             wxFileName::IsMSWUniqueVolumeNamePath(strPath)))
+        {
             break;
+        }
 
         strPath.Truncate(len - 1);
     }
@@ -649,10 +685,10 @@ bool wxFileName::DirExists( const wxString &dirPath )
 
     wxStructStat st;
 #ifndef __VISAGECPP__
-    return wxStat(strPath.c_str(), &st) == 0 && ((st.st_mode & S_IFMT) == S_IFDIR);
+    return wxStat(strPath, &st) == 0 && ((st.st_mode & S_IFMT) == S_IFDIR);
 #else
     // S_IFMT not supported in VA compilers.. st_mode is a 2byte value only
-    return wxStat(strPath.c_str(), &st) == 0 && (st.st_mode == S_IFDIR);
+    return wxStat(strPath, &st) == 0 && (st.st_mode == S_IFDIR);
 #endif
 
 #endif // __WIN32__/!__WIN32__
@@ -1803,6 +1839,18 @@ bool wxFileName::IsPathSeparator(wxChar ch, wxPathFormat format)
     return ch != wxT('\0') && GetPathSeparators(format).Find(ch) != wxNOT_FOUND;
 }
 
+/* static */
+bool
+wxFileName::IsMSWUniqueVolumeNamePath(const wxString& path, wxPathFormat format)
+{
+    // return true if the format used is the DOS/Windows one and the string begins
+    // with a Windows unique volume name ("\\?\Volume{guid}\")
+    return format == wxPATH_DOS &&
+            path.length() >= wxMSWUniqueVolumePrefixLength &&
+             path.StartsWith(wxS("\\\\?\\Volume{")) &&
+              path[wxMSWUniqueVolumePrefixLength - 1] == wxFILE_SEP_PATH_DOS;
+}
+
 // ----------------------------------------------------------------------------
 // path components manipulation
 // ----------------------------------------------------------------------------
@@ -2187,9 +2235,26 @@ wxFileName::SplitVolume(const wxString& fullpathWithVolume,
 
     wxString fullpath = fullpathWithVolume;
 
-    // special Windows UNC paths hack: transform \\share\path into share:path
-    if ( IsUNCPath(fullpath, format) )
+    if ( IsMSWUniqueVolumeNamePath(fullpath, format) )
     {
+        // special Windows unique volume names hack: transform
+        // \\?\Volume{guid}\path into Volume{guid}:path
+        // note: this check must be done before the check for UNC path
+
+        // we know the last backslash from the unique volume name is located
+        // there from IsMSWUniqueVolumeNamePath
+        fullpath[wxMSWUniqueVolumePrefixLength - 1] = wxFILE_SEP_DSK;
+
+        // paths starting with a unique volume name should always be absolute
+        fullpath.insert(wxMSWUniqueVolumePrefixLength, 1, wxFILE_SEP_PATH_DOS);
+
+        // remove the leading "\\?\" part
+        fullpath.erase(0, 4);
+    }
+    else if ( IsUNCPath(fullpath, format) )
+    {
+        // special Windows UNC paths hack: transform \\share\path into share:path
+
         fullpath.erase(0, 2);
 
         size_t posFirstSlash =
@@ -2519,7 +2584,7 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
 #elif defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__OS2__) || (defined(__DOS__) && defined(__WATCOMC__))
     // no need to test for IsDir() here
     wxStructStat stBuf;
-    if ( wxStat( GetFullPath().c_str(), &stBuf) == 0 )
+    if ( wxStat( GetFullPath(), &stBuf) == 0 )
     {
         if ( dtAccess )
             dtAccess->Set(stBuf.st_atime);
@@ -2573,11 +2638,7 @@ wxULongLong wxFileName::GetSize(const wxString &filename)
     return wxULongLong(lpFileSizeHigh, ret);
 #else // ! __WIN32__
     wxStructStat st;
-#ifndef wxNEED_WX_UNISTD_H
-    if (wxStat( filename.fn_str() , &st) != 0)
-#else
     if (wxStat( filename, &st) != 0)
-#endif
         return wxInvalidSize;
     return wxULongLong(st.st_size);
 #endif