- Fix a bug which broke build
[reactos.git] / reactos / dll / win32 / shell32 / shfldr_fs.c
index 6d57372..381293d 100644 (file)
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#define COBJMACROS
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-
-#include "winerror.h"
-#include "windef.h"
-#include "winbase.h"
-#include "winreg.h"
-#include "wingdi.h"
-#include "winuser.h"
-
-#include "ole2.h"
-#include "shlguid.h"
-
-#include "enumidlist.h"
-#include "pidl.h"
-#include "undocshell.h"
-#include "shell32_main.h"
-#include "shresdef.h"
-#include "shlwapi.h"
-#include "shellfolder.h"
-#include "wine/debug.h"
-#include "debughlp.h"
-#include "shfldr.h"
+#include <precomp.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL (shell);
 
@@ -72,13 +41,13 @@ typedef struct {
     CLSID *pclsid;
 
     /* both paths are parsible from the desktop */
-    LPSTR sPathTarget;     /* complete path to target used for enumeration and ChangeNotify */
+    LPWSTR sPathTarget;     /* complete path to target used for enumeration and ChangeNotify */
 
     LPITEMIDLIST pidlRoot; /* absolute pidl */
 
     UINT cfShellIDList;    /* clipboardformat for IDropTarget */
     BOOL fAcceptFmt;       /* flag for pending Drop */
-} IGenericSFImpl;
+} IGenericSFImpl, *LPIGenericSFImpl;
 
 static const IUnknownVtbl unkvt;
 static const IShellFolder2Vtbl sfvt;
@@ -86,24 +55,24 @@ static const IPersistFolder3Vtbl vt_FSFldr_PersistFolder3; /* IPersistFolder3 fo
 static const IDropTargetVtbl dtvt;
 static const ISFHelperVtbl shvt;
 
-static inline IGenericSFImpl *impl_from_IShellFolder2( IShellFolder2 *iface )
+static LPIGenericSFImpl __inline impl_from_IShellFolder2( IShellFolder2 *iface )
 {
-    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblShellFolder));
+    return (LPIGenericSFImpl)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblShellFolder));
 }
 
-static inline IGenericSFImpl *impl_from_IPersistFolder3( IPersistFolder3 *iface )
+static LPIGenericSFImpl __inline impl_from_IPersistFolder3( IPersistFolder3 *iface )
 {
-    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblPersistFolder3));
+    return (LPIGenericSFImpl)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblPersistFolder3));
 }
 
-static inline IGenericSFImpl *impl_from_IDropTarget( IDropTarget *iface )
+static LPIGenericSFImpl __inline impl_from_IDropTarget( IDropTarget *iface )
 {
-    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblDropTarget));
+    return (LPIGenericSFImpl)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblDropTarget));
 }
 
-static inline IGenericSFImpl *impl_from_ISFHelper( ISFHelper *iface )
+static LPIGenericSFImpl __inline impl_from_ISFHelper( ISFHelper *iface )
 {
-    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblSFHelper));
+    return (LPIGenericSFImpl)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblSFHelper));
 }
 
 
@@ -179,7 +148,7 @@ static ULONG WINAPI IUnknown_fnAddRef (IUnknown * iface)
     IGenericSFImpl *This = (IGenericSFImpl *)iface;
     ULONG refCount = InterlockedIncrement(&This->ref);
 
-    TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);
+    TRACE ("(%p)->(count=%u)\n", This, refCount - 1);
 
     return refCount;
 }
@@ -189,15 +158,13 @@ static ULONG WINAPI IUnknown_fnRelease (IUnknown * iface)
     IGenericSFImpl *This = (IGenericSFImpl *)iface;
     ULONG refCount = InterlockedDecrement(&This->ref);
 
-    TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);
+    TRACE ("(%p)->(count=%u)\n", This, refCount + 1);
 
     if (!refCount) {
         TRACE ("-- destroying IShellFolder(%p)\n", This);
 
-        if (This->pidlRoot)
-            SHFree (This->pidlRoot);
-        if (This->sPathTarget)
-            SHFree (This->sPathTarget);
+        SHFree (This->pidlRoot);
+        SHFree (This->sPathTarget);
         LocalFree ((HLOCAL) This);
     }
     return refCount;
@@ -210,7 +177,7 @@ static const IUnknownVtbl unkvt =
       IUnknown_fnRelease,
 };
 
-static shvheader GenericSFHeader[] = {
+static const shvheader GenericSFHeader[] = {
     {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
     {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
     {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
@@ -285,7 +252,7 @@ static ULONG WINAPI IShellFolder_fnAddRef (IShellFolder2 * iface)
 {
     IGenericSFImpl *This = impl_from_IShellFolder2(iface);
 
-    TRACE ("(%p)->(count=%lu)\n", This, This->ref);
+    TRACE ("(%p)->(count=%u)\n", This, This->ref);
 
     return IUnknown_AddRef (This->pUnkOuter);
 }
@@ -297,7 +264,7 @@ static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface)
 {
     IGenericSFImpl *This = impl_from_IShellFolder2(iface);
 
-    TRACE ("(%p)->(count=%lu)\n", This, This->ref);
+    TRACE ("(%p)->(count=%u)\n", This, This->ref);
 
     return IUnknown_Release (This->pUnkOuter);
 }
@@ -305,13 +272,13 @@ static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface)
 /**************************************************************************
  *  SHELL32_CreatePidlFromBindCtx  [internal]
  *
- *  If the caller bound File System Bind Data, assume it is the 
+ *  If the caller bound File System Bind Data, assume it is the
  *   find data for the path.
  *  This allows binding of paths that don't exist.
  */
 LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
 {
-    static const WCHAR szfsbc[] = {
+    static WCHAR szfsbc[] = {
         'F','i','l','e',' ','S','y','s','t','e','m',' ',
         'B','i','n','d',' ','D','a','t','a',0 };
     IFileSystemBindData *fsbd = NULL;
@@ -342,7 +309,7 @@ LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
         }
         IFileSystemBindData_Release( fsbd );
     }
