From: Spencer Wallace spencerwallace@esri.com
--- dlls/shell32/shlfileop.c | 52 +++++++++++++++++++++++++-- dlls/shell32/tests/shlfileop.c | 64 +++++++++++++++------------------- 2 files changed, 79 insertions(+), 37 deletions(-)
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c index a7e88c813d2..b861d20ccb4 100644 --- a/dlls/shell32/shlfileop.c +++ b/dlls/shell32/shlfileop.c @@ -1382,12 +1382,55 @@ static int delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom) return ERROR_SUCCESS; }
-/* moves a file or directory to another directory */ +/* moves a directory to another directory */ +static void move_dir_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo) +{ + WCHAR szFrom[MAX_PATH], szDestPath[MAX_PATH]; + + /* Windows doesn't combine path when FOF_MULTIDESTFILES is set */ + if (lpFileOp->fFlags & FOF_MULTIDESTFILES) + lstrcpyW(szDestPath, feTo->szFullPath); + else + PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename); + + szDestPath[lstrlenW(szDestPath) + 1] = '\0'; + + /* If destination directory already exists, append source directory + with wildcard and restart SHFileOperationW */ + if (PathFileExistsW(szDestPath)) + { + SHFILEOPSTRUCTW fileOp; + + PathCombineW(szFrom, feFrom->szFullPath, L"*.*"); + szFrom[lstrlenW(szFrom) + 1] = '\0'; + + fileOp = *lpFileOp; + fileOp.pFrom = szFrom; + fileOp.pTo = szDestPath; + fileOp.fFlags &= ~FOF_MULTIDESTFILES; /* we know we're moving to one dir */ + + /* Don't ask the user about overwriting files when he accepted to overwrite the + folder. FIXME: this is not exactly what Windows does - e.g. there would be + an additional confirmation for a nested folder */ + fileOp.fFlags |= FOF_NOCONFIRMATION; + + if (!SHFileOperationW(&fileOp)) + RemoveDirectoryW(feFrom->szFullPath); + return; + } + else + { + SHNotifyMoveFileW(feFrom->szFullPath, szDestPath); + } +} + +/* moves a file to another directory */ static void move_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo) { WCHAR szDestPath[MAX_PATH];
PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename); + szDestPath[lstrlenW(szDestPath) + 1] = '\0'; SHNotifyMoveFileW(feFrom->szFullPath, szDestPath); }
@@ -1448,7 +1491,12 @@ static int move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const }
if (fileDest->bExists && IsAttribDir(fileDest->attributes)) - move_to_dir(lpFileOp, entryToMove, fileDest); + { + if (IsAttribDir(entryToMove->attributes)) + move_dir_to_dir(lpFileOp, entryToMove, fileDest); + else + move_to_dir(lpFileOp, entryToMove, fileDest); + } else SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath); } diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c index 0ce4fa2e29c..60303d1e032 100644 --- a/dlls/shell32/tests/shlfileop.c +++ b/dlls/shell32/tests/shlfileop.c @@ -171,23 +171,17 @@ static void clean_after_shfo_tests(void) RemoveDirectoryA("testdir4\nested"); RemoveDirectoryA("testdir4"); DeleteFileA("testdir6\nested\subnested\3.txt"); - DeleteFileA("testdir6\nested\nested\two.txt"); DeleteFileA("testdir6\nested\two.txt"); DeleteFileA("testdir6\nested\2.txt"); DeleteFileA("testdir6\two.txt"); RemoveDirectoryA("testdir6\nested\subnested"); - RemoveDirectoryA("testdir6\nested\nested"); RemoveDirectoryA("testdir6\subnested"); RemoveDirectoryA("testdir6\nested"); RemoveDirectoryA("testdir6"); DeleteFileA("testdir8\nested\subnested\3.txt"); - DeleteFileA("testdir8\nested\nested\subnested\3.txt"); - DeleteFileA("testdir8\nested\nested\2.txt"); DeleteFileA("testdir8\subnested\3.txt"); DeleteFileA("testdir8\nested\2.txt"); DeleteFileA("testdir8\2.txt"); - RemoveDirectoryA("testdir8\nested\nested\subnested"); - RemoveDirectoryA("testdir8\nested\nested"); RemoveDirectoryA("testdir8\nested\subnested"); RemoveDirectoryA("testdir8\subnested"); RemoveDirectoryA("testdir8\nested"); @@ -2037,11 +2031,11 @@ static void test_move(void) ok(!retval, "got %ld\n", retval); ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
- todo_wine ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n"); + ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); + ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n");
ok(dir_exists("testdir4\nested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir4\nested\two.txt"), "file should exist\n"); + ok(file_exists("testdir4\nested\two.txt"), "file should exist\n"); ok(file_exists("testdir4\nested\2.txt"), "file should exist\n");
clean_after_shfo_tests(); @@ -2055,7 +2049,7 @@ static void test_move(void) ok(!retval, "got %ld\n", retval); ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
- todo_wine ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); + ok(!dir_exists("testdir2\nested"), "dir should be moved\n");
ok(dir_exists("testdir4\nested"), "dir should exist\n"); ok(file_exists("testdir4\nested\2.txt"), "file should exist\n"); @@ -2070,19 +2064,19 @@ static void test_move(void) ok(!retval, "got %ld\n", retval); ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
- todo_wine ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n"); + ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); + ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n");
- todo_wine ok(!dir_exists("testdir4\nested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir4\nested\2.txt"), "file should be moved\n"); - todo_wine ok(!dir_exists("testdir4\nested\subnested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir4\nested\subnested\3.txt"), "file should be moved\n"); + ok(!dir_exists("testdir4\nested"), "dir should be moved\n"); + ok(!file_exists("testdir4\nested\2.txt"), "file should be moved\n"); + ok(!dir_exists("testdir4\nested\subnested"), "dir should be moved\n"); + ok(!file_exists("testdir4\nested\subnested\3.txt"), "file should be moved\n");
ok(dir_exists("testdir6\nested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir6\nested\two.txt"), "file should exist\n"); - todo_wine ok(file_exists("testdir6\nested\2.txt"), "file should exist\n"); - todo_wine ok(dir_exists("testdir6\nested\subnested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir6\nested\subnested\3.txt"), "file should exist\n"); + ok(file_exists("testdir6\nested\two.txt"), "file should exist\n"); + ok(file_exists("testdir6\nested\2.txt"), "file should exist\n"); + ok(dir_exists("testdir6\nested\subnested"), "dir should exist\n"); + ok(file_exists("testdir6\nested\subnested\3.txt"), "file should exist\n");
clean_after_shfo_tests(); init_shfo_tests(); @@ -2097,12 +2091,12 @@ static void test_move(void) ok(!retval, "got %ld\n", retval); ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
- todo_wine ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n"); + ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); + ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n");
ok(!file_exists("testdir6\nested\two.txt"), "file should not exist\n"); ok(dir_exists("testdir6\nested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir6\two.txt"), "file should exist\n"); + ok(file_exists("testdir6\two.txt"), "file should exist\n");
clean_after_shfo_tests(); init_shfo_tests(); @@ -2114,25 +2108,25 @@ static void test_move(void) ok(!retval, "got %ld\n", retval); ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
- todo_wine ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n"); + ok(!dir_exists("testdir2\nested"), "dir should be moved\n"); + ok(!file_exists("testdir2\nested\two.txt"), "file should be moved\n");
- todo_wine ok(!dir_exists("testdir4\nested"), "dir should be moved\n"); - todo_wine ok(!file_exists("testdir4\nested\2.txt"), "file should be moved\n"); + ok(!dir_exists("testdir4\nested"), "dir should be moved\n"); + ok(!file_exists("testdir4\nested\2.txt"), "file should be moved\n");
ok(!file_exists("testdir6\nested\two.txt"), "file should not exist\n"); ok(!file_exists("testdir6\nested\2.txt"), "file should not exist\n"); ok(dir_exists("testdir6\nested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir6\two.txt"), "file should exist\n"); + ok(file_exists("testdir6\two.txt"), "file should exist\n");
ok(!dir_exists("testdir8\nested\subnested"), "dir should not exist\n"); ok(!file_exists("testdir8\nested\subnested\3.txt"), "file should not exist\n"); ok(!file_exists("testdir8\nested\two.txt"), "file should not exist\n"); ok(!file_exists("testdir8\nested\2.txt"), "file should not exist\n"); ok(dir_exists("testdir8\nested"), "dir should exist\n"); - todo_wine ok(dir_exists("testdir8\subnested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir8\subnested\3.txt"), "file should exist\n"); - todo_wine ok(file_exists("testdir8\2.txt"), "file should exist\n"); + ok(dir_exists("testdir8\subnested"), "dir should exist\n"); + ok(file_exists("testdir8\subnested\3.txt"), "file should exist\n"); + ok(file_exists("testdir8\2.txt"), "file should exist\n");
clean_after_shfo_tests(); init_shfo_tests(); @@ -2151,7 +2145,7 @@ static void test_move(void) ok(!file_exists("testdir4\nested\2.txt"), "file should be moved\n");
ok(dir_exists("testdir6\nested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir6\nested\two.txt"), "file should exist\n"); + ok(file_exists("testdir6\nested\two.txt"), "file should exist\n"); ok(!file_exists("testdir6\nested\2.txt"), "file should not exist\n"); ok(!file_exists("testdir6\two.txt"), "file should not exist\n");
@@ -2159,9 +2153,9 @@ static void test_move(void) ok(!file_exists("testdir8\2.txt"), "file should not exist\n"); ok(!file_exists("testdir8\nested\two.txt"), "file should not exist\n"); ok(dir_exists("testdir8\nested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir8\nested\2.txt"), "file should exist\n"); - todo_wine ok(dir_exists("testdir8\nested\subnested"), "dir should exist\n"); - todo_wine ok(file_exists("testdir8\nested\subnested\3.txt"), "file should exist\n"); + ok(file_exists("testdir8\nested\2.txt"), "file should exist\n"); + ok(dir_exists("testdir8\nested\subnested"), "dir should exist\n"); + ok(file_exists("testdir8\nested\subnested\3.txt"), "file should exist\n");
clean_after_shfo_tests(); init_shfo_tests();