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