-    
+
     return pidl;
 }
 
@@ -405,10 +372,9 @@ IShellFolder_fnParseDisplayName (IShellFolder2 * iface,
         szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
 
         /* build the full pathname to the element */
-        /* lstrcpyW(szPath, This->sPathTarget); */
-        MultiByteToWideChar(CP_ACP, 0, This->sPathTarget, -1, szPath, MAX_PATH);
+        lstrcpynW(szPath, This->sPathTarget, MAX_PATH - 1);
         PathAddBackslashW(szPath);
-        len = lstrlenW(szPath);
+        len = wcslen(szPath);
         lstrcpynW(szPath + len, szElement, MAX_PATH - len);
 
         /* get the pidl */
@@ -434,7 +400,7 @@ IShellFolder_fnParseDisplayName (IShellFolder2 * iface,
     else
         *ppidl = NULL;
 
-    TRACE ("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl ? *ppidl : 0, hr);
+    TRACE ("(%p)->(-- pidl=%p ret=0x%08x)\n", This, ppidl ? *ppidl : 0, hr);
 
     return hr;
 }
@@ -452,16 +418,12 @@ IShellFolder_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner,
 {
     IGenericSFImpl *This = impl_from_IShellFolder2(iface);
 
-    TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner,
+    TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", This, hwndOwner,
      dwFlags, ppEnumIDList);
 
     *ppEnumIDList = IEnumIDList_Constructor();
     if (*ppEnumIDList)
-    {
-        WCHAR path[MAX_PATH];
-        MultiByteToWideChar(CP_ACP, 0, This->sPathTarget, -1, path, MAX_PATH);
-        CreateFolderEnumList(*ppEnumIDList, path, dwFlags);
-    }
+        CreateFolderEnumList(*ppEnumIDList, This->sPathTarget, dwFlags);
 
     TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
 
@@ -481,13 +443,11 @@ IShellFolder_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl,
                              LPBC pbc, REFIID riid, LPVOID * ppvOut)
 {
     IGenericSFImpl *This = impl_from_IShellFolder2(iface);
-    WCHAR szPath[MAX_PATH];
 
     TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbc,
      shdebugstr_guid (riid), ppvOut);
 
-    MultiByteToWideChar(CP_ACP, 0, This->sPathTarget, -1, szPath, MAX_PATH);
-    return SHELL32_BindToChild (This->pidlRoot, szPath, pidl, riid,
+    return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid,
      ppvOut);
 }
 
@@ -582,7 +542,7 @@ IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl,
 
     HRESULT hr = S_OK;
 
-    TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08lx))\n", This, cidl, apidl,
+    TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This, cidl, apidl,
      rgfInOut, rgfInOut ? *rgfInOut : 0);
 
     if (!rgfInOut)
@@ -614,7 +574,7 @@ IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl,
     /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
     *rgfInOut &= ~SFGAO_VALIDATE;
 
-    TRACE ("-- result=0x%08lx\n", *rgfInOut);
+    TRACE ("-- result=0x%08x\n", *rgfInOut);
 
     return hr;
 }
@@ -661,13 +621,18 @@ IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
         *ppvOut = NULL;
 
         if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
