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
{
// 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 )
{
!IsDOSPathSep(path[2u]);
}
+// ----------------------------------------------------------------------------
+// private constants
+// ----------------------------------------------------------------------------
+
+// length of \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\ string
+static const size_t wxMSWUniqueVolumePrefixLength = 49;
+
} // anonymous namespace
// ============================================================================
/* 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
#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__
}
#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);
}
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__
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
// ----------------------------------------------------------------------------
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 =
#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);
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