Handle wParam in WM_PAINT properly: if non-null, it is the hdc we are
[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 void createTestFile(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 BOOL file_exists(CHAR *name)
60 {
61     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
62 }
63
64 /* initializes the tests */
65 void init_shfo_tests(void)
66 {
67     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
68     createTestFile(".\\test1.txt");
69     createTestFile(".\\test2.txt");
70     createTestFile(".\\test3.txt");
71     CreateDirectoryA(".\\test4.txt", NULL);
72     CreateDirectoryA(".\\testdir2", NULL);
73 }
74
75 /* cleans after tests */
76 void clean_after_shfo_tests(void)
77 {
78     DeleteFileA(".\\test1.txt");
79     DeleteFileA(".\\test2.txt");
80     DeleteFileA(".\\test3.txt");
81     DeleteFileA(".\\test4.txt\\test1.txt");
82     DeleteFileA(".\\test4.txt\\test2.txt");
83     DeleteFileA(".\\test4.txt\\test3.txt");
84     RemoveDirectoryA(".\\test4.txt");
85     DeleteFileA(".\\testdir2\\test1.txt");
86     DeleteFileA(".\\testdir2\\test2.txt");
87     DeleteFileA(".\\testdir2\\test3.txt");
88     DeleteFileA(".\\testdir2\\test4.txt\\test1.txt");
89     RemoveDirectoryA(".\\testdir2\\test4.txt");
90     RemoveDirectoryA(".\\testdir2");
91 }
92
93 /*
94  puts into the specified buffer file names with current directory.
95  files - string with file names, separated by null characters. Ends on a double
96  null characters
97 */
98 void set_curr_dir_path(CHAR *buf, CHAR* files)
99 {
100     buf[0] = 0;
101     while (files[0])
102     {
103         strcpy(buf, CURR_DIR);
104         buf += strlen(buf);
105         buf[0] = '\\';
106         buf++;
107         strcpy(buf, files);
108         buf += strlen(buf) + 1;
109         files += strlen(files) + 1;
110     }
111     buf[0] = 0;
112 }
113
114
115 /* tests the FO_DELETE action */
116 void test_delete(void)
117 {
118     SHFILEOPSTRUCTA shfo;
119     DWORD ret;
120     CHAR buf[MAX_PATH];
121
122     sprintf(buf, "%s\\%s", CURR_DIR, "test?.txt");
123     buf[strlen(buf) + 1] = '\0';
124
125     shfo.hwnd = NULL;
126     shfo.wFunc = FO_DELETE;
127     shfo.pFrom = buf;
128     shfo.pTo = "\0";
129     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
130     shfo.hNameMappings = NULL;
131     shfo.lpszProgressTitle = NULL;
132
133     ok(!SHFileOperationA(&shfo), "Deletion was successful\n");
134     ok(file_exists(".\\test4.txt"), "Directory should not be removed\n");
135     ok(!file_exists(".\\test1.txt"), "File should be removed\n");
136
137     ret = SHFileOperationA(&shfo);
138     ok(!ret, "Directory exists, but is not removed, ret=%ld\n", ret);
139     ok(file_exists(".\\test4.txt"), "Directory should not be removed\n");
140
141     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
142
143     ok(!SHFileOperationA(&shfo), "Directory removed\n");
144     ok(!file_exists(".\\test4.txt"), "Directory should be removed\n");
145
146     ret = SHFileOperationA(&shfo);
147     ok(!ret, "The requested file does not exist, ret=%ld\n", ret);
148
149     init_shfo_tests();
150     sprintf(buf, "%s\\%s", CURR_DIR, "test4.txt");
151     buf[strlen(buf) + 1] = '\0';
152     ok(MoveFileA(".\\test1.txt", ".\\test4.txt\\test1.txt"), "Fill the subdirectory\n");
153     ok(!SHFileOperationA(&shfo), "Directory removed\n");
154     ok(!file_exists(".\\test4.txt"), "Directory is removed\n");
155
156     init_shfo_tests();
157     shfo.pFrom = ".\\test1.txt\0.\\test4.txt\0";
158     ok(!SHFileOperationA(&shfo), "Directory and a file removed\n");
159     ok(!file_exists(".\\test1.txt"), "The file should be removed\n");
160     ok(!file_exists(".\\test4.txt"), "Directory should be removed\n");
161     ok(file_exists(".\\test2.txt"), "This file should not be removed\n");
162 }
163
164 /* tests the FO_RENAME action */
165 void test_rename()
166 {
167     SHFILEOPSTRUCTA shfo, shfo2;
168     CHAR from[MAX_PATH];
169     CHAR to[MAX_PATH];
170     DWORD retval;
171
172     shfo.hwnd = NULL;
173     shfo.wFunc = FO_RENAME;
174     shfo.pFrom = from;
175     shfo.pTo = to;
176     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
177     shfo.hNameMappings = NULL;
178     shfo.lpszProgressTitle = NULL;
179
180     set_curr_dir_path(from, "test1.txt\0");
181     set_curr_dir_path(to, "test4.txt\0");
182     ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
183        "when specifying directory name only\n");
184     ok(file_exists(".\\test1.txt"), "The file is not removed\n");
185
186     set_curr_dir_path(from, "test3.txt\0");
187     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
188     ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
189     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is renamed\n");
190
191     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
192     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
193     retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
194     ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_REDIR_PAUSED,
195        "Can't rename many files, retval = %lx\n", retval);
196     ok(file_exists(".\\test1.txt"), "The file is not renamed - many files are specified\n");
197
198     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
199     shfo2.fFlags |= FOF_MULTIDESTFILES;
200
201     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
202     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
203     retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
204     ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_REDIR_PAUSED,
205        "Can't rename many files, retval = %lx\n", retval);
206     ok(file_exists(".\\test1.txt"), "The file is not renamed - many files are specified\n");
207
208     set_curr_dir_path(from, "test1.txt\0");
209     set_curr_dir_path(to, "test6.txt\0");
210     ok(!SHFileOperationA(&shfo), "Rename file\n");
211     ok(!file_exists(".\\test1.txt"), "The file is renamed\n");
212     ok(file_exists(".\\test6.txt"), "The file is renamed\n");
213     set_curr_dir_path(from, "test6.txt\0");
214     set_curr_dir_path(to, "test1.txt\0");
215     ok(!SHFileOperationA(&shfo), "Rename file back\n");
216
217     set_curr_dir_path(from, "test4.txt\0");
218     set_curr_dir_path(to, "test6.txt\0");
219     ok(!SHFileOperationA(&shfo), "Rename dir\n");
220     ok(!file_exists(".\\test4.txt"), "The dir is renamed\n");
221     ok(file_exists(".\\test6.txt"), "The dir is renamed\n");
222     set_curr_dir_path(from, "test6.txt\0");
223     set_curr_dir_path(to, "test4.txt\0");
224     ok(!SHFileOperationA(&shfo), "Rename dir back\n");
225 }
226
227 /* tests the FO_COPY action */
228 void test_copy(void)
229 {
230     SHFILEOPSTRUCTA shfo, shfo2;
231     CHAR from[MAX_PATH];
232     CHAR to[MAX_PATH];
233     FILEOP_FLAGS tmp_flags;
234     DWORD retval;
235
236     shfo.hwnd = NULL;
237     shfo.wFunc = FO_COPY;
238     shfo.pFrom = from;
239     shfo.pTo = to;
240     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
241     shfo.hNameMappings = NULL;
242     shfo.lpszProgressTitle = NULL;
243
244     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
245     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
246     ok(SHFileOperationA(&shfo), "Can't copy many files\n");
247     ok(!file_exists(".\\test6.txt"), "The file is not copied - many files are "
248        "specified as a target\n");
249
250     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
251     shfo2.fFlags |= FOF_MULTIDESTFILES;
252
253     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
254     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
255     ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
256     ok(file_exists(".\\test6.txt"), "The file is copied - many files are "
257        "specified as a target\n");
258     DeleteFileA(".\\test6.txt");
259     DeleteFileA(".\\test7.txt");
260     RemoveDirectoryA(".\\test8.txt");
261
262     /* number of sources do not correspond to number of targets */
263     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
264     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
265     ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
266     ok(!file_exists(".\\test6.txt"), "The file is not copied - many files are "
267        "specified as a target\n");
268
269     set_curr_dir_path(from, "test1.txt\0");
270     set_curr_dir_path(to, "test4.txt\0");
271     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are copied recursively\n");
272     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is copied\n");
273
274     set_curr_dir_path(from, "test?.txt\0");
275     set_curr_dir_path(to, "testdir2\0");
276     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
277     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not copied yet\n");
278     ok(!SHFileOperationA(&shfo), "Files and directories are copied to directory\n");
279     ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
280     ok(file_exists(".\\testdir2\\test4.txt"), "The directory is copied\n");
281     ok(file_exists(".\\testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is copied\n");
282     clean_after_shfo_tests();
283
284     init_shfo_tests();
285     shfo.fFlags |= FOF_FILESONLY;
286     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
287     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not copied yet\n");
288     ok(!SHFileOperationA(&shfo), "Files are copied to other directory\n");
289     ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
290     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is copied\n");
291     clean_after_shfo_tests();
292
293     init_shfo_tests();
294     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
295     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
296     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not copied yet\n");
297     ok(!SHFileOperationA(&shfo), "Files are copied to other directory \n");
298     ok(file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
299     ok(file_exists(".\\testdir2\\test2.txt"), "The file is copied\n");
300     clean_after_shfo_tests();
301
302     /* Copying multiple files with one not existing as source, fails the
303        entire operation in Win98/ME/2K/XP, but not in 95/NT */
304     init_shfo_tests();
305     tmp_flags = shfo.fFlags;
306     set_curr_dir_path(from, "test1.txt\0test10.txt\0test2.txt\0");
307     ok(!file_exists(".\\testdir2\\test1.txt"), "The file is not copied yet\n");
308     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not copied yet\n");
309     retval = SHFileOperationA(&shfo);
310     if (!retval)
311       /* Win 95/NT returns success but copies only the files up to the nonexistent source */
312       ok(file_exists(".\\testdir2\\test1.txt"), "The file is not copied\n");
313     else
314     {
315       /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
316       ok(retval == 1026, "Files are copied to other directory\n");
317       ok(!file_exists(".\\testdir2\\test1.txt"), "The file is copied\n");
318     }
319     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is copied\n");
320     shfo.fFlags = tmp_flags;
321 }
322
323 /* tests the FO_MOVE action */
324 void test_move(void)
325 {
326     SHFILEOPSTRUCTA shfo, shfo2;
327     CHAR from[MAX_PATH];
328     CHAR to[MAX_PATH];
329
330     shfo.hwnd = NULL;
331     shfo.wFunc = FO_MOVE;
332     shfo.pFrom = from;
333     shfo.pTo = to;
334     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
335     shfo.hNameMappings = NULL;
336     shfo.lpszProgressTitle = NULL;
337
338     set_curr_dir_path(from, "test1.txt\0");
339     set_curr_dir_path(to, "test4.txt\0");
340     ok(!SHFileOperationA(&shfo), "Prepare test to check how directories are moved recursively\n");
341     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is moved\n");
342
343     set_curr_dir_path(from, "test?.txt\0");
344     set_curr_dir_path(to, "testdir2\0");
345     ok(!file_exists(".\\testdir2\\test2.txt"), "The file is not moved yet\n");
346     ok(!file_exists(".\\testdir2\\test4.txt"), "The directory is not moved yet\n");
347     ok(!SHFileOperationA(&shfo), "Files and directories are moved to directory\n");
348     ok(file_exists(".\\testdir2\\test2.txt"), "The file is moved\n");
349     ok(file_exists(".\\testdir2\\test4.txt"), "The directory is moved\n");
350     ok(file_exists(".\\testdir2\\test4.txt\\test1.txt"), "The file in subdirectory is moved\n");
351
352     clean_after_shfo_tests();
353     init_shfo_tests();
354
355     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
356     shfo2.fFlags |= FOF_MULTIDESTFILES;
357
358     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
359     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
360     ok(!SHFileOperationA(&shfo2), "Move many files\n");
361     ok(file_exists(".\\test6.txt"), "The file is moved - many files are "
362        "specified as a target\n");
363     DeleteFileA(".\\test6.txt");
364     DeleteFileA(".\\test7.txt");
365     RemoveDirectoryA(".\\test8.txt");
366
367     init_shfo_tests();
368
369     /* number of sources do not correspond to number of targets */
370     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
371     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
372     ok(SHFileOperationA(&shfo2), "Can't move many files\n");
373     ok(!file_exists(".\\test6.txt"), "The file is not moved - many files are "
374        "specified as a target\n");
375
376     init_shfo_tests();
377
378     set_curr_dir_path(from, "test3.txt\0");
379     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
380     ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
381     ok(file_exists(".\\test4.txt\\test1.txt"), "The file is moved\n");
382
383     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
384     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
385     ok(SHFileOperationA(&shfo), "Can not move many files\n");
386     ok(file_exists(".\\test1.txt"), "The file is not moved. Many files are specified\n");
387     ok(file_exists(".\\test4.txt"), "The directory is not moved. Many files are specified\n");
388
389     set_curr_dir_path(from, "test1.txt\0");
390     set_curr_dir_path(to, "test6.txt\0");
391     ok(!SHFileOperationA(&shfo), "Move file\n");
392     ok(!file_exists(".\\test1.txt"), "The file is moved\n");
393     ok(file_exists(".\\test6.txt"), "The file is moved\n");
394     set_curr_dir_path(from, "test6.txt\0");
395     set_curr_dir_path(to, "test1.txt\0");
396     ok(!SHFileOperationA(&shfo), "Move file back\n");
397
398     set_curr_dir_path(from, "test4.txt\0");
399     set_curr_dir_path(to, "test6.txt\0");
400     ok(!SHFileOperationA(&shfo), "Move dir\n");
401     ok(!file_exists(".\\test4.txt"), "The dir is moved\n");
402     ok(file_exists(".\\test6.txt"), "The dir is moved\n");
403     set_curr_dir_path(from, "test6.txt\0");
404     set_curr_dir_path(to, "test4.txt\0");
405     ok(!SHFileOperationA(&shfo), "Move dir back\n");
406 }
407
408 void test_sh_create_dir()
409 {
410     CHAR path[MAX_PATH];
411     int ret;
412
413     if(!pSHCreateDirectoryExA)
414     {
415         trace("skipping SHCreateDirectoryExA tests\n");
416         return;
417     }
418
419     set_curr_dir_path(path, "testdir2\\test4.txt\0");
420     ret = pSHCreateDirectoryExA(NULL, path, NULL);
421     ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory recursively, ret = %d\n", ret);
422     ok(file_exists(".\\testdir2"), "The first directory is not created\n");
423     ok(file_exists(".\\testdir2\\test4.txt"), "The second directory is not created\n");
424
425     ret = pSHCreateDirectoryExA(NULL, path, NULL);
426     ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
427 }
428
429 START_TEST(shlfileop)
430 {
431     InitFunctionPointers();
432
433     clean_after_shfo_tests();
434
435     init_shfo_tests();
436     test_delete();
437     clean_after_shfo_tests();
438
439     init_shfo_tests();
440     test_rename();
441     clean_after_shfo_tests();
442
443     init_shfo_tests();
444     test_copy();
445     clean_after_shfo_tests();
446
447     init_shfo_tests();
448     test_move();
449     clean_after_shfo_tests();
450
451     test_sh_create_dir();
452     clean_after_shfo_tests();
453 }