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 "precomp.h"
22 
23 #ifndef FOF_NORECURSION
24 #define FOF_NORECURSION 0x1000
25 #endif
26 
27 /* Error codes could be pre-Win32 */
28 #define DE_SAMEFILE      0x71
29 #define DE_MANYSRC1DEST  0x72
30 #define DE_DIFFDIR       0x73
31 #define DE_OPCANCELLED   0x75
32 #define DE_DESTSUBTREE   0x76
33 #define DE_INVALIDFILES  0x7C
34 #define DE_DESTSAMETREE  0x7D
35 #define DE_FLDDESTISFILE 0x7E
36 #define DE_FILEDESTISFLD 0x80
37 #define expect_retval(ret, ret_prewin32)\
38     ok(retval == ret ||\
39        broken(retval == ret_prewin32),\
40        "Expected %d, got %d\n", ret, retval)
41 
42 static BOOL old_shell32 = FALSE;
43 
44 static CHAR CURR_DIR[MAX_PATH];
45 static const WCHAR UNICODE_PATH[] = {'c',':','\\',0x00ae,'\0','\0'};
46     /* "c:\®" can be used in all codepages */
47     /* Double-null termination needed for pFrom field of SHFILEOPSTRUCT */
48 
49 static HMODULE hshell32;
50 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
51 static int (WINAPI *pSHCreateDirectoryExW)(HWND, LPCWSTR, LPSECURITY_ATTRIBUTES);
52 static int (WINAPI *pSHFileOperationW)(LPSHFILEOPSTRUCTW);
53 static DWORD_PTR (WINAPI *pSHGetFileInfoW)(LPCWSTR, DWORD , SHFILEINFOW*, UINT, UINT);
54 static int (WINAPI *pSHPathPrepareForWriteA)(HWND, IUnknown*, LPCSTR, DWORD);
55 static int (WINAPI *pSHPathPrepareForWriteW)(HWND, IUnknown*, LPCWSTR, DWORD);
56 
57 static void InitFunctionPointers(void)
58 {
59     hshell32 = GetModuleHandleA("shell32.dll");
60     pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
61     pSHCreateDirectoryExW = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExW");
62     pSHFileOperationW = (void*)GetProcAddress(hshell32, "SHFileOperationW");
63     pSHGetFileInfoW = (void*)GetProcAddress(hshell32, "SHGetFileInfoW");
64     pSHPathPrepareForWriteA = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteA");
65     pSHPathPrepareForWriteW = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteW");
66 }
67 
68 /* creates a file with the specified name for tests */
69 static void createTestFile(const CHAR *name)
70 {
71     HANDLE file;
72     DWORD written;
73 
74     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
75     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
76     WriteFile(file, name, strlen(name), &written, NULL);
77     WriteFile(file, "\n", strlen("\n"), &written, NULL);
78     CloseHandle(file);
79 }
80 
81 static void createTestFileW(const WCHAR *name)
82 {
83     HANDLE file;
84 
85     file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
86     ok(file != INVALID_HANDLE_VALUE, "Failure to open file\n");
87     CloseHandle(file);
88 }
89 
90 static BOOL file_exists(const CHAR *name)
91 {
92     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
93 }
94 
95 static BOOL dir_exists(const CHAR *name)
96 {
97     DWORD attr;
98     BOOL dir;
99 
100     attr = GetFileAttributesA(name);
101     dir = ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
102 
103     return ((attr != INVALID_FILE_ATTRIBUTES) && dir);
104 }
105 
106 static BOOL file_existsW(LPCWSTR name)
107 {
108   return GetFileAttributesW(name) != INVALID_FILE_ATTRIBUTES;
109 }
110 
111 static BOOL file_has_content(const CHAR *name, const CHAR *content)
112 {
113     CHAR buf[MAX_PATH];
114     HANDLE file;
115     DWORD read;
116 
117     file = CreateFileA(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
118     if (file == INVALID_HANDLE_VALUE)
119         return FALSE;
120     ReadFile(file, buf, MAX_PATH - 1, &read, NULL);
121     buf[read] = 0;
122     CloseHandle(file);
123     return strcmp(buf, content)==0;
124 }
125 
126 /* initializes the tests */
127 static void init_shfo_tests(void)
128 {
129     int len;
130 
131     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
132     len = lstrlenA(CURR_DIR);
133 
134     if(len && (CURR_DIR[len-1] == '\\'))
135         CURR_DIR[len-1] = 0;
136 
137     createTestFile("test1.txt");
138     createTestFile("test2.txt");
139     createTestFile("test3.txt");
140     createTestFile("test_5.txt");
141     CreateDirectoryA("test4.txt", NULL);
142     CreateDirectoryA("testdir2", NULL);
143     CreateDirectoryA("testdir2\\nested", NULL);
144     createTestFile("testdir2\\one.txt");
145     createTestFile("testdir2\\nested\\two.txt");
146 }
147 
148 /* cleans after tests */
149 static void clean_after_shfo_tests(void)
150 {
151     DeleteFileA("test1.txt");
152     DeleteFileA("test2.txt");
153     DeleteFileA("test3.txt");
154     DeleteFileA("test_5.txt");
155     DeleteFileA("one.txt");
156     DeleteFileA("test4.txt\\test1.txt");
157     DeleteFileA("test4.txt\\test2.txt");
158     DeleteFileA("test4.txt\\test3.txt");
159     DeleteFileA("test4.txt\\one.txt");
160     DeleteFileA("test4.txt\\nested\\two.txt");
161     RemoveDirectoryA("test4.txt\\nested");
162     RemoveDirectoryA("test4.txt");
163     DeleteFileA("testdir2\\one.txt");
164     DeleteFileA("testdir2\\test1.txt");
165     DeleteFileA("testdir2\\test2.txt");
166     DeleteFileA("testdir2\\test3.txt");
167     DeleteFileA("testdir2\\test4.txt\\test1.txt");
168     DeleteFileA("testdir2\\nested\\two.txt");
169     RemoveDirectoryA("testdir2\\test4.txt");
170     RemoveDirectoryA("testdir2\\nested");
171     RemoveDirectoryA("testdir2");
172     RemoveDirectoryA("c:\\testdir3");
173     DeleteFileA("nonexistent\\notreal\\test2.txt");
174     RemoveDirectoryA("nonexistent\\notreal");
175     RemoveDirectoryA("nonexistent");
176 }
177 
178 
179 static void test_get_file_info(void)
180 {
181     DWORD rc, rc2;
182     SHFILEINFOA shfi, shfi2;
183     SHFILEINFOW shfiw;
184     char notepad[MAX_PATH];
185 
186     /* Test whether fields of SHFILEINFOA are always cleared */
187     memset(&shfi, 0xcf, sizeof(shfi));
188     rc=SHGetFileInfoA("", 0, &shfi, sizeof(shfi), 0);
189     ok(rc == 1, "SHGetFileInfoA('' | 0) should return 1, got 0x%x\n", rc);
190     todo_wine ok(shfi.hIcon == 0, "SHGetFileInfoA('' | 0) did not clear hIcon\n");
191     todo_wine ok(shfi.szDisplayName[0] == 0, "SHGetFileInfoA('' | 0) did not clear szDisplayName[0]\n");
192     todo_wine ok(shfi.szTypeName[0] == 0, "SHGetFileInfoA('' | 0) did not clear szTypeName[0]\n");
193     ok(shfi.iIcon == 0xcfcfcfcf ||
194        broken(shfi.iIcon != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
195        "SHGetFileInfoA('' | 0) should not clear iIcon\n");
196     ok(shfi.dwAttributes == 0xcfcfcfcf ||
197        broken(shfi.dwAttributes != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
198        "SHGetFileInfoA('' | 0) should not clear dwAttributes\n");
199 
200     if (pSHGetFileInfoW)
201     {
202         HANDLE unset_icon;
203         /* Test whether fields of SHFILEINFOW are always cleared */
204         memset(&shfiw, 0xcf, sizeof(shfiw));
205         memset(&unset_icon, 0xcf, sizeof(unset_icon));
206         rc=pSHGetFileInfoW(NULL, 0, &shfiw, sizeof(shfiw), 0);
207         ok(!rc, "SHGetFileInfoW(NULL | 0) should fail\n");
208         ok(shfiw.hIcon == unset_icon, "SHGetFileInfoW(NULL | 0) should not clear hIcon\n");
209         ok(shfiw.szDisplayName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szDisplayName[0]\n");
210         ok(shfiw.szTypeName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szTypeName[0]\n");
211         ok(shfiw.iIcon == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear iIcon\n");
212         ok(shfiw.dwAttributes == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear dwAttributes\n");
213     }
214     else
215         win_skip("SHGetFileInfoW is not available\n");
216 
217 
218     /* Test some flag combinations that MSDN claims are not allowed,
219      * but which work anyway
220      */
221     memset(&shfi, 0xcf, sizeof(shfi));
222     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
223                       &shfi, sizeof(shfi),
224                       SHGFI_ATTRIBUTES | SHGFI_USEFILEATTRIBUTES);
225     ok(rc == 1, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) should return 1, got 0x%x\n", rc);
226     if (rc)
227         ok(shfi.dwAttributes != 0xcfcfcfcf, "dwFileAttributes is not set\n");
228     todo_wine ok(shfi.hIcon == 0, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) did not clear hIcon\n");
229     todo_wine ok(shfi.szDisplayName[0] == 0, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) did not clear szDisplayName[0]\n");
230     todo_wine ok(shfi.szTypeName[0] == 0, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) did not clear szTypeName[0]\n");
231     ok(shfi.iIcon == 0xcfcfcfcf ||
232        broken(shfi.iIcon != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
233        "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) should not clear iIcon\n");
234 
235     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
236                       &shfi, sizeof(shfi),
237                       SHGFI_EXETYPE | SHGFI_USEFILEATTRIBUTES);
238     todo_wine ok(rc == 1, "SHGetFileInfoA(c:\\nonexistent | SHGFI_EXETYPE) should return 1, got 0x%x\n", rc);
239 
240     /* Test SHGFI_USEFILEATTRIBUTES support */
241     strcpy(shfi.szDisplayName, "dummy");
242     shfi.iIcon=0xdeadbeef;
243     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
244                       &shfi, sizeof(shfi),
245                       SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
246     ok(rc == 1, "SHGetFileInfoA(c:\\nonexistent) should return 1, got 0x%x\n", rc);
247     if (rc)
248     {
249         ok(strcmp(shfi.szDisplayName, "dummy"), "SHGetFileInfoA(c:\\nonexistent) displayname is not set\n");
250         ok(shfi.iIcon != 0xdeadbeef, "SHGetFileInfoA(c:\\nonexistent) iIcon is not set\n");
251     }
252 
253     /* Wine does not have a default icon for text files, and Windows 98 fails
254      * if we give it an empty executable. So use notepad.exe as the test
255      */
256     if (SearchPathA(NULL, "notepad.exe", NULL, sizeof(notepad), notepad, NULL))
257     {
258         strcpy(shfi.szDisplayName, "dummy");
259         shfi.iIcon=0xdeadbeef;
260         rc=SHGetFileInfoA(notepad, GetFileAttributesA(notepad),
261                           &shfi, sizeof(shfi),
262                           SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
263         ok(rc == 1, "SHGetFileInfoA(%s, SHGFI_USEFILEATTRIBUTES) should return 1, got 0x%x\n", notepad, rc);
264         strcpy(shfi2.szDisplayName, "dummy");
265         shfi2.iIcon=0xdeadbeef;
266         rc2=SHGetFileInfoA(notepad, 0,
267                            &shfi2, sizeof(shfi2),
268                            SHGFI_ICONLOCATION);
269         ok(rc2 == 1, "SHGetFileInfoA(%s) failed %x\n", notepad, rc2);
270         if (rc && rc2)
271         {
272             ok(lstrcmpiA(shfi2.szDisplayName, shfi.szDisplayName) == 0, "wrong display name %s != %s\n", shfi.szDisplayName, shfi2.szDisplayName);
273             ok(shfi2.iIcon == shfi.iIcon, "wrong icon index %d != %d\n", shfi.iIcon, shfi2.iIcon);
274         }
275     }
276 
277     /* with a directory now */
278     strcpy(shfi.szDisplayName, "dummy");
279     shfi.iIcon=0xdeadbeef;
280     rc=SHGetFileInfoA("test4.txt", GetFileAttributesA("test4.txt"),
281                       &shfi, sizeof(shfi),
282                       SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
283     ok(rc == 1, "SHGetFileInfoA(test4.txt/, SHGFI_USEFILEATTRIBUTES) should return 1, got 0x%x\n", rc);
284     strcpy(shfi2.szDisplayName, "dummy");
285     shfi2.iIcon=0xdeadbeef;
286     rc2=SHGetFileInfoA("test4.txt", 0,
287                       &shfi2, sizeof(shfi2),
288                       SHGFI_ICONLOCATION);
289     ok(rc2 == 1, "SHGetFileInfoA(test4.txt/) should return 1, got 0x%x\n", rc2);
290     if (rc && rc2)
291     {
292         ok(lstrcmpiA(shfi2.szDisplayName, shfi.szDisplayName) == 0, "wrong display name %s != %s\n", shfi.szDisplayName, shfi2.szDisplayName);
293         ok(shfi2.iIcon == shfi.iIcon, "wrong icon index %d != %d\n", shfi.iIcon, shfi2.iIcon);
294     }
295     /* with drive root directory */
296     strcpy(shfi.szDisplayName, "dummy");
297     strcpy(shfi.szTypeName, "dummy");
298     shfi.hIcon=(HICON) 0xdeadbeef;
299     shfi.iIcon=0xdeadbeef;
300     shfi.dwAttributes=0xdeadbeef;
301     rc=SHGetFileInfoA("c:\\", 0, &shfi, sizeof(shfi),
302                       SHGFI_TYPENAME | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON);
303     ok(rc == 1, "SHGetFileInfoA(c:\\) should return 1, got 0x%x\n", rc);
304     ok(strcmp(shfi.szDisplayName, "dummy") != 0, "display name was expected to change\n");
305     ok(strcmp(shfi.szTypeName, "dummy") != 0, "type name was expected to change\n");
306     ok(shfi.hIcon != (HICON) 0xdeadbeef, "hIcon was expected to change\n");
307     ok(shfi.iIcon != 0xdeadbeef, "iIcon was expected to change\n");
308 }
309 
310 static void check_icon_size( HICON icon, DWORD flags )
311 {
312     ICONINFO info;
313     BITMAP bm;
314     SIZE list_size, metrics_size;
315     IImageList *list;
316 
317     GetIconInfo( icon, &info );
318     GetObjectW( info.hbmColor, sizeof(bm), &bm );
319 
320     SHGetImageList( (flags & SHGFI_SMALLICON) ? SHIL_SMALL : SHIL_LARGE,
321                     &IID_IImageList, (void **)&list );
322     IImageList_GetIconSize( list, &list_size.cx, &list_size.cy );
323     IImageList_Release( list );
324 
325     metrics_size.cx = GetSystemMetrics( (flags & SHGFI_SMALLICON) ? SM_CXSMICON : SM_CXICON );
326     metrics_size.cy = GetSystemMetrics( (flags & SHGFI_SMALLICON) ? SM_CYSMICON : SM_CYICON );
327 
328 
329     if (flags & SHGFI_SHELLICONSIZE)
330     {
331         ok( bm.bmWidth == list_size.cx, "got %d expected %d\n", bm.bmWidth, list_size.cx );
332         ok( bm.bmHeight == list_size.cy, "got %d expected %d\n", bm.bmHeight, list_size.cy );
333     }
334     else
335     {
336         ok( bm.bmWidth == metrics_size.cx, "got %d expected %d\n", bm.bmWidth, metrics_size.cx );
337         ok( bm.bmHeight == metrics_size.cy, "got %d expected %d\n", bm.bmHeight, metrics_size.cy );
338     }
339 }
340 
341 static void test_get_file_info_iconlist(void)
342 {
343     /* Test retrieving a handle to the system image list, and
344      * what that returns for hIcon
345      */
346     HRESULT hr;
347     HIMAGELIST hSysImageList;
348     LPITEMIDLIST pidList;
349     SHFILEINFOA shInfoa;
350     SHFILEINFOW shInfow;
351     IImageList *small_list, *large_list;
352     ULONG start_refs, refs;
353 
354     hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidList);
355     if (FAILED(hr)) {
356          skip("can't get desktop pidl\n");
357          return;
358     }
359 
360     SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&large_list );
361     SHGetImageList( SHIL_SMALL, &IID_IImageList, (void **)&small_list );
362 
363     start_refs = IImageList_AddRef( small_list );
364     IImageList_Release( small_list );
365 
366     memset(&shInfoa, 0xcf, sizeof(shInfoa));
367     hSysImageList = (HIMAGELIST) SHGetFileInfoA((const char *)pidList, 0,
368             &shInfoa, sizeof(shInfoa),
369 	    SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_PIDL);
370     ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
371     refs = IImageList_AddRef( small_list );
372     IImageList_Release( small_list );
373     ok( refs == start_refs + 1 ||
374         broken( refs == start_refs ), /* XP and 2003 */
375         "got %d, start_refs %d\n", refs, start_refs );
376     todo_wine ok(shInfoa.hIcon == 0, "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear hIcon\n");
377     todo_wine ok(shInfoa.szTypeName[0] == 0, "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear szTypeName[0]\n");
378     ok(shInfoa.iIcon != 0xcfcfcfcf, "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) should set iIcon\n");
379     ok(shInfoa.dwAttributes == 0xcfcfcfcf ||
380        shInfoa.dwAttributes ==  0 || /* Vista */
381        broken(shInfoa.dwAttributes != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
382        "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL), unexpected dwAttributes\n");
383     /* Don't release hSysImageList here (and in similar places below) because of the broken reference behaviour of XP and 2003. */
384 
385     if (!pSHGetFileInfoW)
386     {
387         win_skip("SHGetFileInfoW is not available\n");
388         ILFree(pidList);
389         return;
390     }
391 
392     memset(&shInfow, 0xcf, sizeof(shInfow));
393     hSysImageList = (HIMAGELIST) pSHGetFileInfoW((const WCHAR *)pidList, 0,
394             &shInfow, sizeof(shInfow),
395 	    SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_PIDL);
396     if (!hSysImageList)
397     {
398         win_skip("SHGetFileInfoW is not implemented\n");
399         return;
400     }
401     ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
402     todo_wine ok(shInfow.hIcon == 0, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear hIcon\n");
403     ok(shInfow.szTypeName[0] == 0, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear szTypeName[0]\n");
404     ok(shInfow.iIcon != 0xcfcfcfcf, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) should set iIcon\n");
405     ok(shInfow.dwAttributes == 0xcfcfcfcf ||
406        shInfoa.dwAttributes ==  0, /* Vista */
407        "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) unexpected dwAttributes\n");
408 
409     /* Various suposidly invalid flag testing */
410     memset(&shInfow, 0xcf, sizeof(shInfow));
411     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
412 	    SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
413     ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
414     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
415     ok(shInfow.dwAttributes==0xcfcfcfcf ||
416        shInfoa.dwAttributes==0, /* Vista */
417        "unexpected dwAttributes\n");
418 
419     memset(&shInfow, 0xcf, sizeof(shInfow));
420     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
421 	    SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
422     ok(hr != 0, " SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
423     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
424     check_icon_size( shInfow.hIcon, SHGFI_SMALLICON );
425     DestroyIcon(shInfow.hIcon);
426     todo_wine ok(shInfow.dwAttributes==0,"dwAttributes not set\n");
427 
428     memset(&shInfow, 0xcf, sizeof(shInfow));
429     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
430 	    SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON);
431     ok(hr != 0, "SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON Failed\n");
432     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
433     check_icon_size( shInfow.hIcon, SHGFI_LARGEICON );
434     DestroyIcon( shInfow.hIcon );
435     todo_wine ok(shInfow.dwAttributes==0,"dwAttributes not set\n");
436 
437     memset(&shInfow, 0xcf, sizeof(shInfow));
438     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
439 	    SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON);
440     ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, small_list);
441     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
442     ok(shInfow.dwAttributes==0xcfcfcfcf ||
443        shInfoa.dwAttributes==0, /* Vista */
444        "unexpected dwAttributes\n");
445 
446     memset(&shInfow, 0xcf, sizeof(shInfow));
447     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
448 	    SHGFI_OPENICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
449     ok(hr != 0, "SHGFI_OPENICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
450     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
451     ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
452 
453     memset(&shInfow, 0xcf, sizeof(shInfow));
454     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
455 	    SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
456     ok(hr != 0, "SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
457     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
458     ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
459 
460     memset(&shInfow, 0xcf, sizeof(shInfow));
461     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
462 	    SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
463     ok(hr != 0, "SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
464     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
465     ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
466 
467     memset(&shInfow, 0xcf, sizeof(shInfow));
468     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
469 	    SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|
470         SHGFI_ATTRIBUTES);
471     ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
472     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
473     ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
474 
475     memset(&shInfow, 0xcf, sizeof(shInfow));
476     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
477 	    SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|
478         SHGFI_EXETYPE);
479     todo_wine ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
480     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
481     ok(shInfow.dwAttributes==0xcfcfcfcf ||
482        shInfoa.dwAttributes==0, /* Vista */
483        "unexpected dwAttributes\n");
484 
485     memset(&shInfow, 0xcf, sizeof(shInfow));
486     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
487         SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE);
488     todo_wine ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE Failed\n");
489     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
490     ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
491 
492     memset(&shInfow, 0xcf, sizeof(shInfow));
493     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
494         SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES);
495     ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES Failed\n");
496     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
497     ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
498 
499     memset(&shInfow, 0xcf, sizeof(shInfow));
500     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
501 	    SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|
502         SHGFI_ATTRIBUTES);
503     ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, large_list);
504     ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES Failed\n");
505     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
506     ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
507 
508     memset(&shInfow, 0xcf, sizeof(shInfow));
509     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
510         SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE);
511     todo_wine ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, large_list);
512     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
513     ok(shInfow.dwAttributes==0xcfcfcfcf ||
514        shInfoa.dwAttributes==0, /* Vista */
515        "unexpected dwAttributes\n");
516 
517     memset(&shInfow, 0xcf, sizeof(shInfow));
518     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
519         SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE);
520     todo_wine ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE Failed\n");
521     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
522     ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
523 
524     memset(&shInfow, 0xcf, sizeof(shInfow));
525     hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
526         SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES);
527     ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES Failed\n");
528     todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
529     ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
530 
531     memset(&shInfow, 0xcf, sizeof(shInfow));
532     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
533 	    SHGFI_SYSICONINDEX|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_SHELLICONSIZE|SHGFI_ICON);
534     ok(hSysImageList == (HIMAGELIST)small_list, "got %p expect %p\n", hSysImageList, small_list);
535     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
536     check_icon_size( shInfow.hIcon, SHGFI_SMALLICON | SHGFI_SHELLICONSIZE );
537     DestroyIcon( shInfow.hIcon );
538 
539     memset(&shInfow, 0xcf, sizeof(shInfow));
540     hSysImageList = (HIMAGELIST)pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
541 	    SHGFI_SYSICONINDEX|SHGFI_PIDL|SHGFI_SHELLICONSIZE|SHGFI_ICON);
542     ok(hSysImageList == (HIMAGELIST)large_list, "got %p expect %p\n", hSysImageList, small_list);
543     ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
544     check_icon_size( shInfow.hIcon, SHGFI_LARGEICON | SHGFI_SHELLICONSIZE );
545     DestroyIcon( shInfow.hIcon );
546 
547     ILFree(pidList);
548     IImageList_Release( small_list );
549     IImageList_Release( large_list );
550 }
551 
552 
553 /*
554  puts into the specified buffer file names with current directory.
555  files - string with file names, separated by null characters. Ends on a double
556  null characters
557 */
558 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
559 {
560     buf[0] = 0;
561     while (files[0])
562     {
563         strcpy(buf, CURR_DIR);
564         buf += strlen(buf);
565         buf[0] = '\\';
566         buf++;
567         strcpy(buf, files);
568         buf += strlen(buf) + 1;
569         files += strlen(files) + 1;
570     }
571     buf[0] = 0;
572 }
573 
574 
575 /* tests the FO_DELETE action */
576 static void test_delete(void)
577 {
578     SHFILEOPSTRUCTA shfo;
579     DWORD ret;
580     CHAR buf[sizeof(CURR_DIR)+sizeof("/test?.txt")+1];
581 
582     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
583     buf[strlen(buf) + 1] = '\0';
584 
585     shfo.hwnd = NULL;
586     shfo.wFunc = FO_DELETE;
587     shfo.pFrom = buf;
588     shfo.pTo = NULL;
589     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
590     shfo.hNameMappings = NULL;
591     shfo.lpszProgressTitle = NULL;
592 
593     ok(!SHFileOperationA(&shfo), "Deletion was not successful\n");
594     ok(dir_exists("test4.txt"), "Directory should not have been removed\n");
595     ok(!file_exists("test1.txt"), "File should have been removed\n");
596     ok(!file_exists("test2.txt"), "File should have been removed\n");
597     ok(!file_exists("test3.txt"), "File should have been removed\n");
598 
599     ret = SHFileOperationA(&shfo);
600     ok(ret == ERROR_SUCCESS, "Directory exists, but is not removed, ret=%d\n", ret);
601     ok(dir_exists("test4.txt"), "Directory should not have been removed\n");
602 
603     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
604 
605     ok(!SHFileOperationA(&shfo), "Directory is not removed\n");
606     ok(!dir_exists("test4.txt"), "Directory should have been removed\n");
607 
608     ret = SHFileOperationA(&shfo);
609     ok(!ret, "The requested file does not exist, ret=%d\n", ret);
610 
611     init_shfo_tests();
612     sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
613     buf[strlen(buf) + 1] = '\0';
614     ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Filling the subdirectory failed\n");
615     ok(!SHFileOperationA(&shfo), "Directory is not removed\n");
616     ok(!dir_exists("test4.txt"), "Directory is not removed\n");
617 
618     init_shfo_tests();
619     shfo.pFrom = "test1.txt\0test4.txt\0";
620     ok(!SHFileOperationA(&shfo), "Directory and a file are not removed\n");
621     ok(!file_exists("test1.txt"), "The file should have been removed\n");
622     ok(!dir_exists("test4.txt"), "Directory should have been removed\n");
623     ok(file_exists("test2.txt"), "This file should not have been removed\n");
624 
625     /* FOF_FILESONLY does not delete a dir matching a wildcard */
626     init_shfo_tests();
627     shfo.fFlags |= FOF_FILESONLY;
628     shfo.pFrom = "*.txt\0";
629     ok(!SHFileOperationA(&shfo), "Failed to delete files\n");
630     ok(!file_exists("test1.txt"), "test1.txt should have been removed\n");
631     ok(!file_exists("test_5.txt"), "test_5.txt should have been removed\n");
632     ok(dir_exists("test4.txt"), "test4.txt should not have been removed\n");
633 
634     /* FOF_FILESONLY only deletes a dir if explicitly specified */
635     init_shfo_tests();
636     shfo.pFrom = "test_?.txt\0test4.txt\0";
637     ok(!SHFileOperationA(&shfo), "Failed to delete files and directory\n");
638     ok(!dir_exists("test4.txt") ||
639        broken(dir_exists("test4.txt")), /* NT4 */
640       "test4.txt should have been removed\n");
641     ok(!file_exists("test_5.txt"), "test_5.txt should have been removed\n");
642     ok(file_exists("test1.txt"), "test1.txt should not have been removed\n");
643 
644     /* try to delete an invalid filename */
645     if (0) {
646         /* this crashes on win9x */
647         init_shfo_tests();
648         shfo.pFrom = "\0";
649         shfo.fFlags &= ~FOF_FILESONLY;
650         shfo.fAnyOperationsAborted = FALSE;
651         ret = SHFileOperationA(&shfo);
652         ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
653         ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
654         ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
655     }
656 
657     /* try an invalid function */
658     init_shfo_tests();
659     shfo.pFrom = "test1.txt\0";
660     shfo.wFunc = 0;
661     ret = SHFileOperationA(&shfo);
662     ok(ret == ERROR_INVALID_PARAMETER ||
663        broken(ret == ERROR_SUCCESS), /* Win9x, NT4 */
664        "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
665     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
666 
667     /* try an invalid list, only one null terminator */
668     if (0) {
669         /* this crashes on win9x */
670         init_shfo_tests();
671         shfo.pFrom = "";
672         shfo.wFunc = FO_DELETE;
673         ret = SHFileOperationA(&shfo);
674         ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
675         ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
676     }
677 
678     /* delete a nonexistent file */
679     shfo.pFrom = "nonexistent.txt\0";
680     shfo.wFunc = FO_DELETE;
681     ret = SHFileOperationA(&shfo);
682     ok(ret == 1026 ||
683        ret == ERROR_FILE_NOT_FOUND || /* Vista */
684        broken(ret == ERROR_SUCCESS), /* NT4 */
685        "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", ret);
686 
687     /* delete a dir, and then a file inside the dir, same as
688     * deleting a nonexistent file
689     */
690     if (ret != ERROR_FILE_NOT_FOUND)
691     {
692         /* Vista would throw up a dialog box that we can't suppress */
693         init_shfo_tests();
694         shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
695         ret = SHFileOperationA(&shfo);
696         ok(ret == ERROR_PATH_NOT_FOUND ||
697            broken(ret == ERROR_SUCCESS), /* NT4 */
698            "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret);
699         ok(!dir_exists("testdir2"), "Expected testdir2 to not exist\n");
700         ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
701     }
702     else
703         skip("Test would show a dialog box\n");
704 
705     /* delete an existent file and a nonexistent file */
706     init_shfo_tests();
707     shfo.pFrom = "test1.txt\0nonexistent.txt\0test2.txt\0";
708     shfo.wFunc = FO_DELETE;
709     ret = SHFileOperationA(&shfo);
710     ok(ret == 1026 ||
711        ret == ERROR_FILE_NOT_FOUND || /* Vista */
712        broken(ret == ERROR_SUCCESS), /* NT4 */
713        "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", ret);
714     todo_wine
715     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
716     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
717 
718     /* delete a nonexistent file in an existent dir or a nonexistent dir */
719     init_shfo_tests();
720     shfo.pFrom = "testdir2\\nonexistent.txt\0";
721     ret = SHFileOperationA(&shfo);
722     ok(ret == ERROR_FILE_NOT_FOUND || /* Vista */
723        broken(ret == 0x402) || /* XP */
724        broken(ret == ERROR_SUCCESS), /* NT4 */
725        "Expected 0x402 or ERROR_FILE_NOT_FOUND, got %x\n", ret);
726     shfo.pFrom = "nonexistent\\one.txt\0";
727     ret = SHFileOperationA(&shfo);
728     ok(ret == DE_INVALIDFILES || /* Vista or later */
729        broken(ret == 0x402), /* XP */
730        "Expected 0x402 or DE_INVALIDFILES, got %x\n", ret);
731 
732     /* try the FOF_NORECURSION flag, continues deleting subdirs */
733     init_shfo_tests();
734     shfo.pFrom = "testdir2\0";
735     shfo.fFlags |= FOF_NORECURSION;
736     ret = SHFileOperationA(&shfo);
737     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
738     ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
739     ok(!dir_exists("testdir2\\nested"), "Expected testdir2\\nested to not exist\n");
740 }
741 
742 /* tests the FO_RENAME action */
743 static void test_rename(void)
744 {
745     SHFILEOPSTRUCTA shfo, shfo2;
746     CHAR from[5*MAX_PATH];
747     CHAR to[5*MAX_PATH];
748     DWORD retval;
749 
750     shfo.hwnd = NULL;
751     shfo.wFunc = FO_RENAME;
752     shfo.pFrom = from;
753     shfo.pTo = to;
754     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
755     shfo.hNameMappings = NULL;
756     shfo.lpszProgressTitle = NULL;
757 
758     set_curr_dir_path(from, "test1.txt\0");
759     set_curr_dir_path(to, "test4.txt\0");
760     retval = SHFileOperationA(&shfo);
761     ok(retval == ERROR_ALREADY_EXISTS ||
762        retval == DE_FILEDESTISFLD || /* Vista */
763        broken(retval == ERROR_INVALID_NAME), /* Win9x, NT4 */
764        "Expected ERROR_ALREADY_EXISTS or DE_FILEDESTISFLD, got %d\n", retval);
765     ok(file_exists("test1.txt"), "The file is renamed\n");
766 
767     set_curr_dir_path(from, "test3.txt\0");
768     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
769     retval = SHFileOperationA(&shfo);
770     if (retval == DE_DIFFDIR)
771     {
772         /* Vista and W2K8 (broken or new behavior ?) */
773         ok(!file_exists("test4.txt\\test1.txt"), "The file is renamed\n");
774     }
775     else
776     {
777         ok(retval == ERROR_SUCCESS, "File is renamed moving to other directory\n");
778         ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
779     }
780 
781     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
782     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
783     retval = SHFileOperationA(&shfo);
784     ok(retval == ERROR_GEN_FAILURE ||
785        retval == DE_MANYSRC1DEST || /* Vista */
786        broken(retval == ERROR_SUCCESS), /* Win9x */
787        "Expected ERROR_GEN_FAILURE or DE_MANYSRC1DEST , got %d\n", retval);
788     ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
789 
790     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
791     shfo2.fFlags |= FOF_MULTIDESTFILES;
792 
793     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
794     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
795     retval = SHFileOperationA(&shfo2);
796     ok(retval == ERROR_GEN_FAILURE ||
797        retval == DE_MANYSRC1DEST || /* Vista */
798        broken(retval == ERROR_SUCCESS), /* Win9x */
799        "Expected ERROR_GEN_FAILURE or DE_MANYSRC1DEST files, got %d\n", retval);
800     ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
801 
802     set_curr_dir_path(from, "test1.txt\0");
803     set_curr_dir_path(to, "test6.txt\0");
804     retval = SHFileOperationA(&shfo);
805     ok(retval == ERROR_SUCCESS, "Rename file failed, retval = %d\n", retval);
806     ok(!file_exists("test1.txt"), "The file is not renamed\n");
807     ok(file_exists("test6.txt"), "The file is not renamed\n");
808 
809     set_curr_dir_path(from, "test6.txt\0");
810     set_curr_dir_path(to, "test1.txt\0");
811     retval = SHFileOperationA(&shfo);
812     ok(retval == ERROR_SUCCESS, "Rename file back failed, retval = %d\n", retval);
813 
814     set_curr_dir_path(from, "test4.txt\0");
815     set_curr_dir_path(to, "test6.txt\0");
816     retval = SHFileOperationA(&shfo);
817     ok(retval == ERROR_SUCCESS, "Rename dir failed, retval = %d\n", retval);
818     ok(!dir_exists("test4.txt"), "The dir is not renamed\n");
819     ok(dir_exists("test6.txt"), "The dir is not renamed\n");
820 
821     set_curr_dir_path(from, "test6.txt\0");
822     set_curr_dir_path(to, "test4.txt\0");
823     retval = SHFileOperationA(&shfo);
824     ok(retval == ERROR_SUCCESS, "Rename dir back failed, retval = %d\n", retval);
825     ok(dir_exists("test4.txt"), "The dir is not renamed\n");
826 
827     /* try to rename more than one file to a single file */
828     shfo.pFrom = "test1.txt\0test2.txt\0";
829     shfo.pTo = "a.txt\0";
830     retval = SHFileOperationA(&shfo);
831     ok(retval == ERROR_GEN_FAILURE ||
832        retval == DE_MANYSRC1DEST || /* Vista */
833        broken(retval == ERROR_SUCCESS), /* Win9x */
834        "Expected ERROR_GEN_FAILURE or DE_MANYSRC1DEST, got %d\n", retval);
835     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
836     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
837     ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
838 
839     /* pFrom doesn't exist */
840     shfo.pFrom = "idontexist\0";
841     shfo.pTo = "newfile\0";
842     retval = SHFileOperationA(&shfo);
843     ok(retval == 1026 ||
844        retval == ERROR_FILE_NOT_FOUND || /* Vista */
845        broken(retval == ERROR_SUCCESS), /* NT4 */
846        "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", retval);
847     ok(!file_exists("newfile"), "Expected newfile to not exist\n");
848 
849     /* pTo already exist */
850     shfo.pFrom = "test1.txt\0";
851     shfo.pTo = "test2.txt\0";
852     if (old_shell32)
853         shfo.fFlags |= FOF_NOCONFIRMMKDIR;
854     retval = SHFileOperationA(&shfo);
855     if (retval == ERROR_SUCCESS)
856     {
857         /* Vista and W2K8 (broken or new behavior ?) */
858         createTestFile("test1.txt");
859     }
860     else
861     {
862         ok(retval == ERROR_ALREADY_EXISTS ||
863            broken(retval == DE_OPCANCELLED) || /* NT4 */
864            broken(retval == ERROR_INVALID_NAME), /* Win9x */
865            "Expected ERROR_ALREADY_EXISTS, got %d\n", retval);
866     }
867 
868     /* pFrom is valid, but pTo is empty */
869     shfo.pFrom = "test1.txt\0";
870     shfo.pTo = "\0";
871     retval = SHFileOperationA(&shfo);
872     ok(retval == ERROR_CANCELLED ||
873        retval == DE_DIFFDIR || /* Vista */
874        retval == DE_FILEDESTISFLD || /* Vista, running from c: */
875        broken(retval == DE_OPCANCELLED) || /* Win9x */
876        broken(retval == 65652), /* NT4 */
877        "Expected ERROR_CANCELLED or DE_DIFFDIR, got %u\n", retval);
878     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
879 
880     /* pFrom is empty */
881     shfo.pFrom = "\0";
882     retval = SHFileOperationA(&shfo);
883     ok(retval == ERROR_ACCESS_DENIED ||
884        retval == DE_MANYSRC1DEST || /* Vista */
885        broken(retval == ERROR_SUCCESS), /* Win9x */
886        "Expected ERROR_ACCESS_DENIED or DE_MANYSRC1DEST, got %d\n", retval);
887 
888     /* pFrom is NULL, commented out because it crashes on nt 4.0 */
889     if (0)
890     {
891         shfo.pFrom = NULL;
892         retval = SHFileOperationA(&shfo);
893         ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", retval);
894     }
895 }
896 
897 /* tests the FO_COPY action */
898 static void test_copy(void)
899 {
900     SHFILEOPSTRUCTA shfo, shfo2;
901     CHAR from[5*MAX_PATH];
902     CHAR to[5*MAX_PATH];
903     FILEOP_FLAGS tmp_flags;
904     DWORD retval;
905     LPSTR ptr;
906     BOOL on_nt4 = FALSE;
907     BOOL ret;
908 
909     if (old_shell32)
910     {
911         win_skip("Too many differences for old shell32\n");
912         return;
913     }
914 
915     shfo.hwnd = NULL;
916     shfo.wFunc = FO_COPY;
917     shfo.pFrom = from;
918     shfo.pTo = to;
919     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
920     shfo.hNameMappings = NULL;
921     shfo.lpszProgressTitle = NULL;
922 
923     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
924     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
925     retval = SHFileOperationA(&shfo);
926     if (dir_exists("test6.txt"))
927     {
928         /* Vista and W2K8 (broken or new behavior ?) */
929         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
930         ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not copied - many files "
931            "are specified as a target\n");
932         DeleteFileA("test6.txt\\test2.txt");
933         RemoveDirectoryA("test6.txt\\test4.txt");
934         RemoveDirectoryA("test6.txt");
935     }
936     else
937     {
938         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
939         ok(!file_exists("test6.txt"), "The file is copied - many files are "
940            "specified as a target\n");
941     }
942 
943     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
944     shfo2.fFlags |= FOF_MULTIDESTFILES;
945 
946     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
947     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
948     ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
949     ok(file_exists("test6.txt"), "The file is not copied - many files are "
950        "specified as a target\n");
951     DeleteFileA("test6.txt");
952     DeleteFileA("test7.txt");
953     RemoveDirectoryA("test8.txt");
954 
955     /* number of sources does not correspond to number of targets */
956     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
957     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
958     retval = SHFileOperationA(&shfo2);
959     if (dir_exists("test6.txt"))
960     {
961         /* Vista and W2K8 (broken or new behavior?) */
962         ok(retval == DE_DESTSAMETREE, "Expected DE_DESTSAMETREE, got %d\n", retval);
963         ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not copied - many files "
964            "are specified as a target\n");
965         RemoveDirectoryA("test6.txt");
966         ok(DeleteFileA("test7.txt\\test2.txt"), "The file is not copied - many files "
967            "are specified as a target\n");
968         RemoveDirectoryA("test7.txt");
969     }
970     else
971     {
972         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
973         ok(!file_exists("test6.txt"), "The file is copied - many files are "
974            "specified as a target\n");
975     }
976 
977     set_curr_dir_path(from, "test1.txt\0");
978     set_curr_dir_path(to, "test4.txt\0");
979     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
980     ok(file_exists("test4.txt\\test1.txt"), "The file is copied\n");
981 
982     set_curr_dir_path(from, "test?.txt\0");
983     set_curr_dir_path(to, "testdir2\0");
984     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
985     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
986     ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
987     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
988     ok(file_exists("testdir2\\test4.txt"), "The directory is copied\n");
989     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
990     clean_after_shfo_tests();
991 
992     init_shfo_tests();
993     shfo.fFlags |= FOF_FILESONLY;
994     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
995     ok(!file_exists("testdir2\\test4.txt"), "The directory is not copied yet\n");
996     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
997     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
998     ok(!file_exists("testdir2\\test4.txt"), "The directory is copied\n");
999     clean_after_shfo_tests();
1000 
1001     init_shfo_tests();
1002     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
1003     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
1004     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
1005     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
1006     ok(file_exists("testdir2\\test1.txt"), "The file is copied\n");
1007     ok(file_exists("testdir2\\test2.txt"), "The file is copied\n");
1008     clean_after_shfo_tests();
1009 
1010     /* Copying multiple files with one not existing as source, fails the
1011        entire operation in Win98/ME/2K/XP, but not in 95/NT */
1012     init_shfo_tests();
1013     tmp_flags = shfo.fFlags;
1014     set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
1015     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
1016     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
1017     retval = SHFileOperationA(&shfo);
1018     if (retval == ERROR_SUCCESS)
1019         /* Win 95/NT returns success but copies only the files up to the nonexistent source */
1020         ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
1021     else
1022     {
1023         /* Failure if one source file does not exist */
1024         ok(retval == 1026 || /* Win 98/ME/2K/XP */
1025            retval == ERROR_FILE_NOT_FOUND, /* Vista and W2K8 */
1026            "Files are copied to other directory\n");
1027         ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
1028     }
1029     ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
1030     shfo.fFlags = tmp_flags;
1031 
1032     /* copy into a nonexistent directory */
1033     init_shfo_tests();
1034     shfo.fFlags = FOF_NOCONFIRMMKDIR;
1035     set_curr_dir_path(from, "test1.txt\0");
1036     set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
1037     retval= SHFileOperationA(&shfo);
1038     ok(!retval, "Error copying into nonexistent directory\n");
1039     ok(file_exists("nonexistent"), "nonexistent not created\n");
1040     ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
1041     ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
1042     ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
1043 
1044     /* a relative dest directory is OK */
1045     clean_after_shfo_tests();
1046     init_shfo_tests();
1047     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
1048     shfo.pTo = "testdir2\0";
1049     retval = SHFileOperationA(&shfo);
1050     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1051     ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1 to exist\n");
1052 
1053     /* try to overwrite an existing write protected file */
1054     clean_after_shfo_tests();
1055     init_shfo_tests();
1056     tmp_flags = shfo.fFlags;
1057     shfo.pFrom = "test1.txt\0";
1058     shfo.pTo = "test2.txt\0";
1059     /* suppress the error-dialog in win9x here */
1060     shfo.fFlags = FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT;
1061     ret = SetFileAttributesA(shfo.pTo, FILE_ATTRIBUTE_READONLY);
1062     ok(ret, "Failure to set file attributes (error %x)\n", GetLastError());
1063     retval = CopyFileA(shfo.pFrom, shfo.pTo, FALSE);
1064     ok(!retval && GetLastError() == ERROR_ACCESS_DENIED, "CopyFileA should have fail with ERROR_ACCESS_DENIED\n");
1065     retval = SHFileOperationA(&shfo);
1066     /* Does not work on Win95, Win95B, NT4WS and NT4SRV */
1067     ok(!retval || broken(retval == DE_OPCANCELLED), "SHFileOperationA failed to copy (error %x)\n", retval);
1068     /* Set back normal attributes to make the file deletion succeed */
1069     ret = SetFileAttributesA(shfo.pTo, FILE_ATTRIBUTE_NORMAL);
1070     ok(ret, "Failure to set file attributes (error %x)\n", GetLastError());
1071     shfo.fFlags = tmp_flags;
1072 
1073     /* try to copy files to a file */
1074     clean_after_shfo_tests();
1075     init_shfo_tests();
1076     shfo.pFrom = from;
1077     shfo.pTo = to;
1078     /* suppress the error-dialog in win9x here */
1079     shfo.fFlags |= FOF_NOERRORUI;
1080     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
1081     set_curr_dir_path(to, "test3.txt\0");
1082     shfo.fAnyOperationsAborted = 0xdeadbeef;
1083     retval = SHFileOperationA(&shfo);
1084     ok(shfo.fAnyOperationsAborted != 0xdeadbeef ||
1085        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1086        "Expected TRUE/FALSE fAnyOperationsAborted not 0xdeadbeef\n");
1087     if (retval == DE_FLDDESTISFILE || /* Vista and W2K8 */
1088         retval == DE_INVALIDFILES)    /* Win7 */
1089     {
1090         /* Most likely new behavior */
1091         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1092     }
1093     else
1094     {
1095         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1096         ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
1097     }
1098     ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
1099 
1100     /* try to copy many files to nonexistent directory */
1101     DeleteFileA(to);
1102     shfo.fFlags &= ~FOF_NOERRORUI;
1103     shfo.fAnyOperationsAborted = 0xdeadbeef;
1104     retval = SHFileOperationA(&shfo);
1105     ok(!shfo.fAnyOperationsAborted ||
1106        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1107        "Didn't expect aborted operations\n");
1108     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1109     ok(DeleteFileA("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
1110     ok(DeleteFileA("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
1111     ok(RemoveDirectoryA(to), "Expected test3.txt to exist\n");
1112 
1113     /* send in FOF_MULTIDESTFILES with too many destination files */
1114     init_shfo_tests();
1115     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
1116     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
1117     shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
1118     shfo.fAnyOperationsAborted = 0xdeadbeef;
1119     retval = SHFileOperationA(&shfo);
1120     ok(shfo.fAnyOperationsAborted != 0xdeadbeef ||
1121        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1122        "Expected TRUE/FALSE fAnyOperationsAborted not 0xdeadbeef\n");
1123     if (dir_exists("testdir2\\a.txt"))
1124     {
1125         /* Vista and W2K8 (broken or new behavior ?) */
1126         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1127         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1128         ok(DeleteFileA("testdir2\\a.txt\\test1.txt"), "Expected testdir2\\a.txt\\test1.txt to exist\n");
1129         RemoveDirectoryA("testdir2\\a.txt");
1130         ok(DeleteFileA("testdir2\\b.txt\\test2.txt"), "Expected testdir2\\b.txt\\test2.txt to exist\n");
1131         RemoveDirectoryA("testdir2\\b.txt");
1132         ok(DeleteFileA("testdir2\\c.txt\\test3.txt"), "Expected testdir2\\c.txt\\test3.txt to exist\n");
1133         RemoveDirectoryA("testdir2\\c.txt");
1134         ok(!file_exists("testdir2\\d.txt"), "Expected testdir2\\d.txt to not exist\n");
1135     }
1136     else
1137     {
1138         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1139         ok(shfo.fAnyOperationsAborted ||
1140            broken(!shfo.fAnyOperationsAborted), /* NT4 */
1141            "Expected aborted operations\n");
1142         ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
1143     }
1144 
1145     /* send in FOF_MULTIDESTFILES with too many destination files */
1146     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
1147     shfo.pTo = "e.txt\0f.txt\0";
1148     shfo.fAnyOperationsAborted = 0xdeadbeef;
1149     retval = SHFileOperationA(&shfo);
1150     ok(shfo.fAnyOperationsAborted != 0xdeadbeef ||
1151        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1152        "Expected TRUE/FALSE fAnyOperationsAborted not 0xdeadbeef\n");
1153     if (dir_exists("e.txt"))
1154     {
1155         /* Vista and W2K8 (broken or new behavior ?) */
1156         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1157         ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
1158         ok(DeleteFileA("e.txt\\test1.txt"), "Expected e.txt\\test1.txt to exist\n");
1159         RemoveDirectoryA("e.txt");
1160         ok(DeleteFileA("f.txt\\test2.txt"), "Expected f.txt\\test2.txt to exist\n");
1161         RemoveDirectoryA("f.txt");
1162     }
1163     else
1164     {
1165         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1166         ok(shfo.fAnyOperationsAborted ||
1167            broken(!shfo.fAnyOperationsAborted), /* NT4 */
1168            "Expected aborted operations\n");
1169         ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
1170     }
1171 
1172     /* use FOF_MULTIDESTFILES with files and a source directory */
1173     shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
1174     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
1175     shfo.fAnyOperationsAborted = 0xdeadbeef;
1176     retval = SHFileOperationA(&shfo);
1177     ok(!shfo.fAnyOperationsAborted ||
1178        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1179        "Didn't expect aborted operations\n");
1180     ok(retval == ERROR_SUCCESS ||
1181        broken(retval == 0x100a1), /* WinMe */
1182        "Expected ERROR_SUCCESS, got %d\n", retval);
1183     ok(DeleteFileA("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
1184     ok(DeleteFileA("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
1185     if (retval == ERROR_SUCCESS)
1186         ok(RemoveDirectoryA("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
1187 
1188     /* try many dest files without FOF_MULTIDESTFILES flag */
1189     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
1190     shfo.pTo = "a.txt\0b.txt\0c.txt\0";
1191     shfo.fAnyOperationsAborted = 0xdeadbeef;
1192     shfo.fFlags &= ~FOF_MULTIDESTFILES;
1193     retval = SHFileOperationA(&shfo);
1194     ok(shfo.fAnyOperationsAborted != 0xdeadbeef ||
1195        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1196        "Expected TRUE/FALSE fAnyOperationsAborted not 0xdeadbeef\n");
1197     if (dir_exists("a.txt"))
1198     {
1199         /* Vista and W2K8 (broken or new behavior ?) */
1200         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1201         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1202         ok(DeleteFileA("a.txt\\test1.txt"), "Expected a.txt\\test1.txt to exist\n");
1203         ok(DeleteFileA("a.txt\\test2.txt"), "Expected a.txt\\test2.txt to exist\n");
1204         ok(DeleteFileA("a.txt\\test3.txt"), "Expected a.txt\\test3.txt to exist\n");
1205         RemoveDirectoryA("a.txt");
1206     }
1207     else
1208     {
1209 
1210         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1211         ok(shfo.fAnyOperationsAborted ||
1212            broken(!shfo.fAnyOperationsAborted), /* NT4 */
1213            "Expected aborted operations\n");
1214         ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
1215     }
1216 
1217     /* try a glob */
1218     shfo.pFrom = "test?.txt\0";
1219     shfo.pTo = "testdir2\0";
1220     shfo.fFlags &= ~FOF_MULTIDESTFILES;
1221     retval = SHFileOperationA(&shfo);
1222     ok(retval == ERROR_SUCCESS ||
1223        broken(retval == 0x100a1), /* WinMe */
1224        "Expected ERROR_SUCCESS, got %d\n", retval);
1225     ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
1226 
1227     /* try a glob with FOF_FILESONLY */
1228     clean_after_shfo_tests();
1229     init_shfo_tests();
1230     shfo.pFrom = "test?.txt\0";
1231     shfo.fFlags |= FOF_FILESONLY;
1232     retval = SHFileOperationA(&shfo);
1233     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1234     ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
1235     ok(!dir_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
1236 
1237     /* try a glob with FOF_MULTIDESTFILES and the same number
1238     * of dest files that we would expect
1239     */
1240     clean_after_shfo_tests();
1241     init_shfo_tests();
1242     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
1243     shfo.fFlags &= ~FOF_FILESONLY;
1244     shfo.fFlags |= FOF_MULTIDESTFILES;
1245     retval = SHFileOperationA(&shfo);
1246     if (dir_exists("testdir2\\a.txt"))
1247     {
1248         /* Vista and W2K8 (broken or new behavior ?) */
1249         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1250         ok(DeleteFileA("testdir2\\a.txt\\test1.txt"), "Expected testdir2\\a.txt\\test1.txt to exist\n");
1251         ok(DeleteFileA("testdir2\\a.txt\\test2.txt"), "Expected testdir2\\a.txt\\test2.txt to exist\n");
1252         ok(DeleteFileA("testdir2\\a.txt\\test3.txt"), "Expected testdir2\\a.txt\\test3.txt to exist\n");
1253         ok(RemoveDirectoryA("testdir2\\a.txt\\test4.txt"), "Expected testdir2\\a.txt\\test4.txt to exist\n");
1254         RemoveDirectoryA("testdir2\\a.txt");
1255     }
1256     else
1257     {
1258         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1259         ok(shfo.fAnyOperationsAborted ||
1260            broken(!shfo.fAnyOperationsAborted), /* NT4 */
1261            "Expected aborted operations\n");
1262         ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
1263     }
1264     ok(!RemoveDirectoryA("b.txt"), "b.txt should not exist\n");
1265 
1266     /* copy one file to two others, second is ignored */
1267     clean_after_shfo_tests();
1268     init_shfo_tests();
1269     shfo.pFrom = "test1.txt\0";
1270     shfo.pTo = "b.txt\0c.txt\0";
1271     shfo.fAnyOperationsAborted = 0xdeadbeef;
1272     retval = SHFileOperationA(&shfo);
1273     ok(!shfo.fAnyOperationsAborted ||
1274        broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1275        "Didn't expect aborted operations\n");
1276     if (retval == DE_OPCANCELLED)
1277     {
1278         /* NT4 fails and doesn't copy any files */
1279         ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
1280         /* Needed to skip some tests */
1281         win_skip("Skipping some tests on NT4\n");
1282         on_nt4 = TRUE;
1283     }
1284     else
1285     {
1286         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1287         ok(DeleteFileA("b.txt"), "Expected b.txt to exist\n");
1288     }
1289     ok(!DeleteFileA("c.txt"), "Expected c.txt to not exist\n");
1290 
1291     /* copy two file to three others, all fail */
1292     shfo.pFrom = "test1.txt\0test2.txt\0";
1293     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
1294     shfo.fAnyOperationsAborted = 0xdeadbeef;
1295     retval = SHFileOperationA(&shfo);
1296     if (dir_exists("b.txt"))
1297     {
1298         /* Vista and W2K8 (broken or new behavior ?) */
1299         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1300         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1301         ok(DeleteFileA("b.txt\\test1.txt"), "Expected b.txt\\test1.txt to exist\n");
1302         RemoveDirectoryA("b.txt");
1303         ok(DeleteFileA("c.txt\\test2.txt"), "Expected c.txt\\test2.txt to exist\n");
1304         RemoveDirectoryA("c.txt");
1305     }
1306     else
1307     {
1308         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1309         ok(shfo.fAnyOperationsAborted ||
1310            broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1311            "Expected aborted operations\n");
1312         ok(!DeleteFileA("b.txt"), "Expected b.txt to not exist\n");
1313     }
1314 
1315     /* copy one file and one directory to three others */
1316     shfo.pFrom = "test1.txt\0test4.txt\0";
1317     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
1318     shfo.fAnyOperationsAborted = 0xdeadbeef;
1319     retval = SHFileOperationA(&shfo);
1320     if (dir_exists("b.txt"))
1321     {
1322         /* Vista and W2K8 (broken or new behavior ?) */
1323         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1324         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1325         ok(DeleteFileA("b.txt\\test1.txt"), "Expected b.txt\\test1.txt to exist\n");
1326         RemoveDirectoryA("b.txt");
1327         ok(RemoveDirectoryA("c.txt\\test4.txt"), "Expected c.txt\\test4.txt to exist\n");
1328         RemoveDirectoryA("c.txt");
1329     }
1330     else
1331     {
1332         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1333         ok(shfo.fAnyOperationsAborted ||
1334            broken(shfo.fAnyOperationsAborted == 0xdeadbeef), /* NT4 */
1335            "Expected aborted operations\n");
1336         ok(!DeleteFileA("b.txt"), "Expected b.txt to not exist\n");
1337         ok(!DeleteFileA("c.txt"), "Expected c.txt to not exist\n");
1338     }
1339 
1340     /* copy a directory with a file beneath it, plus some files */
1341     createTestFile("test4.txt\\a.txt");
1342     shfo.pFrom = "test4.txt\0test1.txt\0";
1343     shfo.pTo = "testdir2\0";
1344     shfo.fFlags &= ~FOF_MULTIDESTFILES;
1345     shfo.fAnyOperationsAborted = FALSE;
1346     retval = SHFileOperationA(&shfo);
1347     ok(retval == ERROR_SUCCESS ||
1348        broken(retval == 0x100a1), /* WinMe */
1349        "Expected ERROR_SUCCESS, got %d\n", retval);
1350     if (retval == ERROR_SUCCESS)
1351     {
1352         ok(DeleteFileA("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
1353         ok(DeleteFileA("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
1354         ok(RemoveDirectoryA("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
1355     }
1356 
1357     /* copy one directory and a file in that dir to another dir */
1358     shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
1359     shfo.pTo = "testdir2\0";
1360     retval = SHFileOperationA(&shfo);
1361     ok(retval == ERROR_SUCCESS ||
1362        broken(retval == 0x100a1), /* WinMe */
1363        "Expected ERROR_SUCCESS, got %d\n", retval);
1364     if (retval == ERROR_SUCCESS)
1365     {
1366         ok(DeleteFileA("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
1367         ok(DeleteFileA("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
1368     }
1369 
1370     /* copy a file in a directory first, and then the directory to a nonexistent dir */
1371     shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
1372     shfo.pTo = "nonexistent\0";
1373     retval = SHFileOperationA(&shfo);
1374     if (dir_exists("nonexistent"))
1375     {
1376         /* Vista and W2K8 (broken or new behavior ?) */
1377         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1378         ok(DeleteFileA("nonexistent\\test4.txt\\a.txt"), "Expected nonexistent\\test4.txt\\a.txt to exist\n");
1379         RemoveDirectoryA("nonexistent\\test4.txt");
1380         ok(DeleteFileA("nonexistent\\a.txt"), "Expected nonexistent\\a.txt to exist\n");
1381         RemoveDirectoryA("nonexistent");
1382     }
1383     else
1384     {
1385         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1386         ok(shfo.fAnyOperationsAborted ||
1387            broken(!shfo.fAnyOperationsAborted), /* NT4 */
1388            "Expected aborted operations\n");
1389         ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
1390     }
1391     DeleteFileA("test4.txt\\a.txt");
1392 
1393     /* destination is same as source file */
1394     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
1395     shfo.pTo = "b.txt\0test2.txt\0c.txt\0";
1396     shfo.fAnyOperationsAborted = FALSE;
1397     shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
1398     retval = SHFileOperationA(&shfo);
1399     if (retval == DE_OPCANCELLED)
1400     {
1401         /* NT4 fails and doesn't copy any files */
1402         ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
1403     }
1404     else
1405     {
1406         ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
1407         ok(DeleteFileA("b.txt"), "Expected b.txt to exist\n");
1408     }
1409     ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
1410     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
1411 
1412     /* destination is same as source directory */
1413     shfo.pFrom = "test1.txt\0test4.txt\0test3.txt\0";
1414     shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
1415     shfo.fAnyOperationsAborted = FALSE;
1416     retval = SHFileOperationA(&shfo);
1417     if (retval == DE_OPCANCELLED)
1418     {
1419         /* NT4 fails and doesn't copy any files */
1420         ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
1421     }
1422     else
1423     {
1424         ok(retval == ERROR_SUCCESS ||
1425            retval == DE_DESTSAMETREE, /* Vista */
1426            "Expected ERROR_SUCCESS or DE_DESTSAMETREE, got %d\n", retval);
1427         ok(DeleteFileA("b.txt"), "Expected b.txt to exist\n");
1428     }
1429     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
1430 
1431     /* copy a directory into itself, error displayed in UI */
1432     shfo.pFrom = "test4.txt\0";
1433     shfo.pTo = "test4.txt\\newdir\0";
1434     shfo.fFlags &= ~FOF_MULTIDESTFILES;
1435     shfo.fAnyOperationsAborted = FALSE;
1436     retval = SHFileOperationA(&shfo);
1437     ok(retval == ERROR_SUCCESS ||
1438        retval == DE_DESTSUBTREE, /* Vista */
1439        "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
1440     ok(!RemoveDirectoryA("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
1441 
1442     /* copy a directory to itself, error displayed in UI */
1443     shfo.pFrom = "test4.txt\0";
1444     shfo.pTo = "test4.txt\0";
1445     shfo.fAnyOperationsAborted = FALSE;
1446     retval = SHFileOperationA(&shfo);
1447     ok(retval == ERROR_SUCCESS ||
1448        retval == DE_DESTSUBTREE, /* Vista */
1449        "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
1450 
1451     /* copy a file into a directory, and the directory into itself */
1452     shfo.pFrom = "test1.txt\0test4.txt\0";
1453     shfo.pTo = "test4.txt\0";
1454     shfo.fAnyOperationsAborted = FALSE;
1455     shfo.fFlags |= FOF_NOCONFIRMATION;
1456     retval = SHFileOperationA(&shfo);
1457     ok(retval == ERROR_SUCCESS ||
1458        retval == DE_DESTSUBTREE, /* Vista */
1459        "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
1460     ok(DeleteFileA("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
1461 
1462     /* copy a file to a file, and the directory into itself */
1463     shfo.pFrom = "test1.txt\0test4.txt\0";
1464     shfo.pTo = "test4.txt\\a.txt\0";
1465     shfo.fAnyOperationsAborted = FALSE;
1466     retval = SHFileOperationA(&shfo);
1467     if (dir_exists("test4.txt\\a.txt"))
1468     {
1469         /* Vista and W2K8 (broken or new behavior ?) */
1470         ok(retval == DE_DESTSUBTREE, "Expected DE_DESTSUBTREE, got %d\n", retval);
1471         ok(DeleteFileA("test4.txt\\a.txt\\test1.txt"), "Expected test4.txt\\a.txt\\test1.txt to exist\n");
1472         RemoveDirectoryA("test4.txt\\a.txt");
1473     }
1474     else
1475     {
1476         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1477         ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
1478     }
1479 
1480     /* copy a nonexistent file to a nonexistent directory */
1481     shfo.pFrom = "e.txt\0";
1482     shfo.pTo = "nonexistent\0";
1483     shfo.fAnyOperationsAborted = FALSE;
1484     retval = SHFileOperationA(&shfo);
1485     ok(retval == 1026 ||
1486        retval == ERROR_FILE_NOT_FOUND || /* Vista */
1487        broken(retval == ERROR_SUCCESS), /* NT4 */
1488        "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", retval);
1489     ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
1490     ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
1491 
1492     /* Overwrite tests */
1493     clean_after_shfo_tests();
1494     init_shfo_tests();
1495     if (!on_nt4)
1496     {
1497         /* NT4 would throw up some dialog boxes and doesn't copy files that are needed
1498          * in subsequent tests.
1499          */
1500         shfo.fFlags = FOF_NOCONFIRMATION;
1501         shfo.pFrom = "test1.txt\0";
1502         shfo.pTo = "test2.txt\0";
1503         shfo.fAnyOperationsAborted = 0xdeadbeef;
1504         /* without FOF_NOCONFIRMATION the confirmation is Yes/No */
1505         retval = SHFileOperationA(&shfo);
1506         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1507         ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1508         ok(file_has_content("test2.txt", "test1.txt\n"), "The file was not copied\n");
1509 
1510         shfo.pFrom = "test3.txt\0test1.txt\0";
1511         shfo.pTo = "test2.txt\0one.txt\0";
1512         shfo.fFlags = FOF_NOCONFIRMATION | FOF_MULTIDESTFILES;
1513         /* without FOF_NOCONFIRMATION the confirmation is Yes/Yes to All/No/Cancel */
1514         retval = SHFileOperationA(&shfo);
1515         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1516         ok(file_has_content("test2.txt", "test3.txt\n"), "The file was not copied\n");
1517 
1518         shfo.pFrom = "one.txt\0";
1519         shfo.pTo = "testdir2\0";
1520         shfo.fFlags = FOF_NOCONFIRMATION;
1521         /* without FOF_NOCONFIRMATION the confirmation is Yes/No */
1522         retval = SHFileOperationA(&shfo);
1523         ok(retval == 0, "Expected 0, got %d\n", retval);
1524         ok(file_has_content("testdir2\\one.txt", "test1.txt\n"), "The file was not copied\n");
1525     }
1526 
1527     createTestFile("test4.txt\\test1.txt");
1528     shfo.pFrom = "test4.txt\0";
1529     shfo.pTo = "testdir2\0";
1530     /* WinMe needs FOF_NOERRORUI */
1531     shfo.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI;
1532     retval = SHFileOperationA(&shfo);
1533     ok(retval == ERROR_SUCCESS ||
1534        broken(retval == 0x100a1), /* WinMe */
1535        "Expected ERROR_SUCCESS, got %d\n", retval);
1536     shfo.fFlags = FOF_NOCONFIRMATION;
1537     if (ERROR_SUCCESS)
1538     {
1539         createTestFile("test4.txt\\.\\test1.txt"); /* modify the content of the file */
1540         /* without FOF_NOCONFIRMATION the confirmation is "This folder already contains a folder named ..." */
1541         retval = SHFileOperationA(&shfo);
1542         ok(retval == 0, "Expected 0, got %d\n", retval);
1543         ok(file_has_content("testdir2\\test4.txt\\test1.txt", "test4.txt\\.\\test1.txt\n"), "The file was not copied\n");
1544     }
1545 
1546     createTestFile("one.txt");
1547 
1548     /* pFrom contains bogus 2nd name longer than MAX_PATH */
1549     memset(from, 'a', MAX_PATH*2);
1550     memset(from+MAX_PATH*2, 0, 2);
1551     lstrcpyA(from, "one.txt");
1552     shfo.pFrom = from;
1553     shfo.pTo = "two.txt\0";
1554     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1555     retval = SHFileOperationA(&shfo);
1556     ok(retval == 1148 || retval == 1026 ||
1557        retval == ERROR_ACCESS_DENIED || /* win2k */
1558        retval == DE_INVALIDFILES, /* Vista */
1559        "Unexpected return value, got %d\n", retval);
1560     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1561     if (dir_exists("two.txt"))
1562         /* Vista and W2K8 (broken or new behavior ?) */
1563         ok(RemoveDirectoryA("two.txt"), "Expected two.txt to exist\n");
1564     else
1565         ok(!DeleteFileA("two.txt"), "Expected file to not exist\n");
1566 
1567     createTestFile("one.txt");
1568 
1569     /* pTo contains bogus 2nd name longer than MAX_PATH */
1570     memset(to, 'a', MAX_PATH*2);
1571     memset(to+MAX_PATH*2, 0, 2);
1572     lstrcpyA(to, "two.txt");
1573     shfo.pFrom = "one.txt\0";
1574     shfo.pTo = to;
1575     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1576     retval = SHFileOperationA(&shfo);
1577     if (retval == DE_OPCANCELLED)
1578     {
1579         /* NT4 fails and doesn't copy any files */
1580         ok(!file_exists("two.txt"), "Expected two.txt to not exist\n");
1581     }
1582     else
1583     {
1584         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1585         ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1586     }
1587     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1588 
1589     createTestFile("one.txt");
1590 
1591     /* no FOF_MULTIDESTFILES, two files in pTo */
1592     shfo.pFrom = "one.txt\0";
1593     shfo.pTo = "two.txt\0three.txt\0";
1594     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1595     retval = SHFileOperationA(&shfo);
1596     if (retval == DE_OPCANCELLED)
1597     {
1598         /* NT4 fails and doesn't copy any files */
1599         ok(!file_exists("two.txt"), "Expected two.txt to not exist\n");
1600     }
1601     else
1602     {
1603         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1604         ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1605     }
1606     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1607 
1608     createTestFile("one.txt");
1609 
1610     /* both pFrom and pTo contain bogus 2nd names longer than MAX_PATH */
1611     memset(from, 'a', MAX_PATH*2);
1612     memset(from+MAX_PATH*2, 0, 2);
1613     memset(to, 'a', MAX_PATH*2);
1614     memset(to+MAX_PATH*2, 0, 2);
1615     lstrcpyA(from, "one.txt");
1616     lstrcpyA(to, "two.txt");
1617     shfo.pFrom = from;
1618     shfo.pTo = to;
1619     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1620     retval = SHFileOperationA(&shfo);
1621     ok(retval == 1148 || retval == 1026 ||
1622        retval == ERROR_ACCESS_DENIED ||  /* win2k */
1623        retval == DE_INVALIDFILES, /* Vista */
1624        "Unexpected return value, got %d\n", retval);
1625     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1626     if (dir_exists("two.txt"))
1627         /* Vista and W2K8 (broken or new behavior ?) */
1628         ok(RemoveDirectoryA("two.txt"), "Expected two.txt to exist\n");
1629     else
1630         ok(!DeleteFileA("two.txt"), "Expected file to not exist\n");
1631 
1632     createTestFile("one.txt");
1633 
1634     /* pTo contains bogus 2nd name longer than MAX_PATH, FOF_MULTIDESTFILES */
1635     memset(to, 'a', MAX_PATH*2);
1636     memset(to+MAX_PATH*2, 0, 2);
1637     lstrcpyA(to, "two.txt");
1638     shfo.pFrom = "one.txt\0";
1639     shfo.pTo = to;
1640     shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
1641                   FOF_SILENT | FOF_NOERRORUI;
1642     retval = SHFileOperationA(&shfo);
1643     if (retval == DE_OPCANCELLED)
1644     {
1645         /* NT4 fails and doesn't copy any files */
1646         ok(!file_exists("two.txt"), "Expected two.txt to not exist\n");
1647     }
1648     else
1649     {
1650         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1651         ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1652     }
1653     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1654 
1655     createTestFile("one.txt");
1656     createTestFile("two.txt");
1657 
1658     /* pTo contains bogus 2nd name longer than MAX_PATH,
1659      * multiple source files,
1660      * dest directory does not exist
1661      */
1662     memset(to, 'a', 2 * MAX_PATH);
1663     memset(to+MAX_PATH*2, 0, 2);
1664     lstrcpyA(to, "threedir");
1665     shfo.pFrom = "one.txt\0two.txt\0";
1666     shfo.pTo = to;
1667     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1668     retval = SHFileOperationA(&shfo);
1669     if (dir_exists("threedir"))
1670     {
1671         /* Vista and W2K8 (broken or new behavior ?) */
1672         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1673         ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
1674         ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
1675         ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
1676     }
1677     else
1678     {
1679         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
1680         ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
1681         ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
1682         ok(!DeleteFileA("threedir"), "Expected file to not exist\n");
1683         ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n");
1684     }
1685     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1686     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1687 
1688     createTestFile("one.txt");
1689     createTestFile("two.txt");
1690     CreateDirectoryA("threedir", NULL);
1691 
1692     /* pTo contains bogus 2nd name longer than MAX_PATH,
1693      * multiple source files,
1694      * dest directory does exist
1695      */
1696     memset(to, 'a', 2 * MAX_PATH);
1697     memset(to+MAX_PATH*2, 0, 2);
1698     lstrcpyA(to, "threedir");
1699     shfo.pFrom = "one.txt\0two.txt\0";
1700     shfo.pTo = to;
1701     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1702     retval = SHFileOperationA(&shfo);
1703     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1704     ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
1705     ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
1706     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1707     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1708     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
1709 
1710     if (0) {
1711         /* this crashes on win9x */
1712         createTestFile("one.txt");
1713         createTestFile("two.txt");
1714 
1715         /* pTo contains bogus 2nd name longer than MAX_PATH,
1716          * multiple source files, FOF_MULTIDESTFILES
1717          * dest dir does not exist
1718          */
1719 
1720         memset(to, 'a', 2 * MAX_PATH);
1721         memset(to+MAX_PATH*2, 0, 2);
1722         lstrcpyA(to, "threedir");
1723         shfo.pFrom = "one.txt\0two.txt\0";
1724         shfo.pTo = to;
1725         shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
1726                       FOF_SILENT | FOF_NOERRORUI;
1727         retval = SHFileOperationA(&shfo);
1728         ok(retval == ERROR_CANCELLED ||
1729            retval == ERROR_SUCCESS, /* win2k3 */
1730            "Expected ERROR_CANCELLED or ERROR_SUCCESS, got %d\n", retval);
1731         ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
1732         ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
1733         ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1734         ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1735         ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n");
1736 
1737         /* file exists in win2k */
1738         DeleteFileA("threedir");
1739     }
1740 
1741 
1742     createTestFile("one.txt");
1743     createTestFile("two.txt");
1744     CreateDirectoryA("threedir", NULL);
1745 
1746     /* pTo contains bogus 2nd name longer than MAX_PATH,
1747      * multiple source files, FOF_MULTIDESTFILES
1748      * dest dir does exist
1749      */
1750     memset(to, 'a', 2 * MAX_PATH);
1751     memset(to+MAX_PATH*2, 0, 2);
1752     lstrcpyA(to, "threedir");
1753     ptr = to + lstrlenA(to) + 1;
1754     lstrcpyA(ptr, "fourdir");
1755     shfo.pFrom = "one.txt\0two.txt\0";
1756     shfo.pTo = to;
1757     shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
1758                   FOF_SILENT | FOF_NOERRORUI;
1759     retval = SHFileOperationA(&shfo);
1760     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1761     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1762     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1763     ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
1764     if (dir_exists("fourdir"))
1765     {
1766         /* Vista and W2K8 (broken or new behavior ?) */
1767         ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
1768         ok(DeleteFileA("fourdir\\two.txt"), "Expected file to exist\n");
1769         RemoveDirectoryA("fourdir");
1770     }
1771     else
1772     {
1773         ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
1774         ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
1775         ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
1776     }
1777     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
1778 
1779     createTestFile("one.txt");
1780     createTestFile("two.txt");
1781     CreateDirectoryA("threedir", NULL);
1782 
1783     /* multiple source files, FOF_MULTIDESTFILES
1784      * multiple dest files, but first dest dir exists
1785      * num files in lists is equal
1786      */
1787     shfo.pFrom = "one.txt\0two.txt\0";
1788     shfo.pTo = "threedir\0fourdir\0";
1789     shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
1790                   FOF_SILENT | FOF_NOERRORUI;
1791     retval = SHFileOperationA(&shfo);
1792     ok(retval == ERROR_CANCELLED ||
1793        retval == DE_FILEDESTISFLD || /* Vista */
1794        broken(retval == DE_OPCANCELLED), /* Win9x, NT4 */
1795        "Expected ERROR_CANCELLED or DE_FILEDESTISFLD. got %d\n", retval);
1796     if (file_exists("threedir\\threedir"))
1797     {
1798         /* NT4 */
1799         ok(DeleteFileA("threedir\\threedir"), "Expected file to exist\n");
1800     }
1801     ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
1802     ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
1803     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1804     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1805     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
1806     ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
1807     ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
1808 
1809     createTestFile("one.txt");
1810     createTestFile("two.txt");
1811     CreateDirectoryA("threedir", NULL);
1812 
1813     /* multiple source files, FOF_MULTIDESTFILES
1814      * multiple dest files, but first dest dir exists
1815      * num files in lists is not equal
1816      */
1817     shfo.pFrom = "one.txt\0two.txt\0";
1818     shfo.pTo = "threedir\0fourdir\0five\0";
1819     shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
1820                   FOF_SILENT | FOF_NOERRORUI;
1821     retval = SHFileOperationA(&shfo);
1822     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1823     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
1824     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
1825     ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
1826     if (dir_exists("fourdir"))
1827     {
1828         /* Vista and W2K8 (broken or new behavior ?) */
1829         ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
1830         ok(DeleteFileA("fourdir\\two.txt"), "Expected file to exist\n");
1831         RemoveDirectoryA("fourdir");
1832     }
1833     else
1834     {
1835         ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
1836         ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
1837         ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
1838     }
1839     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
1840     ok(!DeleteFileA("five"), "Expected file to not exist\n");
1841     ok(!RemoveDirectoryA("five"), "Expected dir to not exist\n");
1842 
1843     createTestFile("aa.txt");
1844     createTestFile("ab.txt");
1845     CreateDirectoryA("one", NULL);
1846     CreateDirectoryA("two", NULL);
1847 
1848     /* pFrom has a glob, pTo has more than one dest */
1849     shfo.pFrom = "a*.txt\0";
1850     shfo.pTo = "one\0two\0";
1851     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1852     retval = SHFileOperationA(&shfo);
1853     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
1854     ok(DeleteFileA("one\\aa.txt"), "Expected file to exist\n");
1855     ok(DeleteFileA("one\\ab.txt"), "Expected file to exist\n");
1856     ok(!DeleteFileA("two\\aa.txt"), "Expected file to not exist\n");
1857     ok(!DeleteFileA("two\\ab.txt"), "Expected file to not exist\n");
1858     ok(DeleteFileA("aa.txt"), "Expected file to exist\n");
1859     ok(DeleteFileA("ab.txt"), "Expected file to exist\n");
1860     ok(RemoveDirectoryA("one"), "Expected dir to exist\n");
1861     ok(RemoveDirectoryA("two"), "Expected dir to exist\n");
1862 
1863     /* pTo is an empty string  */
1864     CreateDirectoryA("dir", NULL);
1865     createTestFile("dir\\abcdefgh.abc");
1866     shfo.pFrom = "dir\\abcdefgh.abc\0";
1867     shfo.pTo = "\0";
1868     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1869     retval = SHFileOperationA(&shfo);
1870     ok(retval == ERROR_SUCCESS ||
1871        broken(retval == DE_OPCANCELLED), /* NT4 */
1872        "Expected ERROR_SUCCESS, got %d\n", retval);
1873     if (retval == ERROR_SUCCESS)
1874         ok(DeleteFileA("abcdefgh.abc"), "Expected file to exist\n");
1875     ok(DeleteFileA("dir\\abcdefgh.abc"), "Expected file to exist\n");
1876     ok(RemoveDirectoryA("dir"), "Expected dir to exist\n");
1877 
1878     /* Check last error after a successful file operation. */
1879     clean_after_shfo_tests();
1880     init_shfo_tests();
1881     shfo.pFrom = "test1.txt\0";
1882     shfo.pTo = "testdir2\0";
1883     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1884     SetLastError(0xdeadbeef);
1885     retval = SHFileOperationA(&shfo);
1886     ok(retval == ERROR_SUCCESS, "File copy failed with %d\n", retval);
1887     ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1888     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
1889 
1890     /* Check last error after a failed file operation. */
1891     clean_after_shfo_tests();
1892     init_shfo_tests();
1893     shfo.pFrom = "nonexistent\0";
1894     shfo.pTo = "testdir2\0";
1895     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1896     SetLastError(0xdeadbeef);
1897     retval = SHFileOperationA(&shfo);
1898     ok(retval != ERROR_SUCCESS, "Unexpected ERROR_SUCCESS\n");
1899     ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
1900     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
1901 }
1902 
1903 /* tests the FO_MOVE action */
1904 static void test_move(void)
1905 {
1906     SHFILEOPSTRUCTA shfo, shfo2;
1907     CHAR from[5*MAX_PATH];
1908     CHAR to[5*MAX_PATH];
1909     DWORD retval;
1910 
1911     clean_after_shfo_tests();
1912     init_shfo_tests();
1913 
1914     shfo.hwnd = NULL;
1915     shfo.wFunc = FO_MOVE;
1916     shfo.pFrom = from;
1917     shfo.pTo = to;
1918     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR;
1919     shfo.hNameMappings = NULL;
1920     shfo.lpszProgressTitle = NULL;
1921     shfo.fAnyOperationsAborted = FALSE;
1922 
1923     set_curr_dir_path(from, "testdir2\\*.*\0");
1924     set_curr_dir_path(to, "test4.txt\\*.*\0");
1925     retval = SHFileOperationA(&shfo);
1926     ok(retval != 0, "SHFileOperation should fail\n");
1927     ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
1928 
1929     ok(file_exists("testdir2"), "dir should not be moved\n");
1930     ok(file_exists("testdir2\\one.txt"), "file should not be moved\n");
1931     ok(file_exists("testdir2\\nested"), "dir should not be moved\n");
1932     ok(file_exists("testdir2\\nested\\two.txt"), "file should not be moved\n");
1933 
1934     set_curr_dir_path(from, "testdir2\\*.*\0");
1935     set_curr_dir_path(to, "test4.txt\0");
1936     retval = SHFileOperationA(&shfo);
1937     ok(!retval, "SHFileOperation error %#x\n", retval);
1938     ok(!shfo.fAnyOperationsAborted, "fAnyOperationsAborted %d\n", shfo.fAnyOperationsAborted);
1939 
1940     ok(file_exists("testdir2"), "dir should not be moved\n");
1941     ok(!file_exists("testdir2\\one.txt"), "file should be moved\n");
1942     ok(!file_exists("testdir2\\nested"), "dir should be moved\n");
1943     ok(!file_exists("testdir2\\nested\\two.txt"), "file should be moved\n");
1944 
1945     ok(file_exists("test4.txt"), "dir should exist\n");
1946     ok(file_exists("test4.txt\\one.txt"), "file should exist\n");
1947     ok(file_exists("test4.txt\\nested"), "dir should exist\n");
1948     ok(file_exists("test4.txt\\nested\\two.txt"), "file should exist\n");
1949 
1950     clean_after_shfo_tests();
1951     init_shfo_tests();
1952 
1953     shfo.hwnd = NULL;
1954     shfo.wFunc = FO_MOVE;
1955     shfo.pFrom = from;
1956     shfo.pTo = to;
1957     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
1958     shfo.hNameMappings = NULL;
1959     shfo.lpszProgressTitle = NULL;
1960 
1961     set_curr_dir_path(from, "test1.txt\0");
1962     set_curr_dir_path(to, "test4.txt\0");
1963     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
1964     ok(!file_exists("test1.txt"), "test1.txt should not exist\n");
1965     ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
1966 
1967     set_curr_dir_path(from, "test?.txt\0");
1968     set_curr_dir_path(to, "testdir2\0");
1969     ok(!file_exists("testdir2\\test2.txt"), "The file is not moved yet\n");
1970     ok(!file_exists("testdir2\\test4.txt"), "The directory is not moved yet\n");
1971     ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
1972     ok(file_exists("testdir2\\test2.txt"), "The file is moved\n");
1973     ok(file_exists("testdir2\\test4.txt"), "The directory is moved\n");
1974     ok(file_exists("testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
1975 
1976     clean_after_shfo_tests();
1977     init_shfo_tests();
1978 
1979     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
1980     shfo2.fFlags |= FOF_MULTIDESTFILES;
1981 
1982     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
1983     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
1984     if (old_shell32)
1985         shfo2.fFlags |= FOF_NOCONFIRMMKDIR;
1986     ok(!SHFileOperationA(&shfo2), "Move many files\n");
1987     ok(DeleteFileA("test6.txt"), "The file is not moved - many files are "
1988        "specified as a target\n");
1989     ok(DeleteFileA("test7.txt"), "The file is not moved\n");
1990     ok(RemoveDirectoryA("test8.txt"), "The directory is not moved\n");
1991 
1992     init_shfo_tests();
1993 
1994     /* number of sources does not correspond to number of targets,
1995        include directories */
1996     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
1997     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
1998     retval = SHFileOperationA(&shfo2);
1999     if (dir_exists("test6.txt"))
2000     {
2001         if (retval == ERROR_SUCCESS)
2002         {
2003             /* Old shell32 */
2004             DeleteFileA("test6.txt\\test1.txt");
2005             DeleteFileA("test6.txt\\test2.txt");
2006             RemoveDirectoryA("test6.txt\\test4.txt");
2007             RemoveDirectoryA("test6.txt");
2008         }
2009         else
2010         {
2011             /* Vista and W2K8 (broken or new behavior ?) */
2012             ok(retval == DE_DESTSAMETREE, "Expected DE_DESTSAMETREE, got %d\n", retval);
2013             ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not moved\n");
2014             RemoveDirectoryA("test6.txt");
2015             ok(DeleteFileA("test7.txt\\test2.txt"), "The file is not moved\n");
2016             RemoveDirectoryA("test7.txt");
2017         }
2018     }
2019     else
2020     {
2021         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2022         ok(!file_exists("test6.txt"), "The file is not moved - many files are "
2023            "specified as a target\n");
2024     }
2025 
2026     init_shfo_tests();
2027     /* number of sources does not correspond to number of targets,
2028        files only,
2029        from exceeds to */
2030     set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
2031     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
2032     retval = SHFileOperationA(&shfo2);
2033     if (dir_exists("test6.txt"))
2034     {
2035         if (retval == ERROR_SUCCESS)
2036         {
2037             /* Old shell32 */
2038             DeleteFileA("test6.txt\\test1.txt");
2039             DeleteFileA("test6.txt\\test2.txt");
2040             RemoveDirectoryA("test6.txt\\test4.txt");
2041             RemoveDirectoryA("test6.txt");
2042         }
2043         else
2044         {
2045             /* Vista and W2K8 (broken or new behavior ?) */
2046             ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
2047             ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not moved\n");
2048             RemoveDirectoryA("test6.txt");
2049             ok(DeleteFileA("test7.txt\\test2.txt"), "The file is not moved\n");
2050             RemoveDirectoryA("test7.txt");
2051             ok(file_exists("test3.txt"), "File should not be moved\n");
2052         }
2053     }
2054     else
2055     {
2056         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2057         ok(!file_exists("test6.txt"), "The file is not moved - many files are "
2058            "specified as a target\n");
2059     }
2060 
2061     init_shfo_tests();
2062     /* number of sources does not correspond to number of targets,
2063        files only,
2064        too exceeds from */
2065     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
2066     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
2067     retval = SHFileOperationA(&shfo2);
2068     if (dir_exists("test6.txt"))
2069     {
2070         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2071         ok(DeleteFileA("test6.txt\\test1.txt"),"The file is not moved\n");
2072         ok(DeleteFileA("test7.txt\\test2.txt"),"The file is not moved\n");
2073         ok(!dir_exists("test8.txt") && !file_exists("test8.txt"),
2074             "Directory should not be created\n");
2075         RemoveDirectoryA("test6.txt");
2076         RemoveDirectoryA("test7.txt");
2077     }
2078     else
2079     {
2080         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* WinXp, Win2k */);
2081         ok(!file_exists("test6.txt"), "The file is not moved - many files are "
2082            "specified as a target\n");
2083     }
2084 
2085     init_shfo_tests();
2086     /* number of sources does not correspond to number of targets,
2087        target directories */
2088     set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
2089     set_curr_dir_path(to, "test4.txt\0test5.txt\0");
2090     retval = SHFileOperationA(&shfo2);
2091     if (dir_exists("test5.txt"))
2092     {
2093         ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
2094         ok(DeleteFileA("test4.txt\\test1.txt"),"The file is not moved\n");
2095         ok(DeleteFileA("test5.txt\\test2.txt"),"The file is not moved\n");
2096         ok(file_exists("test3.txt"), "The file is not moved\n");
2097         RemoveDirectoryA("test4.txt");
2098         RemoveDirectoryA("test5.txt");
2099     }
2100     else
2101     {
2102         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2103         ok(DeleteFileA("test4.txt\\test1.txt"),"The file is not moved\n");
2104         ok(DeleteFileA("test4.txt\\test2.txt"),"The file is not moved\n");
2105         ok(DeleteFileA("test4.txt\\test3.txt"),"The file is not moved\n");
2106     }
2107 
2108 
2109     init_shfo_tests();
2110     /*  0 incoming files */
2111     set_curr_dir_path(from, "\0\0");
2112     set_curr_dir_path(to, "test6.txt\0\0");
2113     retval = SHFileOperationA(&shfo2);
2114     ok(retval == ERROR_SUCCESS || retval == ERROR_ACCESS_DENIED
2115         , "Expected ERROR_SUCCESS || ERROR_ACCESS_DENIED, got %d\n", retval);
2116     ok(!file_exists("test6.txt"), "The file should not exist\n");
2117 
2118     init_shfo_tests();
2119     /*  0 outgoing files */
2120     set_curr_dir_path(from, "test1\0\0");
2121     set_curr_dir_path(to, "\0\0");
2122     retval = SHFileOperationA(&shfo2);
2123     ok(retval == ERROR_FILE_NOT_FOUND ||
2124         broken(retval == 1026)
2125         , "Expected ERROR_FILE_NOT_FOUND, got %d\n", retval);
2126     ok(!file_exists("test6.txt"), "The file should not exist\n");
2127 
2128     init_shfo_tests();
2129 
2130     set_curr_dir_path(from, "test3.txt\0");
2131     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
2132     ok(!SHFileOperationA(&shfo), "Can't move file to other directory\n");
2133     ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
2134 
2135     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
2136     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
2137     if (old_shell32)
2138         shfo.fFlags |= FOF_NOCONFIRMMKDIR;
2139     retval = SHFileOperationA(&shfo);
2140     if (dir_exists("test6.txt"))
2141     {
2142         /* Old shell32 */
2143         /* Vista and W2K8 (broken or new behavior ?) */
2144         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2145         ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not moved. Many files are specified\n");
2146         ok(DeleteFileA("test6.txt\\test2.txt"), "The file is not moved. Many files are specified\n");
2147         ok(DeleteFileA("test6.txt\\test4.txt\\test1.txt"), "The file is not moved. Many files are specified\n");
2148         ok(RemoveDirectoryA("test6.txt\\test4.txt"), "The directory is not moved. Many files are specified\n");
2149         RemoveDirectoryA("test6.txt");
2150         init_shfo_tests();
2151     }
2152     else
2153     {
2154         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2155         ok(file_exists("test1.txt"), "The file is moved. Many files are specified\n");
2156         ok(dir_exists("test4.txt"), "The directory is moved. Many files are specified\n");
2157     }
2158 
2159     set_curr_dir_path(from, "test1.txt\0");
2160     set_curr_dir_path(to, "test6.txt\0");
2161     ok(!SHFileOperationA(&shfo), "Move file failed\n");
2162     ok(!file_exists("test1.txt"), "The file is not moved\n");
2163     ok(file_exists("test6.txt"), "The file is not moved\n");
2164     set_curr_dir_path(from, "test6.txt\0");
2165     set_curr_dir_path(to, "test1.txt\0");
2166     ok(!SHFileOperationA(&shfo), "Move file back failed\n");
2167 
2168     set_curr_dir_path(from, "test4.txt\0");
2169     set_curr_dir_path(to, "test6.txt\0");
2170     ok(!SHFileOperationA(&shfo), "Move dir failed\n");
2171     ok(!dir_exists("test4.txt"), "The dir is not moved\n");
2172     ok(dir_exists("test6.txt"), "The dir is moved\n");
2173     set_curr_dir_path(from, "test6.txt\0");
2174     set_curr_dir_path(to, "test4.txt\0");
2175     ok(!SHFileOperationA(&shfo), "Move dir back failed\n");
2176 
2177     /* move one file to two others */
2178     init_shfo_tests();
2179     shfo.pFrom = "test1.txt\0";
2180     shfo.pTo = "a.txt\0b.txt\0";
2181     retval = SHFileOperationA(&shfo);
2182     if (retval == DE_OPCANCELLED)
2183     {
2184         /* NT4 fails and doesn't move any files */
2185         ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
2186         DeleteFileA("test1.txt");
2187     }
2188     else
2189     {
2190         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2191         if (old_shell32)
2192         {
2193             DeleteFileA("a.txt\\a.txt");
2194             RemoveDirectoryA("a.txt");
2195         }
2196         else
2197             ok(DeleteFileA("a.txt"), "Expected a.txt to exist\n");
2198         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
2199     }
2200     ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
2201 
2202     /* move two files to one other */
2203     shfo.pFrom = "test2.txt\0test3.txt\0";
2204     shfo.pTo = "test1.txt\0";
2205     retval = SHFileOperationA(&shfo);
2206     if (dir_exists("test1.txt"))
2207     {
2208         /* Old shell32 */
2209         /* Vista and W2K8 (broken or new behavior ?) */
2210         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2211         ok(DeleteFileA("test1.txt\\test2.txt"), "Expected test1.txt\\test2.txt to exist\n");
2212         ok(DeleteFileA("test1.txt\\test3.txt"), "Expected test1.txt\\test3.txt to exist\n");
2213         RemoveDirectoryA("test1.txt");
2214         createTestFile("test2.txt");
2215         createTestFile("test3.txt");
2216     }
2217     else
2218     {
2219         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2220         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
2221         ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
2222         ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
2223     }
2224 
2225     /* move a directory into itself */
2226     shfo.pFrom = "test4.txt\0";
2227     shfo.pTo = "test4.txt\\b.txt\0";
2228     retval = SHFileOperationA(&shfo);
2229     ok(retval == ERROR_SUCCESS ||
2230        retval == DE_DESTSUBTREE, /* Vista */
2231        "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
2232     ok(!RemoveDirectoryA("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
2233     ok(dir_exists("test4.txt"), "Expected test4.txt to exist\n");
2234 
2235     /* move many files without FOF_MULTIDESTFILES */
2236     shfo.pFrom = "test2.txt\0test3.txt\0";
2237     shfo.pTo = "d.txt\0e.txt\0";
2238     retval = SHFileOperationA(&shfo);
2239     if (dir_exists("d.txt"))
2240     {
2241         /* Old shell32 */
2242         /* Vista and W2K8 (broken or new behavior ?) */
2243         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2244         ok(DeleteFileA("d.txt\\test2.txt"), "Expected d.txt\\test2.txt to exist\n");
2245         ok(DeleteFileA("d.txt\\test3.txt"), "Expected d.txt\\test3.txt to exist\n");
2246         RemoveDirectoryA("d.txt");
2247         createTestFile("test2.txt");
2248         createTestFile("test3.txt");
2249     }
2250     else
2251     {
2252         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2253         ok(!DeleteFileA("d.txt"), "Expected d.txt to not exist\n");
2254         ok(!DeleteFileA("e.txt"), "Expected e.txt to not exist\n");
2255     }
2256 
2257     /* number of sources != number of targets */
2258     shfo.pTo = "d.txt\0";
2259     shfo.fFlags |= FOF_MULTIDESTFILES;
2260     retval = SHFileOperationA(&shfo);
2261     if (dir_exists("d.txt"))
2262     {
2263         if (old_shell32)
2264         {
2265             DeleteFileA("d.txt\\test2.txt");
2266             DeleteFileA("d.txt\\test3.txt");
2267             RemoveDirectoryA("d.txt");
2268             createTestFile("test2.txt");
2269         }
2270         else
2271         {
2272             /* Vista and W2K8 (broken or new behavior ?) */
2273             ok(retval == DE_SAMEFILE,
2274                "Expected DE_SAMEFILE, got %d\n", retval);
2275             ok(DeleteFileA("d.txt\\test2.txt"), "Expected d.txt\\test2.txt to exist\n");
2276             ok(!file_exists("d.txt\\test3.txt"), "Expected d.txt\\test3.txt to not exist\n");
2277             RemoveDirectoryA("d.txt");
2278             createTestFile("test2.txt");
2279         }
2280     }
2281     else
2282     {
2283         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2284         ok(!DeleteFileA("d.txt"), "Expected d.txt to not exist\n");
2285     }
2286 
2287     /* FO_MOVE should create dest directories */
2288     shfo.pFrom = "test2.txt\0";
2289     shfo.pTo = "dir1\\dir2\\test2.txt\0";
2290     retval = SHFileOperationA(&shfo);
2291     if (dir_exists("dir1"))
2292     {
2293         /* New behavior on Vista or later */
2294         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2295         ok(DeleteFileA("dir1\\dir2\\test2.txt"), "Expected dir1\\dir2\\test2.txt to exist\n");
2296         RemoveDirectoryA("dir1\\dir2");
2297         RemoveDirectoryA("dir1");
2298         createTestFile("test2.txt");
2299     }
2300     else
2301     {
2302         expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
2303     }
2304 
2305     /* try to overwrite an existing file */
2306     shfo.pTo = "test3.txt\0";
2307     retval = SHFileOperationA(&shfo);
2308     if (retval == DE_OPCANCELLED)
2309     {
2310         /* NT4 fails and doesn't move any files */
2311         ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
2312     }
2313     else
2314     {
2315         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
2316         ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
2317         if (old_shell32)
2318         {
2319             DeleteFileA("test3.txt\\test3.txt");
2320             RemoveDirectoryA("test3.txt");
2321         }
2322         else
2323             ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
2324     }
2325 }
2326 
2327 static void test_sh_create_dir(void)
2328 {
2329     CHAR path[MAX_PATH];
2330     int ret;
2331 
2332     if(!pSHCreateDirectoryExA)
2333     {
2334         win_skip("skipping SHCreateDirectoryExA tests\n");
2335         return;
2336     }
2337 
2338     set_curr_dir_path(path, "testdir2\\test4.txt\0");
2339     ret = pSHCreateDirectoryExA(NULL, path, NULL);
2340     ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
2341     ok(file_exists("testdir2"), "The first directory is not created\n");
2342     ok(file_exists("testdir2\\test4.txt"), "The second directory is not created\n");
2343 
2344     ret = pSHCreateDirectoryExA(NULL, path, NULL);
2345     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
2346 
2347     ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
2348     ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory, ret = %d\n", ret);
2349     ok(file_exists("c:\\testdir3"), "The directory is not created\n");
2350 }
2351 
2352 static void test_sh_path_prepare(void)
2353 {
2354     HRESULT res;
2355     CHAR path[MAX_PATH];
2356     CHAR UNICODE_PATH_A[MAX_PATH];
2357     BOOL UsedDefaultChar;
2358 
2359     if(!pSHPathPrepareForWriteA)
2360     {
2361 	win_skip("skipping SHPathPrepareForWriteA tests\n");
2362 	return;
2363     }
2364 
2365     /* directory exists, SHPPFW_NONE */
2366     set_curr_dir_path(path, "testdir2\0");
2367     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
2368     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2369 
2370     /* directory exists, SHPPFW_IGNOREFILENAME */
2371     set_curr_dir_path(path, "testdir2\\test4.txt\0");
2372     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
2373     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2374 
2375     /* directory exists, SHPPFW_DIRCREATE */
2376     set_curr_dir_path(path, "testdir2\0");
2377     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
2378     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2379 
2380     /* directory exists, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */
2381     set_curr_dir_path(path, "testdir2\\test4.txt\0");
2382     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
2383     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2384     ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n");
2385 
2386     /* file exists, SHPPFW_NONE */
2387     set_curr_dir_path(path, "test1.txt\0");
2388     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
2389     ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
2390        res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
2391        res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
2392        "Unexpected result : 0x%08x\n", res);
2393 
2394     /* file exists, SHPPFW_DIRCREATE */
2395     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
2396     ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
2397        res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
2398        res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
2399        "Unexpected result : 0x%08x\n", res);
2400 
2401     /* file exists, SHPPFW_NONE, trailing \ */
2402     set_curr_dir_path(path, "test1.txt\\\0");
2403     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
2404     ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
2405        res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
2406        res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
2407        "Unexpected result : 0x%08x\n", res);
2408 
2409     /* relative path exists, SHPPFW_DIRCREATE */
2410     res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2", SHPPFW_DIRCREATE);
2411     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2412 
2413     /* relative path doesn't exist, SHPPFW_DIRCREATE -- Windows does not create the directory in this case */
2414     res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2\\test4.txt", SHPPFW_DIRCREATE);
2415     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
2416     ok(!file_exists(".\\testdir2\\test4.txt\\"), ".\\testdir2\\test4.txt\\ exists but shouldn't\n");
2417 
2418     /* directory doesn't exist, SHPPFW_NONE */
2419     set_curr_dir_path(path, "nonexistent\0");
2420     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
2421     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
2422 
2423     /* directory doesn't exist, SHPPFW_IGNOREFILENAME */
2424     set_curr_dir_path(path, "nonexistent\\notreal\0");
2425     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME);
2426     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
2427     ok(!file_exists("nonexistent\\notreal"), "nonexistent\\notreal exists but shouldn't\n");
2428     ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n");
2429 
2430     /* directory doesn't exist, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */
2431     set_curr_dir_path(path, "testdir2\\test4.txt\\\0");
2432     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE);
2433     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2434     ok(file_exists("testdir2\\test4.txt\\"), "testdir2\\test4.txt doesn't exist but should\n");
2435 
2436     /* nested directory doesn't exist, SHPPFW_DIRCREATE */
2437     set_curr_dir_path(path, "nonexistent\\notreal\0");
2438     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
2439     ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res);
2440     ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal doesn't exist but should\n");
2441 
2442     /* SHPPFW_ASKDIRCREATE, SHPPFW_NOWRITECHECK, and SHPPFW_MEDIACHECKONLY are untested */
2443 
2444     if(!pSHPathPrepareForWriteW)
2445     {
2446         win_skip("Skipping SHPathPrepareForWriteW tests\n");
2447         return;
2448     }
2449 
2450     SetLastError(0xdeadbeef);
2451     UsedDefaultChar = FALSE;
2452     if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, UNICODE_PATH, -1, UNICODE_PATH_A, sizeof(UNICODE_PATH_A), NULL, &UsedDefaultChar) == 0)
2453     {
2454         win_skip("Could not convert Unicode path name to multibyte (%d)\n", GetLastError());
2455         return;
2456     }
2457     if (UsedDefaultChar)
2458     {
2459         win_skip("Could not find unique multibyte representation for directory name using default codepage\n");
2460         return;
2461     }
2462 
2463     /* unicode directory doesn't exist, SHPPFW_NONE */
2464     RemoveDirectoryA(UNICODE_PATH_A);
2465     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
2466     ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
2467     ok(!file_exists(UNICODE_PATH_A), "unicode path was created but shouldn't be\n");
2468     RemoveDirectoryA(UNICODE_PATH_A);
2469 
2470     /* unicode directory doesn't exist, SHPPFW_DIRCREATE */
2471     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
2472     ok(res == S_OK, "res == %08x, expected S_OK\n", res);
2473     ok(file_exists(UNICODE_PATH_A), "unicode path should've been created\n");
2474 
2475     /* unicode directory exists, SHPPFW_NONE */
2476     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
2477     ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
2478 
2479     /* unicode directory exists, SHPPFW_DIRCREATE */
2480     res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
2481     ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
2482     RemoveDirectoryA(UNICODE_PATH_A);
2483 }
2484 
2485 static void test_sh_new_link_info(void)
2486 {
2487     BOOL ret, mustcopy=TRUE;
2488     CHAR linkto[MAX_PATH];
2489     CHAR destdir[MAX_PATH];
2490     CHAR result[MAX_PATH];
2491     CHAR result2[MAX_PATH];
2492 
2493     /* source file does not exist */
2494     set_curr_dir_path(linkto, "nosuchfile.txt\0");
2495     set_curr_dir_path(destdir, "testdir2\0");
2496     ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
2497     ok(ret == FALSE ||
2498        broken(ret == lstrlenA(result) + 1), /* NT4 */
2499        "SHGetNewLinkInfoA succeeded\n");
2500     ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
2501 
2502     /* dest dir does not exist */
2503     set_curr_dir_path(linkto, "test1.txt\0");
2504     set_curr_dir_path(destdir, "nosuchdir\0");
2505     ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
2506     ok(ret == TRUE ||
2507        broken(ret == lstrlenA(result) + 1), /* NT4 */
2508        "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
2509     ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
2510 
2511     /* source file exists */
2512     set_curr_dir_path(linkto, "test1.txt\0");
2513     set_curr_dir_path(destdir, "testdir2\0");
2514     ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
2515     ok(ret == TRUE ||
2516        broken(ret == lstrlenA(result) + 1), /* NT4 */
2517        "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
2518     ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
2519     ok(CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, destdir,
2520                       lstrlenA(destdir), result, lstrlenA(destdir)) == CSTR_EQUAL,
2521        "%s does not start with %s\n", result, destdir);
2522     ok(lstrlenA(result) > 4 && lstrcmpiA(result+lstrlenA(result)-4, ".lnk") == 0,
2523        "%s does not end with .lnk\n", result);
2524 
2525     /* preferred target name already exists */
2526     createTestFile(result);
2527     ret = SHGetNewLinkInfoA(linkto, destdir, result2, &mustcopy, 0);
2528     ok(ret == TRUE ||
2529        broken(ret == lstrlenA(result2) + 1), /* NT4 */
2530        "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
2531     ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
2532     ok(CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, destdir,
2533                       lstrlenA(destdir), result2, lstrlenA(destdir)) == CSTR_EQUAL,
2534        "%s does not start with %s\n", result2, destdir);
2535     ok(lstrlenA(result2) > 4 && lstrcmpiA(result2+lstrlenA(result2)-4, ".lnk") == 0,
2536        "%s does not end with .lnk\n", result2);
2537     ok(lstrcmpiA(result, result2) != 0, "%s and %s are the same\n", result, result2);
2538     DeleteFileA(result);
2539 }
2540 
2541 static void test_unicode(void)
2542 {
2543     SHFILEOPSTRUCTW shfoW;
2544     int ret;
2545     HANDLE file;
2546     static const WCHAR UNICODE_PATH_TO[] = {'c',':','\\',0x00ae,0x00ae,'\0'};
2547 
2548     if (!pSHFileOperationW)
2549     {
2550         skip("SHFileOperationW() is missing\n");
2551         return;
2552     }
2553 
2554     shfoW.hwnd = NULL;
2555     shfoW.wFunc = FO_DELETE;
2556     shfoW.pFrom = UNICODE_PATH;
2557     shfoW.pTo = NULL;
2558     shfoW.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
2559     shfoW.hNameMappings = NULL;
2560     shfoW.lpszProgressTitle = NULL;
2561 
2562     /* Clean up before start test */
2563     DeleteFileW(UNICODE_PATH);
2564     RemoveDirectoryW(UNICODE_PATH);
2565 
2566     /* Make sure we are on a system that supports unicode */
2567     SetLastError(0xdeadbeef);
2568     file = CreateFileW(UNICODE_PATH, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2569     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2570     {
2571         skip("Unicode tests skipped on non-unicode system\n");
2572         return;
2573     }
2574     if (GetLastError()==ERROR_ACCESS_DENIED)
2575     {
2576         skip("test needs admin rights\n");
2577         return;
2578     }
2579     CloseHandle(file);
2580 
2581     /* Try to delete a file with unicode filename */
2582     ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
2583     ret = pSHFileOperationW(&shfoW);
2584     ok(!ret, "File is not removed, ErrorCode: %d\n", ret);
2585     ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
2586 
2587     /* Try to trash a file with unicode filename */
2588     createTestFileW(UNICODE_PATH);
2589     shfoW.fFlags |= FOF_ALLOWUNDO;
2590     ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
2591     ret = pSHFileOperationW(&shfoW);
2592     ok(!ret, "File is not removed, ErrorCode: %d\n", ret);
2593     ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
2594 
2595     if(!pSHCreateDirectoryExW)
2596     {
2597         skip("Skipping SHCreateDirectoryExW tests\n");
2598         return;
2599     }
2600 
2601     /* Try to delete a directory with unicode filename */
2602     ret = pSHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
2603     ok(!ret, "SHCreateDirectoryExW returned %d\n", ret);
2604     ok(file_existsW(UNICODE_PATH), "The directory is not created\n");
2605     shfoW.fFlags &= ~FOF_ALLOWUNDO;
2606     ret = pSHFileOperationW(&shfoW);
2607     ok(!ret, "Directory is not removed, ErrorCode: %d\n", ret);
2608     ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n");
2609 
2610     /* Try to trash a directory with unicode filename */
2611     ret = pSHCreateDirectoryExW(NULL, UNICODE_PATH, NULL);
2612     ok(!ret, "SHCreateDirectoryExW returned %d\n", ret);
2613     ok(file_existsW(UNICODE_PATH), "The directory was not created\n");
2614     shfoW.fFlags |= FOF_ALLOWUNDO;
2615     ret = pSHFileOperationW(&shfoW);
2616     ok(!ret, "Directory is not removed, ErrorCode: %d\n", ret);
2617     ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n");
2618 
2619     shfoW.hwnd = NULL;
2620     shfoW.wFunc = FO_COPY;
2621     shfoW.pFrom = UNICODE_PATH;
2622     shfoW.pTo = UNICODE_PATH_TO;
2623     shfoW.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
2624     shfoW.hNameMappings = NULL;
2625     shfoW.lpszProgressTitle = NULL;
2626 
2627     /* Check last error after a successful file operation. */
2628     createTestFileW(UNICODE_PATH);
2629     ok(file_existsW(UNICODE_PATH), "The file does not exist\n");
2630     SetLastError(0xdeadbeef);
2631     ret = SHFileOperationW(&shfoW);
2632     ok(ret == ERROR_SUCCESS, "File copy failed with %d\n", ret);
2633     ok(!shfoW.fAnyOperationsAborted, "Didn't expect aborted operations\n");
2634     ok(GetLastError() == ERROR_SUCCESS ||
2635        broken(GetLastError() == ERROR_INVALID_HANDLE), /* WinXp, win2k3 */
2636        "Expected ERROR_SUCCESS, got %d\n", GetLastError());
2637     DeleteFileW(UNICODE_PATH_TO);
2638 
2639     /* Check last error after a failed file operation. */
2640     DeleteFileW(UNICODE_PATH);
2641     ok(!file_existsW(UNICODE_PATH), "The file should have been removed\n");
2642     SetLastError(0xdeadbeef);
2643     ret = SHFileOperationW(&shfoW);
2644     ok(ret != ERROR_SUCCESS, "Unexpected ERROR_SUCCESS\n");
2645     ok(!shfoW.fAnyOperationsAborted, "Didn't expect aborted operations\n");
2646     ok(GetLastError() == ERROR_SUCCESS ||
2647        broken(GetLastError() == ERROR_INVALID_HANDLE), /* WinXp, win2k3 */
2648        "Expected ERROR_SUCCESS, got %d\n", GetLastError());
2649 }
2650 
2651 static void
2652 test_shlmenu(void) {
2653 	HRESULT hres;
2654 	hres = Shell_MergeMenus (0, 0, 0x42, 0x4242, 0x424242, 0);
2655 	ok (hres == 0x4242, "expected 0x4242 but got %x\n", hres);
2656 	hres = Shell_MergeMenus ((HMENU)42, 0, 0x42, 0x4242, 0x424242, 0);
2657 	ok (hres == 0x4242, "expected 0x4242 but got %x\n", hres);
2658 }
2659 
2660 /* Check for old shell32 (4.0.x) */
2661 static BOOL is_old_shell32(void)
2662 {
2663     SHFILEOPSTRUCTA shfo;
2664     CHAR from[5*MAX_PATH];
2665     CHAR to[5*MAX_PATH];
2666     DWORD retval;
2667 
2668     shfo.hwnd = NULL;
2669     shfo.wFunc = FO_COPY;
2670     shfo.pFrom = from;
2671     shfo.pTo = to;
2672     /* FOF_NOCONFIRMMKDIR is needed for old shell32 */
2673     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI | FOF_MULTIDESTFILES | FOF_NOCONFIRMMKDIR;
2674     shfo.hNameMappings = NULL;
2675     shfo.lpszProgressTitle = NULL;
2676 
2677     set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
2678     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
2679     retval = SHFileOperationA(&shfo);
2680 
2681     /* Delete extra files on old shell32 and Vista+*/
2682     DeleteFileA("test6.txt\\test1.txt");
2683     /* Delete extra files on old shell32 */
2684     DeleteFileA("test6.txt\\test2.txt");
2685     DeleteFileA("test6.txt\\test3.txt");
2686     /* Delete extra directory on old shell32 and Vista+ */
2687     RemoveDirectoryA("test6.txt");
2688     /* Delete extra files/directories on Vista+*/
2689     DeleteFileA("test7.txt\\test2.txt");
2690     RemoveDirectoryA("test7.txt");
2691 
2692     if (retval == ERROR_SUCCESS)
2693         return TRUE;
2694 
2695     return FALSE;
2696 }
2697 
2698 START_TEST(shlfileop)
2699 {
2700     InitFunctionPointers();
2701 
2702     clean_after_shfo_tests();
2703 
2704     init_shfo_tests();
2705     old_shell32 = is_old_shell32();
2706     if (old_shell32)
2707         win_skip("Need to cater for old shell32 (4.0.x) on Win95\n");
2708     clean_after_shfo_tests();
2709 
2710     init_shfo_tests();
2711     test_get_file_info();
2712     test_get_file_info_iconlist();
2713     clean_after_shfo_tests();
2714 
2715     init_shfo_tests();
2716     test_delete();
2717     clean_after_shfo_tests();
2718 
2719     init_shfo_tests();
2720     test_rename();
2721     clean_after_shfo_tests();
2722 
2723     init_shfo_tests();
2724     test_copy();
2725     clean_after_shfo_tests();
2726 
2727     init_shfo_tests();
2728     test_move();
2729     clean_after_shfo_tests();
2730 
2731     test_sh_create_dir();
2732     clean_after_shfo_tests();
2733 
2734     init_shfo_tests();
2735     test_sh_path_prepare();
2736     clean_after_shfo_tests();
2737 
2738     init_shfo_tests();
2739     test_sh_new_link_info();
2740     clean_after_shfo_tests();
2741 
2742     test_unicode();
2743 
2744     test_shlmenu();
2745 }
2746