-            pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface,
-             This->pidlRoot, apidl, cidl);
-            hr = S_OK;
-        } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
+            hr = CDefFolderMenu_Create2(This->pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)iface, NULL, 0, NULL, (IContextMenu**)&pObj);
+        } else if (IsEqualIID (riid, &IID_IDataObject)){
+                       if (cidl >= 1) {
             pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner,
              This->pidlRoot, apidl, cidl);
             hr = S_OK;
+                       }
+                       else
+                       {
+                pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, (LPCITEMIDLIST*)&This->pidlRoot, 1);
+                hr = S_OK;
+                       }
         } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
             pidl = ILCombine (This->pidlRoot, apidl[0]);
             pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
@@ -695,7 +660,7 @@ IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
 
         *ppvOut = pObj;
     }
-    TRACE ("(%p)->hr=0x%08lx\n", This, hr);
+    TRACE ("(%p)->hr=0x%08x\n", This, hr);
     return hr;
 }
 
@@ -711,12 +676,12 @@ static const WCHAR NeverShowExtW[] = { 'N','e','v','e','r','S','h','o','w','E',
 /******************************************************************************
  * SHELL_FS_HideExtension [Internal]
  *
- * Query the registry if the filename extension of a given path should be 
+ * 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.
@@ -727,7 +692,7 @@ BOOL SHELL_FS_HideExtension(LPWSTR szPath)
     DWORD dwData;
     DWORD dwDataSize = sizeof (DWORD);
     BOOL doHide = FALSE; /* The default value is FALSE (win98 at least) */
-    
+
     if (!RegCreateKeyExW(HKEY_CURRENT_USER, AdvancedW, 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) {
         if (!RegQueryValueExW(hKey, HideFileExtW, 0, 0, (LPBYTE) &dwData, &dwDataSize))
             doHide = dwData;
@@ -751,17 +716,14 @@ BOOL SHELL_FS_HideExtension(LPWSTR szPath)
     }
     return doHide;
 }
-    
-void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags)
-{
-    WCHAR pathW[MAX_PATH];
 
+void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags)
+{
     /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */
     if (!(dwFlags & SHGDN_FORPARSING) &&
         ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) {
-        MultiByteToWideChar(CP_ACP, 0, szPath, -1, pathW, MAX_PATH);
-        if (SHELL_FS_HideExtension(pathW) && szPath[0] != '.')
-            PathRemoveExtensionA (szPath);
+        if (SHELL_FS_HideExtension(szPath) && szPath[0] != '.')
+            PathRemoveExtensionW(szPath);
     }
 }
 
@@ -783,43 +745,62 @@ IShellFolder_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl,
                                  DWORD dwFlags, LPSTRRET strRet)
 {
     IGenericSFImpl *This = impl_from_IShellFolder2(iface);
+    LPWSTR pszPath;
 
     HRESULT hr = S_OK;
     int len = 0;
 
-    TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
+    TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", This, pidl, dwFlags, strRet);
     pdump (pidl);
 
     if (!pidl || !strRet)
         return E_INVALIDARG;
-    
-    strRet->uType = STRRET_CSTR;
+
+    pszPath = CoTaskMemAlloc((MAX_PATH +1) * sizeof(WCHAR));
+    if (!pszPath)
+        return E_OUTOFMEMORY;
+
     if (_ILIsDesktop(pidl)) { /* empty pidl */
         if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
-            (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER)) 
+            (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
         {
             if (This->sPathTarget)
-                lstrcpynA(strRet->u.cStr, This->sPathTarget, MAX_PATH);
+                lstrcpynW(pszPath, This->sPathTarget, MAX_PATH);
         } else {
             /* pidl has to contain exactly one non null SHITEMID */
             hr = E_INVALIDARG;
         }
     } else if (_ILIsPidlSimple(pidl)) {
         if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
-            (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) && 
-            This->sPathTarget) 
+            (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
+            This->sPathTarget)
         {
-            lstrcpynA(strRet->u.cStr, This->sPathTarget, MAX_PATH);
-            PathAddBackslashA(strRet->u.cStr);
-            len = lstrlenA(strRet->u.cStr);
+            lstrcpynW(pszPath, This->sPathTarget, MAX_PATH);
+            PathAddBackslashW(pszPath);
+            len = wcslen(pszPath);
         }
-        _ILSimpleGetText(pidl, strRet->u.cStr + len, MAX_PATH - len);
-        if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(strRet->u.cStr, dwFlags);
+        _ILSimpleGetTextW(pidl, pszPath + len, MAX_PATH + 1 - len);
+        if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
     } else {
-        hr = SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, strRet->u.cStr, MAX_PATH);
+        hr = SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, pszPath, MAX_PATH);
     }
 
