Mikołaj Zalewski : shell32: If possible use SHFileOperationW to delete in unixfs.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jul 7 11:10:15 CDT 2006


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

Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date:   Thu Jul  6 20:38:37 2006 +0200

shell32: If possible use SHFileOperationW to delete in unixfs.

This gives confirmation dialogs, recursive directory removal etc.

---

 dlls/shell32/shfldr_unixfs.c |  104 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 93 insertions(+), 11 deletions(-)

diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c
index b74b458..2fd7de5 100644
--- a/dlls/shell32/shfldr_unixfs.c
+++ b/dlls/shell32/shfldr_unixfs.c
@@ -1763,6 +1763,87 @@ static HRESULT WINAPI UnixFolder_ISFHelp
     }
 }
 
+/*
+ * Delete specified files by converting the path to DOS paths and calling
+ * SHFileOperationW. If an error occurs it returns an error code. If the paths can't
+ * be converted, S_FALSE is returned. In such situation DeleteItems will try to delete
+ * the files using syscalls
+ */
+static HRESULT UNIXFS_delete_with_shfileop(UnixFolder *This, UINT cidl, LPCITEMIDLIST *apidl)
+{
+    char szAbsolute[FILENAME_MAX], *pszRelative;
+    LPWSTR wszPathsList, wszListPos;
+    SHFILEOPSTRUCTW op;
+    HRESULT ret;
+    int i;
+    
+    lstrcpyA(szAbsolute, This->m_pszPath);
+    pszRelative = szAbsolute + lstrlenA(szAbsolute);
+    
+    wszListPos = wszPathsList = HeapAlloc(GetProcessHeap(), 0, cidl*MAX_PATH*sizeof(WCHAR)+1);
+    if (wszPathsList == NULL)
+        return E_OUTOFMEMORY;
+    for (i=0; i<cidl; i++) {
+        LPWSTR wszDosPath;
+        
+        if (!_ILIsFolder(apidl[i]) && !_ILIsValue(apidl[i]))
+            continue;
+        if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
+        {
+            HeapFree(GetProcessHeap(), 0, wszPathsList);
+            return E_INVALIDARG;
+        }
+        wszDosPath = wine_get_dos_file_name(szAbsolute);
+        if (wszDosPath == NULL || lstrlenW(wszDosPath) >= MAX_PATH)
+        {
+            HeapFree(GetProcessHeap(), 0, wszPathsList);
+            HeapFree(GetProcessHeap(), 0, wszDosPath);
+            return S_FALSE;
+        }
+        lstrcpyW(wszListPos, wszDosPath);
+        wszListPos += lstrlenW(wszListPos)+1;
+        HeapFree(GetProcessHeap(), 0, wszDosPath);
+    }
+    *wszListPos = 0;
+    
+    ZeroMemory(&op, sizeof(op));
+    op.hwnd = GetActiveWindow();
+    op.wFunc = FO_DELETE;
+    op.pFrom = wszPathsList;
+    if (!SHFileOperationW(&op))
+    {
+        WARN("SHFileOperationW failed\n");
+        ret = E_FAIL;
+    }
+    else
+        ret = S_OK;
+
+    HeapFree(GetProcessHeap(), 0, wszPathsList);
+    return ret;
+}
+
+static HRESULT UNIXFS_delete_with_syscalls(UnixFolder *This, UINT cidl, LPCITEMIDLIST *apidl)
+{
+    char szAbsolute[FILENAME_MAX], *pszRelative;
+    int i;
+    
+    lstrcpyA(szAbsolute, This->m_pszPath);
+    pszRelative = szAbsolute + lstrlenA(szAbsolute);
+    
+    for (i=0; i<cidl; i++) {
+        if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
+            return E_INVALIDARG;
+        if (_ILIsFolder(apidl[i])) {
+            if (rmdir(szAbsolute))
+                return E_FAIL;
+        } else if (_ILIsValue(apidl[i])) {
+            if (unlink(szAbsolute))
+                return E_FAIL;
+        }
+    }
+    return S_OK;
+}
+
 static HRESULT WINAPI UnixFolder_ISFHelper_DeleteItems(ISFHelper* iface, UINT cidl, 
     LPCITEMIDLIST* apidl)
 {
@@ -1771,26 +1852,27 @@ static HRESULT WINAPI UnixFolder_ISFHelp
     LPITEMIDLIST pidlAbsolute;
     HRESULT hr = S_OK;
     UINT i;
+    struct stat st;
     
     TRACE("(iface=%p, cidl=%d, apidl=%p)\n", iface, cidl, apidl);
 
+    hr = UNIXFS_delete_with_shfileop(This, cidl, apidl);
+    if (hr == S_FALSE)
+        hr = UNIXFS_delete_with_syscalls(This, cidl, apidl);
+
     lstrcpyA(szAbsolute, This->m_pszPath);
     pszRelative = szAbsolute + lstrlenA(szAbsolute);
     
-    for (i=0; i<cidl && SUCCEEDED(hr); i++) {
+    /* we need to manually send the notifies if the files doesn't exist */
+    for (i=0; i<cidl; i++) {
         if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
-            return E_INVALIDARG;
+            continue;
         pidlAbsolute = ILCombine(This->m_pidlLocation, apidl[i]);
-        if (_ILIsFolder(apidl[i])) {
-            if (rmdir(szAbsolute)) {
-                hr = E_FAIL;
-            } else {
+        if (stat(szAbsolute, &st))
+        {
+            if (_ILIsFolder(apidl[i])) {
                 SHChangeNotify(SHCNE_RMDIR, SHCNF_IDLIST, pidlAbsolute, NULL);
-            }
-        } else if (_ILIsValue(apidl[i])) {
-            if (unlink(szAbsolute)) {
-                hr = E_FAIL;
-            } else {
+            } else if (_ILIsValue(apidl[i])) {
                 SHChangeNotify(SHCNE_DELETE, SHCNF_IDLIST, pidlAbsolute, NULL);
             }
         }




More information about the wine-cvs mailing list