Remove redundant check.
[wine] / dlls / shell32 / tests / shlfileop.c
1 /*
2  * Unit test of the SHFileOperation function.
3  *
4  * Copyright 2002 Andriy Palamarchuk
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define WINE_NOWINSOCK
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wtypes.h"
28 #include "shellapi.h"
29 #include "shlobj.h"
30
31 #include "wine/test.h"
32
33 CHAR CURR_DIR[MAX_PATH];
34
35 static HMODULE hshell32;
36 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
37
38 static void InitFunctionPointers(void)
39 {
40     hshell32 = GetModuleHandleA("shell32.dll");
41
42     if(hshell32)
43         pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
44 }
45
46 /* creates a file with the specified name for tests */
47 static void createTestFile(const CHAR *name)
48 {
49     HANDLE file;
50     DWORD written;
51
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);
56     CloseHandle(file);
57 }
58
59 static BOOL file_exists(const CHAR *name)
60 {
61     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
62 }
63
64 /* initializes the tests */
65 static void init_shfo_tests(void)
66 {
67     int len;
68
69     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
70     len = lstrlenA(CURR_DIR);
71
72     if(len && (CURR_DIR[len-1] == '\\'))
73         CURR_DIR[len-1] = 0;
74
75     createTestFile(".\\test1.txt");
76     createTestFile(".\\test2.txt");
77     createTestFile(".\\test3.txt");
78     CreateDirectoryA(".\\test4.txt", NULL);
79     CreateDirectoryA(".\\testdir2", NULL);
80 }
81
82 /* cleans after tests */
83 static void clean_after_shfo_tests(void)
84 {
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");
98 }
99
100 /*
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
103  null characters
104 */
105 static void set_curr_dir_path(CHAR *buf, const CHAR* files)
106 {
107     buf[0] = 0;
108     while (files[0])
109     {
110         strcpy(buf, CURR_DIR);
111         buf += strlen(buf);
112         buf[0] = '\\';
113         buf++;
114         strcpy(buf, files);
115         buf += strlen(buf) + 1;
116         files += strlen(files) + 1;
117     }
118     buf[0] = 0;
119 }
120
121
122 /* tests the FO_DELETE action */
123 static void test_delete(void)
124 {
125     SHFILEOPSTRUCTA shfo;
126     DWORD ret;
127     CHAR buf[MAX_PATH];
128
129     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
130     buf[strlen(buf) + 1] = '\0';
131
132     shfo.hwnd = NULL;
133     shfo.wFunc = FO_DELETE;
134     shfo.pFrom = buf;
135     shfo.pTo = "\0";
136     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
137     shfo.hNameMappings = NULL;
138     shfo.lpszProgressTitle = NULL;
139
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");
143
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");
147
148     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
149
150     ok(!SHFileOperationA(&shfo), "Directory removed\n");
151     ok(!file_exists(".\\test4.txt"), "Directory should be removed\n");
152
153     ret = SHFileOperationA(&shfo);
154     ok(!ret, "The requested file does not exist, ret=%ld\n", ret);
155
156     init_shfo_tests();
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");
162
163     init_shfo_tests();
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");
169 }
170
171 /* tests the FO_RENAME action */
172 static void test_rename(void)
173 {
174     SHFILEOPSTRUCTA shfo, shfo2;
175     CHAR from[MAX_PATH];
176     CHAR to[MAX_PATH];
177     DWORD retval;
178
179     shfo.hwnd = NULL;
180     shfo.wFunc = FO_RENAME;
181     shfo.pFrom = from;
182     shfo.pTo = to;
183     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
184     shfo.hNameMappings = NULL;
185     shfo.lpszProgressTitle = NULL;
186
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");
192
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");
197
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");
204
205     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
206     shfo2.fFlags |= FOF_MULTIDESTFILES;
207
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");
214
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");
221
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);
226
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");
233
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);
238 }
239
240 /* tests the FO_COPY action */
241 static void test_copy(void)
242 {
243     SHFILEOPSTRUCTA shfo, shfo2;
244     CHAR from[MAX_PATH];
245     CHAR to[MAX_PATH];
246     FILEOP_FLAGS tmp_flags;
247     DWORD retval;
248
249     shfo.hwnd = NULL;
250     shfo.wFunc = FO_COPY;
251     shfo.pFrom = from;
252     shfo.pTo = to;
253     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
254     shfo.hNameMappings = NULL;
255     shfo.lpszProgressTitle = NULL;
256
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");
262
263     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
264     shfo2.fFlags |= FOF_MULTIDESTFILES;
265
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");
274
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");
281
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");
286
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();
296
297     init_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();
305
306     init_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();
314
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 */
317     init_shfo_tests();
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);
323     if (!retval)
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");
326     else
327     {
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");
331     }
332     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is copied\n");
333     shfo.fFlags = tmp_flags;
334 }
335
336 /* tests the FO_MOVE action */
337 static void test_move(void)
338 {
339     SHFILEOPSTRUCTA shfo, shfo2;
340     CHAR from[MAX_PATH];
341     CHAR to[MAX_PATH];
342
343     shfo.hwnd = NULL;
344     shfo.wFunc = FO_MOVE;
345     shfo.pFrom = from;
346     shfo.pTo = to;
347     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
348     shfo.hNameMappings = NULL;
349     shfo.lpszProgressTitle = NULL;
350
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");
355
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");
364
365     clean_after_shfo_tests();
366     init_shfo_tests();
367
368     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
369     shfo2.fFlags |= FOF_MULTIDESTFILES;
370
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");
379
380     init_shfo_tests();
381
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");
388
389     init_shfo_tests();
390
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");
395
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");
401
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");
410
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");
419 }
420
421 static void test_sh_create_dir(void)
422 {
423     CHAR path[MAX_PATH];
424     int ret;
425
426     if(!pSHCreateDirectoryExA)
427     {
428         trace("skipping SHCreateDirectoryExA tests\n");
429         return;
430     }
431
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");
437
438     ret = pSHCreateDirectoryExA(NULL, path, NULL);
439     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
440 }
441
442 START_TEST(shlfileop)
443 {
444     InitFunctionPointers();
445
446     clean_after_shfo_tests();
447
448     init_shfo_tests();
449     test_delete();
450     clean_after_shfo_tests();
451
452     init_shfo_tests();
453     test_rename();
454     clean_after_shfo_tests();
455
456     init_shfo_tests();
457     test_copy();
458     clean_after_shfo_tests();
459
460     init_shfo_tests();
461     test_move();
462     clean_after_shfo_tests();
463
464     test_sh_create_dir();
465     clean_after_shfo_tests();
466 }