shell32: Improve the FO_MOVE operation.
This commit is contained in:
parent
af0bf54bd0
commit
a2c905244b
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue