Fixed definitions of TTTOOLINFOA/W_V1_SIZE and
[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 #include "windef.h"
25 #include "winbase.h"
26 #include "wtypes.h"
27 #include "shellapi.h"
28
29 #include "wine/test.h"
30
31 CHAR CURR_DIR[MAX_PATH];
32
33 /* creates a file with the specified name for tests */
34 void createTestFile(CHAR *name)
35 {
36     HANDLE file;
37     DWORD written;
38     CHAR msg[MAX_PATH];
39
40     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
41     sprintf(msg, "Failure to open file %s", name);
42     ok(file != INVALID_HANDLE_VALUE, msg);
43     WriteFile(file, name, strlen(name), &written, NULL);
44     WriteFile(file, "\n", strlen("\n"), &written, NULL);
45     CloseHandle(file);
46 }
47
48 BOOL file_exists(CHAR *name)
49 {
50     return GetFileAttributesA(name) != 0xFFFFFFFF;
51 }
52
53 /* initializes the tests */
54 void init_shfo_tests(void)
55 {
56     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
57     createTestFile(".\\test1.txt");
58     createTestFile(".\\test2.txt");
59     createTestFile(".\\test3.txt");
60     CreateDirectoryA(".\\test4.txt", NULL);
61     CreateDirectoryA(".\\testdir2", NULL);
62 }
63
64 /* cleans after tests */
65 void clean_after_shfo_tests(void)
66 {
67     DeleteFileA(".\\test1.txt");
68     DeleteFileA(".\\test2.txt");
69     DeleteFileA(".\\test3.txt");
70     DeleteFileA(".\\test4.txt\\test1.txt");
71     DeleteFileA(".\\test4.txt\\test2.txt");
72     DeleteFileA(".\\test4.txt\\test3.txt");
73     RemoveDirectoryA(".\\test4.txt");
74     DeleteFileA(".\\testdir2\\test1.txt");
75     DeleteFileA(".\\testdir2\\test2.txt");
76     DeleteFileA(".\\testdir2\\test3.txt");
77     DeleteFileA(".\\testdir2\\test4.txt\\test1.txt");
78     RemoveDirectoryA(".\\testdir2\\test4.txt");
79     RemoveDirectoryA(".\\testdir2");
80 }
81
82 /*
83  puts into the specified buffer file names with current directory.
84  files - string with file names, separated by null characters. Ends on a double
85  null characters
86 */
87 void set_curr_dir_path(CHAR *buf, CHAR* files)
88 {
89     buf[0] = 0;
90     while (files[0])
91     {
92         strcpy(buf, CURR_DIR);
93         buf += strlen(buf);
94         buf[0] = '\\';
95         buf++;
96         strcpy(buf, files);
97         buf += strlen(buf) + 1;
98         files += strlen(files) + 1;
99     }
100     buf[0] = 0;
101 }
102
103
104 /* tests the FO_DELETE action */
105 void test_delete(void)
106 {
107     SHFILEOPSTRUCTA shfo;
108     CHAR buf[MAX_PATH];
109
110     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
111     buf[strlen(buf) + 1] = '\0';
112
113     shfo.hwnd = NULL;
114     shfo.wFunc = FO_DELETE;
115     shfo.pFrom = buf;
116     shfo.pTo = "\0";
117     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
118     shfo.hNameMappings = NULL;
119     shfo.lpszProgressTitle = NULL;
120
121     ok(!SHFileOperationA(&shfo), "Deletion was successful");
122     ok(file_exists(".\\test4.txt"), "Directory should not be removed");
123     ok(!file_exists(".\\test1.txt"), "File should be removed");
124
125     ok(!SHFileOperationA(&shfo), "Directory exists, but is not removed");
126     ok(file_exists(".\\test4.txt"), "Directory should not be removed");
127
128     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
129
130     ok(!SHFileOperationA(&shfo), "Directory removed");
131     ok(!file_exists(".\\test4.txt"), "Directory should be removed");
132
133     ok(!SHFileOperationA(&shfo), "The requested file does not exist");
134
135     init_shfo_tests();
136     sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
137     buf[strlen(buf) + 1] = '\0';
138     ok(MoveFileA(".\\test1.txt", ".\\test4.txt\\test1.txt"), "Fill the subdirectory");
139     ok(!SHFileOperationA(&shfo), "Directory removed");
140     ok(!file_exists(".\\test4.txt"), "Directory is removed");
141
142     init_shfo_tests();
143     shfo.pFrom = ".\\test1.txt\0.\\test4.txt\0";
144     ok(!SHFileOperationA(&shfo), "Directory and a file removed");
145     ok(!file_exists(".\\test1.txt"), "The file should be removed");
146     ok(!file_exists(".\\test4.txt"), "Directory should be removed");
147     ok(file_exists(".\\test2.txt"), "This file should not be removed");
148 }
149
150 /* tests the FO_RENAME action */
151 void test_rename()
152 {
153     SHFILEOPSTRUCTA shfo, shfo2;
154     CHAR from[MAX_PATH];
155     CHAR to[MAX_PATH];
156
157     shfo.hwnd = NULL;
158     shfo.wFunc = FO_RENAME;
159     shfo.pFrom = from;
160     shfo.pTo = to;
161     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
162     shfo.hNameMappings = NULL;
163     shfo.lpszProgressTitle = NULL;
164
165     set_curr_dir_path(from, "test1.txt\0");
166     set_curr_dir_path(to, "test4.txt\0");
167     ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
168        "when specifying directory name only");
169     ok(file_exists(".\\test1.txt"), "The file is not removed");
170
171     set_curr_dir_path(from, "test3.txt\0");
172     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
173     ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory");
174     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is renamed");
175
176     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
177     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
178     ok(SHFileOperationA(&shfo), "Can't rename many files");
179     ok(file_exists(".\\test1.txt"), "The file is not renamed - many files are specified ");
180
181     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
182     shfo2.fFlags |= FOF_MULTIDESTFILES;
183
184     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
185     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
186     ok(SHFileOperationA(&shfo2), "Can't rename many files");
187     ok(file_exists(".\\test1.txt"), "The file is not renamed - many files are specified ");
188
189     set_curr_dir_path(from, "test1.txt\0");
190     set_curr_dir_path(to, "test6.txt\0");
191     ok(!SHFileOperationA(&shfo), "Rename file");
192     ok(!file_exists(".\\test1.txt"), "The file is renamed");
193     ok(file_exists(".\\test6.txt"), "The file is renamed ");
194     set_curr_dir_path(from, "test6.txt\0");
195     set_curr_dir_path(to, "test1.txt\0");
196     ok(!SHFileOperationA(&shfo), "Rename file back");
197
198     set_curr_dir_path(from, "test4.txt\0");
199     set_curr_dir_path(to, "test6.txt\0");
200     ok(!SHFileOperationA(&shfo), "Rename dir");
201     ok(!file_exists(".\\test4.txt"), "The dir is renamed");
202     ok(file_exists(".\\test6.txt"), "The dir is renamed ");
203     set_curr_dir_path(from, "test6.txt\0");
204     set_curr_dir_path(to, "test4.txt\0");
205     ok(!SHFileOperationA(&shfo), "Rename dir back");
206 }
207
208 /* tests the FO_COPY action */
209 void test_copy(void)
210 {
211     SHFILEOPSTRUCTA shfo, shfo2;
212     CHAR from[MAX_PATH];
213     CHAR to[MAX_PATH];
214     FILEOP_FLAGS tmp_flags;
215     DWORD retval;
216
217     shfo.hwnd = NULL;
218     shfo.wFunc = FO_COPY;
219     shfo.pFrom = from;
220     shfo.pTo = to;
221     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
222     shfo.hNameMappings = NULL;
223     shfo.lpszProgressTitle = NULL;
224
225     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
226     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
227     ok(SHFileOperationA(&shfo), "Can't copy many files");
228     ok(!file_exists(".\\test6.txt"), "The file is not copied - many files are "
229        "specified as a target");
230
231     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
232     shfo2.fFlags |= FOF_MULTIDESTFILES;
233
234     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
235     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
236     ok(!SHFileOperationA(&shfo2), "Can't copy many files");
237     ok(file_exists(".\\test6.txt"), "The file is copied - many files are "
238        "specified as a target");
239     DeleteFileA(".\\test6.txt");
240     DeleteFileA(".\\test7.txt");
241     RemoveDirectoryA(".\\test8.txt");
242
243     /* number of sources do not correspond to number of targets */
244     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
245     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
246     ok(SHFileOperationA(&shfo2), "Can't copy many files");
247     ok(!file_exists(".\\test6.txt"), "The file is not copied - many files are "
248        "specified as a target");
249
250     set_curr_dir_path(from, "test1.txt\0");
251     set_curr_dir_path(to, "test4.txt\0");
252     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively");
253     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is copied");
254
255     set_curr_dir_path(from, "test?.txt\0");
256     set_curr_dir_path(to, "testdir2\0");
257     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet");
258     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not copied yet");
259     ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory ");
260     ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied");
261     ok(file_exists(".\\testdir2\\test4.txt"), "The directory is copied");
262     ok(file_exists(".\\testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied");
263     clean_after_shfo_tests();
264
265     init_shfo_tests();
266     shfo.fFlags |= FOF_FILESONLY;
267     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet");
268     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not copied yet");
269     ok(!SHFileOperationA(&shfo), "Files are copied to other directory ");
270     ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied");
271     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is copied");
272     clean_after_shfo_tests();
273
274     init_shfo_tests();
275     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
276     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet");
277     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not copied yet");
278     ok(!SHFileOperationA(&shfo), "Files are copied to other directory ");
279     ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied");
280     ok(file_exists(".\\testdir2\\test2.txt"), "The file is copied");
281     clean_after_shfo_tests();
282
283     /* Copying multiple files with one not existing as source, fails the
284        entire operation in Win98/ME/2K/XP, but not in 95/NT */
285     init_shfo_tests();
286     tmp_flags = shfo.fFlags;
287     set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
288     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet");
289     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not copied yet");
290     retval = SHFileOperationA(&shfo);
291     if (!retval)
292       /* Win 95/NT returns success but copies only the files up to the non-existent source */
293       ok(file_exists(".\\testdir2\\test1.txt"), "The file is not copied");
294     else
295     {
296       /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
297       ok(retval == 1026, "Files are copied to other directory ");
298       ok(!file_exists(".\\testdir2\\test1.txt"), "The file is copied");
299     }
300     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is copied");
301     shfo.fFlags = tmp_flags;
302 }
303
304 /* tests the FO_MOVE action */
305 void test_move(void)
306 {
307     SHFILEOPSTRUCTA shfo, shfo2;
308     CHAR from[MAX_PATH];
309     CHAR to[MAX_PATH];
310
311     shfo.hwnd = NULL;
312     shfo.wFunc = FO_MOVE;
313     shfo.pFrom = from;
314     shfo.pTo = to;
315     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
316     shfo.hNameMappings = NULL;
317     shfo.lpszProgressTitle = NULL;
318
319     set_curr_dir_path(from, "test1.txt\0");
320     set_curr_dir_path(to, "test4.txt\0");
321     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively");
322     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is moved");
323
324     set_curr_dir_path(from, "test?.txt\0");
325     set_curr_dir_path(to, "testdir2\0");
326     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not moved yet");
327     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not moved yet");
328     ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory ");
329     ok(file_exists(".\\testdir2\\test2.txt"), "The file is moved");
330     ok(file_exists(".\\testdir2\\test4.txt"), "The directory is moved");
331     ok(file_exists(".\\testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved");
332
333     clean_after_shfo_tests();
334     init_shfo_tests();
335
336     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
337     shfo2.fFlags |= FOF_MULTIDESTFILES;
338
339     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
340     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
341     ok(!SHFileOperationA(&shfo2), "Move many files");
342     ok(file_exists(".\\test6.txt"), "The file is moved - many files are "
343        "specified as a target");
344     DeleteFileA(".\\test6.txt");
345     DeleteFileA(".\\test7.txt");
346     RemoveDirectoryA(".\\test8.txt");
347
348     init_shfo_tests();
349
350     /* number of sources do not correspond to number of targets */
351     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
352     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
353     ok(SHFileOperationA(&shfo2), "Can't move many files");
354     ok(!file_exists(".\\test6.txt"), "The file is not moved - many files are "
355        "specified as a target");
356
357     init_shfo_tests();
358
359     set_curr_dir_path(from, "test3.txt\0");
360     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
361     ok(!SHFileOperationA(&shfo), "File is moved moving to other directory");
362     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is moved");
363
364     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
365     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
366     ok(SHFileOperationA(&shfo), "Can not move many files");
367     ok(file_exists(".\\test1.txt"), "The file is not moved. Many files are specified ");
368     ok(file_exists(".\\test4.txt"), "The directory not is moved. Many files are specified ");
369
370     set_curr_dir_path(from, "test1.txt\0");
371     set_curr_dir_path(to, "test6.txt\0");
372     ok(!SHFileOperationA(&shfo), "Move file");
373     ok(!file_exists(".\\test1.txt"), "The file is moved");
374     ok(file_exists(".\\test6.txt"), "The file is moved ");
375     set_curr_dir_path(from, "test6.txt\0");
376     set_curr_dir_path(to, "test1.txt\0");
377     ok(!SHFileOperationA(&shfo), "Move file back");
378
379     set_curr_dir_path(from, "test4.txt\0");
380     set_curr_dir_path(to, "test6.txt\0");
381     ok(!SHFileOperationA(&shfo), "Move dir");
382     ok(!file_exists(".\\test4.txt"), "The dir is moved");
383     ok(file_exists(".\\test6.txt"), "The dir is moved ");
384     set_curr_dir_path(from, "test6.txt\0");
385     set_curr_dir_path(to, "test4.txt\0");
386     ok(!SHFileOperationA(&shfo), "Move dir back");
387 }
388
389 START_TEST(shlfileop)
390 {
391     clean_after_shfo_tests();
392
393     init_shfo_tests();
394     test_delete();
395     clean_after_shfo_tests();
396
397     init_shfo_tests();
398     test_rename();
399     clean_after_shfo_tests();
400
401     init_shfo_tests();
402     test_copy();
403     clean_after_shfo_tests();
404
405     init_shfo_tests();
406     test_move();
407     clean_after_shfo_tests();
408 }