-    TRACE ("-- (%p)->(%s)\n", This, strRet->u.cStr);
+    if (SUCCEEDED(hr)) {
+        /* Win9x always returns ANSI strings, NT always returns Unicode strings */
+        if (GetVersion() & 0x80000000) {
+            strRet->uType = STRRET_CSTR;
+            if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->u.cStr, MAX_PATH,
+                 NULL, NULL))
+                strRet->u.cStr[0] = '\0';
+            CoTaskMemFree(pszPath);
+        } else {
+            strRet->uType = STRRET_WSTR;
+            strRet->u.pOleStr = pszPath;
+        }
+    } else
+        CoTaskMemFree(pszPath);
+
+    TRACE ("-- (%p)->(%s)\n", This, strRet->uType == STRRET_CSTR ? strRet->u.cStr : debugstr_w(strRet->u.pOleStr));
     return hr;
 }
 
@@ -843,37 +824,47 @@ static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface,
                                                 LPITEMIDLIST * pPidlOut)
 {
     IGenericSFImpl *This = impl_from_IShellFolder2(iface);
-    WCHAR szSrc[MAX_PATH], szDest[MAX_PATH];
+    WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1];
     LPWSTR ptr;
     BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
 
-    TRACE ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl,
+    TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This, hwndOwner, pidl,
      debugstr_w (lpName), dwFlags, pPidlOut);
 
     /* build source path */
-    MultiByteToWideChar(CP_ACP, 0, This->sPathTarget, -1, szSrc, MAX_PATH);
+    lstrcpynW(szSrc, This->sPathTarget, MAX_PATH);
     ptr = PathAddBackslashW (szSrc);
     if (ptr)
-        _ILSimpleGetTextW (pidl, ptr, MAX_PATH - (ptr - szSrc));
+        _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc));
 
     /* build destination path */
     if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) {
-        MultiByteToWideChar(CP_ACP, 0, This->sPathTarget, -1, szDest, MAX_PATH);
+        lstrcpynW(szDest, This->sPathTarget, MAX_PATH);
         ptr = PathAddBackslashW (szDest);
         if (ptr)
-            lstrcpynW(ptr, lpName, MAX_PATH - (ptr - szDest));
+            lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest));
     } else
         lstrcpynW(szDest, lpName, MAX_PATH);
 
     if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) {
         WCHAR *ext = PathFindExtensionW(szSrc);
         if(*ext != '\0') {
-            INT len = strlenW(szDest);
+            INT len = wcslen(szDest);
             lstrcpynW(szDest + len, ext, MAX_PATH - len);
         }
     }
-    
+
     TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest));
+    if (!memcmp(szSrc, szDest, (wcslen(szDest)+1) * sizeof(WCHAR)))
+    {
+        /* src and destination is the same */
+        HRESULT hr = S_OK;
+        if (pPidlOut)
+            hr = _ILCreateFromPathW(szDest, pPidlOut);
+
+        return hr;
+    }
+
 
     if (MoveFileW (szSrc, szDest)) {
         HRESULT hr = S_OK;
@@ -968,6 +959,8 @@ IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl,
          psd->str.u.cStr, MAX_PATH);
         return S_OK;
     } else {
+        hr = S_OK;
+        psd->str.uType = STRRET_CSTR;
         /* the data from the pidl */
         switch (iColumn) {
         case 0:                /* name */
@@ -987,8 +980,6 @@ IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl,
             _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH);
             break;
         }
-        hr = S_OK;
-        psd->str.uType = STRRET_CSTR;
     }
 
     return hr;
@@ -1037,7 +1028,7 @@ ISFHelper_fnQueryInterface (ISFHelper * iface, REFIID riid, LPVOID * ppvObj)
 {
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
 
-    TRACE ("(%p)->(count=%lu)\n", This, This->ref);
+    TRACE ("(%p)->(count=%u)\n", This, This->ref);
 
     return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
 }
@@ -1046,7 +1037,7 @@ static ULONG WINAPI ISFHelper_fnAddRef (ISFHelper * iface)
 {
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
 
-    TRACE ("(%p)->(count=%lu)\n", This, This->ref);
+    TRACE ("(%p)->(count=%u)\n", This, This->ref);
 
     return IUnknown_AddRef (This->pUnkOuter);
 }
@@ -1067,20 +1058,23 @@ static ULONG WINAPI ISFHelper_fnRelease (ISFHelper * iface)
  */
 
 static HRESULT WINAPI
-ISFHelper_fnGetUniqueName (ISFHelper * iface, LPSTR lpName, UINT uLen)
+ISFHelper_fnGetUniqueName (ISFHelper * iface, LPWSTR pwszName, UINT uLen)
 {
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
     IEnumIDList *penum;
     HRESULT hr;
-    char szText[MAX_PATH];
-    const char *szNewFolder = "New Folder";
+    WCHAR wszText[MAX_PATH];
+    WCHAR wszNewFolder[25];
+    const WCHAR wszFormat[] = {'%','s',' ','%','d',0 };
+
+    LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder,  sizeof(wszNewFolder)/sizeof(WCHAR));
 
