2 * Unit test of the SHFileOperation function.
4 * Copyright 2002 Andriy Palamarchuk
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WINE_NOWINSOCK
29 #include "wine/test.h"
31 #ifndef FOF_NORECURSION
32 #define FOF_NORECURSION 0x1000
35 CHAR CURR_DIR[MAX_PATH];
37 static HMODULE hshell32;
38 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
40 static void InitFunctionPointers(void)
42 hshell32 = GetModuleHandleA("shell32.dll");
45 pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
48 /* creates a file with the specified name for tests */
49 static void createTestFile(const CHAR *name)
54 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
55 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
56 WriteFile(file, name, strlen(name), &written, NULL);
57 WriteFile(file, "\n", strlen("\n"), &written, NULL);
61 static BOOL file_exists(const CHAR *name)
63 return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
66 /* initializes the tests */
67 static void init_shfo_tests(void)
71 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
72 len = lstrlenA(CURR_DIR);
74 if(len && (CURR_DIR[len-1] == '\\'))
77 createTestFile("test1.txt");
78 createTestFile("test2.txt");
79 createTestFile("test3.txt");
80 createTestFile("test_5.txt");
81 CreateDirectoryA("test4.txt", NULL);
82 CreateDirectoryA("testdir2", NULL);
83 CreateDirectoryA("testdir2\\nested", NULL);
84 createTestFile("testdir2\\one.txt");
85 createTestFile("testdir2\\nested\\two.txt");
88 /* cleans after tests */
89 static void clean_after_shfo_tests(void)
91 DeleteFileA("test1.txt");
92 DeleteFileA("test2.txt");
93 DeleteFileA("test3.txt");
94 DeleteFileA("test_5.txt");
95 DeleteFileA("test4.txt\\test1.txt");
96 DeleteFileA("test4.txt\\test2.txt");
97 DeleteFileA("test4.txt\\test3.txt");
98 RemoveDirectoryA("test4.txt");
99 DeleteFileA("testdir2\\one.txt");
100 DeleteFileA("testdir2\\test1.txt");
101 DeleteFileA("testdir2\\test2.txt");
102 DeleteFileA("testdir2\\test3.txt");
103 DeleteFileA("testdir2\\test4.txt\\test1.txt");
104 DeleteFileA("testdir2\\nested\\two.txt");
105 RemoveDirectoryA("testdir2\\test4.txt");
106 RemoveDirectoryA("testdir2\\nested");
107 RemoveDirectoryA("testdir2");
108 RemoveDirectoryA("c:\\testdir3");
109 DeleteFileA("nonexistent\\notreal\\test2.txt");
110 RemoveDirectoryA("nonexistent\\notreal");
111 RemoveDirectoryA("nonexistent");
115 puts into the specified buffer file names with current directory.
116 files - string with file names, separated by null characters. Ends on a double
119 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
124 strcpy(buf, CURR_DIR);
129 buf += strlen(buf) + 1;
130 files += strlen(files) + 1;
136 /* tests the FO_DELETE action */
137 static void test_delete(void)
139 SHFILEOPSTRUCTA shfo;
143 sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
144 buf[strlen(buf) + 1] = '\0';
147 shfo.wFunc = FO_DELETE;
150 shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
151 shfo.hNameMappings = NULL;
152 shfo.lpszProgressTitle = NULL;
154 ok(!SHFileOperationA(&shfo), "Deletion was successful\n");
155 ok(file_exists("test4.txt"), "Directory should not be removed\n");
156 ok(!file_exists("test1.txt"), "File should be removed\n");
158 ret = SHFileOperationA(&shfo);
159 ok(!ret, "Directory exists, but is not removed, ret=%ld\n", ret);
160 ok(file_exists("test4.txt"), "Directory should not be removed\n");
162 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
164 ok(!SHFileOperationA(&shfo), "Directory removed\n");
165 ok(!file_exists("test4.txt"), "Directory should be removed\n");
167 ret = SHFileOperationA(&shfo);
168 ok(!ret, "The requested file does not exist, ret=%ld\n", ret);
171 sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
172 buf[strlen(buf) + 1] = '\0';
173 ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Fill the subdirectory\n");
174 ok(!SHFileOperationA(&shfo), "Directory removed\n");
175 ok(!file_exists("test4.txt"), "Directory is removed\n");
178 shfo.pFrom = "test1.txt\0test4.txt\0";
179 ok(!SHFileOperationA(&shfo), "Directory and a file removed\n");
180 ok(!file_exists("test1.txt"), "The file should be removed\n");
181 ok(!file_exists("test4.txt"), "Directory should be removed\n");
182 ok(file_exists("test2.txt"), "This file should not be removed\n");
184 /* FOF_FILESONLY does not delete a dir matching a wildcard */
186 shfo.fFlags |= FOF_FILESONLY;
187 shfo.pFrom = "*.txt\0";
188 ok(!SHFileOperation(&shfo), "Failed to delete files\n");
189 ok(!file_exists("test1.txt"), "test1.txt should be removed\n");
190 ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
191 ok(file_exists("test4.txt"), "test4.txt should not be removed\n");
193 /* FOF_FILESONLY only deletes a dir if explicitly specified */
195 shfo.pFrom = "test_?.txt\0test4.txt\0";
196 ok(!SHFileOperation(&shfo), "Failed to delete files\n");
197 ok(!file_exists("test4.txt"), "test4.txt should be removed\n");
198 ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
199 ok(file_exists("test1.txt"), "test1.txt should not be removed\n");
201 /* try to delete an invalid filename */
204 shfo.fFlags &= ~FOF_FILESONLY;
205 shfo.fAnyOperationsAborted = FALSE;
206 ret = SHFileOperation(&shfo);
207 ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", ret);
208 ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
209 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
211 /* try an invalid function */
213 shfo.pFrom = "test1.txt\0";
215 ret = SHFileOperation(&shfo);
216 ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
217 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
219 /* try an invalid list, only one null terminator */
222 shfo.wFunc = FO_DELETE;
223 ret = SHFileOperation(&shfo);
224 ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", ret);
225 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
227 /* delete a dir, and then a file inside the dir, same as
228 * deleting a nonexistent file
231 shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
232 ret = SHFileOperation(&shfo);
233 ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %ld\n", ret);
234 ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n");
235 ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
237 /* try the FOF_NORECURSION flag, continues deleting subdirs */
239 shfo.pFrom = "testdir2\0";
240 shfo.fFlags |= FOF_NORECURSION;
241 ret = SHFileOperation(&shfo);
242 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
243 ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
244 ok(!file_exists("testdir2\\nested"), "Expected testdir2\\nested to exist\n");
247 /* tests the FO_RENAME action */
248 static void test_rename(void)
250 SHFILEOPSTRUCTA shfo, shfo2;
256 shfo.wFunc = FO_RENAME;
259 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
260 shfo.hNameMappings = NULL;
261 shfo.lpszProgressTitle = NULL;
263 set_curr_dir_path(from, "test1.txt\0");
264 set_curr_dir_path(to, "test4.txt\0");
265 ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
266 "when specifying directory name only\n");
267 ok(file_exists("test1.txt"), "The file is removed\n");
269 set_curr_dir_path(from, "test3.txt\0");
270 set_curr_dir_path(to, "test4.txt\\test1.txt\0");
271 ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
272 ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
274 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
275 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
276 retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
277 ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
278 "Can't rename many files, retval = %ld\n", retval);
279 ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
281 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
282 shfo2.fFlags |= FOF_MULTIDESTFILES;
284 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
285 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
286 retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
287 ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
288 "Can't rename many files, retval = %ld\n", retval);
289 ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
291 set_curr_dir_path(from, "test1.txt\0");
292 set_curr_dir_path(to, "test6.txt\0");
293 retval = SHFileOperationA(&shfo);
294 ok(!retval, "Rename file failed, retval = %ld\n", retval);
295 ok(!file_exists("test1.txt"), "The file is not renamed\n");
296 ok(file_exists("test6.txt"), "The file is not renamed\n");
298 set_curr_dir_path(from, "test6.txt\0");
299 set_curr_dir_path(to, "test1.txt\0");
300 retval = SHFileOperationA(&shfo);
301 ok(!retval, "Rename file back failed, retval = %ld\n", retval);
303 set_curr_dir_path(from, "test4.txt\0");
304 set_curr_dir_path(to, "test6.txt\0");
305 retval = SHFileOperationA(&shfo);
306 ok(!retval, "Rename dir failed, retval = %ld\n", retval);
307 ok(!file_exists("test4.txt"), "The dir is not renamed\n");
308 ok(file_exists("test6.txt"), "The dir is not renamed\n");
310 set_curr_dir_path(from, "test6.txt\0");
311 set_curr_dir_path(to, "test4.txt\0");
312 retval = SHFileOperationA(&shfo);
313 ok(!retval, "Rename dir back failed, retval = %ld\n", retval);
315 /* try to rename more than one file to a single file */
316 shfo.pFrom = "test1.txt\0test2.txt\0";
317 shfo.pTo = "a.txt\0";
318 retval = SHFileOperationA(&shfo);
319 ok(retval == ERROR_GEN_FAILURE, "Expected ERROR_GEN_FAILURE, got %ld\n", retval);
320 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
321 ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
323 /* pFrom doesn't exist */
324 shfo.pFrom = "idontexist\0";
325 shfo.pTo = "newfile\0";
326 retval = SHFileOperationA(&shfo);
327 ok(retval == 1026, "Expected 1026, got %ld\n", retval);
328 ok(!file_exists("newfile"), "Expected newfile to not exist\n");
330 /* pTo already exist */
331 shfo.pFrom = "test1.txt\0";
332 shfo.pTo = "test2.txt\0";
333 retval = SHFileOperationA(&shfo);
334 ok(retval == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %ld\n", retval);
336 /* pFrom is valid, but pTo is empty */
337 shfo.pFrom = "test1.txt\0";
339 retval = SHFileOperationA(&shfo);
340 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
341 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
345 retval = SHFileOperationA(&shfo);
346 ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", retval);
348 /* pFrom is NULL, commented out because it crashes on nt 4.0 */
351 retval = SHFileOperationA(&shfo);
352 ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", retval);
356 /* tests the FO_COPY action */
357 static void test_copy(void)
359 SHFILEOPSTRUCTA shfo, shfo2;
362 FILEOP_FLAGS tmp_flags;
366 shfo.wFunc = FO_COPY;
369 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
370 shfo.hNameMappings = NULL;
371 shfo.lpszProgressTitle = NULL;
373 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
374 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
375 ok(SHFileOperationA(&shfo), "Can't copy many files\n");
376 ok(!file_exists("test6.txt"), "The file is not copied - many files are "
377 "specified as a target\n");
379 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
380 shfo2.fFlags |= FOF_MULTIDESTFILES;
382 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
383 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
384 ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
385 ok(file_exists("test6.txt"), "The file is copied - many files are "
386 "specified as a target\n");
387 DeleteFileA("test6.txt");
388 DeleteFileA("test7.txt");
389 RemoveDirectoryA("test8.txt");
391 /* number of sources do not correspond to number of targets */
392 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
393 set_curr_dir_path(to, "test6.txt\0test7.txt\0");
394 ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
395 ok(!file_exists("test6.txt"), "The file is not copied - many files are "
396 "specified as a target\n");
398 set_curr_dir_path(from, "test1.txt\0");
399 set_curr_dir_path(to, "test4.txt\0");
400 ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
401 ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
403 set_curr_dir_path(from, "test?.txt\0");
404 set_curr_dir_path(to, "testdir2\0");
405 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
406 ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
407 ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
408 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
409 ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
410 ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
411 clean_after_shfo_tests();
414 shfo.fFlags |= FOF_FILESONLY;
415 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
416 ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
417 ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
418 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
419 ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
420 clean_after_shfo_tests();
423 set_curr_dir_path(from, "test1.txt\0test2.txt\0");
424 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
425 ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
426 ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
427 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
428 ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
429 clean_after_shfo_tests();
431 /* Copying multiple files with one not existing as source, fails the
432 entire operation in Win98/ME/2K/XP, but not in 95/NT */
434 tmp_flags = shfo.fFlags;
435 set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
436 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
437 ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
438 retval = SHFileOperationA(&shfo);
440 /* Win 95/NT returns success but copies only the files up to the nonexistent source */
441 ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
444 /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
445 ok(retval == 1026, "Files are copied to other directory\n");
446 ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
448 ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
449 shfo.fFlags = tmp_flags;
451 /* copy into a nonexistent directory */
453 shfo.fFlags = FOF_NOCONFIRMMKDIR;
454 set_curr_dir_path(from, "test1.txt\0");
455 set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
456 retval= SHFileOperation(&shfo);
457 ok(!retval, "Error copying into nonexistent directory\n");
458 ok(file_exists("nonexistent"), "nonexistent not created\n");
459 ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
460 ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
461 ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
463 /* a relative dest directory is OK */
464 clean_after_shfo_tests();
466 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
467 shfo.pTo = "testdir2\0";
468 retval = SHFileOperation(&shfo);
469 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
470 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
472 /* try to copy files to a file */
473 clean_after_shfo_tests();
477 set_curr_dir_path(from, "test1.txt\0test2.txt\0");
478 set_curr_dir_path(to, "test3.txt\0");
479 retval = SHFileOperation(&shfo);
480 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
481 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
482 ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
484 /* try to copy many files to nonexistent directory */
486 shfo.fAnyOperationsAborted = FALSE;
487 retval = SHFileOperation(&shfo);
488 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
489 ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
490 ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
491 ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
493 /* send in FOF_MULTIDESTFILES with too many destination files */
495 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
496 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
497 shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
498 retval = SHFileOperation(&shfo);
499 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
500 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
501 ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
503 /* send in FOF_MULTIDESTFILES with too many destination files */
504 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
505 shfo.pTo = "e.txt\0f.txt\0";
506 shfo.fAnyOperationsAborted = FALSE;
507 retval = SHFileOperation(&shfo);
508 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
509 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
510 ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
512 /* use FOF_MULTIDESTFILES with files and a source directory */
513 shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
514 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
515 shfo.fAnyOperationsAborted = FALSE;
516 retval = SHFileOperation(&shfo);
517 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
518 ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
519 ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
520 ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
522 /* try many dest files without FOF_MULTIDESTFILES flag */
523 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
524 shfo.pTo = "a.txt\0b.txt\0c.txt\0";
525 shfo.fAnyOperationsAborted = FALSE;
526 shfo.fFlags &= ~FOF_MULTIDESTFILES;
527 retval = SHFileOperation(&shfo);
528 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
529 ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
532 shfo.pFrom = "test?.txt\0";
533 shfo.pTo = "testdir2\0";
534 shfo.fFlags &= ~FOF_MULTIDESTFILES;
535 retval = SHFileOperation(&shfo);
536 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
537 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
539 /* try a glob with FOF_FILESONLY */
540 clean_after_shfo_tests();
542 shfo.pFrom = "test?.txt\0";
543 shfo.fFlags |= FOF_FILESONLY;
544 retval = SHFileOperation(&shfo);
545 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
546 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
547 ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
549 /* try a glob with FOF_MULTIDESTFILES and the same number
550 * of dest files that we would expect
552 clean_after_shfo_tests();
554 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
555 shfo.fFlags &= ~FOF_FILESONLY;
556 shfo.fFlags |= FOF_MULTIDESTFILES;
557 retval = SHFileOperation(&shfo);
558 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
559 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
560 ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
561 ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
563 /* copy one file to two others, second is ignored */
564 clean_after_shfo_tests();
566 shfo.pFrom = "test1.txt\0";
567 shfo.pTo = "b.txt\0c.txt\0";
568 shfo.fAnyOperationsAborted = FALSE;
569 retval = SHFileOperation(&shfo);
570 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
571 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
572 ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
574 /* copy two file to three others, all fail */
575 shfo.pFrom = "test1.txt\0test2.txt\0";
576 shfo.pTo = "b.txt\0c.txt\0d.txt\0";
577 retval = SHFileOperation(&shfo);
578 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
579 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
580 ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
582 /* copy one file and one directory to three others */
583 shfo.pFrom = "test1.txt\0test4.txt\0";
584 shfo.pTo = "b.txt\0c.txt\0d.txt\0";
585 shfo.fAnyOperationsAborted = FALSE;
586 retval = SHFileOperation(&shfo);
587 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
588 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
589 ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
590 ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
592 /* copy a directory with a file beneath it, plus some files */
593 createTestFile("test4.txt\\a.txt");
594 shfo.pFrom = "test4.txt\0test1.txt\0";
595 shfo.pTo = "testdir2\0";
596 shfo.fFlags &= ~FOF_MULTIDESTFILES;
597 shfo.fAnyOperationsAborted = FALSE;
598 retval = SHFileOperation(&shfo);
599 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
600 ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
601 ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
602 ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
604 /* copy one directory and a file in that dir to another dir */
605 shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
606 shfo.pTo = "testdir2\0";
607 retval = SHFileOperation(&shfo);
608 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
609 ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
610 ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
612 /* copy a file in a directory first, and then the directory to a nonexistent dir */
613 shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
614 shfo.pTo = "nonexistent\0";
615 retval = SHFileOperation(&shfo);
616 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
617 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
618 ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
619 DeleteFile("test4.txt\\a.txt");
621 /* destination is same as source file */
622 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
623 shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
624 shfo.fAnyOperationsAborted = FALSE;
625 shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
626 retval = SHFileOperation(&shfo);
627 ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
628 "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %ld\n", retval);
629 ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
630 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
631 ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
633 /* destination is same as source directory */
634 shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
635 shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
636 shfo.fAnyOperationsAborted = FALSE;
637 retval = SHFileOperation(&shfo);
638 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
639 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
640 ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
642 /* copy a directory into itself, error displayed in UI */
643 shfo.pFrom = "test4.txt\0";
644 shfo.pTo = "test4.txt\\newdir\0";
645 shfo.fFlags &= ~FOF_MULTIDESTFILES;
646 shfo.fAnyOperationsAborted = FALSE;
647 retval = SHFileOperation(&shfo);
648 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
649 ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
651 /* copy a directory to itself, error displayed in UI */
652 shfo.pFrom = "test4.txt\0";
653 shfo.pTo = "test4.txt\0";
654 shfo.fAnyOperationsAborted = FALSE;
655 retval = SHFileOperation(&shfo);
656 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
658 /* copy a file into a directory, and the directory into itself */
659 shfo.pFrom = "test1.txt\0test4.txt\0";
660 shfo.pTo = "test4.txt\0";
661 shfo.fAnyOperationsAborted = FALSE;
662 shfo.fFlags |= FOF_NOCONFIRMATION;
663 retval = SHFileOperation(&shfo);
664 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
665 ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
667 /* copy a file to a file, and the directory into itself */
668 shfo.pFrom = "test1.txt\0test4.txt\0";
669 shfo.pTo = "test4.txt\\a.txt\0";
670 shfo.fAnyOperationsAborted = FALSE;
671 retval = SHFileOperation(&shfo);
672 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
673 ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
675 /* copy a nonexistent file to a nonexistent directory */
676 shfo.pFrom = "e.txt\0";
677 shfo.pTo = "nonexistent\0";
678 shfo.fAnyOperationsAborted = FALSE;
679 retval = SHFileOperation(&shfo);
680 ok(retval == 1026, "Expected 1026, got %ld\n", retval);
681 ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
682 ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
685 /* tests the FO_MOVE action */
686 static void test_move(void)
688 SHFILEOPSTRUCTA shfo, shfo2;
694 shfo.wFunc = FO_MOVE;
697 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
698 shfo.hNameMappings = NULL;
699 shfo.lpszProgressTitle = NULL;
701 set_curr_dir_path(from, "test1.txt\0");
702 set_curr_dir_path(to, "test4.txt\0");
703 ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
704 ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
705 ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
707 set_curr_dir_path(from, "test?.txt\0");
708 set_curr_dir_path(to, "testdir2\0");
709 ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
710 ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
711 ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
712 ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
713 ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
714 ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
716 clean_after_shfo_tests();
719 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
720 shfo2.fFlags |= FOF_MULTIDESTFILES;
722 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
723 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
724 ok(!SHFileOperationA(&shfo2), "Move many files\n");
725 ok(file_exists("test6.txt"), "The file is moved - many files are "
726 "specified as a target\n");
727 DeleteFileA("test6.txt");
728 DeleteFileA("test7.txt");
729 RemoveDirectoryA("test8.txt");
733 /* number of sources do not correspond to number of targets */
734 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
735 set_curr_dir_path(to, "test6.txt\0test7.txt\0");
736 ok(SHFileOperationA(&shfo2), "Can't move many files\n");
737 ok(!file_exists("test6.txt"), "The file is not moved - many files are "
738 "specified as a target\n");
742 set_curr_dir_path(from, "test3.txt\0");
743 set_curr_dir_path(to, "test4.txt\\test1.txt\0");
744 ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
745 ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
747 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
748 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
749 ok(SHFileOperationA(&shfo), "Cannot move many files\n");
750 ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
751 ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
753 set_curr_dir_path(from, "test1.txt\0");
754 set_curr_dir_path(to, "test6.txt\0");
755 ok(!SHFileOperationA(&shfo), "Move file\n");
756 ok(!file_exists("test1.txt"), "The file is moved\n");
757 ok(file_exists("test6.txt"), "The file is moved\n");
758 set_curr_dir_path(from, "test6.txt\0");
759 set_curr_dir_path(to, "test1.txt\0");
760 ok(!SHFileOperationA(&shfo), "Move file back\n");
762 set_curr_dir_path(from, "test4.txt\0");
763 set_curr_dir_path(to, "test6.txt\0");
764 ok(!SHFileOperationA(&shfo), "Move dir\n");
765 ok(!file_exists("test4.txt"), "The dir is moved\n");
766 ok(file_exists("test6.txt"), "The dir is moved\n");
767 set_curr_dir_path(from, "test6.txt\0");
768 set_curr_dir_path(to, "test4.txt\0");
769 ok(!SHFileOperationA(&shfo), "Move dir back\n");
771 /* move one file to two others */
773 shfo.pFrom = "test1.txt\0";
774 shfo.pTo = "a.txt\0b.txt\0";
775 retval = SHFileOperationA(&shfo);
776 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
777 ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
778 ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
779 ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
781 /* move two files to one other */
782 shfo.pFrom = "test2.txt\0test3.txt\0";
783 shfo.pTo = "test1.txt\0";
784 retval = SHFileOperationA(&shfo);
785 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
786 ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
787 ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
788 ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
790 /* move a directory into itself */
791 shfo.pFrom = "test4.txt\0";
792 shfo.pTo = "test4.txt\\b.txt\0";
793 retval = SHFileOperationA(&shfo);
794 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
795 ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
796 ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
798 /* move many files without FOF_MULTIDESTFILES */
799 shfo.pFrom = "test2.txt\0test3.txt\0";
800 shfo.pTo = "d.txt\0e.txt\0";
801 retval = SHFileOperationA(&shfo);
802 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
803 ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
804 ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
806 /* number of sources != number of targets */
807 shfo.pTo = "d.txt\0";
808 shfo.fFlags |= FOF_MULTIDESTFILES;
809 retval = SHFileOperationA(&shfo);
810 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
811 ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
813 /* FO_MOVE does not create dest directories */
814 shfo.pFrom = "test2.txt\0";
815 shfo.pTo = "dir1\\dir2\\test2.txt\0";
816 retval = SHFileOperationA(&shfo);
817 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
818 ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
820 /* try to overwrite an existing file */
821 shfo.pTo = "test3.txt\0";
822 retval = SHFileOperationA(&shfo);
823 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
824 ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
825 ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
828 static void test_sh_create_dir(void)
833 if(!pSHCreateDirectoryExA)
835 trace("skipping SHCreateDirectoryExA tests\n");
839 set_curr_dir_path(path, "testdir2\\test4.txt\0");
840 ret = pSHCreateDirectoryExA(NULL, path, NULL);
841 ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
842 ok(file_exists("testdir2"), "The first directory is not created\n");
843 ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
845 ret = pSHCreateDirectoryExA(NULL, path, NULL);
846 ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
848 ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
849 ok(file_exists("c:\\testdir3"), "The directory is not created\n");
852 START_TEST(shlfileop)
854 InitFunctionPointers();
856 clean_after_shfo_tests();
860 clean_after_shfo_tests();
864 clean_after_shfo_tests();
868 clean_after_shfo_tests();
872 clean_after_shfo_tests();
874 test_sh_create_dir();
875 clean_after_shfo_tests();