shell32: for FO_COPY, if the destination is an empty string, SHFileOperation should use the current directory. Additionally, in parse_file_list, check result of HeapAlloc against NULL.

Lionel Debroux lionel_debroux at yahoo.fr
Thu May 21 07:05:40 CDT 2009


Based on a patch by Nikolay Sivov <bunglehead at gmail.com>.
---
 dlls/shell32/shlfileop.c       |   21 ++++++++++++++++++---
 dlls/shell32/tests/shlfileop.c |   13 +++++++++++++
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c
index b48e46d..b86b86a 100644
--- a/dlls/shell32/shlfileop.c
+++ b/dlls/shell32/shlfileop.c
@@ -1013,13 +1013,16 @@ static HRESULT parse_file_list(FILE_LIST *flList, LPCWSTR szFiles)
     flList->num_alloc = 32;
     flList->dwNumFiles = 0;
 
-    /* empty list */
+    /* Empty list: return without having allocated flList->feFiles. */
     if (!szFiles[0])
         return ERROR_ACCESS_DENIED;
         
     flList->feFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
                                 flList->num_alloc * sizeof(FILE_ENTRY));
 
+    if (!flList->feFiles)
+        return E_OUTOFMEMORY;
+
     while (*ptr)
     {
         if (i >= flList->num_alloc) grow_list( flList );
@@ -1177,8 +1180,20 @@ static HRESULT copy_files(FILE_OPERATION *op, const FILE_LIST *flFrom, FILE_LIST
 {
     DWORD i;
     const FILE_ENTRY *entryToCopy;
-    const FILE_ENTRY *fileDest = &flTo->feFiles[0];
+    const FILE_ENTRY *fileDest;
 
+    /* if the destination is empty, SHFileOperation should use the current directory */
+    if (op->req->pTo[0] == '\0') {
+        WCHAR currd[MAX_PATH];
+        GetCurrentDirectoryW(MAX_PATH, currd);
+        /* Due to the empty destination, a previous call to parse_file_list(), triggered
+           by SHFileOperationW, returned before allocating and filling flTo->feFiles.
+           => destroy_file_list() needn't be called. */
+        parse_file_list(flTo, currd);
+    }
+    
+    fileDest = &flTo->feFiles[0];
+    
     if (flFrom->bAnyDontExist)
         return ERROR_SHELL_INTERNAL_FILE_NOT_FOUND;
 
diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c
index 540fd0d..0495b01 100644
--- a/dlls/shell32/tests/shlfileop.c
+++ b/dlls/shell32/tests/shlfileop.c
@@ -1673,6 +1673,19 @@ static void test_copy(void)
     ok(DeleteFileA("ab.txt"), "Expected file to exist\n");
     ok(RemoveDirectoryA("one"), "Expected dir to exist\n");
     ok(RemoveDirectoryA("two"), "Expected dir to exist\n");
+
+    /* pTo is an empty string  */
+    CreateDirectoryA("one", NULL);
+    createTestFile("one\\abcdefghi.abc");
+    shfo.pFrom = "one\\abcdefghi.abc\0";
+    shfo.pTo = "\0";
+    shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI | FOF_FILESONLY |
+                  FOF_NOCONFIRMMKDIR;
+    retval = SHFileOperation(&shfo);
+    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(DeleteFileA("abcdefghi.abc"), "Expected file to exist\n");
+    ok(DeleteFileA("one\\abcdefghi.abc"), "Expected file to exist\n");
+    ok(RemoveDirectoryA("one"), "Expected dir to exist\n");
 }
 
 /* tests the FO_MOVE action */
-- 
1.6.3.1.61.g065b0


--------------030308050403090406010208--



More information about the wine-devel mailing list