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