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)
118 SHFILEINFO shfi, shfi2;
119 char notepad[MAX_PATH];
121 /* Test some flag combinations that MSDN claims are not allowed,
122 * but which work anyway
124 shfi.dwAttributes=0xdeadbeef;
125 rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
127 SHGFI_ATTRIBUTES | SHGFI_USEFILEATTRIBUTES);
128 todo_wine ok(rc, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) failed\n");
130 ok(shfi.dwAttributes != 0xdeadbeef, "dwFileAttributes is not set\n");
132 rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
134 SHGFI_EXETYPE | SHGFI_USEFILEATTRIBUTES);
135 todo_wine ok(rc == 1, "SHGetFileInfoA(c:\\nonexistent | SHGFI_EXETYPE) returned %d\n", rc);
137 /* Test SHGFI_USEFILEATTRIBUTES support */
138 strcpy(shfi.szDisplayName, "dummy");
139 shfi.iIcon=0xdeadbeef;
140 rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
142 SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
143 ok(rc, "SHGetFileInfoA(c:\\nonexistent) failed\n");
146 ok(strcpy(shfi.szDisplayName, "dummy") != 0, "SHGetFileInfoA(c:\\nonexistent) displayname is not set\n");
147 ok(shfi.iIcon != 0xdeadbeef, "SHGetFileInfoA(c:\\nonexistent) iIcon is not set\n");
150 /* Wine does not have a default icon for text files, and Windows 98 fails
151 * if we give it an empty executable. So use notepad.exe as the test
153 if (SearchPath(NULL, "notepad.exe", NULL, sizeof(notepad), notepad, NULL))
155 strcpy(shfi.szDisplayName, "dummy");
156 shfi.iIcon=0xdeadbeef;
157 rc=SHGetFileInfoA(notepad, GetFileAttributes(notepad),
159 SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
160 ok(rc, "SHGetFileInfoA(%s, SHGFI_USEFILEATTRIBUTES) failed\n", notepad);
161 strcpy(shfi2.szDisplayName, "dummy");
162 shfi2.iIcon=0xdeadbeef;
163 rc2=SHGetFileInfoA(notepad, 0,
164 &shfi2, sizeof(shfi2),
166 ok(rc2, "SHGetFileInfoA(%s) failed\n", notepad);
169 ok(lstrcmpi(shfi2.szDisplayName, shfi.szDisplayName) == 0, "wrong display name %s != %s\n", shfi.szDisplayName, shfi2.szDisplayName);
170 ok(shfi2.iIcon == shfi.iIcon, "wrong icon index %d != %d\n", shfi.iIcon, shfi2.iIcon);
174 /* with a directory now */
175 strcpy(shfi.szDisplayName, "dummy");
176 shfi.iIcon=0xdeadbeef;
177 rc=SHGetFileInfoA("test4.txt", GetFileAttributes("test4.txt"),
179 SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
180 ok(rc, "SHGetFileInfoA(test4.txt/, SHGFI_USEFILEATTRIBUTES) failed\n");
181 strcpy(shfi2.szDisplayName, "dummy");
182 shfi2.iIcon=0xdeadbeef;
183 rc2=SHGetFileInfoA("test4.txt", 0,
184 &shfi2, sizeof(shfi2),
186 ok(rc2, "SHGetFileInfoA(test4.txt/) failed\n");
189 ok(lstrcmpi(shfi2.szDisplayName, shfi.szDisplayName) == 0, "wrong display name %s != %s\n", shfi.szDisplayName, shfi2.szDisplayName);
190 ok(shfi2.iIcon == shfi.iIcon, "wrong icon index %d != %d\n", shfi.iIcon, shfi2.iIcon);
196 puts into the specified buffer file names with current directory.
197 files - string with file names, separated by null characters. Ends on a double
200 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
205 strcpy(buf, CURR_DIR);
210 buf += strlen(buf) + 1;
211 files += strlen(files) + 1;
217 /* tests the FO_DELETE action */
218 static void test_delete(void)
220 SHFILEOPSTRUCTA shfo;
224 sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
225 buf[strlen(buf) + 1] = '\0';
228 shfo.wFunc = FO_DELETE;
231 shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
232 shfo.hNameMappings = NULL;
233 shfo.lpszProgressTitle = NULL;
235 ok(!SHFileOperationA(&shfo), "Deletion was successful\n");
236 ok(file_exists("test4.txt"), "Directory should not be removed\n");
237 ok(!file_exists("test1.txt"), "File should be removed\n");
239 ret = SHFileOperationA(&shfo);
240 ok(!ret, "Directory exists, but is not removed, ret=%d\n", ret);
241 ok(file_exists("test4.txt"), "Directory should not be removed\n");
243 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
245 ok(!SHFileOperationA(&shfo), "Directory removed\n");
246 ok(!file_exists("test4.txt"), "Directory should be removed\n");
248 ret = SHFileOperationA(&shfo);
249 ok(!ret, "The requested file does not exist, ret=%d\n", ret);
252 sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
253 buf[strlen(buf) + 1] = '\0';
254 ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Fill the subdirectory\n");
255 ok(!SHFileOperationA(&shfo), "Directory removed\n");
256 ok(!file_exists("test4.txt"), "Directory is removed\n");
259 shfo.pFrom = "test1.txt\0test4.txt\0";
260 ok(!SHFileOperationA(&shfo), "Directory and a file removed\n");
261 ok(!file_exists("test1.txt"), "The file should be removed\n");
262 ok(!file_exists("test4.txt"), "Directory should be removed\n");
263 ok(file_exists("test2.txt"), "This file should not be removed\n");
265 /* FOF_FILESONLY does not delete a dir matching a wildcard */
267 shfo.fFlags |= FOF_FILESONLY;
268 shfo.pFrom = "*.txt\0";
269 ok(!SHFileOperation(&shfo), "Failed to delete files\n");
270 ok(!file_exists("test1.txt"), "test1.txt should be removed\n");
271 ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
272 ok(file_exists("test4.txt"), "test4.txt should not be removed\n");
274 /* FOF_FILESONLY only deletes a dir if explicitly specified */
276 shfo.pFrom = "test_?.txt\0test4.txt\0";
277 ok(!SHFileOperation(&shfo), "Failed to delete files\n");
278 ok(!file_exists("test4.txt"), "test4.txt should be removed\n");
279 ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
280 ok(file_exists("test1.txt"), "test1.txt should not be removed\n");
282 /* try to delete an invalid filename */
285 shfo.fFlags &= ~FOF_FILESONLY;
286 shfo.fAnyOperationsAborted = FALSE;
287 ret = SHFileOperation(&shfo);
288 ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
289 ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
290 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
292 /* try an invalid function */
294 shfo.pFrom = "test1.txt\0";
296 ret = SHFileOperation(&shfo);
297 ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
298 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
300 /* try an invalid list, only one null terminator */
303 shfo.wFunc = FO_DELETE;
304 ret = SHFileOperation(&shfo);
305 ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
306 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
308 /* delete a dir, and then a file inside the dir, same as
309 * deleting a nonexistent file
312 shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
313 ret = SHFileOperation(&shfo);
314 ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret);
315 ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n");
316 ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
318 /* try the FOF_NORECURSION flag, continues deleting subdirs */
320 shfo.pFrom = "testdir2\0";
321 shfo.fFlags |= FOF_NORECURSION;
322 ret = SHFileOperation(&shfo);
323 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
324 ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
325 ok(!file_exists("testdir2\\nested"), "Expected testdir2\\nested to exist\n");
328 /* tests the FO_RENAME action */
329 static void test_rename(void)
331 SHFILEOPSTRUCTA shfo, shfo2;
337 shfo.wFunc = FO_RENAME;
340 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
341 shfo.hNameMappings = NULL;
342 shfo.lpszProgressTitle = NULL;
344 set_curr_dir_path(from, "test1.txt\0");
345 set_curr_dir_path(to, "test4.txt\0");
346 ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
347 "when specifying directory name only\n");
348 ok(file_exists("test1.txt"), "The file is removed\n");
350 set_curr_dir_path(from, "test3.txt\0");
351 set_curr_dir_path(to, "test4.txt\\test1.txt\0");
352 ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
353 ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
355 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
356 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
357 retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
358 ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
359 "Can't rename many files, retval = %d\n", retval);
360 ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
362 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
363 shfo2.fFlags |= FOF_MULTIDESTFILES;
365 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
366 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
367 retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
368 ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
369 "Can't rename many files, retval = %d\n", retval);
370 ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
372 set_curr_dir_path(from, "test1.txt\0");
373 set_curr_dir_path(to, "test6.txt\0");
374 retval = SHFileOperationA(&shfo);
375 ok(!retval, "Rename file failed, retval = %d\n", retval);
376 ok(!file_exists("test1.txt"), "The file is not renamed\n");
377 ok(file_exists("test6.txt"), "The file is not renamed\n");
379 set_curr_dir_path(from, "test6.txt\0");
380 set_curr_dir_path(to, "test1.txt\0");
381 retval = SHFileOperationA(&shfo);
382 ok(!retval, "Rename file back failed, retval = %d\n", retval);
384 set_curr_dir_path(from, "test4.txt\0");
385 set_curr_dir_path(to, "test6.txt\0");
386 retval = SHFileOperationA(&shfo);
387 ok(!retval, "Rename dir failed, retval = %d\n", retval);
388 ok(!file_exists("test4.txt"), "The dir is not renamed\n");
389 ok(file_exists("test6.txt"), "The dir is not renamed\n");
391 set_curr_dir_path(from, "test6.txt\0");
392 set_curr_dir_path(to, "test4.txt\0");
393 retval = SHFileOperationA(&shfo);
394 ok(!retval, "Rename dir back failed, retval = %d\n", retval);
396 /* try to rename more than one file to a single file */
397 shfo.pFrom = "test1.txt\0test2.txt\0";
398 shfo.pTo = "a.txt\0";
399 retval = SHFileOperationA(&shfo);
400 ok(retval == ERROR_GEN_FAILURE, "Expected ERROR_GEN_FAILURE, got %d\n", retval);
401 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
402 ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
404 /* pFrom doesn't exist */
405 shfo.pFrom = "idontexist\0";
406 shfo.pTo = "newfile\0";
407 retval = SHFileOperationA(&shfo);
408 ok(retval == 1026, "Expected 1026, got %d\n", retval);
409 ok(!file_exists("newfile"), "Expected newfile to not exist\n");
411 /* pTo already exist */
412 shfo.pFrom = "test1.txt\0";
413 shfo.pTo = "test2.txt\0";
414 retval = SHFileOperationA(&shfo);
415 ok(retval == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", retval);
417 /* pFrom is valid, but pTo is empty */
418 shfo.pFrom = "test1.txt\0";
420 retval = SHFileOperationA(&shfo);
421 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
422 ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
426 retval = SHFileOperationA(&shfo);
427 ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", retval);
429 /* pFrom is NULL, commented out because it crashes on nt 4.0 */
432 retval = SHFileOperationA(&shfo);
433 ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", retval);
437 /* tests the FO_COPY action */
438 static void test_copy(void)
440 SHFILEOPSTRUCTA shfo, shfo2;
443 FILEOP_FLAGS tmp_flags;
447 shfo.wFunc = FO_COPY;
450 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
451 shfo.hNameMappings = NULL;
452 shfo.lpszProgressTitle = NULL;
454 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
455 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
456 ok(SHFileOperationA(&shfo), "Can't copy many files\n");
457 ok(!file_exists("test6.txt"), "The file is not copied - many files are "
458 "specified as a target\n");
460 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
461 shfo2.fFlags |= FOF_MULTIDESTFILES;
463 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
464 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
465 ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
466 ok(file_exists("test6.txt"), "The file is copied - many files are "
467 "specified as a target\n");
468 DeleteFileA("test6.txt");
469 DeleteFileA("test7.txt");
470 RemoveDirectoryA("test8.txt");
472 /* number of sources do not correspond to number of targets */
473 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
474 set_curr_dir_path(to, "test6.txt\0test7.txt\0");
475 ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
476 ok(!file_exists("test6.txt"), "The file is not copied - many files are "
477 "specified as a target\n");
479 set_curr_dir_path(from, "test1.txt\0");
480 set_curr_dir_path(to, "test4.txt\0");
481 ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
482 ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
484 set_curr_dir_path(from, "test?.txt\0");
485 set_curr_dir_path(to, "testdir2\0");
486 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
487 ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
488 ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
489 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
490 ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
491 ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
492 clean_after_shfo_tests();
495 shfo.fFlags |= FOF_FILESONLY;
496 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
497 ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
498 ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
499 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
500 ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
501 clean_after_shfo_tests();
504 set_curr_dir_path(from, "test1.txt\0test2.txt\0");
505 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
506 ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
507 ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
508 ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
509 ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
510 clean_after_shfo_tests();
512 /* Copying multiple files with one not existing as source, fails the
513 entire operation in Win98/ME/2K/XP, but not in 95/NT */
515 tmp_flags = shfo.fFlags;
516 set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
517 ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
518 ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
519 retval = SHFileOperationA(&shfo);
521 /* Win 95/NT returns success but copies only the files up to the nonexistent source */
522 ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
525 /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
526 ok(retval == 1026, "Files are copied to other directory\n");
527 ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
529 ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
530 shfo.fFlags = tmp_flags;
532 /* copy into a nonexistent directory */
534 shfo.fFlags = FOF_NOCONFIRMMKDIR;
535 set_curr_dir_path(from, "test1.txt\0");
536 set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
537 retval= SHFileOperation(&shfo);
538 ok(!retval, "Error copying into nonexistent directory\n");
539 ok(file_exists("nonexistent"), "nonexistent not created\n");
540 ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
541 ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
542 ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
544 /* a relative dest directory is OK */
545 clean_after_shfo_tests();
547 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
548 shfo.pTo = "testdir2\0";
549 retval = SHFileOperation(&shfo);
550 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
551 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
553 /* try to copy files to a file */
554 clean_after_shfo_tests();
558 set_curr_dir_path(from, "test1.txt\0test2.txt\0");
559 set_curr_dir_path(to, "test3.txt\0");
560 retval = SHFileOperation(&shfo);
561 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
562 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
563 ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
565 /* try to copy many files to nonexistent directory */
567 shfo.fAnyOperationsAborted = FALSE;
568 retval = SHFileOperation(&shfo);
569 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
570 ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
571 ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
572 ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
574 /* send in FOF_MULTIDESTFILES with too many destination files */
576 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
577 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
578 shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
579 retval = SHFileOperation(&shfo);
580 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
581 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
582 ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
584 /* send in FOF_MULTIDESTFILES with too many destination files */
585 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
586 shfo.pTo = "e.txt\0f.txt\0";
587 shfo.fAnyOperationsAborted = FALSE;
588 retval = SHFileOperation(&shfo);
589 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
590 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
591 ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
593 /* use FOF_MULTIDESTFILES with files and a source directory */
594 shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
595 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
596 shfo.fAnyOperationsAborted = FALSE;
597 retval = SHFileOperation(&shfo);
598 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
599 ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
600 ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
601 ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
603 /* try many dest files without FOF_MULTIDESTFILES flag */
604 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
605 shfo.pTo = "a.txt\0b.txt\0c.txt\0";
606 shfo.fAnyOperationsAborted = FALSE;
607 shfo.fFlags &= ~FOF_MULTIDESTFILES;
608 retval = SHFileOperation(&shfo);
609 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
610 ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
613 shfo.pFrom = "test?.txt\0";
614 shfo.pTo = "testdir2\0";
615 shfo.fFlags &= ~FOF_MULTIDESTFILES;
616 retval = SHFileOperation(&shfo);
617 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
618 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
620 /* try a glob with FOF_FILESONLY */
621 clean_after_shfo_tests();
623 shfo.pFrom = "test?.txt\0";
624 shfo.fFlags |= FOF_FILESONLY;
625 retval = SHFileOperation(&shfo);
626 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
627 ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
628 ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
630 /* try a glob with FOF_MULTIDESTFILES and the same number
631 * of dest files that we would expect
633 clean_after_shfo_tests();
635 shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
636 shfo.fFlags &= ~FOF_FILESONLY;
637 shfo.fFlags |= FOF_MULTIDESTFILES;
638 retval = SHFileOperation(&shfo);
639 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
640 ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
641 ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
642 ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
644 /* copy one file to two others, second is ignored */
645 clean_after_shfo_tests();
647 shfo.pFrom = "test1.txt\0";
648 shfo.pTo = "b.txt\0c.txt\0";
649 shfo.fAnyOperationsAborted = FALSE;
650 retval = SHFileOperation(&shfo);
651 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
652 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
653 ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
655 /* copy two file to three others, all fail */
656 shfo.pFrom = "test1.txt\0test2.txt\0";
657 shfo.pTo = "b.txt\0c.txt\0d.txt\0";
658 retval = SHFileOperation(&shfo);
659 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
660 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
661 ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
663 /* copy one file and one directory to three others */
664 shfo.pFrom = "test1.txt\0test4.txt\0";
665 shfo.pTo = "b.txt\0c.txt\0d.txt\0";
666 shfo.fAnyOperationsAborted = FALSE;
667 retval = SHFileOperation(&shfo);
668 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
669 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
670 ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
671 ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
673 /* copy a directory with a file beneath it, plus some files */
674 createTestFile("test4.txt\\a.txt");
675 shfo.pFrom = "test4.txt\0test1.txt\0";
676 shfo.pTo = "testdir2\0";
677 shfo.fFlags &= ~FOF_MULTIDESTFILES;
678 shfo.fAnyOperationsAborted = FALSE;
679 retval = SHFileOperation(&shfo);
680 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
681 ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
682 ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
683 ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
685 /* copy one directory and a file in that dir to another dir */
686 shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
687 shfo.pTo = "testdir2\0";
688 retval = SHFileOperation(&shfo);
689 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
690 ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
691 ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
693 /* copy a file in a directory first, and then the directory to a nonexistent dir */
694 shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
695 shfo.pTo = "nonexistent\0";
696 retval = SHFileOperation(&shfo);
697 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
698 ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
699 ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
700 DeleteFile("test4.txt\\a.txt");
702 /* destination is same as source file */
703 shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
704 shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
705 shfo.fAnyOperationsAborted = FALSE;
706 shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
707 retval = SHFileOperation(&shfo);
708 ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
709 "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %d\n", retval);
710 ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
711 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
712 ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
714 /* destination is same as source directory */
715 shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
716 shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
717 shfo.fAnyOperationsAborted = FALSE;
718 retval = SHFileOperation(&shfo);
719 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
720 ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
721 ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
723 /* copy a directory into itself, error displayed in UI */
724 shfo.pFrom = "test4.txt\0";
725 shfo.pTo = "test4.txt\\newdir\0";
726 shfo.fFlags &= ~FOF_MULTIDESTFILES;
727 shfo.fAnyOperationsAborted = FALSE;
728 retval = SHFileOperation(&shfo);
729 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
730 ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
732 /* copy a directory to itself, error displayed in UI */
733 shfo.pFrom = "test4.txt\0";
734 shfo.pTo = "test4.txt\0";
735 shfo.fAnyOperationsAborted = FALSE;
736 retval = SHFileOperation(&shfo);
737 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
739 /* copy a file into a directory, and the directory into itself */
740 shfo.pFrom = "test1.txt\0test4.txt\0";
741 shfo.pTo = "test4.txt\0";
742 shfo.fAnyOperationsAborted = FALSE;
743 shfo.fFlags |= FOF_NOCONFIRMATION;
744 retval = SHFileOperation(&shfo);
745 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
746 ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
748 /* copy a file to a file, and the directory into itself */
749 shfo.pFrom = "test1.txt\0test4.txt\0";
750 shfo.pTo = "test4.txt\\a.txt\0";
751 shfo.fAnyOperationsAborted = FALSE;
752 retval = SHFileOperation(&shfo);
753 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
754 ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
756 /* copy a nonexistent file to a nonexistent directory */
757 shfo.pFrom = "e.txt\0";
758 shfo.pTo = "nonexistent\0";
759 shfo.fAnyOperationsAborted = FALSE;
760 retval = SHFileOperation(&shfo);
761 ok(retval == 1026, "Expected 1026, got %d\n", retval);
762 ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
763 ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
766 /* tests the FO_MOVE action */
767 static void test_move(void)
769 SHFILEOPSTRUCTA shfo, shfo2;
775 shfo.wFunc = FO_MOVE;
778 shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
779 shfo.hNameMappings = NULL;
780 shfo.lpszProgressTitle = NULL;
782 set_curr_dir_path(from, "test1.txt\0");
783 set_curr_dir_path(to, "test4.txt\0");
784 ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
785 ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
786 ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
788 set_curr_dir_path(from, "test?.txt\0");
789 set_curr_dir_path(to, "testdir2\0");
790 ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
791 ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
792 ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
793 ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
794 ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
795 ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
797 clean_after_shfo_tests();
800 memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
801 shfo2.fFlags |= FOF_MULTIDESTFILES;
803 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
804 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
805 ok(!SHFileOperationA(&shfo2), "Move many files\n");
806 ok(file_exists("test6.txt"), "The file is moved - many files are "
807 "specified as a target\n");
808 DeleteFileA("test6.txt");
809 DeleteFileA("test7.txt");
810 RemoveDirectoryA("test8.txt");
814 /* number of sources do not correspond to number of targets */
815 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
816 set_curr_dir_path(to, "test6.txt\0test7.txt\0");
817 ok(SHFileOperationA(&shfo2), "Can't move many files\n");
818 ok(!file_exists("test6.txt"), "The file is not moved - many files are "
819 "specified as a target\n");
823 set_curr_dir_path(from, "test3.txt\0");
824 set_curr_dir_path(to, "test4.txt\\test1.txt\0");
825 ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
826 ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
828 set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
829 set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
830 ok(SHFileOperationA(&shfo), "Cannot move many files\n");
831 ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
832 ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
834 set_curr_dir_path(from, "test1.txt\0");
835 set_curr_dir_path(to, "test6.txt\0");
836 ok(!SHFileOperationA(&shfo), "Move file\n");
837 ok(!file_exists("test1.txt"), "The file is moved\n");
838 ok(file_exists("test6.txt"), "The file is moved\n");
839 set_curr_dir_path(from, "test6.txt\0");
840 set_curr_dir_path(to, "test1.txt\0");
841 ok(!SHFileOperationA(&shfo), "Move file back\n");
843 set_curr_dir_path(from, "test4.txt\0");
844 set_curr_dir_path(to, "test6.txt\0");
845 ok(!SHFileOperationA(&shfo), "Move dir\n");
846 ok(!file_exists("test4.txt"), "The dir is moved\n");
847 ok(file_exists("test6.txt"), "The dir is moved\n");
848 set_curr_dir_path(from, "test6.txt\0");
849 set_curr_dir_path(to, "test4.txt\0");
850 ok(!SHFileOperationA(&shfo), "Move dir back\n");
852 /* move one file to two others */
854 shfo.pFrom = "test1.txt\0";
855 shfo.pTo = "a.txt\0b.txt\0";
856 retval = SHFileOperationA(&shfo);
857 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
858 ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
859 ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
860 ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
862 /* move two files to one other */
863 shfo.pFrom = "test2.txt\0test3.txt\0";
864 shfo.pTo = "test1.txt\0";
865 retval = SHFileOperationA(&shfo);
866 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
867 ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
868 ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
869 ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
871 /* move a directory into itself */
872 shfo.pFrom = "test4.txt\0";
873 shfo.pTo = "test4.txt\\b.txt\0";
874 retval = SHFileOperationA(&shfo);
875 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
876 ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
877 ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
879 /* move many files without FOF_MULTIDESTFILES */
880 shfo.pFrom = "test2.txt\0test3.txt\0";
881 shfo.pTo = "d.txt\0e.txt\0";
882 retval = SHFileOperationA(&shfo);
883 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
884 ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
885 ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
887 /* number of sources != number of targets */
888 shfo.pTo = "d.txt\0";
889 shfo.fFlags |= FOF_MULTIDESTFILES;
890 retval = SHFileOperationA(&shfo);
891 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
892 ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
894 /* FO_MOVE does not create dest directories */
895 shfo.pFrom = "test2.txt\0";
896 shfo.pTo = "dir1\\dir2\\test2.txt\0";
897 retval = SHFileOperationA(&shfo);
898 ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
899 ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
901 /* try to overwrite an existing file */
902 shfo.pTo = "test3.txt\0";
903 retval = SHFileOperationA(&shfo);
904 ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
905 ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
906 ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
909 static void test_sh_create_dir(void)
914 if(!pSHCreateDirectoryExA)
916 trace("skipping SHCreateDirectoryExA tests\n");
920 set_curr_dir_path(path, "testdir2\\test4.txt\0");
921 ret = pSHCreateDirectoryExA(NULL, path, NULL);
922 ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
923 ok(file_exists("testdir2"), "The first directory is not created\n");
924 ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
926 ret = pSHCreateDirectoryExA(NULL, path, NULL);
927 ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
929 ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
930 ok(file_exists("c:\\testdir3"), "The directory is not created\n");
933 START_TEST(shlfileop)
935 InitFunctionPointers();
937 clean_after_shfo_tests();
940 test_get_file_info();
941 clean_after_shfo_tests();
945 clean_after_shfo_tests();
949 clean_after_shfo_tests();
953 clean_after_shfo_tests();
957 clean_after_shfo_tests();
959 test_sh_create_dir();
960 clean_after_shfo_tests();