comctl32: Update the version in the created version to the highest current version...
[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 static CHAR CURR_DIR[MAX_PATH];
36 static const WCHAR UNICODE_PATH[] = {'c',':','\\',0x00c4,'\0','\0'};
37     /* "c:\Ä", or "c:\A" with diaeresis */
38     /* Double-null termination needed for pFrom field of SHFILEOPSTRUCT */
39
40 static HMODULE hshell32;
41 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
42 static int (WINAPI *pSHCreateDirectoryExW)(HWND, LPCWSTR, LPSECURITY_ATTRIBUTES);
43 static int (WINAPI *pSHPathPrepareForWriteA)(HWND, IUnknown*, LPCSTR, DWORD);
44 static int (WINAPI *pSHPathPrepareForWriteW)(HWND, IUnknown*, LPCWSTR, DWORD);
45
46 static void InitFunctionPointers(void)
47 {
48     hshell32 = GetModuleHandleA("shell32.dll");
49     pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
50     pSHCreateDirectoryExW = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExW");
51     pSHPathPrepareForWriteA = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteA");
52     pSHPathPrepareForWriteW = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteW");
53 }
54
55 /* creates a file with the specified name for tests */
56 static void createTestFile(const CHAR *name)
57 {
58     HANDLE file;
59     DWORD written;
60
61     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
62     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
63     WriteFile(file, name, strlen(name), &written, NULL);
64     WriteFile(file, "\n", strlen("\n"), &written, NULL);
65     CloseHandle(file);
66 }
67
68 static void createTestFileW(const WCHAR *name)
69 {
70     HANDLE file;
71
72     file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
73     ok(file != INVALID_HANDLE_VALUE, "Failure to open file\n");
74     CloseHandle(file);
75 }
76
77 static BOOL file_exists(const CHAR *name)
78 {
79     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
80 }
81
82 static BOOL file_existsW(LPCWSTR name)
83 {
84   return GetFileAttributesW(name) != INVALID_FILE_ATTRIBUTES;
85 }
86
87 static BOOL file_has_content(const CHAR *name, const CHAR *content)
88 {
89     CHAR buf[MAX_PATH];
90     HANDLE file;
91     DWORD read;
92
93     file = CreateFileA(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
94     if (file == INVALID_HANDLE_VALUE)
95         return FALSE;
96     ReadFile(file, buf, MAX_PATH - 1, &read, NULL);
97     buf[read] = 0;
98     CloseHandle(file);
99     return strcmp(buf, content)==0;
100 }
101
102 /* initializes the tests */
103 static void init_shfo_tests(void)
104 {
105     int len;
106
107     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
108     len = lstrlenA(CURR_DIR);
109
110     if(len && (CURR_DIR[len-1] == '\\'))
111         CURR_DIR[len-1] = 0;
112
113     createTestFile("test1.txt");
114     createTestFile("test2.txt");
115     createTestFile("test3.txt");
116     createTestFile("test_5.txt");
117     CreateDirectoryA("test4.txt", NULL);
118     CreateDirectoryA("testdir2", NULL);
119     CreateDirectoryA("testdir2\\nested", NULL);
120     createTestFile("testdir2\\one.txt");
121     createTestFile("testdir2\\nested\\two.txt");
122 }
123
124 /* cleans after tests */
125 static void clean_after_shfo_tests(void)
126 {
127     DeleteFileA("test1.txt");
128     DeleteFileA("test2.txt");
129     DeleteFileA("test3.txt");
130     DeleteFileA("test_5.txt");
131     DeleteFileA("one.txt");
132     DeleteFileA("test4.txt\\test1.txt");
133     DeleteFileA("test4.txt\\test2.txt");
134     DeleteFileA("test4.txt\\test3.txt");
135     RemoveDirectoryA("test4.txt");
136     DeleteFileA("testdir2\\one.txt");
137     DeleteFileA("testdir2\\test1.txt");
138     DeleteFileA("testdir2\\test2.txt");
139     DeleteFileA("testdir2\\test3.txt");
140     DeleteFileA("testdir2\\test4.txt\\test1.txt");
141     DeleteFileA("testdir2\\nested\\two.txt");
142     RemoveDirectoryA("testdir2\\test4.txt");
143     RemoveDirectoryA("testdir2\\nested");
144     RemoveDirectoryA("testdir2");
145     RemoveDirectoryA("c:\\testdir3");
146     DeleteFileA("nonexistent\\notreal\\test2.txt");
147     RemoveDirectoryA("nonexistent\\notreal");
148     RemoveDirectoryA("nonexistent");
149 }
150
151
152 static void test_get_file_info(void)
153 {
154     DWORD rc, rc2;
155     SHFILEINFO shfi, shfi2;
156     char notepad[MAX_PATH];
157
158     /* Test some flag combinations that MSDN claims are not allowed,
159      * but which work anyway
160      */
161     shfi.dwAttributes=0xdeadbeef;
162     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
163                       &shfi, sizeof(shfi),
164                       SHGFI_ATTRIBUTES | SHGFI_USEFILEATTRIBUTES);
165     todo_wine ok(rc, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) failed\n");
166     if (rc)
167         ok(shfi.dwAttributes != 0xdeadbeef, "dwFileAttributes is not set\n");
168
169     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
170                       &shfi, sizeof(shfi),
171                       SHGFI_EXETYPE | SHGFI_USEFILEATTRIBUTES);
172     todo_wine ok(rc == 1, "SHGetFileInfoA(c:\\nonexistent | SHGFI_EXETYPE) returned %d\n", rc);
173
174     /* Test SHGFI_USEFILEATTRIBUTES support */
175     strcpy(shfi.szDisplayName, "dummy");
176     shfi.iIcon=0xdeadbeef;
177     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
178                       &shfi, sizeof(shfi),
179                       SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
180     ok(rc, "SHGetFileInfoA(c:\\nonexistent) failed\n");
181     if (rc)
182     {
183         ok(strcpy(shfi.szDisplayName, "dummy") != 0, "SHGetFileInfoA(c:\\nonexistent) displayname is not set\n");
184         ok(shfi.iIcon != 0xdeadbeef, "SHGetFileInfoA(c:\\nonexistent) iIcon is not set\n");
185     }
186
187     /* Wine does not have a default icon for text files, and Windows 98 fails
188      * if we give it an empty executable. So use notepad.exe as the test
189      */
190     if (SearchPath(NULL, "notepad.exe", NULL, sizeof(notepad), notepad, NULL))
191     {
192         strcpy(shfi.szDisplayName, "dummy");
193         shfi.iIcon=0xdeadbeef;
194         rc=SHGetFileInfoA(notepad, GetFileAttributes(notepad),
195                           &shfi, sizeof(shfi),
196                           SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
197         ok(rc, "SHGetFileInfoA(%s, SHGFI_USEFILEATTRIBUTES) failed\n", notepad);
198         strcpy(shfi2.szDisplayName, "dummy");
199         shfi2.iIcon=0xdeadbeef;
200         rc2=SHGetFileInfoA(notepad, 0,
201                            &shfi2, sizeof(shfi2),
202                            SHGFI_ICONLOCATION);
203         ok(rc2, "SHGetFileInfoA(%s) failed\n", notepad);
204         if (rc && rc2)
205         {
206             ok(lstrcmpi(shfi2.szDisplayName, shfi.szDisplayName) == 0, "wrong display name %s != %s\n", shfi.szDisplayName, shfi2.szDisplayName);
207             ok(shfi2.iIcon == shfi.iIcon, "wrong icon index %d != %d\n", shfi.iIcon, shfi2.iIcon);
208         }
209     }
210
211     /* with a directory now */
212     strcpy(shfi.szDisplayName, "dummy");
213     shfi.iIcon=0xdeadbeef;
214     rc=SHGetFileInfoA("test4.txt", GetFileAttributes("test4.txt"),
215                       &shfi, sizeof(shfi),
216                       SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
217     ok(rc, "SHGetFileInfoA(test4.txt/, SHGFI_USEFILEATTRIBUTES) failed\n");
218     strcpy(shfi2.szDisplayName, "dummy");
219     shfi2.iIcon=0xdeadbeef;
220     rc2=SHGetFileInfoA("test4.txt", 0,
221                       &shfi2, sizeof(shfi2),
222                       SHGFI_ICONLOCATION);
223     ok(rc2, "SHGetFileInfoA(test4.txt/) failed\n");
224     if (rc && rc2)
225     {
226         ok(lstrcmpi(shfi2.szDisplayName, shfi.szDisplayName) == 0, "wrong display name %s != %s\n", shfi.szDisplayName, shfi2.szDisplayName);
227         ok(shfi2.iIcon == shfi.iIcon, "wrong icon index %d != %d\n", shfi.iIcon, shfi2.iIcon);
228     }
229 }
230
231
232 /*
233  puts into the specified buffer file names with current directory.
234  files - string with file names, separated by null characters. Ends on a double
235  null characters
236 */
237 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
238 {
239     buf[0] = 0;
240     while (files[0])
241     {
242         strcpy(buf, CURR_DIR);
243         buf += strlen(buf);
244         buf[0] = '\\';
245         buf++;
246         strcpy(buf, files);
247         buf += strlen(buf) + 1;
248         files += strlen(files) + 1;
249     }
250     buf[0] = 0;
251 }
252
253
254 /* tests the FO_DELETE action */
255 static void test_delete(void)
256 {
257     SHFILEOPSTRUCTA shfo;
258     DWORD ret;
259     CHAR buf[sizeof(CURR_DIR)+sizeof("/test?.txt")+1];
260
261     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
262     buf[strlen(buf) + 1] = '\0';
263
264     shfo.hwnd = NULL;
265     shfo.wFunc = FO_DELETE;
266     shfo.pFrom = buf;
267     shfo.pTo = "\0";
268     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
269     shfo.hNameMappings = NULL;
270     shfo.lpszProgressTitle = NULL;
271
272     ok(!SHFileOperationA(&shfo), "Deletion was not successful\n");
273     ok(file_exists("test4.txt"), "Directory should not have been removed\n");
274     ok(!file_exists("test1.txt"), "File should have been removed\n");
275
276     ret = SHFileOperationA(&shfo);
277     ok(!ret, "Directory exists, but is not removed, ret=%d\n", ret);
278     ok(file_exists("test4.txt"), "Directory should not have been removed\n");
279
280     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
281
282     ok(!SHFileOperationA(&shfo), "Directory is not removed\n");
283     ok(!file_exists("test4.txt"), "Directory should have been removed\n");
284
285     ret = SHFileOperationA(&shfo);
286     ok(!ret, "The requested file does not exist, ret=%d\n", ret);
287
288     init_shfo_tests();
289     sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
290     buf[strlen(buf) + 1] = '\0';
291     ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Filling the subdirectory failed\n");
292     ok(!SHFileOperationA(&shfo), "Directory is not removed\n");
293     ok(!file_exists("test4.txt"), "Directory is not removed\n");
294
295     init_shfo_tests();
296     shfo.pFrom = "test1.txt\0test4.txt\0";
297     ok(!SHFileOperationA(&shfo), "Directory and a file are not removed\n");
298     ok(!file_exists("test1.txt"), "The file should have been removed\n");
299     ok(!file_exists("test4.txt"), "Directory should have been removed\n");
300     ok(file_exists("test2.txt"), "This file should not have been removed\n");
301
302     /* FOF_FILESONLY does not delete a dir matching a wildcard */
303     init_shfo_tests();
304     shfo.fFlags |= FOF_FILESONLY;
305     shfo.pFrom = "*.txt\0";
306     ok(!SHFileOperation(&shfo), "Failed to delete files\n");
307     ok(!file_exists("test1.txt"), "test1.txt should have been removed\n");
308     ok(!file_exists("test_5.txt"), "test_5.txt should have been removed\n");
309     ok(file_exists("test4.txt"), "test4.txt should not have been removed\n");
310
311     /* FOF_FILESONLY only deletes a dir if explicitly specified */
312     init_shfo_tests();
313     shfo.pFrom = "test_?.txt\0test4.txt\0";
314     ok(!SHFileOperation(&shfo), "Failed to delete files and directory\n");
315     ok(!file_exists("test4.txt"), "test4.txt should have been removed\n");
316     ok(!file_exists("test_5.txt"), "test_5.txt should have been removed\n");
317     ok(file_exists("test1.txt"), "test1.txt should not have been removed\n");
318
319     /* try to delete an invalid filename */
320     init_shfo_tests();
321     shfo.pFrom = "\0";
322     shfo.fFlags &= ~FOF_FILESONLY;
323     shfo.fAnyOperationsAborted = FALSE;
324     ret = SHFileOperation(&shfo);
325     ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
326     ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
327     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
328
329     /* try an invalid function */
330     init_shfo_tests();
331     shfo.pFrom = "test1.txt\0";
332     shfo.wFunc = 0;
333     ret = SHFileOperation(&shfo);
334     ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
335     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
336
337     /* try an invalid list, only one null terminator */
338     init_shfo_tests();
339     shfo.pFrom = "";
340     shfo.wFunc = FO_DELETE;
341     ret = SHFileOperation(&shfo);
342     ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
343     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
344
345     /* delete a dir, and then a file inside the dir, same as
346     * deleting a nonexistent file
347     */
348     init_shfo_tests();
349     shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
350     ret = SHFileOperation(&shfo);
351     ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret);
352     ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n");
353     ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
354
355     /* try the FOF_NORECURSION flag, continues deleting subdirs */
356     init_shfo_tests();
357     shfo.pFrom = "testdir2\0";
358     shfo.fFlags |= FOF_NORECURSION;
359     ret = SHFileOperation(&shfo);
360     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
361     ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
362     ok(!file_exists("testdir2\\nested"), "Expected testdir2\\nested to exist\n");
363 }
364
365 /* tests the FO_RENAME action */
366 static void test_rename(void)
367 {
368     SHFILEOPSTRUCTA shfo, shfo2;
369     CHAR from[5*MAX_PATH];
370     CHAR to[5*MAX_PATH];
371     DWORD retval;
372
373     shfo.hwnd = NULL;
374     shfo.wFunc = FO_RENAME;
375     shfo.pFrom = from;
376     shfo.pTo = to;
377     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
378     shfo.hNameMappings = NULL;
379     shfo.lpszProgressTitle = NULL;
380
381     set_curr_dir_path(from, "test1.txt\0");
382     set_curr_dir_path(to, "test4.txt\0");
383     ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
384        "when specifying directory name only\n");
385     ok(file_exists("test1.txt"), "The file is removed\n");
386
387     set_curr_dir_path(from, "test3.txt\0");
388     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
389     ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
390     ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
391
392     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
393     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
394     retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
395     ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
396        "Can't rename many files, retval = %d\n", retval);
397     ok(file_exists("test1.txt"), "The file is renamed - many files are specified\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     retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
405     ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
406        "Can't rename many files, retval = %d\n", retval);
407     ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
408
409     set_curr_dir_path(from, "test1.txt\0");
410     set_curr_dir_path(to, "test6.txt\0");
411     retval = SHFileOperationA(&shfo);
412     ok(!retval, "Rename file failed, retval = %d\n", retval);
413     ok(!file_exists("test1.txt"), "The file is not renamed\n");
414     ok(file_exists("test6.txt"), "The file is not renamed\n");
415
416     set_curr_dir_path(from, "test6.txt\0");
417     set_curr_dir_path(to, "test1.txt\0");
418     retval = SHFileOperationA(&shfo);
419     ok(!retval, "Rename file back failed, retval = %d\n", retval);
420
421     set_curr_dir_path(from, "test4.txt\0");
422     set_curr_dir_path(to, "test6.txt\0");
423     retval = SHFileOperationA(&shfo);
424     ok(!retval, "Rename dir failed, retval = %d\n", retval);
425     ok(!file_exists("test4.txt"), "The dir is not renamed\n");
426     ok(file_exists("test6.txt"), "The dir is not renamed\n");
427
428     set_curr_dir_path(from, "test6.txt\0");
429     set_curr_dir_path(to, "test4.txt\0");
430     retval = SHFileOperationA(&shfo);
431     ok(!retval, "Rename dir back failed, retval = %d\n", retval);
432
433     /* try to rename more than one file to a single file */
434     shfo.pFrom = "test1.txt\0test2.txt\0";
435     shfo.pTo = "a.txt\0";
436     retval = SHFileOperationA(&shfo);
437     ok(retval == ERROR_GEN_FAILURE, "Expected ERROR_GEN_FAILURE, got %d\n", retval);
438     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
439     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
440
441     /* pFrom doesn't exist */
442     shfo.pFrom = "idontexist\0";
443     shfo.pTo = "newfile\0";
444     retval = SHFileOperationA(&shfo);
445     ok(retval == 1026, "Expected 1026, got %d\n", retval);
446     ok(!file_exists("newfile"), "Expected newfile to not exist\n");
447
448     /* pTo already exist */
449     shfo.pFrom = "test1.txt\0";
450     shfo.pTo = "test2.txt\0";
451     retval = SHFileOperationA(&shfo);
452         ok(retval == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", retval);
453
454     /* pFrom is valid, but pTo is empty */
455     shfo.pFrom = "test1.txt\0";
456     shfo.pTo = "\0";
457     retval = SHFileOperationA(&shfo);
458         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
459     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
460
461     /* pFrom is empty */
462     shfo.pFrom = "\0";
463     retval = SHFileOperationA(&shfo);
464         ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", retval);
465
466     /* pFrom is NULL, commented out because it crashes on nt 4.0 */
467 #if 0
468     shfo.pFrom = NULL;
469     retval = SHFileOperationA(&shfo);
470     ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", retval);
471 #endif
472 }
473
474 /* tests the FO_COPY action */
475 static void test_copy(void)
476 {
477     SHFILEOPSTRUCTA shfo, shfo2;
478     CHAR from[5*MAX_PATH];
479     CHAR to[5*MAX_PATH];
480     FILEOP_FLAGS tmp_flags;
481     DWORD retval;
482
483     shfo.hwnd = NULL;
484     shfo.wFunc = FO_COPY;
485     shfo.pFrom = from;
486     shfo.pTo = to;
487     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
488     shfo.hNameMappings = NULL;
489     shfo.lpszProgressTitle = NULL;
490
491     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
492     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
493     ok(SHFileOperationA(&shfo), "Can't copy many files\n");
494     ok(!file_exists("test6.txt"), "The file is not copied - many files are "
495        "specified as a target\n");
496
497     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
498     shfo2.fFlags |= FOF_MULTIDESTFILES;
499
500     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
501     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
502     ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
503     ok(file_exists("test6.txt"), "The file is copied - many files are "
504        "specified as a target\n");
505     DeleteFileA("test6.txt");
506     DeleteFileA("test7.txt");
507     RemoveDirectoryA("test8.txt");
508
509     /* number of sources do not correspond to number of targets */
510     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
511     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
512     ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
513     ok(!file_exists("test6.txt"), "The file is not copied - many files are "
514        "specified as a target\n");
515
516     set_curr_dir_path(from, "test1.txt\0");
517     set_curr_dir_path(to, "test4.txt\0");
518     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
519     ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
520
521     set_curr_dir_path(from, "test?.txt\0");
522     set_curr_dir_path(to, "testdir2\0");
523     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
524     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
525     ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
526     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
527     ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
528     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
529     clean_after_shfo_tests();
530
531     init_shfo_tests();
532     shfo.fFlags |= FOF_FILESONLY;
533     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
534     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
535     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
536     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
537     ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
538     clean_after_shfo_tests();
539
540     init_shfo_tests();
541     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
542     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
543     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
544     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
545     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
546     ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
547     clean_after_shfo_tests();
548
549     /* Copying multiple files with one not existing as source, fails the
550        entire operation in Win98/ME/2K/XP, but not in 95/NT */
551     init_shfo_tests();
552     tmp_flags = shfo.fFlags;
553     set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
554     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
555     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
556     retval = SHFileOperationA(&shfo);
557     if (!retval)
558         /* Win 95/NT returns success but copies only the files up to the nonexistent source */
559         ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
560     else
561     {
562         /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
563         ok(retval == 1026, "Files are copied to other directory\n");
564         ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
565     }
566     ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
567     shfo.fFlags = tmp_flags;
568
569     /* copy into a nonexistent directory */
570     init_shfo_tests();
571     shfo.fFlags = FOF_NOCONFIRMMKDIR;
572     set_curr_dir_path(from, "test1.txt\0");
573     set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
574     retval= SHFileOperation(&shfo);
575         ok(!retval, "Error copying into nonexistent directory\n");
576         ok(file_exists("nonexistent"), "nonexistent not created\n");
577         ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
578         ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
579     ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
580
581     /* a relative dest directory is OK */
582     clean_after_shfo_tests();
583     init_shfo_tests();
584     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
585     shfo.pTo = "testdir2\0";
586     retval = SHFileOperation(&shfo);
587     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
588     ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
589
590     /* try to copy files to a file */
591     clean_after_shfo_tests();
592     init_shfo_tests();
593     shfo.pFrom = from;
594     shfo.pTo = to;
595     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
596     set_curr_dir_path(to, "test3.txt\0");
597     retval = SHFileOperation(&shfo);
598         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
599     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
600     ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
601
602     /* try to copy many files to nonexistent directory */
603     DeleteFile(to);
604     shfo.fAnyOperationsAborted = FALSE;
605     retval = SHFileOperation(&shfo);
606         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
607         ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
608         ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
609         ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
610
611     /* send in FOF_MULTIDESTFILES with too many destination files */
612     init_shfo_tests();
613     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
614     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
615     shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
616     retval = SHFileOperation(&shfo);
617         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
618     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
619     ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
620
621     /* send in FOF_MULTIDESTFILES with too many destination files */
622     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
623     shfo.pTo = "e.txt\0f.txt\0";
624     shfo.fAnyOperationsAborted = FALSE;
625     retval = SHFileOperation(&shfo);
626         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
627     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
628     ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
629
630     /* use FOF_MULTIDESTFILES with files and a source directory */
631     shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
632     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
633     shfo.fAnyOperationsAborted = FALSE;
634     retval = SHFileOperation(&shfo);
635     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
636     ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
637     ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
638     ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
639
640     /* try many dest files without FOF_MULTIDESTFILES flag */
641     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
642     shfo.pTo = "a.txt\0b.txt\0c.txt\0";
643     shfo.fAnyOperationsAborted = FALSE;
644     shfo.fFlags &= ~FOF_MULTIDESTFILES;
645     retval = SHFileOperation(&shfo);
646         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
647     ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
648
649     /* try a glob */
650     shfo.pFrom = "test?.txt\0";
651     shfo.pTo = "testdir2\0";
652     shfo.fFlags &= ~FOF_MULTIDESTFILES;
653     retval = SHFileOperation(&shfo);
654         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
655         ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
656
657     /* try a glob with FOF_FILESONLY */
658     clean_after_shfo_tests();
659     init_shfo_tests();
660     shfo.pFrom = "test?.txt\0";
661     shfo.fFlags |= FOF_FILESONLY;
662     retval = SHFileOperation(&shfo);
663         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
664         ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
665     ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
666
667     /* try a glob with FOF_MULTIDESTFILES and the same number
668     * of dest files that we would expect
669     */
670     clean_after_shfo_tests();
671     init_shfo_tests();
672     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
673     shfo.fFlags &= ~FOF_FILESONLY;
674     shfo.fFlags |= FOF_MULTIDESTFILES;
675     retval = SHFileOperation(&shfo);
676         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
677     ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
678     ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
679     ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
680
681     /* copy one file to two others, second is ignored */
682     clean_after_shfo_tests();
683     init_shfo_tests();
684     shfo.pFrom = "test1.txt\0";
685     shfo.pTo = "b.txt\0c.txt\0";
686     shfo.fAnyOperationsAborted = FALSE;
687     retval = SHFileOperation(&shfo);
688         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
689         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
690     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
691
692     /* copy two file to three others, all fail */
693     shfo.pFrom = "test1.txt\0test2.txt\0";
694     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
695     retval = SHFileOperation(&shfo);
696         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
697     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
698     ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
699
700     /* copy one file and one directory to three others */
701     shfo.pFrom = "test1.txt\0test4.txt\0";
702     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
703     shfo.fAnyOperationsAborted = FALSE;
704     retval = SHFileOperation(&shfo);
705         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
706     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
707     ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
708     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
709
710     /* copy a directory with a file beneath it, plus some files */
711     createTestFile("test4.txt\\a.txt");
712     shfo.pFrom = "test4.txt\0test1.txt\0";
713     shfo.pTo = "testdir2\0";
714     shfo.fFlags &= ~FOF_MULTIDESTFILES;
715     shfo.fAnyOperationsAborted = FALSE;
716     retval = SHFileOperation(&shfo);
717     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
718     ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
719     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
720     ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
721
722     /* copy one directory and a file in that dir to another dir */
723     shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
724     shfo.pTo = "testdir2\0";
725     retval = SHFileOperation(&shfo);
726     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
727     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
728     ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
729
730     /* copy a file in a directory first, and then the directory to a nonexistent dir */
731     shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
732     shfo.pTo = "nonexistent\0";
733     retval = SHFileOperation(&shfo);
734         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
735     ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
736     ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
737     DeleteFile("test4.txt\\a.txt");
738
739     /* destination is same as source file */
740     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
741     shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
742     shfo.fAnyOperationsAborted = FALSE;
743     shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
744     retval = SHFileOperation(&shfo);
745         ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
746            "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %d\n", retval);
747         ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
748         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
749     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
750
751     /* destination is same as source directory */
752     shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
753     shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
754     shfo.fAnyOperationsAborted = FALSE;
755     retval = SHFileOperation(&shfo);
756         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
757         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
758     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
759
760     /* copy a directory into itself, error displayed in UI */
761     shfo.pFrom = "test4.txt\0";
762     shfo.pTo = "test4.txt\\newdir\0";
763     shfo.fFlags &= ~FOF_MULTIDESTFILES;
764     shfo.fAnyOperationsAborted = FALSE;
765     retval = SHFileOperation(&shfo);
766         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
767     ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
768
769     /* copy a directory to itself, error displayed in UI */
770     shfo.pFrom = "test4.txt\0";
771     shfo.pTo = "test4.txt\0";
772     shfo.fAnyOperationsAborted = FALSE;
773     retval = SHFileOperation(&shfo);
774         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
775
776     /* copy a file into a directory, and the directory into itself */
777     shfo.pFrom = "test1.txt\0test4.txt\0";
778     shfo.pTo = "test4.txt\0";
779     shfo.fAnyOperationsAborted = FALSE;
780     shfo.fFlags |= FOF_NOCONFIRMATION;
781     retval = SHFileOperation(&shfo);
782         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
783     ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
784
785     /* copy a file to a file, and the directory into itself */
786     shfo.pFrom = "test1.txt\0test4.txt\0";
787     shfo.pTo = "test4.txt\\a.txt\0";
788     shfo.fAnyOperationsAborted = FALSE;
789     retval = SHFileOperation(&shfo);
790         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
791     ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
792
793     /* copy a nonexistent file to a nonexistent directory */
794     shfo.pFrom = "e.txt\0";
795     shfo.pTo = "nonexistent\0";
796     shfo.fAnyOperationsAborted = FALSE;
797     retval = SHFileOperation(&shfo);
798     ok(retval == 1026, "Expected 1026, got %d\n", retval);
799     ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
800     ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
801
802     /* Overwrite tests */
803     clean_after_shfo_tests();
804     init_shfo_tests();
805     shfo.fFlags = FOF_NOCONFIRMATION;
806     shfo.pFrom = "test1.txt\0";
807     shfo.pTo = "test2.txt\0";
808     shfo.fAnyOperationsAborted = FALSE;
809     /* without FOF_NOCOFIRMATION the confirmation is Yes/No */
810     retval = SHFileOperation(&shfo);
811     ok(retval == 0, "Expected 0, got %d\n", retval);
812     ok(file_has_content("test2.txt", "test1.txt\n"), "The file was not copied\n");
813
814     shfo.pFrom = "test3.txt\0test1.txt\0";
815     shfo.pTo = "test2.txt\0one.txt\0";
816     shfo.fFlags = FOF_NOCONFIRMATION | FOF_MULTIDESTFILES;
817     /* without FOF_NOCOFIRMATION the confirmation is Yes/Yes to All/No/Cancel */
818     retval = SHFileOperation(&shfo);
819     ok(retval == 0, "Expected 0, got %d\n", retval);
820     ok(file_has_content("test2.txt", "test3.txt\n"), "The file was not copied\n");
821
822     shfo.pFrom = "one.txt\0";
823     shfo.pTo = "testdir2\0";
824     shfo.fFlags = FOF_NOCONFIRMATION;
825     /* without FOF_NOCOFIRMATION the confirmation is Yes/No */
826     retval = SHFileOperation(&shfo);
827     ok(retval == 0, "Expected 0, got %d\n", retval);
828     ok(file_has_content("testdir2\\one.txt", "test1.txt\n"), "The file was not copied\n");
829
830     createTestFile("test4.txt\\test1.txt");
831     shfo.pFrom = "test4.txt\0";
832     shfo.pTo = "testdir2\0";
833     shfo.fFlags = FOF_NOCONFIRMATION;
834     ok(!SHFileOperation(&shfo), "First SHFileOperation failed\n");
835     createTestFile("test4.txt\\.\\test1.txt"); /* modify the content of the file */
836     /* without FOF_NOCOFIRMATION the confirmation is "This folder already contains a folder named ..." */
837     retval = SHFileOperation(&shfo);
838     ok(retval == 0, "Expected 0, got %d\n", retval);
839     ok(file_has_content("testdir2\\test4.txt\\test1.txt", "test4.txt\\.\\test1.txt\n"), "The file was not copied\n");
840 }
841
842 /* tests the FO_MOVE action */
843 static void test_move(void)
844 {
845     SHFILEOPSTRUCTA shfo, shfo2;
846     CHAR from[5*MAX_PATH];
847     CHAR to[5*MAX_PATH];
848     DWORD retval;
849
850     shfo.hwnd = NULL;
851     shfo.wFunc = FO_MOVE;
852     shfo.pFrom = from;
853     shfo.pTo = to;
854     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
855     shfo.hNameMappings = NULL;
856     shfo.lpszProgressTitle = NULL;
857
858     set_curr_dir_path(from, "test1.txt\0");
859     set_curr_dir_path(to, "test4.txt\0");
860     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
861     ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
862     ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
863
864     set_curr_dir_path(from, "test?.txt\0");
865     set_curr_dir_path(to, "testdir2\0");
866     ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
867     ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
868     ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
869     ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
870     ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
871     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
872
873     clean_after_shfo_tests();
874     init_shfo_tests();
875
876     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
877     shfo2.fFlags |= FOF_MULTIDESTFILES;
878
879     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
880     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
881     ok(!SHFileOperationA(&shfo2), "Move many files\n");
882     ok(file_exists("test6.txt"), "The file is moved - many files are "
883        "specified as a target\n");
884     DeleteFileA("test6.txt");
885     DeleteFileA("test7.txt");
886     RemoveDirectoryA("test8.txt");
887
888     init_shfo_tests();
889
890     /* number of sources do not correspond to number of targets */
891     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
892     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
893     ok(SHFileOperationA(&shfo2), "Can't move many files\n");
894     ok(!file_exists("test6.txt"), "The file is not moved - many files are "
895        "specified as a target\n");
896
897     init_shfo_tests();
898
899     set_curr_dir_path(from, "test3.txt\0");
900     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
901     ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
902     ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
903
904     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
905     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
906     ok(SHFileOperationA(&shfo), "Cannot move many files\n");
907     ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
908     ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
909
910     set_curr_dir_path(from, "test1.txt\0");
911     set_curr_dir_path(to, "test6.txt\0");
912     ok(!SHFileOperationA(&shfo), "Move file\n");
913     ok(!file_exists("test1.txt"), "The file is moved\n");
914     ok(file_exists("test6.txt"), "The file is moved\n");
915     set_curr_dir_path(from, "test6.txt\0");
916     set_curr_dir_path(to, "test1.txt\0");
917     ok(!SHFileOperationA(&shfo), "Move file back\n");
918
919     set_curr_dir_path(from, "test4.txt\0");
920     set_curr_dir_path(to, "test6.txt\0");
921     ok(!SHFileOperationA(&shfo), "Move dir\n");
922     ok(!file_exists("test4.txt"), "The dir is moved\n");
923     ok(file_exists("test6.txt"), "The dir is moved\n");
924     set_curr_dir_path(from, "test6.txt\0");
925     set_curr_dir_path(to, "test4.txt\0");
926     ok(!SHFileOperationA(&shfo), "Move dir back\n");
927
928     /* move one file to two others */
929     init_shfo_tests();
930     shfo.pFrom = "test1.txt\0";
931     shfo.pTo = "a.txt\0b.txt\0";
932     retval = SHFileOperationA(&shfo);
933         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
934         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
935         ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
936     ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
937
938     /* move two files to one other */
939     shfo.pFrom = "test2.txt\0test3.txt\0";
940     shfo.pTo = "test1.txt\0";
941     retval = SHFileOperationA(&shfo);
942         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
943         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
944     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
945     ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
946
947     /* move a directory into itself */
948     shfo.pFrom = "test4.txt\0";
949     shfo.pTo = "test4.txt\\b.txt\0";
950     retval = SHFileOperationA(&shfo);
951         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
952     ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
953     ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
954
955     /* move many files without FOF_MULTIDESTFILES */
956     shfo.pFrom = "test2.txt\0test3.txt\0";
957     shfo.pTo = "d.txt\0e.txt\0";
958     retval = SHFileOperationA(&shfo);
959         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
960     ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
961     ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
962
963     /* number of sources != number of targets */
964     shfo.pTo = "d.txt\0";
965     shfo.fFlags |= FOF_MULTIDESTFILES;
966     retval = SHFileOperationA(&shfo);
967         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
968     ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
969
970     /* FO_MOVE does not create dest directories */
971     shfo.pFrom = "test2.txt\0";
972     shfo.pTo = "dir1\\dir2\\test2.txt\0";
973     retval = SHFileOperationA(&shfo);
974         ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
975     ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
976
977     /* try to overwrite an existing file */
978     shfo.pTo = "test3.txt\0";
979     retval = SHFileOperationA(&shfo);
980         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
981         ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
982     ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
983 }
984
985 static void test_sh_create_dir(void)
986 {
987     CHAR path[MAX_PATH];
988     int ret;
989
990     if(!pSHCreateDirectoryExA)
991     {
992         trace("skipping SHCreateDirectoryExA tests\n");
993         return;
994     }
995
996     set_curr_dir_path(path, "testdir2\\test4.txt\0");
997     ret = pSHCreateDirectoryExA(NULL, path, NULL);
998     ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
999     ok(file_exists("testdir2"), "The first directory is not created\n");
1000     ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
1001
1002     ret = pSHCreateDirectoryExA(NULL, path, NULL);
1003     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
1004
1005     ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
1006     ok(file_exists("c:\\testdir3"), "The directory is not created\n");
1007 }
1008
1009 static void test_sh_path_prepare(void)
1010 {
1011     HRESULT res;
1012     CHAR path[MAX_PATH];
1013
1014     if(!pSHPathPrepareForWriteA)
1015     {
1016         trace("skipping SHPathPrepareForWriteA tests\n");
1017             return;
1018     }
1019
1020     /* directory exists, SHPPFW_NONE */
1021     set_curr_dir_path(path, "testdir2\0");
1022     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
1023     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1024
1025     /* directory exists, SHPPFW_IGNOREFILENAME */
1026     set_curr_dir_path(path, "testdir2\\test4.txt\0");
1027     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
1028     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1029
1030     /* directory exists, SHPPFW_DIRCREATE */
1031     set_curr_dir_path(path, "testdir2\0");
1032     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
1033     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1034
1035     /* directory exists, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */
1036     set_curr_dir_path(path, "testdir2\\test4.txt\0");
1037     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
1038     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1039     ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n");
1040
1041     /* file exists, SHPPFW_NONE */
1042     set_curr_dir_path(path, "test1.txt\0");
1043     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
1044     ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res);
1045
1046     /* file exists, SHPPFW_DIRCREATE */
1047     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
1048     ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res);
1049
1050     /* file exists, SHPPFW_NONE, trailing \ */
1051     set_curr_dir_path(path, "test1.txt\\\0");
1052     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
1053     ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res);
1054
1055     /* relative path exists, SHPPFW_DIRCREATE */
1056     res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2", SHPPFW_DIRCREATE);
1057     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1058
1059     /* relative path doesn't exist, SHPPFW_DIRCREATE -- Windows does not create the directory in this case */
1060     res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2\\test4.txt", SHPPFW_DIRCREATE);
1061     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
1062     ok(!file_exists(".\\testdir2\\test4.txt\\"), ".\\testdir2\\test4.txt\\ exists but shouldn't\n");
1063
1064     /* directory doesn't exist, SHPPFW_NONE */
1065     set_curr_dir_path(path, "nonexistent\0");
1066     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
1067     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
1068
1069     /* directory doesn't exist, SHPPFW_IGNOREFILENAME */
1070     set_curr_dir_path(path, "nonexistent\\notreal\0");
1071     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
1072     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
1073     ok(!file_exists("nonexistent\\notreal"), "nonexistent\\notreal exists but shouldn't\n");
1074     ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n");
1075
1076     /* directory doesn't exist, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */
1077     set_curr_dir_path(path, "testdir2\\test4.txt\\\0");
1078     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
1079     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1080     ok(file_exists("testdir2\\test4.txt\\"), "testdir2\\test4.txt doesn't exist but should\n");
1081
1082     /* nested directory doesn't exist, SHPPFW_DIRCREATE */
1083     set_curr_dir_path(path, "nonexistent\\notreal\0");
1084     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
1085     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
1086     ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal doesn't exist but should\n");
1087
1088     /* SHPPFW_ASKDIRCREATE, SHPPFW_NOWRITECHECK, and SHPPFW_MEDIACHECKONLY are untested */
1089
1090     if(!pSHPathPrepareForWriteW)
1091     {
1092         skip("Skipping SHPathPrepareForWriteW tests\n");
1093         return;
1094     }
1095     /* unicode directory doesn't exist, SHPPFW_NONE */
1096     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
1097     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
1098     ok(!file_existsW(UNICODE_PATH), "unicode path was created but shouldn't be\n");
1099     RemoveDirectoryW(UNICODE_PATH);
1100
1101     /* unicode directory doesn't exist, SHPPFW_DIRCREATE */
1102     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
1103     ok(res == S_OK, "res == %08x, expected S_OK\n", res);
1104     ok(file_existsW(UNICODE_PATH), "unicode path should've been created\n");
1105
1106     /* unicode directory exists, SHPPFW_NONE */
1107     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
1108     ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
1109
1110     /* unicode directory exists, SHPPFW_DIRCREATE */
1111     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
1112     ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
1113     RemoveDirectoryW(UNICODE_PATH);
1114 }
1115
1116 static void test_unicode(void)
1117 {
1118     SHFILEOPSTRUCTW shfoW;
1119     int ret;
1120     HANDLE file;
1121
1122     shfoW.hwnd = NULL;
1123     shfoW.wFunc = FO_DELETE;
1124     shfoW.pFrom = UNICODE_PATH;
1125     shfoW.pTo = '\0';
1126     shfoW.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1127     shfoW.hNameMappings = NULL;
1128     shfoW.lpszProgressTitle = NULL;
1129
1130     /* Clean up before start test */
1131     DeleteFileW(UNICODE_PATH);
1132     RemoveDirectoryW(UNICODE_PATH);
1133
1134     /* Make sure we are on a system that supports unicode */
1135     SetLastError(0xdeadbeef);
1136     file = CreateFileW(UNICODE_PATH, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1137     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1138     {
1139         skip("Unicode tests skipped on non-unicode system\n");
1140         return;
1141     }
1142     CloseHandle(file);
1143
1144     /* Try to delete a file with unicode filename */
1145     ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
1146     ret = SHFileOperationW(&shfoW);
1147     ok(!ret, "File is not removed, ErrorCode: %d\n", ret);
1148     ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
1149
1150     /* Try to trash a file with unicode filename */
1151     createTestFileW(UNICODE_PATH);
1152     shfoW.fFlags |= FOF_ALLOWUNDO;
1153     ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
1154     ret = SHFileOperationW(&shfoW);
1155     ok(!ret, "File is not removed, ErrorCode: %d\n", ret);
1156     ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
1157
1158     if(!pSHCreateDirectoryExW)
1159     {
1160         skip("Skipping SHCreateDirectoryExW tests\n");
1161         return;
1162     }
1163
1164     /* Try to delete a directory with unicode filename */
1165     ret = pSHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
1166     ok(!ret, "SHCreateDirectoryExW returned %d\n", ret);
1167     ok(file_existsW(UNICODE_PATH), "The directory is not created\n");
1168     shfoW.fFlags &= ~FOF_ALLOWUNDO;
1169     ret = SHFileOperationW(&shfoW);
1170     ok(!ret, "Directory is not removed, ErrorCode: %d\n", ret);
1171     ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n");
1172
1173     /* Try to trash a directory with unicode filename */
1174     ret = pSHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
1175     ok(!ret, "SHCreateDirectoryExW returned %d\n", ret);
1176     ok(file_existsW(UNICODE_PATH), "The directory was not created\n");
1177     shfoW.fFlags |= FOF_ALLOWUNDO;
1178     ret = SHFileOperationW(&shfoW);
1179     ok(!ret, "Directory is not removed, ErrorCode: %d\n", ret);
1180     ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n");
1181 }
1182
1183 START_TEST(shlfileop)
1184 {
1185     InitFunctionPointers();
1186
1187     clean_after_shfo_tests();
1188
1189     init_shfo_tests();
1190     test_get_file_info();
1191     clean_after_shfo_tests();
1192
1193     init_shfo_tests();
1194     test_delete();
1195     clean_after_shfo_tests();
1196
1197     init_shfo_tests();
1198     test_rename();
1199     clean_after_shfo_tests();
1200
1201     init_shfo_tests();
1202     test_copy();
1203     clean_after_shfo_tests();
1204
1205     init_shfo_tests();
1206     test_move();
1207     clean_after_shfo_tests();
1208
1209     test_sh_create_dir();
1210     clean_after_shfo_tests();
1211
1212     init_shfo_tests();
1213     test_sh_path_prepare();
1214     clean_after_shfo_tests();
1215
1216     test_unicode();
1217 }