tests: Moved some compatibility defines to wine/test.h.
[wine] / dlls / shell32 / tests / shlfileop.c
1 /*
2  * Unit test of the SHFileOperation function.
3  *
4  * Copyright 2002 Andriy Palamarchuk
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define WINE_NOWINSOCK
25 #include <windows.h>
26 #include "shellapi.h"
27 #include "shlobj.h"
28
29 #include "wine/test.h"
30
31 #ifndef FOF_NORECURSION
32 #define FOF_NORECURSION 0x1000
33 #endif
34
35 CHAR CURR_DIR[MAX_PATH];
36
37 static HMODULE hshell32;
38 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
39
40 static void InitFunctionPointers(void)
41 {
42     hshell32 = GetModuleHandleA("shell32.dll");
43
44     if(hshell32)
45         pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
46 }
47
48 /* creates a file with the specified name for tests */
49 static void createTestFile(const CHAR *name)
50 {
51     HANDLE file;
52     DWORD written;
53
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);
58     CloseHandle(file);
59 }
60
61 static BOOL file_exists(const CHAR *name)
62 {
63     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
64 }
65
66 /* initializes the tests */
67 static void init_shfo_tests(void)
68 {
69     int len;
70
71     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
72     len = lstrlenA(CURR_DIR);
73
74     if(len && (CURR_DIR[len-1] == '\\'))
75         CURR_DIR[len-1] = 0;
76
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");
86 }
87
88 /* cleans after tests */
89 static void clean_after_shfo_tests(void)
90 {
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");
112 }
113
114 /*
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
117  null characters
118 */
119 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
120 {
121     buf[0] = 0;
122     while (files[0])
123     {
124         strcpy(buf, CURR_DIR);
125         buf += strlen(buf);
126         buf[0] = '\\';
127         buf++;
128         strcpy(buf, files);
129         buf += strlen(buf) + 1;
130         files += strlen(files) + 1;
131     }
132     buf[0] = 0;
133 }
134
135
136 /* tests the FO_DELETE action */
137 static void test_delete(void)
138 {
139     SHFILEOPSTRUCTA shfo;
140     DWORD ret;
141     CHAR buf[MAX_PATH];
142
143     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
144     buf[strlen(buf) + 1] = '\0';
145
146     shfo.hwnd = NULL;
147     shfo.wFunc = FO_DELETE;
148     shfo.pFrom = buf;
149     shfo.pTo = "\0";
150     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
151     shfo.hNameMappings = NULL;
152     shfo.lpszProgressTitle = NULL;
153
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");
157
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");
161
162     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
163
164     ok(!SHFileOperationA(&shfo), "Directory removed\n");
165     ok(!file_exists("test4.txt"), "Directory should be removed\n");
166
167     ret = SHFileOperationA(&shfo);
168     ok(!ret, "The requested file does not exist, ret=%ld\n", ret);
169
170     init_shfo_tests();
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");
176
177     init_shfo_tests();
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");
183
184     /* FOF_FILESONLY does not delete a dir matching a wildcard */
185     init_shfo_tests();
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");
192
193     /* FOF_FILESONLY only deletes a dir if explicitly specified */
194     init_shfo_tests();
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");
200
201     /* try to delete an invalid filename */
202     init_shfo_tests();
203     shfo.pFrom = "\0";
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");
210
211     /* try an invalid function */
212     init_shfo_tests();
213     shfo.pFrom = "test1.txt\0";
214     shfo.wFunc = 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");
218
219     /* try an invalid list, only one null terminator */
220     init_shfo_tests();
221     shfo.pFrom = "";
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");
226
227     /* delete a dir, and then a file inside the dir, same as
228     * deleting a nonexistent file
229     */
230     init_shfo_tests();
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");
236
237     /* try the FOF_NORECURSION flag, continues deleting subdirs */
238     init_shfo_tests();
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");
245 }
246
247 /* tests the FO_RENAME action */
248 static void test_rename(void)
249 {
250     SHFILEOPSTRUCTA shfo, shfo2;
251     CHAR from[MAX_PATH];
252     CHAR to[MAX_PATH];
253     DWORD retval;
254
255     shfo.hwnd = NULL;
256     shfo.wFunc = FO_RENAME;
257     shfo.pFrom = from;
258     shfo.pTo = to;
259     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
260     shfo.hNameMappings = NULL;
261     shfo.lpszProgressTitle = NULL;
262
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");
268
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");
273
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");
280
281     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
282     shfo2.fFlags |= FOF_MULTIDESTFILES;
283
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");
290
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");
297
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);
302
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");
309
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);
314
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");
322
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");
329
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);
335
336     /* pFrom is valid, but pTo is empty */
337     shfo.pFrom = "test1.txt\0";
338     shfo.pTo = "\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");
342
343     /* pFrom is empty */
344     shfo.pFrom = "\0";
345     retval = SHFileOperationA(&shfo);
346         ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", retval);
347
348     /* pFrom is NULL, commented out because it crashes on nt 4.0 */
349 #if 0
350     shfo.pFrom = NULL;
351     retval = SHFileOperationA(&shfo);
352     ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", retval);
353 #endif
354 }
355
356 /* tests the FO_COPY action */
357 static void test_copy(void)
358 {
359     SHFILEOPSTRUCTA shfo, shfo2;
360     CHAR from[MAX_PATH];
361     CHAR to[MAX_PATH];
362     FILEOP_FLAGS tmp_flags;
363     DWORD retval;
364
365     shfo.hwnd = NULL;
366     shfo.wFunc = FO_COPY;
367     shfo.pFrom = from;
368     shfo.pTo = to;
369     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
370     shfo.hNameMappings = NULL;
371     shfo.lpszProgressTitle = NULL;
372
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");
378
379     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
380     shfo2.fFlags |= FOF_MULTIDESTFILES;
381
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");
390
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");
397
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");
402
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();
412
413     init_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();
421
422     init_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();
430
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 */
433     init_shfo_tests();
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);
439     if (!retval)
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");
442     else
443     {
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");
447     }
448     ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
449     shfo.fFlags = tmp_flags;
450
451     /* copy into a nonexistent directory */
452     init_shfo_tests();
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");
462
463     /* a relative dest directory is OK */
464     clean_after_shfo_tests();
465     init_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");
471
472     /* try to copy files to a file */
473     clean_after_shfo_tests();
474     init_shfo_tests();
475     shfo.pFrom = from;
476     shfo.pTo = to;
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");
483
484     /* try to copy many files to nonexistent directory */
485     DeleteFile(to);
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");
492
493     /* send in FOF_MULTIDESTFILES with too many destination files */
494     init_shfo_tests();
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");
502
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");
511
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");
521
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");
530
531     /* try a glob */
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");
538
539     /* try a glob with FOF_FILESONLY */
540     clean_after_shfo_tests();
541     init_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");
548
549     /* try a glob with FOF_MULTIDESTFILES and the same number
550     * of dest files that we would expect
551     */
552     clean_after_shfo_tests();
553     init_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");
562
563     /* copy one file to two others, second is ignored */
564     clean_after_shfo_tests();
565     init_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");
573
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");
581
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");
591
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");
603
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");
611
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");
620
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");
632
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");
641
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");
650
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);
657
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");
666
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");
674
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");
683 }
684
685 /* tests the FO_MOVE action */
686 static void test_move(void)
687 {
688     SHFILEOPSTRUCTA shfo, shfo2;
689     CHAR from[MAX_PATH];
690     CHAR to[MAX_PATH];
691     DWORD retval;
692
693     shfo.hwnd = NULL;
694     shfo.wFunc = FO_MOVE;
695     shfo.pFrom = from;
696     shfo.pTo = to;
697     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
698     shfo.hNameMappings = NULL;
699     shfo.lpszProgressTitle = NULL;
700
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");
706
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");
715
716     clean_after_shfo_tests();
717     init_shfo_tests();
718
719     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
720     shfo2.fFlags |= FOF_MULTIDESTFILES;
721
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");
730
731     init_shfo_tests();
732
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");
739
740     init_shfo_tests();
741
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");
746
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");
752
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");
761
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");
770
771     /* move one file to two others */
772     init_shfo_tests();
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");
780
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");
789
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");
797
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");
805
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");
812
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");
819
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");
826 }
827
828 static void test_sh_create_dir(void)
829 {
830     CHAR path[MAX_PATH];
831     int ret;
832
833     if(!pSHCreateDirectoryExA)
834     {
835         trace("skipping SHCreateDirectoryExA tests\n");
836         return;
837     }
838
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");
844
845     ret = pSHCreateDirectoryExA(NULL, path, NULL);
846     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
847
848     ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
849     ok(file_exists("c:\\testdir3"), "The directory is not created\n");
850 }
851
852 START_TEST(shlfileop)
853 {
854     InitFunctionPointers();
855
856     clean_after_shfo_tests();
857
858     init_shfo_tests();
859     test_delete();
860     clean_after_shfo_tests();
861
862     init_shfo_tests();
863     test_rename();
864     clean_after_shfo_tests();
865
866     init_shfo_tests();
867     test_copy();
868     clean_after_shfo_tests();
869
870     init_shfo_tests();
871     test_move();
872     clean_after_shfo_tests();
873
874     test_sh_create_dir();
875     clean_after_shfo_tests();
876 }