shell32: Improve the FO_MOVE operation.

This commit is contained in:
Aric Stewart 2014-02-27 20:09:11 +09:00 committed by Alexandre Julliard
parent af0bf54bd0
commit a2c905244b
2 changed files with 136 additions and 11 deletions

View File

@ -53,6 +53,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define FO_MASK 0xF
#define DE_SAMEFILE 0x71
#define DE_DESTSAMETREE 0x7D
static const WCHAR wWildcardFile[] = {'*',0};
static const WCHAR wWildcardChars[] = {'*','?',0};
@ -1428,11 +1431,15 @@ static void move_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom, co
static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const FILE_LIST *flTo)
{
DWORD i;
INT mismatched = 0;
const FILE_ENTRY *entryToMove;
const FILE_ENTRY *fileDest;
if (!flFrom->dwNumFiles || !flTo->dwNumFiles)
return ERROR_CANCELLED;
if (!flFrom->dwNumFiles)
return ERROR_SUCCESS;
if (!flTo->dwNumFiles)
return ERROR_FILE_NOT_FOUND;
if (!(lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
@ -1450,29 +1457,44 @@ static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, con
if (!PathFileExistsW(flTo->feFiles[0].szDirectory))
return ERROR_CANCELLED;
if ((lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
flFrom->dwNumFiles != flTo->dwNumFiles)
{
return ERROR_CANCELLED;
}
if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
mismatched = flFrom->dwNumFiles - flTo->dwNumFiles;
fileDest = &flTo->feFiles[0];
for (i = 0; i < flFrom->dwNumFiles; i++)
{
entryToMove = &flFrom->feFiles[i];
if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
fileDest = &flTo->feFiles[i];
if (!PathFileExistsW(fileDest->szDirectory))
return ERROR_CANCELLED;
if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
{
if (i >= flTo->dwNumFiles)
break;
fileDest = &flTo->feFiles[i];
if (mismatched && !fileDest->bExists)
{
create_dest_dirs(flTo->feFiles[i].szFullPath);
flTo->feFiles[i].bExists = TRUE;
flTo->feFiles[i].attributes = FILE_ATTRIBUTE_DIRECTORY;
}
}
if (fileDest->bExists && IsAttribDir(fileDest->attributes))
move_to_dir(lpFileOp, entryToMove, fileDest);
else
SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath);
}
if (mismatched > 0)
{
if (flFrom->bAnyDirectories)
return DE_DESTSAMETREE;
else
return DE_SAMEFILE;
}
return ERROR_SUCCESS;
}

View File

@ -1871,7 +1871,8 @@ static void test_move(void)
init_shfo_tests();
/* number of sources do not correspond to number of targets */
/* number of sources do not correspond to number of targets,
include directories */
set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
set_curr_dir_path(to, "test6.txt\0test7.txt\0");
retval = SHFileOperationA(&shfo2);
@ -1902,6 +1903,108 @@ static void test_move(void)
"specified as a target\n");
}
init_shfo_tests();
/* number of sources do not correspond to number of targets,
files only,
from exceeds to */
set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
set_curr_dir_path(to, "test6.txt\0test7.txt\0");
retval = SHFileOperationA(&shfo2);
if (dir_exists("test6.txt"))
{
if (retval == ERROR_SUCCESS)
{
/* Old shell32 */
DeleteFileA("test6.txt\\test1.txt");
DeleteFileA("test6.txt\\test2.txt");
RemoveDirectoryA("test6.txt\\test4.txt");
RemoveDirectoryA("test6.txt");
}
else
{
/* Vista and W2K8 (broken or new behavior ?) */
ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not moved\n");
RemoveDirectoryA("test6.txt");
ok(DeleteFileA("test7.txt\\test2.txt"), "The file is not moved\n");
RemoveDirectoryA("test7.txt");
ok(file_exists("test3.txt"), "File should not be moved\n");
}
}
else
{
expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
ok(!file_exists("test6.txt"), "The file is not moved - many files are "
"specified as a target\n");
}
init_shfo_tests();
/* number of sources do not correspond to number of targets,
files only,
too exceeds from */
set_curr_dir_path(from, "test1.txt\0test2.txt\0");
set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
retval = SHFileOperationA(&shfo2);
if (dir_exists("test6.txt"))
{
ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
ok(DeleteFileA("test6.txt\\test1.txt"),"The file is not moved\n");
ok(DeleteFileA("test7.txt\\test2.txt"),"The file is not moved\n");
ok(!dir_exists("test8.txt") && !file_exists("test8.txt"),
"Directory should not be created\n");
RemoveDirectoryA("test6.txt");
RemoveDirectoryA("test7.txt");
}
else
{
expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* WinXp, Win2k */);
ok(!file_exists("test6.txt"), "The file is not moved - many files are "
"specified as a target\n");
}
init_shfo_tests();
/* number of sources do not correspond to number of targets,
target directories */
set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
set_curr_dir_path(to, "test4.txt\0test5.txt\0");
retval = SHFileOperationA(&shfo2);
if (dir_exists("test5.txt"))
{
ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
ok(DeleteFileA("test4.txt\\test1.txt"),"The file is not moved\n");
ok(DeleteFileA("test5.txt\\test2.txt"),"The file is not moved\n");
ok(file_exists("test3.txt"), "The file is not moved\n");
RemoveDirectoryA("test4.txt");
RemoveDirectoryA("test5.txt");
}
else
{
ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
ok(DeleteFileA("test4.txt\\test1.txt"),"The file is not moved\n");
ok(DeleteFileA("test4.txt\\test2.txt"),"The file is not moved\n");
ok(DeleteFileA("test4.txt\\test3.txt"),"The file is not moved\n");
}
init_shfo_tests();
/* 0 incomming files */
set_curr_dir_path(from, "\0\0");
set_curr_dir_path(to, "test6.txt\0\0");
retval = SHFileOperationA(&shfo2);
ok(retval == ERROR_SUCCESS || retval == ERROR_ACCESS_DENIED
, "Expected ERROR_SUCCESS || ERROR_ACCESS_DENIED, got %d\n", retval);
ok(!file_exists("test6.txt"), "The file should not exist\n");
init_shfo_tests();
/* 0 outgoing files */
set_curr_dir_path(from, "test1\0\0");
set_curr_dir_path(to, "\0\0");
retval = SHFileOperationA(&shfo2);
ok(retval == ERROR_FILE_NOT_FOUND ||
broken(retval == 1026)
, "Expected ERROR_FILE_NOT_FOUND, got %d\n", retval);
ok(!file_exists("test6.txt"), "The file should not exist\n");
init_shfo_tests();
set_curr_dir_path(from, "test3.txt\0");