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 static void test_get_file_info(void)
120 strcpy(shfi.szDisplayName, "dummy");
121 shfi.iIcon=0xdeadbeef;
122 rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
124 SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
125 todo_wine ok(rc, "SHGetFileInfoA(c:\\nonexistent) returned %d\n", rc);
128 ok(strcpy(shfi.szDisplayName, "dummy") != 0, "SHGetFileInfoA(c:\\nonexistent) displayname is not set\n");
129 ok(shfi.iIcon != 0xdeadbeef, "SHGetFileInfoA(c:\\nonexistent) iIcon is not set\n");
135 puts into the specified buffer file names with current directory.
136 files - string with file names, separated by null characters. Ends on a double
139 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
144 strcpy(buf, CURR_DIR);
149 buf += strlen(buf) + 1;
150 files += strlen(files) + 1;
156 /* tests the FO_DELETE action */
157 static void test_delete(void)
159 SHFILEOPSTRUCTA shfo;
163 sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
164 buf[strlen(buf) + 1] = '\0';
167 shfo.wFunc = FO_DELETE;
170 shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
171 shfo.hNameMappings = NULL;
172 shfo.lpszProgressTitle = NULL;
174 ok(!SHFileOperationA(&shfo), "Deletion was successful\n");
175 ok(file_exists("test4.txt"), "Directory should not be removed\n");
176 ok(!file_exists("test1.txt"), "File should be removed\n");
178 ret = SHFileOperationA(&shfo);
179 ok(!ret, "Directory exists, but is not removed, ret=%d\n", ret);
180 ok(file_exists("test4.txt"), "Directory should not be removed\n");
182 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
184 ok(!SHFileOperationA(&shfo), "Directory removed\n");
185 ok(!file_exists("test4.txt"), "Directory should be removed\n");
187 ret = SHFileOperationA(&shfo);
188 ok(!ret, "The requested file does not exist, ret=%d\n", ret);
191 sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
192 buf[strlen(buf) + 1] = '\0';
193 ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Fill the subdirectory\n");
194 ok(!SHFileOperationA(&shfo), "Directory removed\n");
195 ok(!file_exists("test4.txt"), "Directory is removed\n");
198 shfo.pFrom = "test1.txt\0test4.txt\0";
199 ok(!SHFileOperationA(&shfo), "Directory and a file removed\n");
200 ok(!file_exists("test1.txt"), "The file should be removed\n");
201 ok(!file_exists("test4.txt"), "Directory should be removed\n");
202 ok(file_exists("test2.txt"), "This file should not be removed\n");
204 /* FOF_FILESONLY does not delete a dir matching a wildcard */
206 shfo.fFlags |= FOF_FILESONLY;
207 shfo.pFrom = "*.txt\0";
208 ok(!SHFileOperation(&shfo), "Failed to delete files\n");
209 ok(!file_exists("test1.txt"), "test1.txt should be removed\n");
210 ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
211 ok(file_exists("test4.txt"), "test4.txt should not be removed\n");
213 /* FOF_FILESONLY only deletes a dir if explicitly specified */
215 shfo.pFrom = "test_?.txt\0test4.txt\0";
216 ok(!SHFileOperation(&shfo), "Failed to delete files\n");
217 ok(!file_exists("test4.txt"), "test4.txt should be removed\n");
218 ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
219 ok(file_exists("test1.txt"), "test1.txt should not be removed\n");
221 /* try to delete an invalid filename */
224 shfo.fFlags &= ~FOF_FILESONLY;
225 shfo.fAnyOperationsAborted = FALSE;
226 ret = SHFileOperation(&shfo);
227 ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
228 ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
229 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
231 /* try an invalid function */
233 shfo.pFrom = "test1.txt\0";
235 ret = SHFileOperation(&shfo);
236 ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
237 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
239 /* try an invalid list, only one null terminator */
242 shfo.wFunc = FO_DELETE;
243 ret = SHFileOperation(&shfo);
244 ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
245 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
247 /* delete a dir, and then a file inside the dir, same as
248 * deleting a nonexistent file
251 shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
252 ret = SHFileOperation(&shfo);
253 ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret);
254 ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n");
255 ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
257 /* try the FOF_NORECURSION flag, continues deleting subdirs */
259 shfo.pFrom = "testdir2\0";
260 shfo.fFlags |= FOF_NORECURSION;
261 ret = SHFileOperation(&shfo);
262 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
263 ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
264 ok(!file_exists("testdir2\\nested"), "Expected testdir2\\nested to exist\n");
267 /* tests the FO_RENAME action */
268 static void test_rename(void)
270 SHFILEOPSTRUCTA shfo, shfo2;
276 shfo.wFunc = FO_RENAME;
279 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
280 shfo.hNameMappings = NULL;
281 shfo.lpszProgressTitle = NULL;
283 set_curr_dir_path(from, "test1.txt\0");
284 set_curr_dir_path(to, "test4.txt\0");
285 ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
286 "when specifying directory name only\n");
287 ok(file_exists("test1.txt"), "The file is removed\n");
289 set_curr_dir_path(from, "test3.txt\0");
290 set_curr_dir_path(to, "test4.txt\\test1.txt\0");
291 ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
292 ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
294 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
295 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
296 retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
297 ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
298 "Can't rename many files, retval = %d\n", retval);
299 ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
301 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
302 shfo2.fFlags |= FOF_MULTIDESTFILES;
304 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
305 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
306 retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
307 ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
308 "Can't rename many files, retval = %d\n", retval);
309 ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
311 set_curr_dir_path(from, "test1.txt\0");
312 set_curr_dir_path(to, "test6.txt\0");
313 retval = SHFileOperationA(&shfo);
314 ok(!retval, "Rename file failed, retval = %d\n", retval);
315 ok(!file_exists("test1.txt"), "The file is not renamed\n");
316 ok(file_exists("test6.txt"), "The file is not renamed\n");
318 set_curr_dir_path(from, "test6.txt\0");
319 set_curr_dir_path(to, "test1.txt\0");
320 retval = SHFileOperationA(&shfo);
321 ok(!retval, "Rename file back failed, retval = %d\n", retval);
323 set_curr_dir_path(from, "test4.txt\0");
324 set_curr_dir_path(to, "test6.txt\0");
325 retval = SHFileOperationA(&shfo);
326 ok(!retval, "Rename dir failed, retval = %d\n", retval);
327 ok(!file_exists("test4.txt"), "The dir is not renamed\n");
328 ok(file_exists("test6.txt"), "The dir is not renamed\n");
330 set_curr_dir_path(from, "test6.txt\0");
331 set_curr_dir_path(to, "test4.txt\0");
332 retval = SHFileOperationA(&shfo);
333 ok(!retval, "Rename dir back failed, retval = %d\n", retval);
335 /* try to rename more than one file to a single file */
336 shfo.pFrom = "test1.txt\0test2.txt\0";
337 shfo.pTo = "a.txt\0";
338 retval = SHFileOperationA(&shfo);
339 ok(retval == ERROR_GEN_FAILURE, "Expected ERROR_GEN_FAILURE, got %d\n", retval);
340 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
341 ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
343 /* pFrom doesn't exist */
344 shfo.pFrom = "idontexist\0";
345 shfo.pTo = "newfile\0";
346 retval = SHFileOperationA(&shfo);
347 ok(retval == 1026, "Expected 1026, got %d\n", retval);
348 ok(!file_exists("newfile"), "Expected newfile to not exist\n");
350 /* pTo already exist */
351 shfo.pFrom = "test1.txt\0";
352 shfo.pTo = "test2.txt\0";
353 retval = SHFileOperationA(&shfo);
354 ok(retval == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", retval);
356 /* pFrom is valid, but pTo is empty */
357 shfo.pFrom = "test1.txt\0";
359 retval = SHFileOperationA(&shfo);
360 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
361 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
365 retval = SHFileOperationA(&shfo);
366 ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", retval);
368 /* pFrom is NULL, commented out because it crashes on nt 4.0 */
371 retval = SHFileOperationA(&shfo);
372 ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", retval);
376 /* tests the FO_COPY action */
377 static void test_copy(void)
379 SHFILEOPSTRUCTA shfo, shfo2;
382 FILEOP_FLAGS tmp_flags;
386 shfo.wFunc = FO_COPY;
389 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
390 shfo.hNameMappings = NULL;
391 shfo.lpszProgressTitle = NULL;
393 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
394 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
395 ok(SHFileOperationA(&shfo), "Can't copy many files\n");
396 ok(!file_exists("test6.txt"), "The file is not copied - many files are "
397 "specified as a target\n");
399 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
400 shfo2.fFlags |= FOF_MULTIDESTFILES;
402 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
403 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
404 ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
405 ok(file_exists("test6.txt"), "The file is copied - many files are "
406 "specified as a target\n");
407 DeleteFileA("test6.txt");
408 DeleteFileA("test7.txt");
409 RemoveDirectoryA("test8.txt");
411 /* number of sources do not correspond to number of targets */
412 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
413 set_curr_dir_path(to, "test6.txt\0test7.txt\0");
414 ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
415 ok(!file_exists("test6.txt"), "The file is not copied - many files are "
416 "specified as a target\n");
418 set_curr_dir_path(from, "test1.txt\0");
419 set_curr_dir_path(to, "test4.txt\0");
420 ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
421 ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
423 set_curr_dir_path(from, "test?.txt\0");
424 set_curr_dir_path(to, "testdir2\0");
425 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
426 ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
427 ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
428 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
429 ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
430 ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
431 clean_after_shfo_tests();
434 shfo.fFlags |= FOF_FILESONLY;
435 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
436 ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
437 ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
438 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
439 ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
440 clean_after_shfo_tests();
443 set_curr_dir_path(from, "test1.txt\0test2.txt\0");
444 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
445 ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
446 ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
447 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
448 ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
449 clean_after_shfo_tests();
451 /* Copying multiple files with one not existing as source, fails the
452 entire operation in Win98/ME/2K/XP, but not in 95/NT */
454 tmp_flags = shfo.fFlags;
455 set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
456 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
457 ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
458 retval = SHFileOperationA(&shfo);
460 /* Win 95/NT returns success but copies only the files up to the nonexistent source */
461 ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
464 /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
465 ok(retval == 1026, "Files are copied to other directory\n");
466 ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
468 ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
469 shfo.fFlags = tmp_flags;
471 /* copy into a nonexistent directory */
473 shfo.fFlags = FOF_NOCONFIRMMKDIR;
474 set_curr_dir_path(from, "test1.txt\0");
475 set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
476 retval= SHFileOperation(&shfo);
477 ok(!retval, "Error copying into nonexistent directory\n");
478 ok(file_exists("nonexistent"), "nonexistent not created\n");
479 ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
480 ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
481 ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
483 /* a relative dest directory is OK */
484 clean_after_shfo_tests();
486 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
487 shfo.pTo = "testdir2\0";
488 retval = SHFileOperation(&shfo);
489 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
490 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
492 /* try to copy files to a file */
493 clean_after_shfo_tests();
497 set_curr_dir_path(from, "test1.txt\0test2.txt\0");
498 set_curr_dir_path(to, "test3.txt\0");
499 retval = SHFileOperation(&shfo);
500 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
501 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
502 ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
504 /* try to copy many files to nonexistent directory */
506 shfo.fAnyOperationsAborted = FALSE;
507 retval = SHFileOperation(&shfo);
508 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
509 ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
510 ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
511 ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
513 /* send in FOF_MULTIDESTFILES with too many destination files */
515 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
516 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
517 shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
518 retval = SHFileOperation(&shfo);
519 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
520 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
521 ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
523 /* send in FOF_MULTIDESTFILES with too many destination files */
524 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
525 shfo.pTo = "e.txt\0f.txt\0";
526 shfo.fAnyOperationsAborted = FALSE;
527 retval = SHFileOperation(&shfo);
528 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
529 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
530 ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
532 /* use FOF_MULTIDESTFILES with files and a source directory */
533 shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
534 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
535 shfo.fAnyOperationsAborted = FALSE;
536 retval = SHFileOperation(&shfo);
537 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
538 ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
539 ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
540 ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
542 /* try many dest files without FOF_MULTIDESTFILES flag */
543 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
544 shfo.pTo = "a.txt\0b.txt\0c.txt\0";
545 shfo.fAnyOperationsAborted = FALSE;
546 shfo.fFlags &= ~FOF_MULTIDESTFILES;
547 retval = SHFileOperation(&shfo);
548 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
549 ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
552 shfo.pFrom = "test?.txt\0";
553 shfo.pTo = "testdir2\0";
554 shfo.fFlags &= ~FOF_MULTIDESTFILES;
555 retval = SHFileOperation(&shfo);
556 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
557 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
559 /* try a glob with FOF_FILESONLY */
560 clean_after_shfo_tests();
562 shfo.pFrom = "test?.txt\0";
563 shfo.fFlags |= FOF_FILESONLY;
564 retval = SHFileOperation(&shfo);
565 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
566 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
567 ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
569 /* try a glob with FOF_MULTIDESTFILES and the same number
570 * of dest files that we would expect
572 clean_after_shfo_tests();
574 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
575 shfo.fFlags &= ~FOF_FILESONLY;
576 shfo.fFlags |= FOF_MULTIDESTFILES;
577 retval = SHFileOperation(&shfo);
578 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
579 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
580 ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
581 ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
583 /* copy one file to two others, second is ignored */
584 clean_after_shfo_tests();
586 shfo.pFrom = "test1.txt\0";
587 shfo.pTo = "b.txt\0c.txt\0";
588 shfo.fAnyOperationsAborted = FALSE;
589 retval = SHFileOperation(&shfo);
590 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
591 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
592 ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
594 /* copy two file to three others, all fail */
595 shfo.pFrom = "test1.txt\0test2.txt\0";
596 shfo.pTo = "b.txt\0c.txt\0d.txt\0";
597 retval = SHFileOperation(&shfo);
598 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
599 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
600 ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
602 /* copy one file and one directory to three others */
603 shfo.pFrom = "test1.txt\0test4.txt\0";
604 shfo.pTo = "b.txt\0c.txt\0d.txt\0";
605 shfo.fAnyOperationsAborted = FALSE;
606 retval = SHFileOperation(&shfo);
607 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
608 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
609 ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
610 ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
612 /* copy a directory with a file beneath it, plus some files */
613 createTestFile("test4.txt\\a.txt");
614 shfo.pFrom = "test4.txt\0test1.txt\0";
615 shfo.pTo = "testdir2\0";
616 shfo.fFlags &= ~FOF_MULTIDESTFILES;
617 shfo.fAnyOperationsAborted = FALSE;
618 retval = SHFileOperation(&shfo);
619 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
620 ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
621 ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
622 ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
624 /* copy one directory and a file in that dir to another dir */
625 shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
626 shfo.pTo = "testdir2\0";
627 retval = SHFileOperation(&shfo);
628 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
629 ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
630 ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
632 /* copy a file in a directory first, and then the directory to a nonexistent dir */
633 shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
634 shfo.pTo = "nonexistent\0";
635 retval = SHFileOperation(&shfo);
636 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
637 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
638 ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
639 DeleteFile("test4.txt\\a.txt");
641 /* destination is same as source file */
642 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
643 shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
644 shfo.fAnyOperationsAborted = FALSE;
645 shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
646 retval = SHFileOperation(&shfo);
647 ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
648 "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %d\n", retval);
649 ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
650 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
651 ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
653 /* destination is same as source directory */
654 shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
655 shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
656 shfo.fAnyOperationsAborted = FALSE;
657 retval = SHFileOperation(&shfo);
658 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
659 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
660 ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
662 /* copy a directory into itself, error displayed in UI */
663 shfo.pFrom = "test4.txt\0";
664 shfo.pTo = "test4.txt\\newdir\0";
665 shfo.fFlags &= ~FOF_MULTIDESTFILES;
666 shfo.fAnyOperationsAborted = FALSE;
667 retval = SHFileOperation(&shfo);
668 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
669 ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
671 /* copy a directory to itself, error displayed in UI */
672 shfo.pFrom = "test4.txt\0";
673 shfo.pTo = "test4.txt\0";
674 shfo.fAnyOperationsAborted = FALSE;
675 retval = SHFileOperation(&shfo);
676 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
678 /* copy a file into a directory, and the directory into itself */
679 shfo.pFrom = "test1.txt\0test4.txt\0";
680 shfo.pTo = "test4.txt\0";
681 shfo.fAnyOperationsAborted = FALSE;
682 shfo.fFlags |= FOF_NOCONFIRMATION;
683 retval = SHFileOperation(&shfo);
684 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
685 ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
687 /* copy a file to a file, and the directory into itself */
688 shfo.pFrom = "test1.txt\0test4.txt\0";
689 shfo.pTo = "test4.txt\\a.txt\0";
690 shfo.fAnyOperationsAborted = FALSE;
691 retval = SHFileOperation(&shfo);
692 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
693 ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
695 /* copy a nonexistent file to a nonexistent directory */
696 shfo.pFrom = "e.txt\0";
697 shfo.pTo = "nonexistent\0";
698 shfo.fAnyOperationsAborted = FALSE;
699 retval = SHFileOperation(&shfo);
700 ok(retval == 1026, "Expected 1026, got %d\n", retval);
701 ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
702 ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
705 /* tests the FO_MOVE action */
706 static void test_move(void)
708 SHFILEOPSTRUCTA shfo, shfo2;
714 shfo.wFunc = FO_MOVE;
717 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
718 shfo.hNameMappings = NULL;
719 shfo.lpszProgressTitle = NULL;
721 set_curr_dir_path(from, "test1.txt\0");
722 set_curr_dir_path(to, "test4.txt\0");
723 ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
724 ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
725 ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
727 set_curr_dir_path(from, "test?.txt\0");
728 set_curr_dir_path(to, "testdir2\0");
729 ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
730 ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
731 ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
732 ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
733 ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
734 ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
736 clean_after_shfo_tests();
739 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
740 shfo2.fFlags |= FOF_MULTIDESTFILES;
742 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
743 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
744 ok(!SHFileOperationA(&shfo2), "Move many files\n");
745 ok(file_exists("test6.txt"), "The file is moved - many files are "
746 "specified as a target\n");
747 DeleteFileA("test6.txt");
748 DeleteFileA("test7.txt");
749 RemoveDirectoryA("test8.txt");
753 /* number of sources do not correspond to number of targets */
754 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
755 set_curr_dir_path(to, "test6.txt\0test7.txt\0");
756 ok(SHFileOperationA(&shfo2), "Can't move many files\n");
757 ok(!file_exists("test6.txt"), "The file is not moved - many files are "
758 "specified as a target\n");
762 set_curr_dir_path(from, "test3.txt\0");
763 set_curr_dir_path(to, "test4.txt\\test1.txt\0");
764 ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
765 ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
767 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
768 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
769 ok(SHFileOperationA(&shfo), "Cannot move many files\n");
770 ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
771 ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
773 set_curr_dir_path(from, "test1.txt\0");
774 set_curr_dir_path(to, "test6.txt\0");
775 ok(!SHFileOperationA(&shfo), "Move file\n");
776 ok(!file_exists("test1.txt"), "The file is moved\n");
777 ok(file_exists("test6.txt"), "The file is moved\n");
778 set_curr_dir_path(from, "test6.txt\0");
779 set_curr_dir_path(to, "test1.txt\0");
780 ok(!SHFileOperationA(&shfo), "Move file back\n");
782 set_curr_dir_path(from, "test4.txt\0");
783 set_curr_dir_path(to, "test6.txt\0");
784 ok(!SHFileOperationA(&shfo), "Move dir\n");
785 ok(!file_exists("test4.txt"), "The dir is moved\n");
786 ok(file_exists("test6.txt"), "The dir is moved\n");
787 set_curr_dir_path(from, "test6.txt\0");
788 set_curr_dir_path(to, "test4.txt\0");
789 ok(!SHFileOperationA(&shfo), "Move dir back\n");
791 /* move one file to two others */
793 shfo.pFrom = "test1.txt\0";
794 shfo.pTo = "a.txt\0b.txt\0";
795 retval = SHFileOperationA(&shfo);
796 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
797 ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
798 ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
799 ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
801 /* move two files to one other */
802 shfo.pFrom = "test2.txt\0test3.txt\0";
803 shfo.pTo = "test1.txt\0";
804 retval = SHFileOperationA(&shfo);
805 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
806 ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
807 ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
808 ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
810 /* move a directory into itself */
811 shfo.pFrom = "test4.txt\0";
812 shfo.pTo = "test4.txt\\b.txt\0";
813 retval = SHFileOperationA(&shfo);
814 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
815 ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
816 ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
818 /* move many files without FOF_MULTIDESTFILES */
819 shfo.pFrom = "test2.txt\0test3.txt\0";
820 shfo.pTo = "d.txt\0e.txt\0";
821 retval = SHFileOperationA(&shfo);
822 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
823 ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
824 ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
826 /* number of sources != number of targets */
827 shfo.pTo = "d.txt\0";
828 shfo.fFlags |= FOF_MULTIDESTFILES;
829 retval = SHFileOperationA(&shfo);
830 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
831 ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
833 /* FO_MOVE does not create dest directories */
834 shfo.pFrom = "test2.txt\0";
835 shfo.pTo = "dir1\\dir2\\test2.txt\0";
836 retval = SHFileOperationA(&shfo);
837 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
838 ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
840 /* try to overwrite an existing file */
841 shfo.pTo = "test3.txt\0";
842 retval = SHFileOperationA(&shfo);
843 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
844 ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
845 ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
848 static void test_sh_create_dir(void)
853 if(!pSHCreateDirectoryExA)
855 trace("skipping SHCreateDirectoryExA tests\n");
859 set_curr_dir_path(path, "testdir2\\test4.txt\0");
860 ret = pSHCreateDirectoryExA(NULL, path, NULL);
861 ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
862 ok(file_exists("testdir2"), "The first directory is not created\n");
863 ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
865 ret = pSHCreateDirectoryExA(NULL, path, NULL);
866 ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
868 ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
869 ok(file_exists("c:\\testdir3"), "The directory is not created\n");
872 START_TEST(shlfileop)
874 InitFunctionPointers();
876 clean_after_shfo_tests();
878 test_get_file_info();
882 clean_after_shfo_tests();
886 clean_after_shfo_tests();
890 clean_after_shfo_tests();
894 clean_after_shfo_tests();
896 test_sh_create_dir();
897 clean_after_shfo_tests();