Add support for MSW unique volume names to wxFileName.
Recognize the paths starting with "\\?\Volume{GUID}" under MSW and provide a way to test for them. Closes #8874. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62782 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
2450225e87
commit
e01a788ee0
@ -432,6 +432,7 @@ All:
|
|||||||
wxVariant.
|
wxVariant.
|
||||||
- wxDateTime timezone functions now dynamic (no caching).
|
- wxDateTime timezone functions now dynamic (no caching).
|
||||||
- Added wxHttp::GetCookie and wxHttp::HasCookies (dodge).
|
- Added wxHttp::GetCookie and wxHttp::HasCookies (dodge).
|
||||||
|
- Added support for unique volume names to wxFileName (Neno Ganchev).
|
||||||
|
|
||||||
Unix:
|
Unix:
|
||||||
|
|
||||||
|
@ -433,6 +433,11 @@ public:
|
|||||||
// is the char a path separator for this format?
|
// is the char a path separator for this format?
|
||||||
static bool IsPathSeparator(wxChar ch, wxPathFormat format = wxPATH_NATIVE);
|
static bool IsPathSeparator(wxChar ch, wxPathFormat format = wxPATH_NATIVE);
|
||||||
|
|
||||||
|
// is this is a DOS path which beings with a windows unique volume name
|
||||||
|
// ('\\?\Volume{guid}\')?
|
||||||
|
static bool IsMSWUniqueVolumeNamePath(const wxString& path,
|
||||||
|
wxPathFormat format = wxPATH_NATIVE);
|
||||||
|
|
||||||
// Dir accessors
|
// Dir accessors
|
||||||
size_t GetDirCount() const { return m_dirs.size(); }
|
size_t GetDirCount() const { return m_dirs.size(); }
|
||||||
void AppendDir(const wxString& dir);
|
void AppendDir(const wxString& dir);
|
||||||
|
@ -819,6 +819,24 @@ public:
|
|||||||
static bool IsPathSeparator(wxChar ch,
|
static bool IsPathSeparator(wxChar ch,
|
||||||
wxPathFormat format = wxPATH_NATIVE);
|
wxPathFormat format = wxPATH_NATIVE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns @true if the volume part of the path is a unique volume name.
|
||||||
|
|
||||||
|
This function will always return @false if the path format is not
|
||||||
|
wxPATH_DOS.
|
||||||
|
|
||||||
|
Unique volume names are Windows volume identifiers which remain the same
|
||||||
|
regardless of where the volume is actually mounted. Example of a path
|
||||||
|
using a volume name could be
|
||||||
|
@code
|
||||||
|
\\?\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\Program Files\setup.exe
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@since 2.9.1
|
||||||
|
*/
|
||||||
|
static bool IsMSWUniqueVolumeNamePath(const wxString& path,
|
||||||
|
wxPathFormat format = wxPATH_NATIVE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns @true if this filename is not absolute.
|
Returns @true if this filename is not absolute.
|
||||||
*/
|
*/
|
||||||
|
@ -22,7 +22,16 @@
|
|||||||
drive:\dir1\dir2\...\dirN\filename.ext where drive is a single
|
drive:\dir1\dir2\...\dirN\filename.ext where drive is a single
|
||||||
letter. "." and ".." as for Unix but no "~".
|
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
|
wxPATH_MAC: Mac OS 8/9 and Mac OS X under CodeWarrior 7 format, absolute file
|
||||||
names have the form
|
names have the form
|
||||||
@ -296,7 +305,18 @@ static wxString wxGetVolumeString(const wxString& volume, wxPathFormat format)
|
|||||||
// although I didn't find any authoritative docs on this)
|
// although I didn't find any authoritative docs on this)
|
||||||
if ( format == wxPATH_DOS && volume.length() > 1 )
|
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 )
|
else if ( format == wxPATH_DOS || format == wxPATH_VMS )
|
||||||
{
|
{
|
||||||
@ -326,6 +346,13 @@ static bool IsUNCPath(const wxString& path, wxPathFormat format)
|
|||||||
!IsDOSPathSep(path[2u]);
|
!IsDOSPathSep(path[2u]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// private constants
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// length of \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\ string
|
||||||
|
static const size_t wxMSWUniqueVolumePrefixLength = 49;
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -620,12 +647,17 @@ bool wxFileName::DirExists( const wxString &dirPath )
|
|||||||
#if defined(__WINDOWS__) || defined(__OS2__)
|
#if defined(__WINDOWS__) || defined(__OS2__)
|
||||||
// Windows fails to find directory named "c:\dir\" even if "c:\dir" exists,
|
// 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
|
// 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) )
|
while ( wxEndsWithPathSeparator(strPath) )
|
||||||
{
|
{
|
||||||
size_t len = strPath.length();
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
strPath.Truncate(len - 1);
|
strPath.Truncate(len - 1);
|
||||||
}
|
}
|
||||||
@ -1810,6 +1842,18 @@ bool wxFileName::IsPathSeparator(wxChar ch, wxPathFormat format)
|
|||||||
return ch != wxT('\0') && GetPathSeparators(format).Find(ch) != wxNOT_FOUND;
|
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
|
// path components manipulation
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -2194,9 +2238,26 @@ wxFileName::SplitVolume(const wxString& fullpathWithVolume,
|
|||||||
|
|
||||||
wxString fullpath = fullpathWithVolume;
|
wxString fullpath = fullpathWithVolume;
|
||||||
|
|
||||||
// special Windows UNC paths hack: transform \\share\path into share:path
|
if ( IsMSWUniqueVolumeNamePath(fullpath, format) )
|
||||||
if ( IsUNCPath(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);
|
fullpath.erase(0, 2);
|
||||||
|
|
||||||
size_t posFirstSlash =
|
size_t posFirstSlash =
|
||||||
|
@ -69,6 +69,10 @@ static struct TestFileNameInfo
|
|||||||
{ "c:foo.bar", "c", "", "foo", "bar", false, wxPATH_DOS },
|
{ "c:foo.bar", "c", "", "foo", "bar", false, wxPATH_DOS },
|
||||||
{ "c:\\foo.bar", "c", "\\", "foo", "bar", true, wxPATH_DOS },
|
{ "c:\\foo.bar", "c", "\\", "foo", "bar", true, wxPATH_DOS },
|
||||||
{ "c:\\Windows\\command.com", "c", "\\Windows", "command", "com", true, wxPATH_DOS },
|
{ "c:\\Windows\\command.com", "c", "\\Windows", "command", "com", true, wxPATH_DOS },
|
||||||
|
{ "\\\\?\\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\\",
|
||||||
|
"Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}", "\\", "", "", true, wxPATH_DOS },
|
||||||
|
{ "\\\\?\\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\\Program Files\\setup.exe",
|
||||||
|
"Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}", "\\Program Files", "setup", "exe", true, wxPATH_DOS },
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// NB: when using the wxFileName::GetLongPath() function on these two
|
// NB: when using the wxFileName::GetLongPath() function on these two
|
||||||
@ -125,6 +129,7 @@ private:
|
|||||||
CPPUNIT_TEST( TestShortLongPath );
|
CPPUNIT_TEST( TestShortLongPath );
|
||||||
#endif // __WINDOWS__
|
#endif // __WINDOWS__
|
||||||
CPPUNIT_TEST( TestUNC );
|
CPPUNIT_TEST( TestUNC );
|
||||||
|
CPPUNIT_TEST( TestVolumeUniqueName );
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
void TestConstruction();
|
void TestConstruction();
|
||||||
@ -138,6 +143,7 @@ private:
|
|||||||
void TestShortLongPath();
|
void TestShortLongPath();
|
||||||
#endif // __WINDOWS__
|
#endif // __WINDOWS__
|
||||||
void TestUNC();
|
void TestUNC();
|
||||||
|
void TestVolumeUniqueName();
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(FileNameTestCase)
|
DECLARE_NO_COPY_CLASS(FileNameTestCase)
|
||||||
};
|
};
|
||||||
@ -507,3 +513,23 @@ void FileNameTestCase::TestUNC()
|
|||||||
CPPUNIT_ASSERT_EQUAL( "\\path2", fn.GetPath(wxPATH_NO_SEPARATOR, wxPATH_DOS) );
|
CPPUNIT_ASSERT_EQUAL( "\\path2", fn.GetPath(wxPATH_NO_SEPARATOR, wxPATH_DOS) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileNameTestCase::TestVolumeUniqueName()
|
||||||
|
{
|
||||||
|
wxFileName fn("\\\\?\\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\\",
|
||||||
|
wxPATH_DOS);
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}",
|
||||||
|
fn.GetVolume() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "\\", fn.GetPath(wxPATH_NO_SEPARATOR, wxPATH_DOS) );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "\\\\?\\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\\",
|
||||||
|
fn.GetFullPath(wxPATH_DOS) );
|
||||||
|
|
||||||
|
fn.Assign("\\\\?\\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\\"
|
||||||
|
"Program Files\\setup.exe", wxPATH_DOS);
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}",
|
||||||
|
fn.GetVolume() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "\\Program Files",
|
||||||
|
fn.GetPath(wxPATH_NO_SEPARATOR, wxPATH_DOS) );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "\\\\?\\Volume{8089d7d7-d0ac-11db-9dd0-806d6172696f}\\"
|
||||||
|
"Program Files\\setup.exe",
|
||||||
|
fn.GetFullPath(wxPATH_DOS) );
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user