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