From 614a0ef4815fa61f46b975da57ee7ef5546e1c86 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 29 Aug 2014 23:22:05 +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/trunk@77509 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/common/filename.cpp | 9 +++-- tests/filename/filenametest.cpp | 59 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/common/filename.cpp b/src/common/filename.cpp index d77cd25235..9a50f81634 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -1752,8 +1752,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 20d110df5e..b44a288dbe 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) }; @@ -985,3 +994,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__