Module: wine Branch: refs/heads/master Commit: f87efbd14eedb076f7f4cb2887ee7c2bcf279afd URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=f87efbd14eedb076f7f4cb28...
Author: Michael Jung mjung@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);