Michael Jung : unixfs: Fix SetNameOf.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jan 16 14:37:44 CST 2006


Module: wine
Branch: refs/heads/master
Commit: f87efbd14eedb076f7f4cb2887ee7c2bcf279afd
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=f87efbd14eedb076f7f4cb2887ee7c2bcf279afd

Author: Michael Jung <mjung at iss.tu-darmstadt.de>
Date:   Mon Jan 16 20:37:51 2006 +0100

unixfs: Fix SetNameOf.
Ensure that pidls passed to SHNotify are absolute SetNameOf should
fail on absolute path names.
Some tests to show this.

---

 dlls/shell32/shfldr_unixfs.c   |   92 ++++++++++++++++++++--------------------
 dlls/shell32/tests/shlfolder.c |   29 +++++++++++++
 2 files changed, 74 insertions(+), 47 deletions(-)

diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c
index 7ffdb9a..c898e67 100644
--- a/dlls/shell32/shfldr_unixfs.c
+++ b/dlls/shell32/shfldr_unixfs.c
@@ -1216,50 +1216,54 @@ static HRESULT WINAPI UnixFolder_IShellF
 }
 
 static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* iface, HWND hwnd, 
-    LPCITEMIDLIST pidl, LPCOLESTR lpszName, SHGDNF uFlags, LPITEMIDLIST* ppidlOut)
+    LPCITEMIDLIST pidl, LPCOLESTR lpcwszName, SHGDNF uFlags, LPITEMIDLIST* ppidlOut)
 {
     UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
 
+    static const WCHAR awcInvalidChars[] = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
     char szSrc[FILENAME_MAX], szDest[FILENAME_MAX];
-    WCHAR *pwszDosDest;
-    int cBasePathLen = lstrlenA(This->m_pszPath);
+    WCHAR wszSrcRelative[MAX_PATH];
+    int cBasePathLen = lstrlenA(This->m_pszPath), i;
     struct stat statDest;
-    LPITEMIDLIST pidlSrc, pidlDest;
+    LPITEMIDLIST pidlSrc, pidlDest, pidlRelativeDest;
+    LPOLESTR lpwszName;
+    HRESULT hr;
    
-    TRACE("(iface=%p, hwnd=%p, pidl=%p, lpszName=%s, uFlags=0x%08lx, ppidlOut=%p)\n",
-          iface, hwnd, pidl, debugstr_w(lpszName), uFlags, ppidlOut); 
+    TRACE("(iface=%p, hwnd=%p, pidl=%p, lpcwszName=%s, uFlags=0x%08lx, ppidlOut=%p)\n",
+          iface, hwnd, pidl, debugstr_w(lpcwszName), uFlags, ppidlOut); 
 
-    /* pidl has to contain a single non-empty SHITEMID */
-    if (_ILIsDesktop(pidl) || !_ILIsPidlSimple(pidl) || !_ILGetTextPointer(pidl))
-        return E_INVALIDARG;
-   
+    /* prepare to fail */
     if (ppidlOut)
         *ppidlOut = NULL;
     
+    /* pidl has to contain a single non-empty SHITEMID */
+    if (_ILIsDesktop(pidl) || !_ILIsPidlSimple(pidl) || !_ILGetTextPointer(pidl))
+        return E_INVALIDARG;
+ 
+    /* check for invalid characters in lpcwszName. */
+    for (i=0; i < sizeof(awcInvalidChars)/sizeof(*awcInvalidChars); i++)
+        if (StrChrW(lpcwszName, awcInvalidChars[i]))
+            return HRESULT_FROM_WIN32(ERROR_CANCELLED);
+
     /* build source path */
     memcpy(szSrc, This->m_pszPath, cBasePathLen);
     UNIXFS_filename_from_shitemid(pidl, szSrc + cBasePathLen);
 
     /* build destination path */
-    if (uFlags & SHGDN_FORPARSING) { /* absolute path in lpszName */
-        WideCharToMultiByte(CP_UNIXCP, 0, lpszName, -1, szDest, FILENAME_MAX, NULL, NULL);
-    } else {
-        WCHAR wszSrcRelative[MAX_PATH];
-        memcpy(szDest, This->m_pszPath, cBasePathLen);
-        WideCharToMultiByte(CP_UNIXCP, 0, lpszName, -1, szDest+cBasePathLen, 
-                            FILENAME_MAX-cBasePathLen, NULL, NULL);
-
-        /* uFlags is SHGDN_FOREDITING of SHGDN_FORADDRESSBAR. If the filename's 
-         * extension is hidden to the user, we have to append it. */
-        if (_ILSimpleGetTextW(pidl, wszSrcRelative, MAX_PATH) && 
-            SHELL_FS_HideExtension(wszSrcRelative))
-        {
-            WCHAR *pwszExt = PathFindExtensionW(wszSrcRelative);
-            int cLenDest = strlen(szDest);
-            WideCharToMultiByte(CP_UNIXCP, 0, pwszExt, -1, szDest + cLenDest, 
-                FILENAME_MAX - cLenDest, NULL, NULL);
-        }
-    } 
+    memcpy(szDest, This->m_pszPath, cBasePathLen);
+    WideCharToMultiByte(CP_UNIXCP, 0, lpcwszName, -1, szDest+cBasePathLen, 
+                        FILENAME_MAX-cBasePathLen, NULL, NULL);
+
+    /* If the filename's extension is hidden to the user, we have to append it. */
+    if (!(uFlags & SHGDN_FORPARSING) && 
+        _ILSimpleGetTextW(pidl, wszSrcRelative, MAX_PATH) && 
+        SHELL_FS_HideExtension(wszSrcRelative))
+    {
+        WCHAR *pwszExt = PathFindExtensionW(wszSrcRelative);
+        int cLenDest = strlen(szDest);
+        WideCharToMultiByte(CP_UNIXCP, 0, pwszExt, -1, szDest + cLenDest, 
+            FILENAME_MAX - cLenDest, NULL, NULL);
+    }
 
     TRACE("src=%s dest=%s\n", szSrc, szDest);
 
@@ -1272,36 +1276,30 @@ static HRESULT WINAPI UnixFolder_IShellF
         return E_FAIL;
     
     /* Build a pidl for the path of the renamed file */
-    if (This->m_dwPathMode == PATHMODE_DOS)
-    {
-        pwszDosDest = wine_get_dos_file_name(szDest);
-    }
-    else
-    {
-        int len = MultiByteToWideChar(CP_UNIXCP, 0, szDest, -1, NULL, 0);
-
-        pwszDosDest = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        MultiByteToWideChar(CP_UNIXCP, 0, szDest, -1, pwszDosDest, len);
-    }
-    if (!pwszDosDest || !UNIXFS_path_to_pidl(This, pwszDosDest, &pidlDest)) {
-        HeapFree(GetProcessHeap(), 0, pwszDosDest);
+    lpwszName = SHAlloc((lstrlenW(lpcwszName)+1)*sizeof(WCHAR)); /* due to const correctness. */
+    lstrcpyW(lpwszName, lpcwszName);
+    hr = IShellFolder2_ParseDisplayName(iface, NULL, NULL, lpwszName, NULL, &pidlRelativeDest, NULL);
+    SHFree(lpwszName);
+    if (FAILED(hr)) {
         rename(szDest, szSrc); /* Undo the renaming */
         return E_FAIL;
     }
+    pidlDest = ILCombine(This->m_pidlLocation, pidlRelativeDest);
+    ILFree(pidlRelativeDest);
+    pidlSrc = ILCombine(This->m_pidlLocation, pidl);
     
     /* Inform the shell */
-    pidlSrc = ILCombine(This->m_pidlLocation, pidl);
     if (_ILIsFolder(ILFindLastID(pidlDest))) 
         SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_IDLIST, pidlSrc, pidlDest);
     else 
         SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_IDLIST, pidlSrc, pidlDest);
