Hi Michael,
Never mind. In your last mail you said that you already implemented "rename" and "new folder" functionality. Are those restricted to shfldr_unixfs? Do you think those could be sent as a separate patch already? That would be sweet.
Here it is, I have cleaned it up so it is only restricted to shfldr_unixfs. I think this should work on your build, it might need other bits on my build. See if it works on your build.
One note, rename currently doesn't check for existing file/folder with same name. Haven't got a chance to fix that yet. Feel free to make any changes. I won't be working on this for a while.
Michael
Index: dlls/shell32/shfldr_unixfs.c =================================================================== RCS file: /home/wine/wine/dlls/shell32/shfldr_unixfs.c,v retrieving revision 1.16 diff -u -r1.16 shfldr_unixfs.c --- dlls/shell32/shfldr_unixfs.c 24 May 2005 11:45:47 -0000 1.16 +++ dlls/shell32/shfldr_unixfs.c 1 Jun 2005 02:08:31 -0000 @@ -47,6 +47,7 @@
#include "shell32_main.h" #include "shfldr.h" +#include "shellfolder.h" #include "shresdef.h" #include "pidl.h"
@@ -88,6 +89,7 @@ typedef struct _UnixFolder { const IShellFolder2Vtbl *lpIShellFolder2Vtbl; const IPersistFolder2Vtbl *lpIPersistFolder2Vtbl; + const ISFHelperVtbl *lpISFHelperVtbl; ULONG m_cRef; CHAR *m_pszPath; LPITEMIDLIST m_pidlLocation; @@ -96,6 +98,10 @@ DWORD m_dwPathMode; } UnixFolder;
+static const IShellFolder2Vtbl UnixFolder_IShellFolder2_Vtbl; +static const IPersistFolder2Vtbl UnixFolder_IPersistFolder2_Vtbl; +static const ISFHelperVtbl shvt; + /****************************************************************************** * UNIXFS_is_pidl_of_type [INTERNAL] * @@ -692,6 +698,9 @@ IsEqualIID(&IID_IPersist, riid)) { *ppv = &This->lpIPersistFolder2Vtbl; + } else if (IsEqualIID(&IID_ISFHelper, riid)) + { + *ppv = &This->lpISFHelperVtbl; } else { *ppv = NULL; return E_NOINTERFACE; @@ -738,14 +747,7 @@ if (result && pdwAttributes && *pdwAttributes) { /* need to traverse to the last element for the attribute */ - LPCITEMIDLIST pidl, last_pidl; - pidl = last_pidl = *ppidl; - while(pidl && pidl->mkid.cb) - { - last_pidl = pidl; - pidl = ILGetNext(pidl); - } - SHELL32_GetItemAttributes((IShellFolder*)iface, last_pidl, pdwAttributes); + SHELL32_GetItemAttributes((IShellFolder*)iface, ILFindLastID(*ppidl), pdwAttributes); }
if (!result) TRACE("FAILED!\n"); @@ -830,11 +832,9 @@ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)-1); if (!_ILIsFolder(pidl1) && _ILIsFolder(pidl2)) return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)1); - compare = CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE, _ILGetTextPointer(pidl1), NAME_LEN_FROM_LPSHITEMID(pidl1), _ILGetTextPointer(pidl2), NAME_LEN_FROM_LPSHITEMID(pidl2)); - if ((compare == CSTR_LESS_THAN) || (compare == CSTR_GREATER_THAN)) return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)((compare == CSTR_LESS_THAN)?-1:1));
@@ -891,8 +891,8 @@ for (i=0; i<cidl; i++) { LPPIDLDATA pData = _ILGetDataPointer(apidl[i]); if (!pData) continue; - if (pData->type == PT_FOLDER) flags &= (SFGAO_FILESYSTEM|SFGAO_FILESYSANCESTOR|SFGAO_FOLDER|SFGAO_HASSUBFOLDER); - if (pData->type == PT_VALUE) flags &= SFGAO_FILESYSTEM; + if (pData->type == PT_FOLDER) flags &= (SFGAO_FILESYSTEM|SFGAO_FILESYSANCESTOR|SFGAO_FOLDER|SFGAO_HASSUBFOLDER|SFGAO_CANRENAME); + if (pData->type == PT_VALUE) flags &= SFGAO_FILESYSTEM|SFGAO_CANRENAME; }
*rgfInOut = *rgfInOut & flags; @@ -979,11 +979,50 @@ return hr; }
-static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* This, HWND hwnd, +static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* iface, HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR lpszName, SHGDNF uFlags, LPITEMIDLIST* ppidlOut) { - TRACE("stub\n"); - return E_NOTIMPL; + UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface); + char szSrc[MAX_PATH], szDest[MAX_PATH], temp[MAX_PATH]; + char* ptr; + BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl)); + TRACE ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", iface, hwnd, pidl, + debugstr_w (lpszName), uFlags, ppidlOut); + + /* build source path */ + strcpy(szSrc, This->m_pszPath); + ptr = szSrc + lstrlenA(szSrc); + if (ptr) + _ILSimpleGetText(pidl, ptr, MAX_PATH - (ptr - szSrc)); + + WideCharToMultiByte(CP_ACP, 0, lpszName, -1, temp, MAX_PATH, NULL, NULL); + /* build destination path */ + if (uFlags == SHGDN_NORMAL || uFlags & SHGDN_INFOLDER) { + strcpy(szDest, This->m_pszPath); + ptr = szDest + lstrlenA(szDest); + if (ptr) + lstrcpynA(ptr, temp, MAX_PATH - (ptr - szDest)); + } else + lstrcpynA(szDest, temp, MAX_PATH); + + TRACE("src=%s dest=%s\n", szSrc, szDest); + + if (!rename(szSrc, szDest)) { + LPITEMIDLIST src_pidl = 0, dest_pidl = 0, new_name_pidl = 0; + HRESULT hr = S_OK; + hr = UNIXFS_path_to_pidl(This, lpszName, &new_name_pidl); + + src_pidl = ILCombine(This->m_pidlLocation, pidl); + dest_pidl = ILCombine(This->m_pidlLocation, new_name_pidl); + if (ppidlOut) + { + *ppidlOut = ILClone(ILFindLastID(dest_pidl)); + } + SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, + SHCNF_IDLIST, src_pidl, ILClone(dest_pidl)); + return hr; + } + return E_FAIL; }
static HRESULT WINAPI UnixFolder_IShellFolder2_EnumSearches(IShellFolder2* iface, @@ -1209,6 +1248,7 @@ if(pUnixFolder) { pUnixFolder->lpIShellFolder2Vtbl = &UnixFolder_IShellFolder2_Vtbl; pUnixFolder->lpIPersistFolder2Vtbl = &UnixFolder_IPersistFolder2_Vtbl; + pUnixFolder->lpISFHelperVtbl = &shvt; pUnixFolder->m_cRef = 0; pUnixFolder->m_pszPath = NULL; pUnixFolder->m_apidlSubDirs = NULL; @@ -1391,3 +1431,127 @@
return (IUnknown*)iterator; } + +static HRESULT WINAPI ISFHelper_fnQueryInterface (ISFHelper* iface, REFIID riid, void** ppvObject) +{ + return UnixFolder_IShellFolder2_QueryInterface( + (IShellFolder2*)ADJUST_THIS(UnixFolder, ISFHelper, iface), riid, ppvObject); +} + +static ULONG WINAPI ISFHelper_fnAddRef (ISFHelper * iface) +{ + return UnixFolder_IShellFolder2_AddRef( + (IShellFolder2*)ADJUST_THIS(UnixFolder, ISFHelper, iface)); +} + +static ULONG WINAPI ISFHelper_fnRelease (ISFHelper * iface) +{ + return UnixFolder_IShellFolder2_Release( + (IShellFolder2*)ADJUST_THIS(UnixFolder, ISFHelper, iface)); +} + +static HRESULT WINAPI ISFHelper_fnGetUniqueName (ISFHelper * iface, LPSTR lpName, UINT uLen) +{ + IShellFolder2 *isf = (IShellFolder2*)ADJUST_THIS(UnixFolder, ISFHelper, iface); + IEnumIDList *penum; + HRESULT hr; + char szText[MAX_PATH]; + char *szNewFolder = "NewFolder"; + + if (uLen < strlen (szNewFolder) + 4) + return E_POINTER; + + strcpy (lpName, szNewFolder); + + hr = UnixFolder_IShellFolder2_EnumObjects (isf, 0, + SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum); + if (penum) { + LPITEMIDLIST pidl; + DWORD dwFetched; + int i = 1; + +next: + IEnumIDList_Reset (penum); + while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) && + dwFetched) { + _ILSimpleGetText (pidl, szText, MAX_PATH); + if (0 == strcasecmp (szText, lpName)) { + sprintf (lpName, "%s %d", szNewFolder, i++); + if (i > 99) { + hr = E_FAIL; + break; + } + goto next; + } + } + + IEnumIDList_Release (penum); + } + return hr; +} + +static HRESULT WINAPI ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCSTR lpName, + LPITEMIDLIST * ppidlOut) +{ + UnixFolder *This = ADJUST_THIS(UnixFolder, ISFHelper, iface); + char lpstrNewDir[MAX_PATH]; + DWORD bRes; + HRESULT hres = E_FAIL; + + TRACE ("(%p)(%s %p)\n", This, lpName, ppidlOut); + strcpy (lpstrNewDir, This->m_pszPath); + strcat(lpstrNewDir, lpName); + bRes = mkdir (lpstrNewDir, 755); + if (!bRes) { + LPITEMIDLIST pidl = 0, full_pidl = 0; + WCHAR nameW[MAX_PATH]; + if (!MultiByteToWideChar(CP_ACP, 0, lpName, -1, nameW, MAX_PATH)) + nameW[MAX_PATH-1] = 0; + hres = UNIXFS_path_to_pidl(This, nameW, &pidl); + + if (ppidlOut) + { + *ppidlOut = pidl; + } + full_pidl = ILCombine(This->m_pidlLocation, pidl); + SHChangeNotify (SHCNE_MKDIR, SHCNF_IDLIST, full_pidl, NULL); + SHFree(full_pidl); + } else { + char lpstrText[128 + MAX_PATH]; + char lpstrTempText[128]; + char lpstrCaption[256]; + + /* Cannot Create folder because of permissions */ + LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, + sizeof (lpstrTempText)); + LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, + sizeof (lpstrCaption)); + sprintf (lpstrText, lpstrTempText, lpstrNewDir); + MessageBoxA (hwnd, lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION); + } + return hres; +} + +static HRESULT WINAPI ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl) +{ + TRACE("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl, + LPCITEMIDLIST * apidl) +{ + TRACE("stub\n"); + return E_NOTIMPL; +} + +static const ISFHelperVtbl shvt = +{ + ISFHelper_fnQueryInterface, + ISFHelper_fnAddRef, + ISFHelper_fnRelease, + ISFHelper_fnGetUniqueName, + ISFHelper_fnAddFolder, + ISFHelper_fnDeleteItems, + ISFHelper_fnCopyItems +};