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