-    TRACE ("(%p)(%s %u)\n", This, lpName, uLen);
+    TRACE ("(%p)(%p %u)\n", This, pwszName, uLen);
 
-    if (uLen < strlen (szNewFolder) + 4)
+    if (uLen < sizeof(wszNewFolder)/sizeof(WCHAR) + 3)
         return E_POINTER;
 
-    strcpy (lpName, szNewFolder);
+    lstrcpynW (pwszName, wszNewFolder, uLen);
 
     hr = IShellFolder_fnEnumObjects (_IShellFolder2_ (This), 0,
      SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
@@ -1093,9 +1087,9 @@ 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++);
+            _ILSimpleGetTextW (pidl, wszText, MAX_PATH);
+            if (0 == lstrcmpiW (wszText, pwszName)) {
+                _snwprintf (pwszName, uLen, wszFormat, wszNewFolder, i++);
                 if (i > 99) {
                     hr = E_FAIL;
                     break;
@@ -1116,45 +1110,75 @@ next:
  */
 
 static HRESULT WINAPI
-ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCSTR lpName,
+ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCWSTR pwszName,
                        LPITEMIDLIST * ppidlOut)
 {
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
-    char lpstrNewDir[MAX_PATH];
+    WCHAR wszNewDir[MAX_PATH];
     DWORD bRes;
     HRESULT hres = E_FAIL;
 
-    TRACE ("(%p)(%s %p)\n", This, lpName, ppidlOut);
+    TRACE ("(%p)(%s %p)\n", This, debugstr_w(pwszName), ppidlOut);
 
-    strcpy (lpstrNewDir, This->sPathTarget);
-    PathAppendA(lpstrNewDir, lpName);
+    wszNewDir[0] = 0;
+    if (This->sPathTarget)
+        lstrcpynW(wszNewDir, This->sPathTarget, MAX_PATH);
+    PathAppendW(wszNewDir, pwszName);
 
-    bRes = CreateDirectoryA (lpstrNewDir, NULL);
+    bRes = CreateDirectoryW (wszNewDir, NULL);
     if (bRes) {
-        SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHA, lpstrNewDir, NULL);
+        SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL);
 
         hres = S_OK;
 
         if (ppidlOut)
-                hres = _ILCreateFromPathA(lpstrNewDir, ppidlOut);
+                hres = _ILCreateFromPathW(wszNewDir, ppidlOut);
     } else {
-        char lpstrText[128 + MAX_PATH];
-        char lpstrTempText[128];
-        char lpstrCaption[256];
+        WCHAR wszText[128 + MAX_PATH];
+        WCHAR wszTempText[128];
+        WCHAR wszCaption[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);
+        LoadStringW (shell32_hInstance, IDS_CREATEFOLDER_DENIED, wszTempText,
+         sizeof (wszTempText));
+        LoadStringW (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, wszCaption,
+         sizeof (wszCaption));
+        swprintf (wszText, wszTempText, wszNewDir);
+        MessageBoxW (hwnd, wszText, wszCaption, MB_OK | MB_ICONEXCLAMATION);
     }
 
     return hres;
 }
 
