shell32/tests: Comment out a test that crashes on windows nt 4.0.
[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, commented out because it crashes on nt 4.0 */
347 #if 0
348     shfo.pFrom = NULL;
349     retval = SHFileOperationA(&shfo);
350     ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", retval);
351 #endif
352 }
353
354 /* tests the FO_COPY action */
355 static void test_copy(void)
356 {
357     SHFILEOPSTRUCTA shfo, shfo2;
358     CHAR from[MAX_PATH];
359     CHAR to[MAX_PATH];
360     FILEOP_FLAGS tmp_flags;
361     DWORD retval;
362
363     shfo.hwnd = NULL;
364     shfo.wFunc = FO_COPY;
365     shfo.pFrom = from;
366     shfo.pTo = to;
367     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
368     shfo.hNameMappings = NULL;
369     shfo.lpszProgressTitle = NULL;
370
371     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
372     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
373     ok(SHFileOperationA(&shfo), "Can't copy many files\n");
374     ok(!file_exists("test6.txt"), "The file is not copied - many files are "
375        "specified as a target\n");
376
377     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
378     shfo2.fFlags |= FOF_MULTIDESTFILES;
379
380     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
381     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
382     ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
383     ok(file_exists("test6.txt"), "The file is copied - many files are "
384        "specified as a target\n");
385     DeleteFileA("test6.txt");
386     DeleteFileA("test7.txt");
387     RemoveDirectoryA("test8.txt");
388
389     /* number of sources do not correspond to number of targets */
390     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
391     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
392     ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
393     ok(!file_exists("test6.txt"), "The file is not copied - many files are "
394        "specified as a target\n");
395
396     set_curr_dir_path(from, "test1.txt\0");
397     set_curr_dir_path(to, "test4.txt\0");
398     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
399     ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
400
401     set_curr_dir_path(from, "test?.txt\0");
402     set_curr_dir_path(to, "testdir2\0");
403     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
404     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
405     ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
406     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
407     ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
408     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
409     clean_after_shfo_tests();
410
411     init_shfo_tests();
412     shfo.fFlags |= FOF_FILESONLY;
413     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
414     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
415     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
416     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
417     ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
418     clean_after_shfo_tests();
419
420     init_shfo_tests();
421     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
422     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
423     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
424     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
425     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
426     ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
427     clean_after_shfo_tests();
428
429     /* Copying multiple files with one not existing as source, fails the
430        entire operation in Win98/ME/2K/XP, but not in 95/NT */
431     init_shfo_tests();
432     tmp_flags = shfo.fFlags;
433     set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
434     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
435     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
436     retval = SHFileOperationA(&shfo);
437     if (!retval)
438         /* Win 95/NT returns success but copies only the files up to the nonexistent source */
439         ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
440     else
441     {
442         /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
443         ok(retval == 1026, "Files are copied to other directory\n");
444         ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
445     }
446     ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
447     shfo.fFlags = tmp_flags;
448
449     /* copy into a nonexistent directory */
450     init_shfo_tests();
451     shfo.fFlags = FOF_NOCONFIRMMKDIR;
452     set_curr_dir_path(from, "test1.txt\0");
453     set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
454     retval= SHFileOperation(&shfo);
455         ok(!retval, "Error copying into nonexistent directory\n");
456         ok(file_exists("nonexistent"), "nonexistent not created\n");
457         ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
458         ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
459     ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
460
461     /* a relative dest directory is OK */
462     clean_after_shfo_tests();
463     init_shfo_tests();
464     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
465     shfo.pTo = "testdir2\0";
466     retval = SHFileOperation(&shfo);
467     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
468     ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
469
470     /* try to copy files to a file */
471     clean_after_shfo_tests();
472     init_shfo_tests();
473     shfo.pFrom = from;
474     shfo.pTo = to;
475     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
476     set_curr_dir_path(to, "test3.txt\0");
477     retval = SHFileOperation(&shfo);
478         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
479     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
480     ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
481
482     /* try to copy many files to nonexistent directory */
483     DeleteFile(to);
484     shfo.fAnyOperationsAborted = FALSE;
485     retval = SHFileOperation(&shfo);
486         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
487         ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
488         ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
489         ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
490
491     /* send in FOF_MULTIDESTFILES with too many destination files */
492     init_shfo_tests();
493     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
494     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
495     shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
496     retval = SHFileOperation(&shfo);
497         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
498     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
499     ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
500
501     /* send in FOF_MULTIDESTFILES with too many destination files */
502     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
503     shfo.pTo = "e.txt\0f.txt\0";
504     shfo.fAnyOperationsAborted = FALSE;
505     retval = SHFileOperation(&shfo);
506         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
507     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
508     ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
509
510     /* use FOF_MULTIDESTFILES with files and a source directory */
511     shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
512     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
513     shfo.fAnyOperationsAborted = FALSE;
514     retval = SHFileOperation(&shfo);
515     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
516     ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
517     ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
518     ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
519
520     /* try many dest files without FOF_MULTIDESTFILES flag */
521     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
522     shfo.pTo = "a.txt\0b.txt\0c.txt\0";
523     shfo.fAnyOperationsAborted = FALSE;
524     shfo.fFlags &= ~FOF_MULTIDESTFILES;
525     retval = SHFileOperation(&shfo);
526         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
527     ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
528
529     /* try a glob */
530     shfo.pFrom = "test?.txt\0";
531     shfo.pTo = "testdir2\0";
532     shfo.fFlags &= ~FOF_MULTIDESTFILES;
533     retval = SHFileOperation(&shfo);
534         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
535         ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
536
537     /* try a glob with FOF_FILESONLY */
538     clean_after_shfo_tests();
539     init_shfo_tests();
540     shfo.pFrom = "test?.txt\0";
541     shfo.fFlags |= FOF_FILESONLY;
542     retval = SHFileOperation(&shfo);
543         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
544         ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
545     ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
546
547     /* try a glob with FOF_MULTIDESTFILES and the same number
548     * of dest files that we would expect
549     */
550     clean_after_shfo_tests();
551     init_shfo_tests();
552     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
553     shfo.fFlags &= ~FOF_FILESONLY;
554     shfo.fFlags |= FOF_MULTIDESTFILES;
555     retval = SHFileOperation(&shfo);
556         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
557     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
558     ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
559     ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
560
561     /* copy one file to two others, second is ignored */
562     clean_after_shfo_tests();
563     init_shfo_tests();
564     shfo.pFrom = "test1.txt\0";
565     shfo.pTo = "b.txt\0c.txt\0";
566     shfo.fAnyOperationsAborted = FALSE;
567     retval = SHFileOperation(&shfo);
568         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
569         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
570     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
571
572     /* copy two file to three others, all fail */
573     shfo.pFrom = "test1.txt\0test2.txt\0";
574     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
575     retval = SHFileOperation(&shfo);
576         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
577     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
578     ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
579
580     /* copy one file and one directory to three others */
581     shfo.pFrom = "test1.txt\0test4.txt\0";
582     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
583     shfo.fAnyOperationsAborted = FALSE;
584     retval = SHFileOperation(&shfo);
585         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
586     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
587     ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
588     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
589
590     /* copy a directory with a file beneath it, plus some files */
591     createTestFile("test4.txt\\a.txt");
592     shfo.pFrom = "test4.txt\0test1.txt\0";
593     shfo.pTo = "testdir2\0";
594     shfo.fFlags &= ~FOF_MULTIDESTFILES;
595     shfo.fAnyOperationsAborted = FALSE;
596     retval = SHFileOperation(&shfo);
597     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
598     ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
599     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
600     ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
601
602     /* copy one directory and a file in that dir to another dir */
603     shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
604     shfo.pTo = "testdir2\0";
605     retval = SHFileOperation(&shfo);
606     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
607     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
608     ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
609
610     /* copy a file in a directory first, and then the directory to a nonexistent dir */
611     shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
612     shfo.pTo = "nonexistent\0";
613     retval = SHFileOperation(&shfo);
614         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
615     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
616     ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
617     DeleteFile("test4.txt\\a.txt");
618
619     /* destination is same as source file */
620     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
621     shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
622     shfo.fAnyOperationsAborted = FALSE;
623     shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
624     retval = SHFileOperation(&shfo);
625         ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
626            "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %ld\n", retval);
627         ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
628         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
629     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
630
631     /* destination is same as source directory */
632     shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
633     shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
634     shfo.fAnyOperationsAborted = FALSE;
635     retval = SHFileOperation(&shfo);
636         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
637         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
638     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
639
640     /* copy a directory into itself, error displayed in UI */
641     shfo.pFrom = "test4.txt\0";
642     shfo.pTo = "test4.txt\\newdir\0";
643     shfo.fFlags &= ~FOF_MULTIDESTFILES;
644     shfo.fAnyOperationsAborted = FALSE;
645     retval = SHFileOperation(&shfo);
646         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
647     ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
648
649     /* copy a directory to itself, error displayed in UI */
650     shfo.pFrom = "test4.txt\0";
651     shfo.pTo = "test4.txt\0";
652     shfo.fAnyOperationsAborted = FALSE;
653     retval = SHFileOperation(&shfo);
654         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
655
656     /* copy a file into a directory, and the directory into itself */
657     shfo.pFrom = "test1.txt\0test4.txt\0";
658     shfo.pTo = "test4.txt\0";
659     shfo.fAnyOperationsAborted = FALSE;
660     shfo.fFlags |= FOF_NOCONFIRMATION;
661     retval = SHFileOperation(&shfo);
662         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
663     ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
664
665     /* copy a file to a file, and the directory into itself */
666     shfo.pFrom = "test1.txt\0test4.txt\0";
667     shfo.pTo = "test4.txt\\a.txt\0";
668     shfo.fAnyOperationsAborted = FALSE;
669     retval = SHFileOperation(&shfo);
670         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
671     ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
672
673     /* copy a nonexistent file to a nonexistent directory */
674     shfo.pFrom = "e.txt\0";
675     shfo.pTo = "nonexistent\0";
676     shfo.fAnyOperationsAborted = FALSE;
677     retval = SHFileOperation(&shfo);
678     ok(retval == 1026, "Expected 1026, got %ld\n", retval);
679     ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
680     ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
681 }
682
683 /* tests the FO_MOVE action */
684 static void test_move(void)
685 {
686     SHFILEOPSTRUCTA shfo, shfo2;
687     CHAR from[MAX_PATH];
688     CHAR to[MAX_PATH];
689     DWORD retval;
690
691     shfo.hwnd = NULL;
692     shfo.wFunc = FO_MOVE;
693     shfo.pFrom = from;
694     shfo.pTo = to;
695     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
696     shfo.hNameMappings = NULL;
697     shfo.lpszProgressTitle = NULL;
698
699     set_curr_dir_path(from, "test1.txt\0");
700     set_curr_dir_path(to, "test4.txt\0");
701     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
702     ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
703     ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
704
705     set_curr_dir_path(from, "test?.txt\0");
706     set_curr_dir_path(to, "testdir2\0");
707     ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
708     ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
709     ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
710     ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
711     ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
712     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
713
714     clean_after_shfo_tests();
715     init_shfo_tests();
716
717     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
718     shfo2.fFlags |= FOF_MULTIDESTFILES;
719
720     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
721     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
722     ok(!SHFileOperationA(&shfo2), "Move many files\n");
723     ok(file_exists("test6.txt"), "The file is moved - many files are "
724        "specified as a target\n");
725     DeleteFileA("test6.txt");
726     DeleteFileA("test7.txt");
727     RemoveDirectoryA("test8.txt");
728
729     init_shfo_tests();
730
731     /* number of sources do not correspond to number of targets */
732     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
733     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
734     ok(SHFileOperationA(&shfo2), "Can't move many files\n");
735     ok(!file_exists("test6.txt"), "The file is not moved - many files are "
736        "specified as a target\n");
737
738     init_shfo_tests();
739
740     set_curr_dir_path(from, "test3.txt\0");
741     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
742     ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
743     ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
744
745     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
746     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
747     ok(SHFileOperationA(&shfo), "Cannot move many files\n");
748     ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
749     ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
750
751     set_curr_dir_path(from, "test1.txt\0");
752     set_curr_dir_path(to, "test6.txt\0");
753     ok(!SHFileOperationA(&shfo), "Move file\n");
754     ok(!file_exists("test1.txt"), "The file is moved\n");
755     ok(file_exists("test6.txt"), "The file is moved\n");
756     set_curr_dir_path(from, "test6.txt\0");
757     set_curr_dir_path(to, "test1.txt\0");
758     ok(!SHFileOperationA(&shfo), "Move file back\n");
759
760     set_curr_dir_path(from, "test4.txt\0");
761     set_curr_dir_path(to, "test6.txt\0");
762     ok(!SHFileOperationA(&shfo), "Move dir\n");
763     ok(!file_exists("test4.txt"), "The dir is moved\n");
764     ok(file_exists("test6.txt"), "The dir is moved\n");
765     set_curr_dir_path(from, "test6.txt\0");
766     set_curr_dir_path(to, "test4.txt\0");
767     ok(!SHFileOperationA(&shfo), "Move dir back\n");
768
769     /* move one file to two others */
770     init_shfo_tests();
771     shfo.pFrom = "test1.txt\0";
772     shfo.pTo = "a.txt\0b.txt\0";
773     retval = SHFileOperationA(&shfo);
774         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
775         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
776         ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
777     ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
778
779     /* move two files to one other */
780     shfo.pFrom = "test2.txt\0test3.txt\0";
781     shfo.pTo = "test1.txt\0";
782     retval = SHFileOperationA(&shfo);
783         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
784         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
785     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
786     ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
787
788     /* move a directory into itself */
789     shfo.pFrom = "test4.txt\0";
790     shfo.pTo = "test4.txt\\b.txt\0";
791     retval = SHFileOperationA(&shfo);
792         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
793     ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
794     ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
795
796     /* move many files without FOF_MULTIDESTFILES */
797     shfo.pFrom = "test2.txt\0test3.txt\0";
798     shfo.pTo = "d.txt\0e.txt\0";
799     retval = SHFileOperationA(&shfo);
800         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
801     ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
802     ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
803
804     /* number of sources != number of targets */
805     shfo.pTo = "d.txt\0";
806     shfo.fFlags |= FOF_MULTIDESTFILES;
807     retval = SHFileOperationA(&shfo);
808         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
809     ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
810
811     /* FO_MOVE does not create dest directories */
812     shfo.pFrom = "test2.txt\0";
813     shfo.pTo = "dir1\\dir2\\test2.txt\0";
814     retval = SHFileOperationA(&shfo);
815         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %ld\n", retval);
816     ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
817
818     /* try to overwrite an existing file */
819     shfo.pTo = "test3.txt\0";
820     retval = SHFileOperationA(&shfo);
821         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", retval);
822         ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
823     ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
824 }
825
826 static void test_sh_create_dir(void)
827 {
828     CHAR path[MAX_PATH];
829     int ret;
830
831     if(!pSHCreateDirectoryExA)
832     {
833         trace("skipping SHCreateDirectoryExA tests\n");
834         return;
835     }
836
837     set_curr_dir_path(path, "testdir2\\test4.txt\0");
838     ret = pSHCreateDirectoryExA(NULL, path, NULL);
839     ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
840     ok(file_exists("testdir2"), "The first directory is not created\n");
841     ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
842
843     ret = pSHCreateDirectoryExA(NULL, path, NULL);
844     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
845
846     ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
847     ok(file_exists("c:\\testdir3"), "The directory is not created\n");
848 }
849
850 START_TEST(shlfileop)
851 {
852     InitFunctionPointers();
853
854     clean_after_shfo_tests();
855
856     init_shfo_tests();
857     test_delete();
858     clean_after_shfo_tests();
859
860     init_shfo_tests();
861     test_rename();
862     clean_after_shfo_tests();
863
864     init_shfo_tests();
865     test_copy();
866     clean_after_shfo_tests();
867
868     init_shfo_tests();
869     test_move();
870     clean_after_shfo_tests();
871
872     test_sh_create_dir();
873     clean_after_shfo_tests();
874 }