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