-extern BOOL fileMoving;
+/****************************************************************************
+ * build_paths_list
+ *
+ * Builds a list of paths like the one used in SHFileOperation from a table of
+ * PIDLs relative to the given base folder
+ */
+WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls)
+{
+    WCHAR *wszPathsList;
+    WCHAR *wszListPos;
+    int iPathLen;
+    int i;
+
+    iPathLen = wcslen(wszBasePath);
+    wszPathsList = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR)*cidl+1);
+    wszListPos = wszPathsList;
+
+    for (i = 0; i < cidl; i++) {
+        if (!_ILIsFolder(pidls[i]) && !_ILIsValue(pidls[i]))
+            continue;
+
+        lstrcpynW(wszListPos, wszBasePath, MAX_PATH);
+        /* FIXME: abort if path too long */
+        _ILSimpleGetTextW(pidls[i], wszListPos+iPathLen, MAX_PATH-iPathLen);
+        wszListPos += wcslen(wszListPos)+1;
+    }
+    *wszListPos=0;
+    return wszPathsList;
+}
 
 /****************************************************************************
  * ISFHelper_fnDeleteItems
@@ -1166,52 +1190,60 @@ ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl)
 {
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
     UINT i;
-    char szPath[MAX_PATH];
-    BOOL bConfirm = TRUE;
+    SHFILEOPSTRUCTW op;
+    WCHAR wszPath[MAX_PATH];
+    WCHAR *wszPathsList;
+    HRESULT ret;
+    WCHAR *wszCurrentPath;
 
     TRACE ("(%p)(%u %p)\n", This, cidl, apidl);
-    
-    /* deleting multiple items so give a slightly different warning */
-    if (cidl != 1) {
-        char tmp[8];
+    if (cidl==0) return S_OK;
 
-        snprintf (tmp, sizeof (tmp), "%d", cidl);
-        if (!SHELL_ConfirmDialog(ASK_DELETE_MULTIPLE_ITEM, tmp))
-            return E_FAIL;
-        bConfirm = FALSE;
+    if (This->sPathTarget)
+        lstrcpynW(wszPath, This->sPathTarget, MAX_PATH);
+    else
+        wszPath[0] = '\0';
+    PathAddBackslashW(wszPath);
+    wszPathsList = build_paths_list(wszPath, cidl, apidl);
+
+    ZeroMemory(&op, sizeof(op));
+    op.hwnd = GetActiveWindow();
+    op.wFunc = FO_DELETE;
+    op.pFrom = wszPathsList;
+    op.fFlags = FOF_ALLOWUNDO;
+    if (SHFileOperationW(&op))
+    {
+        WARN("SHFileOperation failed\n");
+        ret = E_FAIL;
     }
-    
-    for (i = 0; i < cidl; i++) {
-        strcpy (szPath, This->sPathTarget);
-        PathAddBackslashA (szPath);
-        _ILSimpleGetText (apidl[i], szPath + strlen (szPath), MAX_PATH);
+    else
+        ret = S_OK;
 
-        if (_ILIsFolder (apidl[i])) {
-            LPITEMIDLIST pidl;
+    /* we currently need to manually send the notifies */
+    wszCurrentPath = wszPathsList;
+    for (i = 0; i < cidl; i++)
+    {
+        LONG wEventId;
 
-            TRACE ("delete %s\n", szPath);
-            if (!SHELL_DeleteDirectoryA (szPath, bConfirm)) {
-                TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
-                return E_FAIL;
-            }
-            pidl = ILCombine (This->pidlRoot, apidl[i]);
-            SHChangeNotify (SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
-            SHFree (pidl);
-        } else if (_ILIsValue (apidl[i])) {
-            LPITEMIDLIST pidl;
+        if (_ILIsFolder(apidl[i]))
+            wEventId = SHCNE_RMDIR;
+        else if (_ILIsValue(apidl[i]))
+            wEventId = SHCNE_DELETE;
+        else
+            continue;
 
-            TRACE ("delete %s\n", szPath);
-            if (!SHELL_DeleteFileA (szPath, bConfirm)) {
-                TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
-                return E_FAIL;
-            }
-            pidl = ILCombine (This->pidlRoot, apidl[i]);
-            SHChangeNotify (SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
-            SHFree (pidl);
+        /* check if file exists */
+        if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES)
+        {
+            LPITEMIDLIST pidl = ILCombine(This->pidlRoot, apidl[i]);
+            SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL);
+            SHFree(pidl);
         }
 
+        wszCurrentPath += wcslen(wszCurrentPath)+1;
     }
-    return S_OK;
+    HeapFree(GetProcessHeap(), 0, wszPathsList);
+    return ret;
 }
 
 /****************************************************************************
@@ -1223,73 +1255,128 @@ static HRESULT WINAPI
 ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl,
                        LPCITEMIDLIST * apidl)
 {
-    UINT i;
     IPersistFolder2 *ppf2 = NULL;
-    char szSrcPath[MAX_PATH],
-      szDstPath[MAX_PATH];
+    WCHAR szSrcPath[MAX_PATH];
+    WCHAR szTargetPath[MAX_PATH];
+    SHFILEOPSTRUCTW op;
+    LPITEMIDLIST pidl;
+    LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName;
+    int res, length;
+    HRESULT hr;
+    STRRET strRet;
 
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
 
     TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
 
-    IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2,
-     (LPVOID *) & ppf2);
-    if (ppf2) {
-        LPITEMIDLIST pidl;
+    hr = IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2, (LPVOID *) & ppf2);
+    if (SUCCEEDED(hr))
+    {
+        if (FAILED(IPersistFolder2_GetCurFolder (ppf2, &pidl)))
+        {
+            IPersistFolder2_Release(ppf2);
+            return E_FAIL;
+        }
+        IPersistFolder2_Release(ppf2);
+
+        if (FAILED(IShellFolder_GetDisplayNameOf(pSFFrom, pidl, SHGDN_FORPARSING, &strRet)))
+        {
+            SHFree (pidl);
+            return E_FAIL;
+        }
+
+        if (FAILED(StrRetToBufW(&strRet, pidl, szSrcPath, MAX_PATH)))
+        {
+            SHFree (pidl);
+            return E_FAIL;
+        }
+        SHFree (pidl);
+
+        pszSrc = PathAddBackslashW (szSrcPath);
+
+        wcscpy(szTargetPath, This->sPathTarget);
+        pszTarget = PathAddBackslashW (szTargetPath);
+
+        pszSrcList = build_paths_list(szSrcPath, cidl, apidl);
+        pszTargetList = build_paths_list(szTargetPath, cidl, apidl);
 
-        if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) {
-            for (i = 0; i < cidl; i++) 
+        if (!pszSrcList || !pszTargetList)
+        {
+            if (pszSrcList)
+                HeapFree(GetProcessHeap(), 0, pszSrcList);
+
+            if (pszTargetList)
+                HeapFree(GetProcessHeap(), 0, pszTargetList);
+
+            SHFree (pidl);
+            IPersistFolder2_Release (ppf2);
+            return E_OUTOFMEMORY;
+        }
+        ZeroMemory(&op, sizeof(op));
+        if (!pszSrcList[0])
+        {
+            /* remove trailing backslash */
+            pszSrc--;
+            pszSrc[0] = L'\0';
+            op.pFrom = szSrcPath;
+        }
+        else
+        {
+            op.pFrom = pszSrcList;
+        }
+
+        if (!pszTargetList[0])
+        {
+            /* remove trailing backslash */
+            if (pszTarget - szTargetPath > 3)
             {
-                SHGetPathFromIDListA (pidl, szSrcPath);
-                PathAddBackslashA (szSrcPath);
-                _ILSimpleGetText (apidl[i], szSrcPath + strlen (szSrcPath),
-                 MAX_PATH);
-
-                strcpy (szDstPath, This->sPathTarget);
-                PathAddBackslashA (szDstPath);
-                _ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH);
-                DPRINT1 ("copy %s to %s\n", szSrcPath, szDstPath);
-                
-                if (fileMoving)
-                {
-                    fileMoving = FALSE;
-                    SHNotifyMoveFileA(szSrcPath, szDstPath);
-                }
-                else
-                {
-                    SHNotifyCopyFileA(szSrcPath, szDstPath, TRUE);
-                }
-               
-                /*
-                SHFILEOPSTRUCTA op;
-                
-                if (fileMoving)
-                {
-                    op.wFunc = FO_MOVE;
-                    fileMoving = FALSE;
-                }
-                else
-                {
-                    op.wFunc = FO_COPY;
-                }
-                
-                op.pTo = szDstPath;
-                op.pFrom = szSrcPath;
-                op.fFlags = FOF_SIMPLEPROGRESS;                
-                op.hwnd = NULL;
-                op.hNameMappings = NULL;
-                op.lpszProgressTitle = NULL;
-                
-                UINT bRes = SHFileOperationA(&op);
-                DbgPrint("CopyItems SHFileOperationA 0x%08x\n", bRes);
-                */
-                
+                pszTarget--;
+                pszTarget[0] = L'\0';
             }
-            SHFree (pidl);
+            else
+            {
+                pszTarget[1] = L'\0';
+            }
+
+            op.pTo = szTargetPath;
         }
