diff --git a/dlls/shell32/shfldr.h b/dlls/shell32/shfldr.h index bc35caf02e6..0cbdf91fd5e 100644 --- a/dlls/shell32/shfldr.h +++ b/dlls/shell32/shfldr.h @@ -70,3 +70,4 @@ static inline int SHELL32_GUIDToStringW (REFGUID guid, LPWSTR str) } void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags); +BOOL SHELL_FS_HideExtension(LPWSTR pwszPath); diff --git a/dlls/shell32/shfldr_fs.c b/dlls/shell32/shfldr_fs.c index 8329c87a24f..f7bce84e9c7 100644 --- a/dlls/shell32/shfldr_fs.c +++ b/dlls/shell32/shfldr_fs.c @@ -700,7 +700,20 @@ static const WCHAR HideFileExtW[] = { 'H','i','d','e','F','i','l','e','E','x', static const WCHAR NeverShowExtW[] = { 'N','e','v','e','r','S','h','o','w','E', 'x','t',0 }; -static BOOL hide_extension(LPWSTR szPath) +/****************************************************************************** + * SHELL_FS_HideExtension [Internal] + * + * Query the registry if the filename extension of a given path should be + * hidden. + * + * PARAMS + * szPath [I] Relative or absolute path of a file + * + * RETURNS + * TRUE, if the filename's extension should be hidden + * FALSE, otherwise. + */ +BOOL SHELL_FS_HideExtension(LPWSTR szPath) { HKEY hKey; DWORD dwData; @@ -739,7 +752,7 @@ void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags) if (!(dwFlags & SHGDN_FORPARSING) && ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) { MultiByteToWideChar(CP_ACP, 0, szPath, -1, pathW, MAX_PATH); - if (hide_extension(pathW) && szPath[0] != '.') + if (SHELL_FS_HideExtension(pathW) && szPath[0] != '.') PathRemoveExtensionA (szPath); } } @@ -844,7 +857,7 @@ static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface, } else lstrcpynW(szDest, lpName, MAX_PATH); - if(!(dwFlags & SHGDN_FORPARSING) && hide_extension(szSrc)) { + if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) { WCHAR *ext = PathFindExtensionW(szSrc); if(*ext != '\0') { INT len = strlenW(szDest); diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c index 2181024412b..f29a6059345 100644 --- a/dlls/shell32/shfldr_unixfs.c +++ b/dlls/shell32/shfldr_unixfs.c @@ -833,11 +833,12 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* iface, H { UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface); - char szSrc[FILENAME_MAX], szDest[FILENAME_MAX]; + char szSrc[FILENAME_MAX], szDest[FILENAME_MAX], szDosDest[MAX_PATH]; + WCHAR wszDosDest[MAX_PATH]; int cBasePathLen = lstrlenA(This->m_pszPath); struct stat statDest; - LPITEMIDLIST pidlNew; - + LPITEMIDLIST pidlSrc, pidlDest; + TRACE("(iface=%p, hwnd=%p, pidl=%p, lpszName=%s, uFlags=0x%08lx, ppidlOut=%p)\n", iface, hwnd, pidl, debugstr_w(lpszName), uFlags, ppidlOut); @@ -856,9 +857,19 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* iface, H if (uFlags & SHGDN_FORPARSING) { /* absolute path in lpszName */ WideCharToMultiByte(CP_ACP, 0, lpszName, -1, szDest, FILENAME_MAX, NULL, NULL); } else { + WCHAR wszSrcRelative[MAX_PATH]; memcpy(szDest, This->m_pszPath, cBasePathLen); WideCharToMultiByte(CP_ACP, 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)) + { + char *pszExt = PathFindExtensionA(_ILGetTextPointer(pidl)); + lstrcatA(szDest, pszExt); + } } TRACE("src=%s dest=%s\n", szSrc, szDest); @@ -866,24 +877,33 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* iface, H /* Fail, if destination does already exist */ if (!stat(szDest, &statDest)) return E_FAIL; - - /* Rename the file and inform the shell */ - if (!rename(szSrc, szDest) && UNIXFS_path_to_pidl(This, lpszName, &pidlNew)) { - LPITEMIDLIST pidlSrc = ILCombine(This->m_pidlLocation, pidl); - LPITEMIDLIST pidlDest = ILCombine(This->m_pidlLocation, pidlNew); - if (_ILIsFolder(pidlNew)) - SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_IDLIST, pidlSrc, pidlDest); - else - SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_IDLIST, pidlSrc, pidlDest); - ILFree(pidlSrc); - ILFree(pidlDest); - if (ppidlOut) - *ppidlOut = pidlNew; - else - ILFree(pidlNew); - return S_OK; + + /* Rename the file */ + if (rename(szSrc, szDest)) + return E_FAIL; + + /* Build a pidl for the path of the renamed file */ + if (!GetFullPathNameA(szDest, MAX_PATH, szDosDest, NULL) || + !MultiByteToWideChar(CP_ACP, 0, szDosDest, -1, wszDosDest, MAX_PATH) || + !UNIXFS_path_to_pidl(This, wszDosDest, &pidlDest)) + { + rename(szDest, szSrc); /* Undo the renaming */ + return E_FAIL; } - return E_FAIL; + + /* 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(wszDosDest, ppidlOut); + + return S_OK; } static HRESULT WINAPI UnixFolder_IShellFolder2_EnumSearches(IShellFolder2* iface,