Zhenbo Li : shell32: Fix SHFileOperation when deleting a nonexistent directory.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jun 25 13:42:03 CDT 2014


Module: wine
Branch: master
Commit: 2ba9ee018bce4953feb728595f4a4a6e47b186a1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2ba9ee018bce4953feb728595f4a4a6e47b186a1

Author: Zhenbo Li <litimetal at gmail.com>
Date:   Sat Jun 21 22:34:58 2014 +0800

shell32: Fix SHFileOperation when deleting a nonexistent directory.

---

 dlls/shell32/shlfileop.c       | 68 +++++++++++++++++++++---------------------
 dlls/shell32/tests/shlfileop.c |  4 ---
 2 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c
index e6d44b0..62d7880 100644
--- a/dlls/shell32/shlfileop.c
+++ b/dlls/shell32/shlfileop.c
@@ -347,36 +347,36 @@ HRESULT WINAPI SHIsFileAvailableOffline(LPCWSTR path, LPDWORD status)
  * Asks for confirmation when bShowUI is true and deletes the directory and
  * all its subdirectories and files if necessary.
  */
-static BOOL SHELL_DeleteDirectoryW(HWND hwnd, LPCWSTR pszDir, BOOL bShowUI)
+static DWORD SHELL_DeleteDirectoryW(HWND hwnd, LPCWSTR pszDir, BOOL bShowUI)
 {
-	BOOL    ret = TRUE;
-	HANDLE  hFind;
-	WIN32_FIND_DATAW wfd;
-	WCHAR   szTemp[MAX_PATH];
-
-	/* Make sure the directory exists before eventually prompting the user */
-	PathCombineW(szTemp, pszDir, wWildcardFile);
-	hFind = FindFirstFileW(szTemp, &wfd);
-	if (hFind == INVALID_HANDLE_VALUE)
-	  return FALSE;
+    DWORD    ret = 0;
+    HANDLE  hFind;
+    WIN32_FIND_DATAW wfd;
+    WCHAR   szTemp[MAX_PATH];
+
+    PathCombineW(szTemp, pszDir, wWildcardFile);
+    hFind = FindFirstFileW(szTemp, &wfd);
+
+    if (hFind != INVALID_HANDLE_VALUE) {
+        if (!bShowUI || SHELL_ConfirmDialogW(hwnd, ASK_DELETE_FOLDER, pszDir, NULL)) {
+            do {
+                if (IsDotDir(wfd.cFileName))
+                    continue;
+                PathCombineW(szTemp, pszDir, wfd.cFileName);
+                if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
+                    ret = SHELL_DeleteDirectoryW(hwnd, szTemp, FALSE);
+                else
+                    ret = SHNotifyDeleteFileW(szTemp);
+            } while (!ret && FindNextFileW(hFind, &wfd));
+        }
+        FindClose(hFind);
+    }
+    if (ret == ERROR_SUCCESS)
+        ret = SHNotifyRemoveDirectoryW(pszDir);
 
-	if (!bShowUI || (ret = SHELL_ConfirmDialogW(hwnd, ASK_DELETE_FOLDER, pszDir, NULL)))
-	{
-	  do
-	  {
-	    if (IsDotDir(wfd.cFileName))
-	      continue;
-	    PathCombineW(szTemp, pszDir, wfd.cFileName);
-	    if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
-	      ret = SHELL_DeleteDirectoryW(hwnd, szTemp, FALSE);
-	    else
-	      ret = (SHNotifyDeleteFileW(szTemp) == ERROR_SUCCESS);
-	  } while (ret && FindNextFileW(hFind, &wfd));
-	}
-	FindClose(hFind);
-	if (ret)
-	  ret = (SHNotifyRemoveDirectoryW(pszDir) == ERROR_SUCCESS);
-	return ret;
+    return ret == ERROR_PATH_NOT_FOUND ?
+        0x7C: /* DE_INVALIDFILES (legacy Windows error) */
+        ret;
 }
 
 /**************************************************************************
@@ -1331,8 +1331,7 @@ static BOOL confirm_delete_list(HWND hWnd, DWORD fFlags, BOOL fTrash, const FILE
 static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
 {
     const FILE_ENTRY *fileEntry;
-    DWORD i;
-    BOOL bPathExists;
+    DWORD i, ret;
     BOOL bTrash;
 
     if (!flFrom->dwNumFiles)
@@ -1378,12 +1377,13 @@ static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
         
         /* delete the file or directory */
         if (IsAttribFile(fileEntry->attributes))
-            bPathExists = DeleteFileW(fileEntry->szFullPath);
+            ret = DeleteFileW(fileEntry->szFullPath) ?
+                    ERROR_SUCCESS : GetLastError();
         else
-            bPathExists = SHELL_DeleteDirectoryW(lpFileOp->hwnd, fileEntry->szFullPath, FALSE);
+            ret = SHELL_DeleteDirectoryW(lpFileOp->hwnd, fileEntry->szFullPath, FALSE);
 
-        if (!bPathExists)
-            return ERROR_PATH_NOT_FOUND;
+        if (ret)
+            return ret;
     }
 
     return ERROR_SUCCESS;
diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c
index eba5450..3468fcc 100644
--- a/dlls/shell32/tests/shlfileop.c
+++ b/dlls/shell32/tests/shlfileop.c
@@ -622,7 +622,6 @@ static void test_delete(void)
     shfo.pFrom = "nonexistent.txt\0";
     shfo.wFunc = FO_DELETE;
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == 1026 ||
        ret == ERROR_FILE_NOT_FOUND || /* Vista */
        broken(ret == ERROR_SUCCESS), /* NT4 */
@@ -651,7 +650,6 @@ static void test_delete(void)
     shfo.pFrom = "test1.txt\0nonexistent.txt\0test2.txt\0";
     shfo.wFunc = FO_DELETE;
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == 1026 ||
        ret == ERROR_FILE_NOT_FOUND || /* Vista */
        broken(ret == ERROR_SUCCESS), /* NT4 */
@@ -664,14 +662,12 @@ static void test_delete(void)
     init_shfo_tests();
     shfo.pFrom = "testdir2\\nonexistent.txt\0";
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == ERROR_FILE_NOT_FOUND || /* Vista */
        broken(ret == 0x402) || /* XP */
        broken(ret == ERROR_SUCCESS), /* NT4 */
        "Expected 0x402 or ERROR_FILE_NOT_FOUND, got %x\n", ret);
     shfo.pFrom = "nonexistent\\one.txt\0";
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == DE_INVALIDFILES || /* Vista or later */
        broken(ret == 0x402), /* XP */
        "Expected 0x402 or DE_INVALIDFILES, got %x\n", ret);




More information about the wine-cvs mailing list