From 04519a46d7b6674bb3a68d1d1d3e069f1feafe5e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 29 Aug 2014 23:22:45 +0000 Subject: [PATCH] Don't change a shortcut file name when changing its path. wxFileName::MakeRelativeTo() is only supposed to change the path of the file, not its name, but it was doing the latter for the shortcuts as it implicitly resolved them to the name of their target. Fix this by ensuring we do not use wxPATH_NORM_SHORTCUT in MakeRelativeTo(). Closes #16239. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_3_0_BRANCH@77515 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + src/common/filename.cpp | 9 +++-- tests/filename/filenametest.cpp | 59 +++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index eb5982c033..ab1c99876b 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -612,6 +612,7 @@ wxMSW: - Fix order of radial gradient stops (Alexandru Pana). - Fix font created using wxFont(wxFontInfo()) ctor. - Fix wxFileName::GetShortcutTarget() in console applications. +- Fix wxFileName::MakeRelativeTo() for shortcut files (gafatoa). 3.0.1: (released 2014-06-15) diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 51e80c1c83..fcbc0e7206 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -1797,8 +1797,13 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format) // get cwd only once - small time saving wxString cwd = wxGetCwd(); - Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, cwd, format); - fnBase.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, cwd, format); + + // Normalize the paths but avoid changing the case or turning a shortcut + // into a file that it points to. + const int normFlags = wxPATH_NORM_ALL & + ~(wxPATH_NORM_CASE | wxPATH_NORM_SHORTCUT); + Normalize(normFlags, cwd, format); + fnBase.Normalize(normFlags, cwd, format); bool withCase = IsCaseSensitive(format); diff --git a/tests/filename/filenametest.cpp b/tests/filename/filenametest.cpp index f54e8e8376..29bcfaf685 100644 --- a/tests/filename/filenametest.cpp +++ b/tests/filename/filenametest.cpp @@ -27,6 +27,9 @@ #ifdef __WINDOWS__ #include "wx/msw/registry.h" + #include + #include "wx/msw/ole/oleutils.h" + #include "wx/msw/private/comptr.h" #endif // __WINDOWS__ #ifdef __UNIX__ @@ -145,6 +148,9 @@ private: #if defined(__UNIX__) CPPUNIT_TEST( TestSymlinks ); #endif // __UNIX__ +#ifdef __WINDOWS__ + CPPUNIT_TEST( TestShortcuts ); +#endif // __WINDOWS__ CPPUNIT_TEST_SUITE_END(); void TestConstruction(); @@ -168,6 +174,9 @@ private: #if defined(__UNIX__) void TestSymlinks(); #endif // __UNIX__ +#ifdef __WINDOWS__ + void TestShortcuts(); +#endif // __WINDOWS__ DECLARE_NO_COPY_CLASS(FileNameTestCase) }; @@ -996,3 +1005,53 @@ void FileNameTestCase::TestSymlinks() } #endif // __UNIX__ + +#ifdef __WINDOWS__ + +namespace +{ + +void CreateShortcut(const wxString& pathFile, const wxString& pathLink) +{ + wxOleInitializer oleInit; + + HRESULT hr; + + wxCOMPtr sl; + hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, (void **)&sl); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); + + wxCOMPtr pf; + hr = sl->QueryInterface(IID_IPersistFile, (void **)&pf); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); + + hr = sl->SetPath(pathFile.wx_str()); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); + + hr = pf->Save(pathLink.wx_str(), TRUE); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); +} + +} // anonymous namespace + +void FileNameTestCase::TestShortcuts() +{ + wxFileName fn(wxFileName::CreateTempFileName("filenametest")); + CPPUNIT_ASSERT( fn.IsOk() ); + wxON_BLOCK_EXIT1( wxRemoveFile, fn.GetFullPath() ); + + wxFileName fnLink(fn.GetPath(), "sc_" + fn.GetName(), "lnk"); + CPPUNIT_ASSERT( fnLink.IsOk() ); + wxON_BLOCK_EXIT1( wxRemoveFile, fnLink.GetFullPath() ); + + CreateShortcut(fn.GetFullPath(), fnLink.GetFullPath()); + + // MakeRelativeTo() is supposed to change only the path of the file, not its + // name. + wxFileName fnLinkRel(fnLink); + fnLink.MakeRelativeTo("."); + CPPUNIT_ASSERT_EQUAL(fnLink.GetFullName(), fnLinkRel.GetFullName()); +} + +#endif // __WINDOWS__