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