-    ILFree(pidlSrc);
-    ILFree(pidlDest);
     
     if (ppidlOut) 
-        _ILCreateFromPathW(pwszDosDest, ppidlOut);
+        *ppidlOut = ILClone(ILFindLastID(pidlDest));
+        
+    ILFree(pidlSrc);
+    ILFree(pidlDest);
     
-    HeapFree(GetProcessHeap(), 0, pwszDosDest);
     return S_OK;
 }
 
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 7abeae1..6ab6044 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -383,6 +383,35 @@ static void test_GetDisplayName(void)
     if (SUCCEEDED(hr)) {
         IShellFolder_Release(psfFile);
     }
+  
+    /* Some tests for IShellFolder::SetNameOf */
+    hr = pSHBindToParent(pidlTestFile, &IID_IShellFolder, (VOID**)&psfPersonal, &pidlLast);
+    ok(SUCCEEDED(hr), "SHBindToParent failed! hr = %08lx\n", hr);
+    if (SUCCEEDED(hr)) {
+        /* It's ok to use this fixed path. Call will fail anyway. */
+        WCHAR wszAbsoluteFilename[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
+        LPITEMIDLIST pidlNew;
+
+        /* The pidl returned through the last parameter of SetNameOf is a simple one. */
+        hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlLast, wszDirName, SHGDN_NORMAL, &pidlNew);
+        ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08lx\n", hr);
+        ok (((LPITEMIDLIST)((LPBYTE)pidlNew+pidlNew->mkid.cb))->mkid.cb == 0, 
+            "pidl returned from SetNameOf should be simple!\n");
+
+        /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
+         * is implemented on top of SHFileOperation in WinXP. */
+        hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename, 
+                SHGDN_FORPARSING, NULL);
+        ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08lx\n", hr);
+   
+        /* Rename the file back to it's original name. SetNameOf ignores the fact, that the 
+         * SHGDN flags specify an absolute path. */
+        hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL);
+        ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08lx\n", hr);
+
+        ILFree(pidlNew);
+        IShellFolder_Release(psfPersonal);
+    }
     
     /* Deleting the file and the directory */
     DeleteFileA(szTestFile);




More information about the wine-cvs mailing list