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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define WINE_NOWINSOCK
31 #include "wine/test.h"
33 CHAR CURR_DIR
[MAX_PATH
];
35 static HMODULE hshell32
;
36 static int (WINAPI
*pSHCreateDirectoryExA
)(HWND
, LPCSTR
, LPSECURITY_ATTRIBUTES
);
38 static void InitFunctionPointers(void)
40 hshell32
= GetModuleHandleA("shell32.dll");
43 pSHCreateDirectoryExA
= (void*)GetProcAddress(hshell32
, "SHCreateDirectoryExA");
46 /* creates a file with the specified name for tests */
47 static void createTestFile(const CHAR
*name
)
52 file
= CreateFileA(name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
53 ok(file
!= INVALID_HANDLE_VALUE
, "Failure to open file %s\n", name
);
54 WriteFile(file
, name
, strlen(name
), &written
, NULL
);
55 WriteFile(file
, "\n", strlen("\n"), &written
, NULL
);
59 static BOOL
file_exists(const CHAR
*name
)
61 return GetFileAttributesA(name
) != INVALID_FILE_ATTRIBUTES
;
64 /* initializes the tests */
65 static void init_shfo_tests(void)
69 GetCurrentDirectoryA(MAX_PATH
, CURR_DIR
);
70 len
= lstrlenA(CURR_DIR
);
72 if(len
&& (CURR_DIR
[len
-1] == '\\'))
75 createTestFile(".\\test1.txt");
76 createTestFile(".\\test2.txt");
77 createTestFile(".\\test3.txt");
78 CreateDirectoryA(".\\test4.txt", NULL
);
79 CreateDirectoryA(".\\testdir2", NULL
);
82 /* cleans after tests */
83 static void clean_after_shfo_tests(void)
85 DeleteFileA(".\\test1.txt");
86 DeleteFileA(".\\test2.txt");
87 DeleteFileA(".\\test3.txt");
88 DeleteFileA(".\\test4.txt\\test1.txt");
89 DeleteFileA(".\\test4.txt\\test2.txt");
90 DeleteFileA(".\\test4.txt\\test3.txt");
91 RemoveDirectoryA(".\\test4.txt");
92 DeleteFileA(".\\testdir2\\test1.txt");
93 DeleteFileA(".\\testdir2\\test2.txt");
94 DeleteFileA(".\\testdir2\\test3.txt");
95 DeleteFileA(".\\testdir2\\test4.txt\\test1.txt");
96 RemoveDirectoryA(".\\testdir2\\test4.txt");
97 RemoveDirectoryA(".\\testdir2");
101 puts into the specified buffer file names with current directory.
102 files - string with file names, separated by null characters. Ends on a double
105 static void set_curr_dir_path(CHAR
*buf
, const CHAR
* files
)
110 strcpy(buf
, CURR_DIR
);
115 buf
+= strlen(buf
) + 1;
116 files
+= strlen(files
) + 1;
122 /* tests the FO_DELETE action */
123 static void test_delete(void)
125 SHFILEOPSTRUCTA shfo
;
129 sprintf(buf
, "%s\\%s", CURR_DIR
, "test?.txt");
130 buf
[strlen(buf
) + 1] = '\0';
133 shfo
.wFunc
= FO_DELETE
;
136 shfo
.fFlags
= FOF_FILESONLY
| FOF_NOCONFIRMATION
| FOF_SILENT
;
137 shfo
.hNameMappings
= NULL
;
138 shfo
.lpszProgressTitle
= NULL
;
140 ok(!SHFileOperationA(&shfo
), "Deletion was successful\n");
141 ok(file_exists(".\\test4.txt"), "Directory should not be removed\n");
142 ok(!file_exists(".\\test1.txt"), "File should be removed\n");
144 ret
= SHFileOperationA(&shfo
);
145 ok(!ret
, "Directory exists, but is not removed, ret=%ld\n", ret
);
146 ok(file_exists(".\\test4.txt"), "Directory should not be removed\n");
148 shfo
.fFlags
= FOF_NOCONFIRMATION
| FOF_SILENT
| FOF_NOERRORUI
;
150 ok(!SHFileOperationA(&shfo
), "Directory removed\n");
151 ok(!file_exists(".\\test4.txt"), "Directory should be removed\n");
153 ret
= SHFileOperationA(&shfo
);
154 ok(!ret
, "The requested file does not exist, ret=%ld\n", ret
);
157 sprintf(buf
, "%s\\%s", CURR_DIR
, "test4.txt");
158 buf
[strlen(buf
) + 1] = '\0';
159 ok(MoveFileA(".\\test1.txt", ".\\test4.txt\\test1.txt"), "Fill the subdirectory\n");
160 ok(!SHFileOperationA(&shfo
), "Directory removed\n");
161 ok(!file_exists(".\\test4.txt"), "Directory is removed\n");
164 shfo
.pFrom
= ".\\test1.txt\0.\\test4.txt\0";
165 ok(!SHFileOperationA(&shfo
), "Directory and a file removed\n");
166 ok(!file_exists(".\\test1.txt"), "The file should be removed\n");
167 ok(!file_exists(".\\test4.txt"), "Directory should be removed\n");
168 ok(file_exists(".\\test2.txt"), "This file should not be removed\n");
171 /* tests the FO_RENAME action */
172 static void test_rename(void)
174 SHFILEOPSTRUCTA shfo
, shfo2
;
180 shfo
.wFunc
= FO_RENAME
;
183 shfo
.fFlags
= FOF_NOCONFIRMATION
| FOF_SILENT
| FOF_NOERRORUI
;
184 shfo
.hNameMappings
= NULL
;
185 shfo
.lpszProgressTitle
= NULL
;
187 set_curr_dir_path(from
, "test1.txt\0");
188 set_curr_dir_path(to
, "test4.txt\0");
189 ok(SHFileOperationA(&shfo
), "File is not renamed moving to other directory "
190 "when specifying directory name only\n");
191 ok(file_exists(".\\test1.txt"), "The file is removed\n");
193 set_curr_dir_path(from
, "test3.txt\0");
194 set_curr_dir_path(to
, "test4.txt\\test1.txt\0");
195 ok(!SHFileOperationA(&shfo
), "File is renamed moving to other directory\n");
196 ok(file_exists(".\\test4.txt\\test1.txt"), "The file is not renamed\n");
198 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
199 set_curr_dir_path(to
, "test6.txt\0test7.txt\0test8.txt\0");
200 retval
= SHFileOperationA(&shfo
); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
201 ok(!retval
|| retval
== ERROR_GEN_FAILURE
|| retval
== ERROR_INVALID_TARGET_HANDLE
,
202 "Can't rename many files, retval = %ld\n", retval
);
203 ok(file_exists(".\\test1.txt"), "The file is renamed - many files are specified\n");
205 memcpy(&shfo2
, &shfo
, sizeof(SHFILEOPSTRUCTA
));
206 shfo2
.fFlags
|= FOF_MULTIDESTFILES
;
208 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
209 set_curr_dir_path(to
, "test6.txt\0test7.txt\0test8.txt\0");
210 retval
= SHFileOperationA(&shfo2
); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
211 ok(!retval
|| retval
== ERROR_GEN_FAILURE
|| retval
== ERROR_INVALID_TARGET_HANDLE
,
212 "Can't rename many files, retval = %ld\n", retval
);
213 ok(file_exists(".\\test1.txt"), "The file is not renamed - many files are specified\n");
215 set_curr_dir_path(from
, "test1.txt\0");
216 set_curr_dir_path(to
, "test6.txt\0");
217 retval
= SHFileOperationA(&shfo
);
218 ok(!retval
, "Rename file failed, retval = %ld\n", retval
);
219 ok(!file_exists(".\\test1.txt"), "The file is not renamed\n");
220 ok(file_exists(".\\test6.txt"), "The file is not renamed\n");
222 set_curr_dir_path(from
, "test6.txt\0");
223 set_curr_dir_path(to
, "test1.txt\0");
224 retval
= SHFileOperationA(&shfo
);
225 ok(!retval
, "Rename file back failed, retval = %ld\n", retval
);
227 set_curr_dir_path(from
, "test4.txt\0");
228 set_curr_dir_path(to
, "test6.txt\0");
229 retval
= SHFileOperationA(&shfo
);
230 ok(!retval
, "Rename dir failed, retval = %ld\n", retval
);
231 ok(!file_exists(".\\test4.txt"), "The dir is not renamed\n");
232 ok(file_exists(".\\test6.txt"), "The dir is not renamed\n");
234 set_curr_dir_path(from
, "test6.txt\0");
235 set_curr_dir_path(to
, "test4.txt\0");
236 retval
= SHFileOperationA(&shfo
);
237 ok(!retval
, "Rename dir back failed, retval = %ld\n", retval
);
240 /* tests the FO_COPY action */
241 static void test_copy(void)
243 SHFILEOPSTRUCTA shfo
, shfo2
;
246 FILEOP_FLAGS tmp_flags
;
250 shfo
.wFunc
= FO_COPY
;
253 shfo
.fFlags
= FOF_NOCONFIRMATION
| FOF_SILENT
| FOF_NOERRORUI
;
254 shfo
.hNameMappings
= NULL
;
255 shfo
.lpszProgressTitle
= NULL
;
257 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
258 set_curr_dir_path(to
, "test6.txt\0test7.txt\0test8.txt\0");
259 ok(SHFileOperationA(&shfo
), "Can't copy many files\n");
260 ok(!file_exists(".\\test6.txt"), "The file is not copied - many files are "
261 "specified as a target\n");
263 memcpy(&shfo2
, &shfo
, sizeof(SHFILEOPSTRUCTA
));
264 shfo2
.fFlags
|= FOF_MULTIDESTFILES
;
266 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
267 set_curr_dir_path(to
, "test6.txt\0test7.txt\0test8.txt\0");
268 ok(!SHFileOperationA(&shfo2
), "Can't copy many files\n");
269 ok(file_exists(".\\test6.txt"), "The file is copied - many files are "
270 "specified as a target\n");
271 DeleteFileA(".\\test6.txt");
272 DeleteFileA(".\\test7.txt");
273 RemoveDirectoryA(".\\test8.txt");
275 /* number of sources do not correspond to number of targets */
276 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
277 set_curr_dir_path(to
, "test6.txt\0test7.txt\0");
278 ok(SHFileOperationA(&shfo2
), "Can't copy many files\n");
279 ok(!file_exists(".\\test6.txt"), "The file is not copied - many files are "
280 "specified as a target\n");
282 set_curr_dir_path(from
, "test1.txt\0");
283 set_curr_dir_path(to
, "test4.txt\0");
284 ok(!SHFileOperationA(&shfo
), "Prepare test to check how directories are copied recursively\n");
285 ok(file_exists(".\\test4.txt\\test1.txt"), "The file is copied\n");
287 set_curr_dir_path(from
, "test?.txt\0");
288 set_curr_dir_path(to
, "testdir2\0");
289 ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
290 ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not copied yet\n");
291 ok(!SHFileOperationA(&shfo
), "Files and directories are copied to directory\n");
292 ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
293 ok(file_exists(".\\testdir2\\test4.txt"), "The directory is copied\n");
294 ok(file_exists(".\\testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
295 clean_after_shfo_tests();
298 shfo
.fFlags
|= FOF_FILESONLY
;
299 ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
300 ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not copied yet\n");
301 ok(!SHFileOperationA(&shfo
), "Files are copied to other directory\n");
302 ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
303 ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is copied\n");
304 clean_after_shfo_tests();
307 set_curr_dir_path(from
, "test1.txt\0test2.txt\0");
308 ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
309 ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not copied yet\n");
310 ok(!SHFileOperationA(&shfo
), "Files are copied to other directory \n");
311 ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
312 ok(file_exists(".\\testdir2\\test2.txt"), "The file is copied\n");
313 clean_after_shfo_tests();
315 /* Copying multiple files with one not existing as source, fails the
316 entire operation in Win98/ME/2K/XP, but not in 95/NT */
318 tmp_flags
= shfo
.fFlags
;
319 set_curr_dir_path(from
, "test1.txt\0test10.txt\0test2.txt\0");
320 ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
321 ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not copied yet\n");
322 retval
= SHFileOperationA(&shfo
);
324 /* Win 95/NT returns success but copies only the files up to the nonexistent source */
325 ok(file_exists(".\\testdir2\\test1.txt"), "The file is not copied\n");
328 /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
329 ok(retval
== 1026, "Files are copied to other directory\n");
330 ok(!file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
332 ok(!file_exists(".\\testdir2\\test2.txt"), "The file is copied\n");
333 shfo
.fFlags
= tmp_flags
;
336 /* tests the FO_MOVE action */
337 static void test_move(void)
339 SHFILEOPSTRUCTA shfo
, shfo2
;
344 shfo
.wFunc
= FO_MOVE
;
347 shfo
.fFlags
= FOF_NOCONFIRMATION
| FOF_SILENT
| FOF_NOERRORUI
;
348 shfo
.hNameMappings
= NULL
;
349 shfo
.lpszProgressTitle
= NULL
;
351 set_curr_dir_path(from
, "test1.txt\0");
352 set_curr_dir_path(to
, "test4.txt\0");
353 ok(!SHFileOperationA(&shfo
), "Prepare test to check how directories are moved recursively\n");
354 ok(file_exists(".\\test4.txt\\test1.txt"), "The file is moved\n");
356 set_curr_dir_path(from
, "test?.txt\0");
357 set_curr_dir_path(to
, "testdir2\0");
358 ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not moved yet\n");
359 ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not moved yet\n");
360 ok(!SHFileOperationA(&shfo
), "Files and directories are moved to directory\n");
361 ok(file_exists(".\\testdir2\\test2.txt"), "The file is moved\n");
362 ok(file_exists(".\\testdir2\\test4.txt"), "The directory is moved\n");
363 ok(file_exists(".\\testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
365 clean_after_shfo_tests();
368 memcpy(&shfo2
, &shfo
, sizeof(SHFILEOPSTRUCTA
));
369 shfo2
.fFlags
|= FOF_MULTIDESTFILES
;
371 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
372 set_curr_dir_path(to
, "test6.txt\0test7.txt\0test8.txt\0");
373 ok(!SHFileOperationA(&shfo2
), "Move many files\n");
374 ok(file_exists(".\\test6.txt"), "The file is moved - many files are "
375 "specified as a target\n");
376 DeleteFileA(".\\test6.txt");
377 DeleteFileA(".\\test7.txt");
378 RemoveDirectoryA(".\\test8.txt");
382 /* number of sources do not correspond to number of targets */
383 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
384 set_curr_dir_path(to
, "test6.txt\0test7.txt\0");
385 ok(SHFileOperationA(&shfo2
), "Can't move many files\n");
386 ok(!file_exists(".\\test6.txt"), "The file is not moved - many files are "
387 "specified as a target\n");
391 set_curr_dir_path(from
, "test3.txt\0");
392 set_curr_dir_path(to
, "test4.txt\\test1.txt\0");
393 ok(!SHFileOperationA(&shfo
), "File is moved moving to other directory\n");
394 ok(file_exists(".\\test4.txt\\test1.txt"), "The file is moved\n");
396 set_curr_dir_path(from
, "test1.txt\0test2.txt\0test4.txt\0");
397 set_curr_dir_path(to
, "test6.txt\0test7.txt\0test8.txt\0");
398 ok(SHFileOperationA(&shfo
), "Cannot move many files\n");
399 ok(file_exists(".\\test1.txt"), "The file is not moved. Many files are specified\n");
400 ok(file_exists(".\\test4.txt"), "The directory is not moved. Many files are specified\n");
402 set_curr_dir_path(from
, "test1.txt\0");
403 set_curr_dir_path(to
, "test6.txt\0");
404 ok(!SHFileOperationA(&shfo
), "Move file\n");
405 ok(!file_exists(".\\test1.txt"), "The file is moved\n");
406 ok(file_exists(".\\test6.txt"), "The file is moved\n");
407 set_curr_dir_path(from
, "test6.txt\0");
408 set_curr_dir_path(to
, "test1.txt\0");
409 ok(!SHFileOperationA(&shfo
), "Move file back\n");
411 set_curr_dir_path(from
, "test4.txt\0");
412 set_curr_dir_path(to
, "test6.txt\0");
413 ok(!SHFileOperationA(&shfo
), "Move dir\n");
414 ok(!file_exists(".\\test4.txt"), "The dir is moved\n");
415 ok(file_exists(".\\test6.txt"), "The dir is moved\n");
416 set_curr_dir_path(from
, "test6.txt\0");
417 set_curr_dir_path(to
, "test4.txt\0");
418 ok(!SHFileOperationA(&shfo
), "Move dir back\n");
421 static void test_sh_create_dir(void)
426 if(!pSHCreateDirectoryExA
)
428 trace("skipping SHCreateDirectoryExA tests\n");
432 set_curr_dir_path(path
, "testdir2\\test4.txt\0");
433 ret
= pSHCreateDirectoryExA(NULL
, path
, NULL
);
434 ok(ERROR_SUCCESS
== ret
, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret
);
435 ok(file_exists(".\\testdir2"), "The first directory is not created\n");
436 ok(file_exists(".\\testdir2\\test4.txt"), "The second directory is not created\n");
438 ret
= pSHCreateDirectoryExA(NULL
, path
, NULL
);
439 ok(ERROR_ALREADY_EXISTS
== ret
, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret
);
442 START_TEST(shlfileop
)
444 InitFunctionPointers();
446 clean_after_shfo_tests();
450 clean_after_shfo_tests();
454 clean_after_shfo_tests();
458 clean_after_shfo_tests();
462 clean_after_shfo_tests();
464 test_sh_create_dir();
465 clean_after_shfo_tests();