From: Ziqing Hui zhui@codeweavers.com
--- dlls/shell32/shlfileop.c | 52 +++++++++++++++++++++------------- dlls/shell32/tests/shlfileop.c | 37 +++++++++++------------- 2 files changed, 49 insertions(+), 40 deletions(-)
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c index 6e155d2cf65..c5acfd27708 100644 --- a/dlls/shell32/shlfileop.c +++ b/dlls/shell32/shlfileop.c @@ -54,8 +54,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define FO_MASK 0xF
-#define DE_SAMEFILE 0x71 -#define DE_DESTSAMETREE 0x7D +#define DE_SAMEFILE 0x71 +#define DE_MANYSRC1DEST 0x72 +#define DE_DIFFDIR 0x73 +#define DE_ROOTDIR 0x74 +#define DE_OPCANCELLED 0x75 +#define DE_DESTSUBTREE 0x76 +#define DE_ACCESSDENIEDSRC 0x78 +#define DE_PATHTOODEEP 0x79 +#define DE_MANYDEST 0x7A +#define DE_INVALIDFILES 0x7C +#define DE_DESTSAMETREE 0x7D +#define DE_FLDDESTISFILE 0x7E +#define DE_FILEDESTISFLD 0x80
static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec); static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec); @@ -1515,30 +1526,31 @@ static int move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const return ERROR_SUCCESS; }
-/* the FO_RENAME files */ -static int rename_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const FILE_LIST *flTo) +/* The FO_RENAME operation of SHFileOperation. */ +static DWORD rename_files(SHFILEOPSTRUCTW *op, const FILE_LIST *from, const FILE_LIST *to) { - const FILE_ENTRY *feFrom; - const FILE_ENTRY *feTo; + const FILE_ENTRY *entry_from, *entry_to;
- if (flFrom->dwNumFiles != 1) - return ERROR_GEN_FAILURE; + if (from->dwNumFiles != 1) + return DE_MANYSRC1DEST;
- if (flTo->dwNumFiles != 1) - return ERROR_CANCELLED; - - feFrom = &flFrom->feFiles[0]; - feTo= &flTo->feFiles[0]; + entry_from = &from->feFiles[0]; + if (entry_from->bFromWildcard) + return DE_MANYSRC1DEST; + if (!entry_from->bExists) + return ERROR_FILE_NOT_FOUND;
- /* fail if destination doesn't exist */ - if (!feFrom->bExists || feFrom->bFromWildcard) - return ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; + entry_to = &to->feFiles[0]; + if (to->bAnyFromWildcard) + return ERROR_INVALID_NAME; + if (!to->dwNumFiles || wcscmp(entry_from->szDirectory, entry_to->szDirectory) != 0) + return DE_DIFFDIR;
- /* fail if destination already exists */ - if (feTo->bExists) - return ERROR_ALREADY_EXISTS; + /* Fail if target already exists. */ + if (entry_to->bExists) + return IsAttribDir(entry_to->attributes) ? DE_FILEDESTISFLD : DE_FLDDESTISFILE;
- return SHNotifyMoveFileW(feFrom->szFullPath, feTo->szFullPath); + return SHNotifyMoveFileW(entry_from->szFullPath, entry_to->szFullPath); }
/* alert the user if an unsupported flag is used */ diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c index f466d63ad05..3dfe2b32d41 100644 --- a/dlls/shell32/tests/shlfileop.c +++ b/dlls/shell32/tests/shlfileop.c @@ -739,43 +739,42 @@ static void test_rename(void) set_curr_dir_path(from, "test1.txt\0"); set_curr_dir_path(to, "test4.txt\0"); check_file_operation(FO_RENAME, FOF_NO_UI, from, to, - DE_FILEDESTISFLD, FALSE, TRUE, FALSE); + DE_FILEDESTISFLD, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "The file is renamed\n");
/* Rename a dir to an existing file. */ set_curr_dir_path(from, "test4.txt\0"); set_curr_dir_path(to, "test1.txt\0"); check_file_operation(FO_RENAME, FOF_NO_UI, from, to, - DE_FLDDESTISFILE, FALSE, TRUE, FALSE); + DE_FLDDESTISFILE, FALSE, FALSE, FALSE); ok(dir_exists("test4.txt"), "The file is renamed\n");
/* Rename file to a different directory. */ set_curr_dir_path(from, "test3.txt\0"); set_curr_dir_path(to, "test4.txt\test1.txt\0"); check_file_operation(FO_RENAME, FOF_NO_UI, from, to, - DE_DIFFDIR, FALSE, TRUE, FALSE); - todo_wine + DE_DIFFDIR, FALSE, FALSE, FALSE); ok(!file_exists("test4.txt\test1.txt"), "The file is renamed\n");
/* Multiple sources and targets, no FOF_MULTIDESTFILES. */ set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0"); set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0"); check_file_operation(FO_RENAME, FOF_NO_UI, from, to, - DE_MANYSRC1DEST, FALSE, TRUE, FALSE); + DE_MANYSRC1DEST, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
/* Multiple sources and targets, with FOF_MULTIDESTFILES. */ set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0"); set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0"); check_file_operation(FO_RENAME, FOF_NO_UI | FOF_MULTIDESTFILES, from, to, - DE_MANYSRC1DEST, FALSE, TRUE, FALSE); + DE_MANYSRC1DEST, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
/* Sources outnumber targets, with FOF_MULTIDESTFILES. */ set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0"); set_curr_dir_path(to, "test6.txt\0test7.txt\0"); check_file_operation(FO_RENAME, FOF_NO_UI | FOF_MULTIDESTFILES, from, to, - DE_MANYSRC1DEST, FALSE, TRUE, FALSE); + DE_MANYSRC1DEST, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
/* Rename a file. */ @@ -808,7 +807,7 @@ static void test_rename(void) /* Rename multiple files to a single file. */ check_file_operation(FO_RENAME, FOF_NO_UI, "test1.txt\0test2.txt\0", "a.txt\0", - DE_MANYSRC1DEST, FALSE, TRUE, FALSE); + DE_MANYSRC1DEST, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); ok(file_exists("test2.txt"), "Expected test2.txt to exist\n"); ok(!file_exists("a.txt"), "Expected a.txt to not exist\n"); @@ -816,17 +815,15 @@ static void test_rename(void) /* Rename a file to multiple files. */ check_file_operation(FO_RENAME, FOF_NO_UI, "test1.txt\0", "a.txt\0b.txt\0", - ERROR_SUCCESS, FALSE, TRUE, TRUE); - todo_wine + ERROR_SUCCESS, FALSE, FALSE, FALSE); ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n"); - todo_wine ok(DeleteFileA("a.txt"), "Expected a.txt to exist\n"); ok(!DeleteFileA("b.txt"), "Expected b.txt to not exist\n");
/* Rename a nonexistent file. */ check_file_operation(FO_RENAME, FOF_NO_UI, "idontexist\0", "newfile\0", - ERROR_FILE_NOT_FOUND, FALSE, TRUE, FALSE); + ERROR_FILE_NOT_FOUND, FALSE, FALSE, FALSE); ok(!file_exists("newfile"), "Expected newfile to not exist\n");
/* Target already exists. */ @@ -850,15 +847,15 @@ static void test_rename(void) ok(!file_exists("nonexistence"), "Expected nonexistence to not exist\n"); check_file_operation(FO_RENAME, FOF_NO_UI, "testdir2\0", "\0", - DE_DIFFDIR, FALSE, TRUE, TRUE); + DE_DIFFDIR, FALSE, FALSE, FALSE); ok(file_exists("testdir2"), "Expected testdir2 to exist\n"); check_file_operation(FO_RENAME, FOF_NO_UI, "test1.txt\0", "\0", - DE_DIFFDIR, FALSE, TRUE, TRUE); + DE_DIFFDIR, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); check_file_operation(FO_RENAME, FOF_NO_UI, "nonexistence\0", "\0", - ERROR_FILE_NOT_FOUND, FALSE, TRUE, TRUE); + ERROR_FILE_NOT_FOUND, FALSE, FALSE, FALSE); check_file_operation(FO_RENAME, FOF_NO_UI, "\0", "\0", DE_MANYSRC1DEST, FALSE, TRUE, TRUE); @@ -877,13 +874,13 @@ static void test_rename(void) ERROR_INVALID_PARAMETER, 0xdeadbeef, FALSE, FALSE); check_file_operation(FO_RENAME, FOF_NO_UI, "test1.txt\0", NULL, - ERROR_ACCESS_DENIED, FALSE, TRUE, TRUE); + ERROR_ACCESS_DENIED, FALSE, TRUE, FALSE); check_file_operation(FO_RENAME, FOF_NO_UI, "testdir2\0", NULL, - ERROR_ACCESS_DENIED, FALSE, TRUE, TRUE); + ERROR_ACCESS_DENIED, FALSE, TRUE, FALSE); check_file_operation(FO_RENAME, FOF_NO_UI, "nonexistence\0", NULL, - ERROR_ACCESS_DENIED, FALSE, TRUE, TRUE); + ERROR_ACCESS_DENIED, FALSE, TRUE, FALSE); check_file_operation(FO_RENAME, FOF_NO_UI, NULL, NULL, ERROR_INVALID_PARAMETER, 0xdeadbeef, FALSE, FALSE); @@ -893,13 +890,13 @@ static void test_rename(void) init_shfo_tests(); check_file_operation(FO_RENAME, FOF_NO_UI, "test?.txt\0", "test_target.txt\0", - DE_MANYSRC1DEST, FALSE, TRUE, FALSE); + DE_MANYSRC1DEST, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "Expected test1.txt to exist.\n"); ok(!DeleteFileA("test_target.txt"), "Expected test_target.txt to not exist.\n");
check_file_operation(FO_RENAME, FOF_NO_UI, "t?st1.txt\0", "test_target.txt\0", - DE_MANYSRC1DEST, FALSE, TRUE, FALSE); + DE_MANYSRC1DEST, FALSE, FALSE, FALSE); ok(file_exists("test1.txt"), "Expected test1.txt to exist.\n"); ok(!DeleteFileA("test_target.txt"), "Expected test_target.txt to not exist.\n");