Mikołaj Zalewski : shell32: Use SHFileOperationW to delete files.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jun 30 14:15:02 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: 86fe1a0d5fc63c3eef9271a46cba8350e6d38b5d
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=86fe1a0d5fc63c3eef9271a46cba8350e6d38b5d

Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date:   Thu Jun 29 21:03:41 2006 +0200

shell32: Use SHFileOperationW to delete files.

---

 dlls/shell32/shfldr_fs.c |  107 ++++++++++++++++++++++++++++++----------------
 1 files changed, 69 insertions(+), 38 deletions(-)

diff --git a/dlls/shell32/shfldr_fs.c b/dlls/shell32/shfldr_fs.c
index d683007..4e1c878 100644
--- a/dlls/shell32/shfldr_fs.c
+++ b/dlls/shell32/shfldr_fs.c
@@ -1155,6 +1155,36 @@ ISFHelper_fnAddFolder (ISFHelper * iface
 }
 
 /****************************************************************************
+ * 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 = lstrlenW(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 += lstrlenW(wszListPos)+1;
+    }
+    *wszListPos=0;
+    return wszPathsList;
+}
+
+/****************************************************************************
  * ISFHelper_fnDeleteItems
  *
  * deletes items in folder
@@ -1164,59 +1194,60 @@ ISFHelper_fnDeleteItems (ISFHelper * ifa
 {
     IGenericSFImpl *This = impl_from_ISFHelper(iface);
     UINT i;
+    SHFILEOPSTRUCTW op;
     WCHAR wszPath[MAX_PATH];
-    int iPathLen;
-    BOOL bConfirm = TRUE;
+    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) {
-        WCHAR tmp[8];
-        static const WCHAR format[] = {'%','d',0};
-
-        wnsprintfW (tmp, sizeof(tmp)/sizeof(tmp[0]), format, cidl);
-        if (!SHELL_ConfirmDialogW(ASK_DELETE_MULTIPLE_ITEM, tmp))
-            return E_FAIL;
-        bConfirm = FALSE;
-    }
+    if (cidl==0) return S_OK;
 
     if (This->sPathTarget)
         lstrcpynW(wszPath, This->sPathTarget, MAX_PATH);
     else
         wszPath[0] = '\0';
     PathAddBackslashW(wszPath);
-    iPathLen = lstrlenW(wszPath);
-    
-    for (i = 0; i < cidl; i++) {
-        _ILSimpleGetTextW (apidl[i], wszPath+iPathLen, MAX_PATH-iPathLen);
+    wszPathsList = build_paths_list(wszPath, cidl, apidl);
+
+    ZeroMemory(&op, sizeof(op));
+    op.hwnd = GetActiveWindow();
+    op.wFunc = FO_DELETE;
+    op.pFrom = wszPathsList;
+    op.fFlags = 0;
+    if (SHFileOperationW(&op))
+    {
+        WARN("SHFileOperation failed\n");
+        ret = E_FAIL;
+    }
+    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", debugstr_w(wszPath));
-            if (!SHELL_DeleteDirectoryW (wszPath, bConfirm)) {
-                TRACE ("delete %s failed, bConfirm=%d\n", debugstr_w(wszPath), 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", debugstr_w(wszPath));
-            if (!SHELL_DeleteFileW (wszPath, bConfirm)) {
-                TRACE ("delete %s failed, bConfirm=%d\n", debugstr_w(wszPath), 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 += lstrlenW(wszCurrentPath)+1;
     }
-    return S_OK;
+    HeapFree(GetProcessHeap(), 0, wszPathsList);
+    return ret;
 }
 
 /****************************************************************************




More information about the wine-cvs mailing list