-        IPersistFolder2_Release (ppf2);
+        else
+        {
+            op.pTo = pszTargetList;
+        }
+        op.hwnd = GetActiveWindow();
+        op.wFunc = FO_COPY;
+        op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
+
+        res = SHFileOperationW(&op);
+
+        if (res == DE_SAMEFILE)
+        {
+            length = wcslen(szTargetPath);
+
+            pszFileName = wcsrchr(pszSrcList, '\\');
+            pszFileName++;
+
+            if (LoadStringW(shell32_hInstance, IDS_COPY_OF, pszTarget, MAX_PATH - length))
+            {
+                wcscat(szTargetPath, L" ");
+            }
+
+            wcscat(szTargetPath, pszFileName);
+            op.pTo = szTargetPath;
+
+            res = SHFileOperationW(&op);
+        }
+
+        HeapFree(GetProcessHeap(), 0, pszSrcList);
+        HeapFree(GetProcessHeap(), 0, pszTargetList);
+
+        if (res)
+            return E_FAIL;
+        else
+            return S_OK;
     }
-    return S_OK;
+    return E_FAIL;
 }
 
 static const ISFHelperVtbl shvt =
@@ -1327,7 +1414,7 @@ IFSFldr_PersistFolder3_AddRef (IPersistFolder3 * iface)
 {
     IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
 
-    TRACE ("(%p)->(count=%lu)\n", This, This->ref);
+    TRACE ("(%p)->(count=%u)\n", This, This->ref);
 
     return IUnknown_AddRef (This->pUnkOuter);
 }
@@ -1341,7 +1428,7 @@ IFSFldr_PersistFolder3_Release (IPersistFolder3 * iface)
 {
     IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
 
-    TRACE ("(%p)->(count=%lu)\n", This, This->ref);
+    TRACE ("(%p)->(count=%u)\n", This, This->ref);
 
     return IUnknown_Release (This->pUnkOuter);
 }
@@ -1372,26 +1459,28 @@ IFSFldr_PersistFolder3_GetClassID (IPersistFolder3 * iface, CLSID * lpClassId)
 static HRESULT WINAPI
 IFSFldr_PersistFolder3_Initialize (IPersistFolder3 * iface, LPCITEMIDLIST pidl)
 {
-    char sTemp[MAX_PATH];
+    WCHAR wszTemp[MAX_PATH];
 
     IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
 
     TRACE ("(%p)->(%p)\n", This, pidl);
 
-    if (This->pidlRoot)
-        SHFree (This->pidlRoot);     /* free the old pidl */
+    SHFree (This->pidlRoot);     /* free the old pidl */
     This->pidlRoot = ILClone (pidl); /* set my pidl */
 
-    if (This->sPathTarget)
-        SHFree (This->sPathTarget);
+    SHFree (This->sPathTarget);
+    This->sPathTarget = NULL;
 
     /* set my path */
-    if (SHGetPathFromIDListA (pidl, sTemp)) {
-        This->sPathTarget = SHAlloc (strlen (sTemp) + 1);
-        strcpy (This->sPathTarget, sTemp);
+    if (SHGetPathFromIDListW (pidl, wszTemp)) {
+        int len = wcslen(wszTemp);
+        This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
+        if (!This->sPathTarget)
+            return E_OUTOFMEMORY;
+        memcpy(This->sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
     }
 
-    TRACE ("--(%p)->(%s)\n", This, This->sPathTarget);
+    TRACE ("--(%p)->(%s)\n", This, debugstr_w(This->sPathTarget));
     return S_OK;
 }
 
@@ -1421,13 +1510,13 @@ IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface,
                                      IBindCtx * pbc, LPCITEMIDLIST pidlRoot,
                                      const PERSIST_FOLDER_TARGET_INFO * ppfti)
 {
-    char sTemp[MAX_PATH];
+    WCHAR wszTemp[MAX_PATH];
 
     IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
 
     TRACE ("(%p)->(%p,%p,%p)\n", This, pbc, pidlRoot, ppfti);
     if (ppfti)
-        TRACE ("--%p %s %s 0x%08lx 0x%08x\n",
+        TRACE ("--%p %s %s 0x%08x 0x%08x\n",
          ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName),
          debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes,
          ppfti->csidl);
@@ -1452,20 +1541,33 @@ IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface,
      */
     if (ppfti) {
         if (ppfti->csidl != -1) {
-            if (SHGetSpecialFolderPathA (0, sTemp, ppfti->csidl,
+            if (SHGetSpecialFolderPathW (0, wszTemp, ppfti->csidl,
              ppfti->csidl & CSIDL_FLAG_CREATE)) {
-                __SHCloneStrA (&This->sPathTarget, sTemp);
+                int len = wcslen(wszTemp);
+                This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
+                if (!This->sPathTarget)
+                    return E_OUTOFMEMORY;
+                memcpy(This->sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
             }
         } else if (ppfti->szTargetParsingName[0]) {
-            __SHCloneStrWtoA (&This->sPathTarget, ppfti->szTargetParsingName);
+            int len = wcslen(ppfti->szTargetParsingName);
+            This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
+            if (!This->sPathTarget)
+                return E_OUTOFMEMORY;
+            memcpy(This->sPathTarget, ppfti->szTargetParsingName,
+                   (len + 1) * sizeof(WCHAR));
         } else if (ppfti->pidlTargetFolder) {
-            if (SHGetPathFromIDListA (ppfti->pidlTargetFolder, sTemp)) {
-                __SHCloneStrA (&This->sPathTarget, sTemp);
+            if (SHGetPathFromIDListW(ppfti->pidlTargetFolder, wszTemp)) {
+                int len = wcslen(wszTemp);
+                This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
+                if (!This->sPathTarget)
+                    return E_OUTOFMEMORY;
+                memcpy(This->sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
             }
         }
     }
 
-    TRACE ("--(%p)->(target=%s)\n", This, debugstr_(This->sPathTarget));
+    TRACE ("--(%p)->(target=%s)\n", This, debugstr_w(This->sPathTarget));
     pdump (This->pidlRoot);
     return (This->sPathTarget) ? S_OK : E_FAIL;
 }
@@ -1595,11 +1697,9 @@ static HRESULT WINAPI
 ISFDropTarget_Drop (IDropTarget * iface, IDataObject * pDataObject,
                     DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
 {
-    DWORD dwEffect = *pdwEffect;
-    
     IGenericSFImpl *This = impl_from_IDropTarget(iface);
 
-    FIXME ("(%p) object dropped(%d)\n", This, dwKeyState);
+    FIXME ("(%p) object dropped\n", This);
 
     return E_NOTIMPL;
 }