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