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 FO_MASK 0xF
|
||||||
|
|
||||||
|
#define DE_SAMEFILE 0x71
|
||||||
|
#define DE_DESTSAMETREE 0x7D
|
||||||
|
|
||||||
static const WCHAR wWildcardFile[] = {'*',0};
|
static const WCHAR wWildcardFile[] = {'*',0};
|
||||||
static const WCHAR wWildcardChars[] = {'*','?',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)
|
static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const FILE_LIST *flTo)
|
||||||
{
|
{
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
INT mismatched = 0;
|
||||||
const FILE_ENTRY *entryToMove;
|
const FILE_ENTRY *entryToMove;
|
||||||
const FILE_ENTRY *fileDest;
|
const FILE_ENTRY *fileDest;
|
||||||
|
|
||||||
if (!flFrom->dwNumFiles || !flTo->dwNumFiles)
|
if (!flFrom->dwNumFiles)
|
||||||
return ERROR_CANCELLED;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (!flTo->dwNumFiles)
|
||||||
|
return ERROR_FILE_NOT_FOUND;
|
||||||
|
|
||||||
if (!(lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
|
if (!(lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
|
||||||
flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
|
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))
|
if (!PathFileExistsW(flTo->feFiles[0].szDirectory))
|
||||||
return ERROR_CANCELLED;
|
return ERROR_CANCELLED;
|
||||||
|
|
||||||
if ((lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
|
if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
|
||||||
flFrom->dwNumFiles != flTo->dwNumFiles)
|
mismatched = flFrom->dwNumFiles - flTo->dwNumFiles;
|
||||||
{
|
|
||||||
return ERROR_CANCELLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
fileDest = &flTo->feFiles[0];
|
fileDest = &flTo->feFiles[0];
|
||||||
for (i = 0; i < flFrom->dwNumFiles; i++)
|
for (i = 0; i < flFrom->dwNumFiles; i++)
|
||||||
{
|
{
|
||||||
entryToMove = &flFrom->feFiles[i];
|
entryToMove = &flFrom->feFiles[i];
|
||||||
|
|
||||||
if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
|
|
||||||
fileDest = &flTo->feFiles[i];
|
|
||||||
|
|
||||||
if (!PathFileExistsW(fileDest->szDirectory))
|
if (!PathFileExistsW(fileDest->szDirectory))
|
||||||
return ERROR_CANCELLED;
|
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))
|
if (fileDest->bExists && IsAttribDir(fileDest->attributes))
|
||||||
move_to_dir(lpFileOp, entryToMove, fileDest);
|
move_to_dir(lpFileOp, entryToMove, fileDest);
|
||||||
else
|
else
|
||||||
SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath);
|
SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mismatched > 0)
|
||||||
|
{
|
||||||
|
if (flFrom->bAnyDirectories)
|
||||||
|
return DE_DESTSAMETREE;
|
||||||
|
else
|
||||||
|
return DE_SAMEFILE;
|
||||||
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1871,7 +1871,8 @@ static void test_move(void)
|
||||||
|
|
||||||
init_shfo_tests();
|
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(from, "test1.txt\0test2.txt\0test4.txt\0");
|
||||||
set_curr_dir_path(to, "test6.txt\0test7.txt\0");
|
set_curr_dir_path(to, "test6.txt\0test7.txt\0");
|
||||||
retval = SHFileOperationA(&shfo2);
|
retval = SHFileOperationA(&shfo2);
|
||||||
|
@ -1902,6 +1903,108 @@ static void test_move(void)
|
||||||
"specified as a target\n");
|
"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();
|
init_shfo_tests();
|
||||||
|
|
||||||
set_curr_dir_path(from, "test3.txt\0");
|
set_curr_dir_path(from, "test3.txt\0");
|
||||||
|
|
Loading…
Reference in New Issue