comctl32: A couple fixes for tab icon offsets.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define WINE_NOWINSOCK
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wtypes.h"
28 #include "shellapi.h"
29 #include "shlobj.h"
30
31 #include "wine/test.h"
32
33 CHAR CURR_DIR[MAX_PATH];
34
35 static HMODULE hshell32;
36 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
37
38 static void InitFunctionPointers(void)
39 {
40     hshell32 = GetModuleHandleA("shell32.dll");
41
42     if(hshell32)
43         pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
44 }
45
46 /* creates a file with the specified name for tests */
47 static void createTestFile(const CHAR *name)
48 {
49     HANDLE file;
50     DWORD written;
51
52     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
53     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
54     WriteFile(file, name, strlen(name), &written, NULL);
55     WriteFile(file, "\n", strlen("\n"), &written, NULL);
56     CloseHandle(file);
57 }
58
59 static BOOL file_exists(const CHAR *name)
60 {
61     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
62 }
63
64 /* initializes the tests */
65 static void init_shfo_tests(void)
66 {
67     int len;
68
69     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
70     len = lstrlenA(CURR_DIR);
71
72     if(len && (CURR_DIR[len-1] == '\\'))
73         CURR_DIR[len-1] = 0;
74
75     createTestFile("test1.txt");
76     createTestFile("test2.txt");
77     createTestFile("test3.txt");
78     createTestFile("test_5.txt");
79     CreateDirectoryA("test4.txt", NULL);
80     CreateDirectoryA("testdir2", NULL);
81     CreateDirectoryA("testdir2\\nested", NULL);
82     createTestFile("testdir2\\one.txt");
83     createTestFile("testdir2\\nested\\two.txt");
84 }
85
86 /* cleans after tests */
87 static void clean_after_shfo_tests(void)
88 {
89     DeleteFileA("test1.txt");
90     DeleteFileA("test2.txt");
91     DeleteFileA("test3.txt");
92     DeleteFileA("test_5.txt");
93     DeleteFileA("test4.txt\\test1.txt");
94     DeleteFileA("test4.txt\\test2.txt");
95     DeleteFileA("test4.txt\\test3.txt");
96     RemoveDirectoryA("test4.txt");
97     DeleteFileA("testdir2\\one.txt");
98     DeleteFileA("testdir2\\test1.txt");
99     DeleteFileA("testdir2\\test2.txt");
100     DeleteFileA("testdir2\\test3.txt");
101     DeleteFileA("testdir2\\test4.txt\\test1.txt");
102     DeleteFileA("testdir2\\nested\\two.txt");
103     RemoveDirectoryA("testdir2\\test4.txt");
104     RemoveDirectoryA("testdir2\\nested");
105     RemoveDirectoryA("testdir2");
106     DeleteFileA("nonexistent\\notreal\\test2.txt");
107     RemoveDirectoryA("nonexistent\\notreal");
108     RemoveDirectoryA("nonexistent");
109 }
110
111 /*
112  puts into the specified buffer file names with current directory.
113  files - string with file names, separated by null characters. Ends on a double
114  null characters
115 */
116 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
117 {
118     buf[0] = 0;
119     while (files[0])
120     {
121         strcpy(buf, CURR_DIR);
122         buf += strlen(buf);
123         buf[0] = '\\';
124         buf++;
125         strcpy(buf, files);
126         buf += strlen(buf) + 1;
127         files += strlen(files) + 1;
128     }
129     buf[0] = 0;
130 }
131
132
133 /* tests the FO_DELETE action */
134 static void test_delete(void)
135 {
136     SHFILEOPSTRUCTA shfo;
137     DWORD ret;
138     CHAR buf[MAX_PATH];
139
140     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
141     buf[strlen(buf) + 1] = '\0';
142
143     shfo.hwnd = NULL;
144     shfo.wFunc = FO_DELETE;
145     shfo.pFrom = buf;
146     shfo.pTo = "\0";
147     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
148     shfo.hNameMappings = NULL;
149     shfo.lpszProgressTitle = NULL;
150
151     ok(!SHFileOperationA(&shfo), "Deletion was successful\n");
152     ok(file_exists("test4.txt"), "Directory should not be removed\n");
153     ok(!file_exists("test1.txt"), "File should be removed\n");
154
155     ret = SHFileOperationA(&shfo);
156     ok(!ret, "Directory exists, but is not removed, ret=%ld\n", ret);
157     ok(file_exists("test4.txt"), "Directory should not be removed\n");
158
159     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
160
161     ok(!SHFileOperationA(&shfo), "Directory removed\n");
162     ok(!file_exists("test4.txt"), "Directory should be removed\n");
163
164     ret = SHFileOperationA(&shfo);
165     ok(!ret, "The requested file does not exist, ret=%ld\n", ret);
166
167     init_shfo_tests();
168     sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
169     buf[strlen(buf) + 1] = '\0';
170     ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Fill the subdirectory\n");
171     ok(!SHFileOperationA(&shfo), "Directory removed\n");
172     ok(!file_exists("test4.txt"), "Directory is removed\n");
173
174     init_shfo_tests();
175     shfo.pFrom = "test1.txt\0test4.txt\0";
176         ok(!SHFileOperationA(&shfo), "Directory and a file removed\n");
177         ok(!file_exists("test1.txt"), "The file should be removed\n");
178         ok(!file_exists("test4.txt"), "Directory should be removed\n");
179     ok(file_exists("test2.txt"), "This file should not be removed\n");
180
181     /* FOF_FILESONLY does not delete a dir matching a wildcard */
182     init_shfo_tests();
183     shfo.fFlags |= FOF_FILESONLY;
184     shfo.pFrom = "*.txt\0";
185         ok(!SHFileOperation(&shfo), "Failed to delete files\n");
186         ok(!file_exists("test1.txt"), "test1.txt should be removed\n");
187         ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
188     ok(file_exists("test4.txt"), "test4.txt should not be removed\n");
189
190     /* FOF_FILESONLY only deletes a dir if explicitly specified */
191     init_shfo_tests();
192     shfo.pFrom = "test_?.txt\0test4.txt\0";
193         ok(!SHFileOperation(&shfo), "Failed to delete files\n");
194         ok(!file_exists("test4.txt"), "test4.txt should be removed\n");
195         ok(!file_exists("test_5.txt"), "test_5.txt should be removed\n");
196     ok(file_exists("test1.txt"), "test1.txt should not be removed\n");
197
198     /* try to delete an invalid filename */
199     init_shfo_tests();
200     shfo.pFrom = "\0";
201     shfo.fFlags &= ~FOF_FILESONLY;
202     shfo.fAnyOperationsAborted = FALSE;
203     ret = SHFileOperation(&shfo);
204         ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", ret);
205     ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
206     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
207
208     /* try an invalid function */
209     init_shfo_tests();
210     shfo.pFrom = "test1.txt\0";
211     shfo.wFunc = 0;
212     ret = SHFileOperation(&shfo);
213         ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
214     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
215
216     /* try an invalid list, only one null terminator */
217     init_shfo_tests();
218     shfo.pFrom = "";
219     shfo.wFunc = FO_DELETE;
220     ret = SHFileOperation(&shfo);
221         ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", ret);
222     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
223
224     /* delete a dir, and then a file inside the dir, same as
225     * deleting a nonexistent file
226     */
227     init_shfo_tests();
228     shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
229     ret = SHFileOperation(&shfo);
230         ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %ld\n", ret);
231         ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n");
232     ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
233
234     /* try the FOF_NORECURSION flag, continues deleting subdirs */
235     init_shfo_tests();
236     shfo.pFrom = "testdir2\0";
237     shfo.fFlags |= FOF_NORECURSION;
238     ret = SHFileOperation(&shfo);
239         ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
240         ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
241         ok(!file_exists("testdir2\\nested"), "Expected testdir2\\nested to exist\n");
242 }
243
244 /* tests the FO_RENAME action */
245 static void test_rename(void)
246 {
247     SHFILEOPSTRUCTA shfo, shfo2;
248     CHAR from[MAX_PATH];
249     CHAR to[MAX_PATH];
250     DWORD retval;
251
252     shfo.hwnd = NULL;
253     shfo.wFunc = FO_RENAME;
254     shfo.pFrom = from;
255     shfo.pTo = to;
256     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
257     shfo.hNameMappings = NULL;
258     shfo.lpszProgressTitle = NULL;
259
260     set_curr_dir_path(from, "test1.txt\0");
261     set_curr_dir_path(to, "test4.txt\0");
262     ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
263        "when specifying directory name only\n");
264     ok(file_exists("test1.txt"), "The file is removed\n");
265
266     set_curr_dir_path(from, "test3.txt\0");
267     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
268     ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
269     ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
270
271     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
272     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
273     retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
274     ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
275        "Can't rename many files, retval = %ld\n", retval);
276     ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
277
278     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
279     shfo2.fFlags |= FOF_MULTIDESTFILES;
280
281     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
282     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
283     retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
284     ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
285        "Can't rename many files, retval = %ld\n", retval);
286     ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
287
288     set_curr_dir_path(from, "test1.txt\0");
289     set_curr_dir_path(to, "test6.txt\0");
290     retval = SHFileOperationA(&shfo);
291     ok(!retval, "Rename file failed, retval = %ld\n", retval);
292     ok(!file_exists("test1.txt"), "The file is not renamed\n");
293     ok(file_exists("test6.txt"), "The file is not renamed\n");
294
295     set_curr_dir_path(from, "test6.txt\0");
296     set_curr_dir_path(to, "test1.txt\0");
297     retval = SHFileOperationA(&shfo);
298     ok(!retval, "Rename file back failed, retval = %ld\n", retval);
299
300     set_curr_dir_path(from, "test4.txt\0");
301     set_curr_dir_path(to, "test6.txt\0");
302     retval = SHFileOperationA(&shfo);
303     ok(!retval, "Rename dir failed, retval = %ld\n", retval);
304     ok(!file_exists("test4.txt"), "The dir is not renamed\n");
305     ok(file_exists("test6.txt"), "The dir is not renamed\n");
306
307     set_curr_dir_path(from, "test6.txt\0");
308     set_curr_dir_path(to, "test4.txt\0");
309     retval = SHFileOperationA(&shfo);
310     ok(!retval, "Rename dir back failed, retval = %ld\n", retval);
311
312     /* try to rename more than one file to a single file */
313     shfo.pFrom = "test1.txt\0test2.txt\0";
314     shfo.pTo = "a.txt\0";
315     retval = SHFileOperationA(&shfo);
316     ok(retval == ERROR_GEN_FAILURE, "Expected ERROR_GEN_FAILURE, got %ld\n", retval);
317     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
318     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
319
320     /* pFrom doesn't exist */
321     shfo.pFrom = "idontexist\0";
322     shfo.pTo = "newfile\0";
323     retval = SHFileOperationA(&shfo);
324     ok(retval == 1026, "Expected 1026, got %ld\n", retval);
325     ok(!file_exists("newfile"), "Expected newfile to not exist\n");
326
327     /* pTo already exist */
328     shfo.pFrom = "test1.txt\0";
329     shfo.pTo = "test2.txt\0";
330     retval = SHFileOperationA(&shfo);
331         ok(retval == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %ld\n", retval);
332
333     /* pFrom is valid, but pTo is empty */
334     shfo.pFrom = "test1.txt\0";
335     shfo.pTo = "\0";
336     retval = SHFileOperationA(&shfo);
337         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
338     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
339
340     /* pFrom is empty */
341     shfo.pFrom = "\0";
342     retval = SHFileOperationA(&shfo);
343         ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", retval);
344
345     /* pFrom is NULL */
346     shfo.pFrom = NULL;
347     retval = SHFileOperationA(&shfo);
348         ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", retval);
349 }
350
351 /* tests the FO_COPY action */
352 static void test_copy(void)
353 {
354     SHFILEOPSTRUCTA shfo, shfo2;
355     CHAR from[MAX_PATH];
356     CHAR to[MAX_PATH];
357     FILEOP_FLAGS tmp_flags;
358     DWORD retval;
359
360     shfo.hwnd = NULL;
361     shfo.wFunc = FO_COPY;
362     shfo.pFrom = from;
363     shfo.pTo = to;
364     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
365     shfo.hNameMappings = NULL;
366     shfo.lpszProgressTitle = NULL;
367
368     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
369     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
370     ok(SHFileOperationA(&shfo), "Can't copy many files\n");
371     ok(!file_exists("test6.txt"), "The file is not copied - many files are "
372        "specified as a target\n");
373
374     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
375     shfo2.fFlags |= FOF_MULTIDESTFILES;
376
377     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
378     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
379     ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
380     ok(file_exists("test6.txt"), "The file is copied - many files are "
381        "specified as a target\n");
382     DeleteFileA("test6.txt");
383     DeleteFileA("test7.txt");
384     RemoveDirectoryA("test8.txt");
385
386     /* number of sources do not correspond to number of targets */
387     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
388     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
389     ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
390     ok(!file_exists("test6.txt"), "The file is not copied - many files are "
391        "specified as a target\n");
392
393     set_curr_dir_path(from, "test1.txt\0");
394     set_curr_dir_path(to, "test4.txt\0");
395     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
396     ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
397
398     set_curr_dir_path(from, "test?.txt\0");
399     set_curr_dir_path(to, "testdir2\0");
400     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
401     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
402     ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
403     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
404     ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
405     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
406     clean_after_shfo_tests();
407
408     init_shfo_tests();
409     shfo.fFlags |= FOF_FILESONLY;
410     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
411     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
412     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
413     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
414     ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
415     clean_after_shfo_tests();
416
417     init_shfo_tests();
418     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
419     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
420     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
421     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
422     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
423     ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
424     clean_after_shfo_tests();
425
426     /* Copying multiple files with one not existing as source, fails the
427        entire operation in Win98/ME/2K/XP, but not in 95/NT */
428     init_shfo_tests();
429     tmp_flags = shfo.fFlags;
430     set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
431     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
432     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
433     retval = SHFileOperationA(&shfo);
434     if (!retval)
435         /* Win 95/NT returns success but copies only the files up to the nonexistent source */
436         ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
437     else
438     {
439         /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
440         ok(retval == 1026, "Files are copied to other directory\n");
441         ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
442     }
443     ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
444     shfo.fFlags = tmp_flags;
445
446     /* copy into a nonexistent directory */
447     init_shfo_tests();
448     shfo.fFlags = FOF_NOCONFIRMMKDIR;
449     set_curr_dir_path(from, "test1.txt\0");
450     set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
451     retval= SHFileOperation(&shfo);
452         ok(!retval, "Error copying into nonexistent directory\n");
453         ok(file_exists("nonexistent"), "nonexistent not created\n");
454         ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
455         ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
456     ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
457
458     /* a relative dest directory is OK */
459     clean_after_shfo_tests();
460     init_shfo_tests();
461     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
462     shfo.pTo = "testdir2\0";
463     retval = SHFileOperation(&shfo);
464     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
465     ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
466
467     /* try to copy files to a file */
468     clean_after_shfo_tests();
469     init_shfo_tests();
470     shfo.pFrom = from;
471     shfo.pTo = to;
472     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
473     set_curr_dir_path(to, "test3.txt\0");
474     retval = SHFileOperation(&shfo);
475         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
476     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
477     ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
478
479     /* try to copy many files to nonexistent directory */
480     DeleteFile(to);
481     shfo.fAnyOperationsAborted = FALSE;
482     retval = SHFileOperation(&shfo);
483         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
484         ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
485         ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
486         ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
487
488     /* send in FOF_MULTIDESTFILES with too many destination files */
489     init_shfo_tests();
490     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
491     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
492     shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
493     retval = SHFileOperation(&shfo);
494         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
495     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
496     ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
497
498     /* send in FOF_MULTIDESTFILES with too many destination files */
499     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
500     shfo.pTo = "e.txt\0f.txt\0";
501     shfo.fAnyOperationsAborted = FALSE;
502     retval = SHFileOperation(&shfo);
503         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
504     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
505     ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
506
507     /* use FOF_MULTIDESTFILES with files and a source directory */
508     shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
509     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
510     shfo.fAnyOperationsAborted = FALSE;
511     retval = SHFileOperation(&shfo);
512     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
513     ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
514     ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
515     ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
516
517     /* try many dest files without FOF_MULTIDESTFILES flag */
518     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
519     shfo.pTo = "a.txt\0b.txt\0c.txt\0";
520     shfo.fAnyOperationsAborted = FALSE;
521     shfo.fFlags &= ~FOF_MULTIDESTFILES;
522     retval = SHFileOperation(&shfo);
523         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
524     ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
525
526     /* try a glob */
527     shfo.pFrom = "test?.txt\0";
528     shfo.pTo = "testdir2\0";
529     shfo.fFlags &= ~FOF_MULTIDESTFILES;
530     retval = SHFileOperation(&shfo);
531         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
532         ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
533
534     /* try a glob with FOF_FILESONLY */
535     clean_after_shfo_tests();
536     init_shfo_tests();
537     shfo.pFrom = "test?.txt\0";
538     shfo.fFlags |= FOF_FILESONLY;
539     retval = SHFileOperation(&shfo);
540         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
541         ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
542     ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
543
544     /* try a glob with FOF_MULTIDESTFILES and the same number
545     * of dest files that we would expect
546     */
547     clean_after_shfo_tests();
548     init_shfo_tests();
549     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
550     shfo.fFlags &= ~FOF_FILESONLY;
551     shfo.fFlags |= FOF_MULTIDESTFILES;
552     retval = SHFileOperation(&shfo);
553         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
554     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
555     ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
556     ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
557
558     /* copy one file to two others, second is ignored */
559     clean_after_shfo_tests();
560     init_shfo_tests();
561     shfo.pFrom = "test1.txt\0";
562     shfo.pTo = "b.txt\0c.txt\0";
563     shfo.fAnyOperationsAborted = FALSE;
564     retval = SHFileOperation(&shfo);
565         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
566         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
567     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
568
569     /* copy two file to three others, all fail */
570     shfo.pFrom = "test1.txt\0test2.txt\0";
571     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
572     retval = SHFileOperation(&shfo);
573         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
574     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
575     ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
576
577     /* copy one file and one directory to three others */
578     shfo.pFrom = "test1.txt\0test4.txt\0";
579     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
580     shfo.fAnyOperationsAborted = FALSE;
581     retval = SHFileOperation(&shfo);
582         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
583     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
584     ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
585     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
586
587     /* copy a directory with a file beneath it, plus some files */
588     createTestFile("test4.txt\\a.txt");
589     shfo.pFrom = "test4.txt\0test1.txt\0";
590     shfo.pTo = "testdir2\0";
591     shfo.fFlags &= ~FOF_MULTIDESTFILES;
592     shfo.fAnyOperationsAborted = FALSE;
593     retval = SHFileOperation(&shfo);
594     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
595     ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
596     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
597     ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
598
599     /* copy one directory and a file in that dir to another dir */
600     shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
601     shfo.pTo = "testdir2\0";
602     retval = SHFileOperation(&shfo);
603     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
604     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
605     ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
606
607     /* copy a file in a directory first, and then the directory to a nonexistent dir */
608     shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
609     shfo.pTo = "nonexistent\0";
610     retval = SHFileOperation(&shfo);
611         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
612     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
613     ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
614     DeleteFile("test4.txt\\a.txt");
615
616     /* destination is same as source file */
617     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
618     shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
619     shfo.fAnyOperationsAborted = FALSE;
620     shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
621     retval = SHFileOperation(&shfo);
622         ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
623            "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %ld\n", retval);
624         ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
625         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
626     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
627
628     /* destination is same as source directory */
629     shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
630     shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
631     shfo.fAnyOperationsAborted = FALSE;
632     retval = SHFileOperation(&shfo);
633         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
634         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
635     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
636
637     /* copy a directory into itself, error displayed in UI */
638     shfo.pFrom = "test4.txt\0";
639     shfo.pTo = "test4.txt\\newdir\0";
640     shfo.fFlags &= ~FOF_MULTIDESTFILES;
641     shfo.fAnyOperationsAborted = FALSE;
642     retval = SHFileOperation(&shfo);
643         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
644     ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
645
646     /* copy a directory to itself, error displayed in UI */
647     shfo.pFrom = "test4.txt\0";
648     shfo.pTo = "test4.txt\0";
649     shfo.fAnyOperationsAborted = FALSE;
650     retval = SHFileOperation(&shfo);
651         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
652
653     /* copy a file into a directory, and the directory into itself */
654     shfo.pFrom = "test1.txt\0test4.txt\0";
655     shfo.pTo = "test4.txt\0";
656     shfo.fAnyOperationsAborted = FALSE;
657     shfo.fFlags |= FOF_NOCONFIRMATION;
658     retval = SHFileOperation(&shfo);
659         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
660     ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
661
662     /* copy a file to a file, and the directory into itself */
663     shfo.pFrom = "test1.txt\0test4.txt\0";
664     shfo.pTo = "test4.txt\\a.txt\0";
665     shfo.fAnyOperationsAborted = FALSE;
666     retval = SHFileOperation(&shfo);
667         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
668     ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
669
670     /* copy a nonexistent file to a nonexistent directory */
671     shfo.pFrom = "e.txt\0";
672     shfo.pTo = "nonexistent\0";
673     shfo.fAnyOperationsAborted = FALSE;
674     retval = SHFileOperation(&shfo);
675     ok(retval == 1026, "Expected 1026, got %ld\n", retval);
676     ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
677     ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
678 }
679
680 /* tests the FO_MOVE action */
681 static void test_move(void)
682 {
683     SHFILEOPSTRUCTA shfo, shfo2;
684     CHAR from[MAX_PATH];
685     CHAR to[MAX_PATH];
686     DWORD retval;
687
688     shfo.hwnd = NULL;
689     shfo.wFunc = FO_MOVE;
690     shfo.pFrom = from;
691     shfo.pTo = to;
692     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
693     shfo.hNameMappings = NULL;
694     shfo.lpszProgressTitle = NULL;
695
696     set_curr_dir_path(from, "test1.txt\0");
697     set_curr_dir_path(to, "test4.txt\0");
698     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
699     ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
700     ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
701
702     set_curr_dir_path(from, "test?.txt\0");
703     set_curr_dir_path(to, "testdir2\0");
704     ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
705     ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
706     ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
707     ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
708     ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
709     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
710
711     clean_after_shfo_tests();
712     init_shfo_tests();
713
714     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
715     shfo2.fFlags |= FOF_MULTIDESTFILES;
716
717     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
718     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
719     ok(!SHFileOperationA(&shfo2), "Move many files\n");
720     ok(file_exists("test6.txt"), "The file is moved - many files are "
721        "specified as a target\n");
722     DeleteFileA("test6.txt");
723     DeleteFileA("test7.txt");
724     RemoveDirectoryA("test8.txt");
725
726     init_shfo_tests();
727
728     /* number of sources do not correspond to number of targets */
729     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
730     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
731     ok(SHFileOperationA(&shfo2), "Can't move many files\n");
732     ok(!file_exists("test6.txt"), "The file is not moved - many files are "
733        "specified as a target\n");
734
735     init_shfo_tests();
736
737     set_curr_dir_path(from, "test3.txt\0");
738     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
739     ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
740     ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
741
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(&shfo), "Cannot move many files\n");
745     ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
746     ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
747
748     set_curr_dir_path(from, "test1.txt\0");
749     set_curr_dir_path(to, "test6.txt\0");
750     ok(!SHFileOperationA(&shfo), "Move file\n");
751     ok(!file_exists("test1.txt"), "The file is moved\n");
752     ok(file_exists("test6.txt"), "The file is moved\n");
753     set_curr_dir_path(from, "test6.txt\0");
754     set_curr_dir_path(to, "test1.txt\0");
755     ok(!SHFileOperationA(&shfo), "Move file back\n");
756
757     set_curr_dir_path(from, "test4.txt\0");
758     set_curr_dir_path(to, "test6.txt\0");
759     ok(!SHFileOperationA(&shfo), "Move dir\n");
760     ok(!file_exists("test4.txt"), "The dir is moved\n");
761     ok(file_exists("test6.txt"), "The dir is moved\n");
762     set_curr_dir_path(from, "test6.txt\0");
763     set_curr_dir_path(to, "test4.txt\0");
764     ok(!SHFileOperationA(&shfo), "Move dir back\n");
765
766     /* move one file to two others */
767     init_shfo_tests();
768     shfo.pFrom = "test1.txt\0";
769     shfo.pTo = "a.txt\0b.txt\0";
770     retval = SHFileOperationA(&shfo);
771         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
772         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
773         ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
774     ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
775
776     /* move two files to one other */
777     shfo.pFrom = "test2.txt\0test3.txt\0";
778     shfo.pTo = "test1.txt\0";
779     retval = SHFileOperationA(&shfo);
780         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
781         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
782     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
783     ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
784
785     /* move a directory into itself */
786     shfo.pFrom = "test4.txt\0";
787     shfo.pTo = "test4.txt\\b.txt\0";
788     retval = SHFileOperationA(&shfo);
789         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
790     ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
791     ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
792
793     /* move many files without FOF_MULTIDESTFILES */
794     shfo.pFrom = "test2.txt\0test3.txt\0";
795     shfo.pTo = "d.txt\0e.txt\0";
796     retval = SHFileOperationA(&shfo);
797         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
798     ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
799     ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
800
801     /* number of sources != number of targets */
802     shfo.pTo = "d.txt\0";
803     shfo.fFlags |= FOF_MULTIDESTFILES;
804     retval = SHFileOperationA(&shfo);
805         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
806     ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
807
808     /* FO_MOVE does not create dest directories */
809     shfo.pFrom = "test2.txt\0";
810     shfo.pTo = "dir1\\dir2\\test2.txt\0";
811     retval = SHFileOperationA(&shfo);
812         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
813     ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
814
815     /* try to overwrite an existing file */
816     shfo.pTo = "test3.txt\0";
817     retval = SHFileOperationA(&shfo);
818         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
819         ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
820     ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
821 }
822
823 static void test_sh_create_dir(void)
824 {
825     CHAR path[MAX_PATH];
826     int ret;
827
828     if(!pSHCreateDirectoryExA)
829     {
830         trace("skipping SHCreateDirectoryExA tests\n");
831         return;
832     }
833
834     set_curr_dir_path(path, "testdir2\\test4.txt\0");
835     ret = pSHCreateDirectoryExA(NULL, path, NULL);
836     ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
837     ok(file_exists("testdir2"), "The first directory is not created\n");
838     ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
839
840     ret = pSHCreateDirectoryExA(NULL, path, NULL);
841     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
842 }
843
844 START_TEST(shlfileop)
845 {
846     InitFunctionPointers();
847
848     clean_after_shfo_tests();
849
850     init_shfo_tests();
851     test_delete();
852     clean_after_shfo_tests();
853
854     init_shfo_tests();
855     test_rename();
856     clean_after_shfo_tests();
857
858     init_shfo_tests();
859     test_copy();
860     clean_after_shfo_tests();
861
862     init_shfo_tests();
863     test_move();
864     clean_after_shfo_tests();
865
866     test_sh_create_dir();
867     clean_after_shfo_tests();
868 }