1 /*
2  * Unit tests for disk space functions
3  *
4  * Copyright 2010 Andrew Nguyen
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 #include <stdio.h>
23 
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "setupapi.h"
30 
31 #include "wine/test.h"
32 
33 static BOOL is_win9x;
34 
35 #define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n"
36 
debugstr_longlong(ULONGLONG ll)37 static inline const char* debugstr_longlong(ULONGLONG ll)
38 {
39     static char string[17];
40     if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
41         sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
42     else
43         sprintf(string, "%lx", (unsigned long)ll);
44     return string;
45 }
46 
47 /* create a new file with specified contents and open it */
inf_open_file_content(const char * tmpfilename,const char * data,UINT * err_line)48 static HINF inf_open_file_content(const char * tmpfilename, const char *data, UINT *err_line)
49 {
50     DWORD res;
51     HANDLE handle = CreateFileA(tmpfilename, GENERIC_READ|GENERIC_WRITE,
52                                 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
53     if (handle == INVALID_HANDLE_VALUE) return 0;
54     if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
55     CloseHandle( handle );
56     return SetupOpenInfFileA( tmpfilename, 0, INF_STYLE_WIN4, err_line );
57 }
58 
test_SetupCreateDiskSpaceListA(void)59 static void test_SetupCreateDiskSpaceListA(void)
60 {
61     HDSKSPC ret;
62 
63     ret = SetupCreateDiskSpaceListA(NULL, 0, 0);
64     ok(ret != NULL,
65        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
66 
67     ok(SetupDestroyDiskSpaceList(ret), "Expected SetupDestroyDiskSpaceList to succeed\n");
68 
69     ret = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
70     ok(ret != NULL,
71        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
72 
73     ok(SetupDestroyDiskSpaceList(ret), "Expected SetupDestroyDiskSpaceList to succeed\n");
74 
75     SetLastError(0xdeadbeef);
76     ret = SetupCreateDiskSpaceListA(NULL, 0, ~0U);
77     ok(ret == NULL ||
78        broken(ret != NULL), /* NT4/Win9x/Win2k */
79        "Expected SetupCreateDiskSpaceListA to return NULL, got %p\n", ret);
80     if (!ret)
81         ok(GetLastError() == ERROR_INVALID_PARAMETER,
82            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
83            GetLastError());
84     else
85         ok(SetupDestroyDiskSpaceList(ret), "Expected SetupDestroyDiskSpaceList to succeed\n");
86 
87     SetLastError(0xdeadbeef);
88     ret = SetupCreateDiskSpaceListA(NULL, 0xdeadbeef, 0);
89     ok(ret == NULL,
90        "Expected SetupCreateDiskSpaceListA to return NULL, got %p\n", ret);
91     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
92        broken(GetLastError() == 0xdeadbeef), /* NT4/Win9x/Win2k */
93        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
94        GetLastError());
95 
96     SetLastError(0xdeadbeef);
97     ret = SetupCreateDiskSpaceListA((void *)0xdeadbeef, 0, 0);
98     ok(ret == NULL,
99        "Expected SetupCreateDiskSpaceListA to return NULL, got %p\n", ret);
100     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
101        broken(GetLastError() == 0xdeadbeef), /* NT4/Win9x/Win2k */
102        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
103        GetLastError());
104 
105     SetLastError(0xdeadbeef);
106     ret = SetupCreateDiskSpaceListA((void *)0xdeadbeef, 0xdeadbeef, 0);
107     ok(ret == NULL,
108        "Expected SetupCreateDiskSpaceListA to return NULL, got %p\n", ret);
109     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
110        broken(GetLastError() == 0xdeadbeef), /* NT4/Win9x/Win2k */
111        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
112        GetLastError());
113 }
114 
test_SetupCreateDiskSpaceListW(void)115 static void test_SetupCreateDiskSpaceListW(void)
116 {
117     HDSKSPC ret;
118 
119     ret = SetupCreateDiskSpaceListW(NULL, 0, 0);
120     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
121     {
122         win_skip("SetupCreateDiskSpaceListW is not implemented\n");
123         return;
124     }
125     ok(ret != NULL,
126        "Expected SetupCreateDiskSpaceListW to return a valid handle, got NULL\n");
127 
128     ok(SetupDestroyDiskSpaceList(ret), "Expected SetupDestroyDiskSpaceList to succeed\n");
129 
130     ret = SetupCreateDiskSpaceListW(NULL, 0, SPDSL_IGNORE_DISK);
131     ok(ret != NULL,
132        "Expected SetupCreateDiskSpaceListW to return a valid handle, got NULL\n");
133 
134     ok(SetupDestroyDiskSpaceList(ret), "Expected SetupDestroyDiskSpaceList to succeed\n");
135 
136     SetLastError(0xdeadbeef);
137     ret = SetupCreateDiskSpaceListW(NULL, 0, ~0U);
138     ok(ret == NULL ||
139        broken(ret != NULL), /* NT4/Win2k */
140        "Expected SetupCreateDiskSpaceListW to return NULL, got %p\n", ret);
141     if (!ret)
142         ok(GetLastError() == ERROR_INVALID_PARAMETER,
143            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
144            GetLastError());
145     else
146         ok(SetupDestroyDiskSpaceList(ret), "Expected SetupDestroyDiskSpaceList to succeed\n");
147 
148     SetLastError(0xdeadbeef);
149     ret = SetupCreateDiskSpaceListW(NULL, 0xdeadbeef, 0);
150     ok(ret == NULL,
151        "Expected SetupCreateDiskSpaceListW to return NULL, got %p\n", ret);
152     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
153        broken(GetLastError() == 0xdeadbeef), /* NT4/Win2k */
154        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
155        GetLastError());
156 
157     SetLastError(0xdeadbeef);
158     ret = SetupCreateDiskSpaceListW((void *)0xdeadbeef, 0, 0);
159     ok(ret == NULL,
160        "Expected SetupCreateDiskSpaceListW to return NULL, got %p\n", ret);
161     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
162        broken(GetLastError() == 0xdeadbeef), /* NT4/Win2k */
163        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
164        GetLastError());
165 
166     SetLastError(0xdeadbeef);
167     ret = SetupCreateDiskSpaceListW((void *)0xdeadbeef, 0xdeadbeef, 0);
168     ok(ret == NULL,
169        "Expected SetupCreateDiskSpaceListW to return NULL, got %p\n", ret);
170     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
171        broken(GetLastError() == 0xdeadbeef), /* NT4/Win2k */
172        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
173        GetLastError());
174 }
175 
test_SetupDuplicateDiskSpaceListA(void)176 static void test_SetupDuplicateDiskSpaceListA(void)
177 {
178     HDSKSPC handle, duplicate;
179 
180     if (is_win9x)
181         win_skip("SetupDuplicateDiskSpaceListA crashes with NULL disk space handle on Win9x\n");
182     else
183     {
184         SetLastError(0xdeadbeef);
185         duplicate = SetupDuplicateDiskSpaceListA(NULL, NULL, 0, 0);
186         ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
187         ok(GetLastError() == ERROR_INVALID_HANDLE,
188            "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n", GetLastError());
189 
190         SetLastError(0xdeadbeef);
191         duplicate = SetupDuplicateDiskSpaceListA(NULL, (void *)0xdeadbeef, 0, 0);
192         ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
193         ok(GetLastError() == ERROR_INVALID_PARAMETER,
194            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
195 
196         SetLastError(0xdeadbeef);
197         duplicate = SetupDuplicateDiskSpaceListA(NULL, NULL, 0xdeadbeef, 0);
198         ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
199         ok(GetLastError() == ERROR_INVALID_PARAMETER,
200            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
201 
202         SetLastError(0xdeadbeef);
203         duplicate = SetupDuplicateDiskSpaceListA(NULL, NULL, 0, ~0U);
204         ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
205         ok(GetLastError() == ERROR_INVALID_PARAMETER,
206            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
207     }
208 
209     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
210     ok(handle != NULL,
211        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
212 
213     if (!handle)
214     {
215         skip("Failed to create a disk space handle\n");
216         return;
217     }
218 
219     SetLastError(0xdeadbeef);
220     duplicate = SetupDuplicateDiskSpaceListA(handle, (void *)0xdeadbeef, 0, 0);
221     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
222     ok(GetLastError() == ERROR_INVALID_PARAMETER,
223        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
224 
225     SetLastError(0xdeadbeef);
226     duplicate = SetupDuplicateDiskSpaceListA(handle, NULL, 0xdeadbeef, 0);
227     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
228     ok(GetLastError() == ERROR_INVALID_PARAMETER,
229        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
230 
231     SetLastError(0xdeadbeef);
232     duplicate = SetupDuplicateDiskSpaceListA(handle, NULL, 0, SPDSL_IGNORE_DISK);
233     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
234     ok(GetLastError() == ERROR_INVALID_PARAMETER,
235        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
236 
237     SetLastError(0xdeadbeef);
238     duplicate = SetupDuplicateDiskSpaceListA(handle, NULL, 0, ~0U);
239     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
240     ok(GetLastError() == ERROR_INVALID_PARAMETER,
241        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
242 
243     duplicate = SetupDuplicateDiskSpaceListA(handle, NULL, 0, 0);
244     ok(duplicate != NULL, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
245     ok(duplicate != handle,
246        "Expected new handle (%p) to be different from the old handle (%p)\n", duplicate, handle);
247 
248     ok(SetupDestroyDiskSpaceList(duplicate), "Expected SetupDestroyDiskSpaceList to succeed\n");
249     ok(SetupDestroyDiskSpaceList(handle), "Expected SetupDestroyDiskSpaceList to succeed\n");
250 }
251 
test_SetupDuplicateDiskSpaceListW(void)252 static void test_SetupDuplicateDiskSpaceListW(void)
253 {
254     HDSKSPC handle, duplicate;
255 
256     SetLastError(0xdeadbeef);
257     duplicate = SetupDuplicateDiskSpaceListW(NULL, NULL, 0, 0);
258     if (!duplicate && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
259     {
260         win_skip("SetupDuplicateDiskSpaceListW is not available\n");
261         return;
262     }
263     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
264     ok(GetLastError() == ERROR_INVALID_HANDLE,
265        "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n", GetLastError());
266 
267     SetLastError(0xdeadbeef);
268     duplicate = SetupDuplicateDiskSpaceListW(NULL, (void *)0xdeadbeef, 0, 0);
269     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
270     ok(GetLastError() == ERROR_INVALID_PARAMETER,
271        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
272 
273     SetLastError(0xdeadbeef);
274     duplicate = SetupDuplicateDiskSpaceListW(NULL, NULL, 0xdeadbeef, 0);
275     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
276     ok(GetLastError() == ERROR_INVALID_PARAMETER,
277        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
278 
279     SetLastError(0xdeadbeef);
280     duplicate = SetupDuplicateDiskSpaceListW(NULL, NULL, 0, ~0U);
281     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
282     ok(GetLastError() == ERROR_INVALID_PARAMETER,
283        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
284 
285     handle = SetupCreateDiskSpaceListW(NULL, 0, 0);
286     ok(handle != NULL,
287        "Expected SetupCreateDiskSpaceListW to return a valid handle, got NULL\n");
288 
289     if (!handle)
290     {
291         skip("Failed to create a disk space handle\n");
292         return;
293     }
294 
295     SetLastError(0xdeadbeef);
296     duplicate = SetupDuplicateDiskSpaceListW(handle, (void *)0xdeadbeef, 0, 0);
297     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
298     ok(GetLastError() == ERROR_INVALID_PARAMETER,
299        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
300 
301     SetLastError(0xdeadbeef);
302     duplicate = SetupDuplicateDiskSpaceListW(handle, NULL, 0xdeadbeef, 0);
303     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
304     ok(GetLastError() == ERROR_INVALID_PARAMETER,
305        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
306 
307     SetLastError(0xdeadbeef);
308     duplicate = SetupDuplicateDiskSpaceListW(handle, NULL, 0, SPDSL_IGNORE_DISK);
309     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
310     ok(GetLastError() == ERROR_INVALID_PARAMETER,
311        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
312 
313     SetLastError(0xdeadbeef);
314     duplicate = SetupDuplicateDiskSpaceListW(handle, NULL, 0, ~0U);
315     ok(!duplicate, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
316     ok(GetLastError() == ERROR_INVALID_PARAMETER,
317        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
318 
319     duplicate = SetupDuplicateDiskSpaceListW(handle, NULL, 0, 0);
320     ok(duplicate != NULL, "Expected SetupDuplicateDiskSpaceList to return NULL, got %p\n", duplicate);
321     ok(duplicate != handle,
322        "Expected new handle (%p) to be different from the old handle (%p)\n", duplicate, handle);
323 
324     ok(SetupDestroyDiskSpaceList(duplicate), "Expected SetupDestroyDiskSpaceList to succeed\n");
325     ok(SetupDestroyDiskSpaceList(handle), "Expected SetupDestroyDiskSpaceList to succeed\n");
326 }
327 
get_file_size(char * path)328 static LONGLONG get_file_size(char *path)
329 {
330     HANDLE file;
331     LARGE_INTEGER size;
332 
333     file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
334                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
335     if (file == INVALID_HANDLE_VALUE) return 0;
336 
337     if (!GetFileSizeEx(file, &size))
338         size.QuadPart = 0;
339 
340     CloseHandle(file);
341     return size.QuadPart;
342 }
343 
test_SetupQuerySpaceRequiredOnDriveA(void)344 static void test_SetupQuerySpaceRequiredOnDriveA(void)
345 {
346     BOOL ret;
347     HDSKSPC handle;
348     LONGLONG space;
349     char windir[MAX_PATH];
350     char drive[3];
351     char tmp[MAX_PATH];
352     LONGLONG size;
353 
354     if (is_win9x)
355         win_skip("SetupQuerySpaceRequiredOnDriveA crashes with NULL disk space handle on Win9x\n");
356     else
357     {
358         SetLastError(0xdeadbeef);
359         ret = SetupQuerySpaceRequiredOnDriveA(NULL, NULL, NULL, NULL, 0);
360         ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
361         ok(GetLastError() == ERROR_INVALID_PARAMETER,
362            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
363            GetLastError());
364 
365         SetLastError(0xdeadbeef);
366         space = 0xdeadbeef;
367         ret = SetupQuerySpaceRequiredOnDriveA(NULL, NULL, &space, NULL, 0);
368         ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
369         ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
370         ok(GetLastError() == ERROR_INVALID_PARAMETER,
371            "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
372            GetLastError());
373 
374         SetLastError(0xdeadbeef);
375         ret = SetupQuerySpaceRequiredOnDriveA(NULL, "", NULL, NULL, 0);
376         ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
377         ok(GetLastError() == ERROR_INVALID_HANDLE,
378            "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n",
379            GetLastError());
380 
381         SetLastError(0xdeadbeef);
382         space = 0xdeadbeef;
383         ret = SetupQuerySpaceRequiredOnDriveA(NULL, "", &space, NULL, 0);
384         ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
385         ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
386         ok(GetLastError() == ERROR_INVALID_HANDLE,
387            "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n",
388            GetLastError());
389     }
390 
391     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
392     ok(handle != NULL,
393        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
394 
395     SetLastError(0xdeadbeef);
396     ret = SetupQuerySpaceRequiredOnDriveA(handle, NULL, NULL, NULL, 0);
397     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
398     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
399        GetLastError() == ERROR_INVALID_DRIVE, /* Win9x */
400        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
401        GetLastError());
402 
403     SetLastError(0xdeadbeef);
404     space = 0xdeadbeef;
405     ret = SetupQuerySpaceRequiredOnDriveA(handle, NULL, &space, NULL, 0);
406     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
407     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
408     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
409        GetLastError() == ERROR_INVALID_DRIVE, /* Win9x */
410        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
411        GetLastError());
412 
413     SetLastError(0xdeadbeef);
414     ret = SetupQuerySpaceRequiredOnDriveA(handle, "", NULL, NULL, 0);
415     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
416     ok(GetLastError() == ERROR_INVALID_DRIVE,
417        "Expected GetLastError() to return ERROR_INVALID_DRIVE, got %u\n",
418        GetLastError());
419 
420     SetLastError(0xdeadbeef);
421     space = 0xdeadbeef;
422     ret = SetupQuerySpaceRequiredOnDriveA(handle, "", &space, NULL, 0);
423     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
424     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
425     ok(GetLastError() == ERROR_INVALID_DRIVE,
426        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
427        GetLastError());
428 
429     GetWindowsDirectoryA(windir, MAX_PATH);
430     drive[0] = windir[0]; drive[1] = windir[1]; drive[2] = 0;
431 
432     snprintf(tmp, MAX_PATH, "%c:\\wine-test-should-not-exist.txt", drive[0]);
433     ret = SetupAddToDiskSpaceListA(handle, tmp, 0x100000, FILEOP_COPY, 0, 0);
434     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
435 
436     space = 0;
437     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
438     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
439     ok(space == 0x100000, "Expected 0x100000 as required space, got %s\n", debugstr_longlong(space));
440 
441     /* adding the same file again doesn't sum up the size */
442     ret = SetupAddToDiskSpaceListA(handle, tmp, 0x200000, FILEOP_COPY, 0, 0);
443     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
444 
445     space = 0;
446     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
447     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
448     ok(space == 0x200000, "Expected 0x200000 as required space, got %s\n", debugstr_longlong(space));
449 
450     /* the device doesn't need to exist */
451     snprintf(tmp, MAX_PATH, "F:\\wine-test-should-not-exist.txt");
452     ret = SetupAddToDiskSpaceListA(handle, tmp, 0x200000, FILEOP_COPY, 0, 0);
453     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
454 
455     ret = SetupQuerySpaceRequiredOnDriveA(handle, "F:", &space, NULL, 0);
456     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
457     ok(space == 0x200000, "Expected 0x200000 as required space, got %s\n", debugstr_longlong(space));
458 
459     snprintf(tmp, MAX_PATH, "F:\\wine-test-should-not-exist.txt");
460     ret = SetupAddToDiskSpaceListA(handle, tmp, 0x200000, FILEOP_DELETE, 0, 0);
461     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
462 
463     ret = SetupQuerySpaceRequiredOnDriveA(handle, "F:", &space, NULL, 0);
464     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
465     ok(space == 0x200000, "Expected 0x200000 as required space, got %s\n", debugstr_longlong(space));
466 
467     ok(SetupDestroyDiskSpaceList(handle),
468        "Expected SetupDestroyDiskSpaceList to succeed\n");
469 
470     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
471     ok(handle != NULL,
472        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
473 
474     /* the real size is subtracted unless SPDSL_IGNORE_DISK is specified */
475     snprintf(tmp, MAX_PATH, "%s\\regedit.exe", windir);
476 
477     size = get_file_size(tmp);
478     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0);
479     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
480     space = 0;
481     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
482     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
483     ok(space == 0 || broken(space == -0x5000) || broken(space == -0x7000),
484        "Expected 0x0 as required space, got %s\n", debugstr_longlong(space));
485 
486     ret = SetupAddToDiskSpaceListA(handle, tmp, size + 0x100000, FILEOP_COPY, 0, 0);
487     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
488     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
489     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
490     ok(space == 0x100000 || broken(space == 0xf9000) || broken(space == 0xfb000),
491        "Expected 0x100000 as required space, got %s\n", debugstr_longlong(space));
492 
493     ret = SetupAddToDiskSpaceListA(handle, tmp, size - 0x1000, FILEOP_COPY, 0, 0);
494     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
495     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
496     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
497     ok(space == -0x1000 || broken(space == -0x6000) || broken(space == -0x8000),
498        "Expected -0x1000 as required space, got %s\n", debugstr_longlong(space));
499 
500     ok(SetupDestroyDiskSpaceList(handle),
501        "Expected SetupDestroyDiskSpaceList to succeed\n");
502 
503     /* test FILEOP_DELETE, then FILEOP_COPY */
504     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
505     ok(handle != NULL,
506        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
507 
508     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0);
509     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
510     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0);
511     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
512 
513     space = 0;
514     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
515     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
516     ok(space == 0 || broken(space == -0x5000) || broken(space == -0x7000),
517        "Expected 0x0 as required space, got %s\n", debugstr_longlong(space));
518 
519     ok(SetupDestroyDiskSpaceList(handle),
520        "Expected SetupDestroyDiskSpaceList to succeed\n");
521 
522     /* test FILEOP_COPY, then FILEOP_DELETE */
523     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
524     ok(handle != NULL,
525        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
526 
527     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0);
528     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
529     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0);
530     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
531 
532     space = 0;
533     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
534     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
535     ok(space == 0 || broken(space == -0x5000) || broken(space == -0x7000),
536        "Expected 0x0 as required space, got %s\n", debugstr_longlong(space));
537 
538     ok(SetupDestroyDiskSpaceList(handle),
539        "Expected SetupDestroyDiskSpaceList to succeed\n");
540 
541     /* test FILEOP_DELETE without SPDSL_IGNORE_DISK */
542     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
543     ok(handle != NULL,
544        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
545 
546     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0);
547     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
548     space = 0;
549     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
550     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
551     ok(space <= -size, "Expected space <= -size, got %s\n", debugstr_longlong(space));
552 
553     ok(SetupDestroyDiskSpaceList(handle),
554        "Expected SetupDestroyDiskSpaceList to succeed\n");
555 
556     /* test FILEOP_COPY and FILEOP_DELETE with SPDSL_IGNORE_DISK */
557     handle = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
558     ok(handle != NULL,
559        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
560 
561     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0);
562     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
563     space = 0;
564     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
565     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
566     ok(space == 0, "Expected size = 0, got %s\n", debugstr_longlong(space));
567 
568     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0);
569     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
570     ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0);
571     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
572 
573     space = 0;
574     ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0);
575     ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n");
576     ok(space >= size, "Expected size >= %s\n", debugstr_longlong(space));
577 
578     ok(SetupDestroyDiskSpaceList(handle),
579        "Expected SetupDestroyDiskSpaceList to succeed\n");
580 }
581 
test_SetupQuerySpaceRequiredOnDriveW(void)582 static void test_SetupQuerySpaceRequiredOnDriveW(void)
583 {
584     static const WCHAR emptyW[] = {0};
585 
586     BOOL ret;
587     HDSKSPC handle;
588     LONGLONG space;
589 
590     SetLastError(0xdeadbeef);
591     ret = SetupQuerySpaceRequiredOnDriveW(NULL, NULL, NULL, NULL, 0);
592     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
593     {
594         win_skip("SetupQuerySpaceRequiredOnDriveW is not available\n");
595         return;
596     }
597     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
598     ok(GetLastError() == ERROR_INVALID_HANDLE,
599        "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n",
600        GetLastError());
601 
602     SetLastError(0xdeadbeef);
603     space = 0xdeadbeef;
604     ret = SetupQuerySpaceRequiredOnDriveW(NULL, NULL, &space, NULL, 0);
605     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
606     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
607     ok(GetLastError() == ERROR_INVALID_HANDLE,
608        "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n",
609        GetLastError());
610 
611     SetLastError(0xdeadbeef);
612     ret = SetupQuerySpaceRequiredOnDriveW(NULL, emptyW, NULL, NULL, 0);
613     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
614     ok(GetLastError() == ERROR_INVALID_HANDLE,
615        "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n",
616        GetLastError());
617 
618     SetLastError(0xdeadbeef);
619     space = 0xdeadbeef;
620     ret = SetupQuerySpaceRequiredOnDriveW(NULL, emptyW, &space, NULL, 0);
621     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
622     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
623     ok(GetLastError() == ERROR_INVALID_HANDLE,
624        "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n",
625        GetLastError());
626 
627     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
628     ok(handle != NULL,
629        "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n");
630 
631     SetLastError(0xdeadbeef);
632     ret = SetupQuerySpaceRequiredOnDriveW(handle, NULL, NULL, NULL, 0);
633     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
634     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
635        GetLastError() == ERROR_INVALID_DRIVE, /* NT4/Win2k/XP/Win2k3 */
636        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
637        GetLastError());
638 
639     SetLastError(0xdeadbeef);
640     space = 0xdeadbeef;
641     ret = SetupQuerySpaceRequiredOnDriveW(handle, NULL, &space, NULL, 0);
642     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
643     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
644     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
645        GetLastError() == ERROR_INVALID_DRIVE, /* NT4/Win2k/XP/Win2k3 */
646        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
647        GetLastError());
648 
649     SetLastError(0xdeadbeef);
650     ret = SetupQuerySpaceRequiredOnDriveW(handle, emptyW, NULL, NULL, 0);
651     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
652     ok(GetLastError() == ERROR_INVALID_DRIVE,
653        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
654        GetLastError());
655 
656     SetLastError(0xdeadbeef);
657     space = 0xdeadbeef;
658     ret = SetupQuerySpaceRequiredOnDriveW(handle, emptyW, &space, NULL, 0);
659     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveW to return FALSE, got %d\n", ret);
660     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
661     ok(GetLastError() == ERROR_INVALID_DRIVE,
662        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
663        GetLastError());
664 
665     ok(SetupDestroyDiskSpaceList(handle),
666        "Expected SetupDestroyDiskSpaceList to succeed\n");
667 }
668 
test_SetupAddToDiskSpaceListA(void)669 static void test_SetupAddToDiskSpaceListA(void)
670 {
671     HDSKSPC handle;
672     BOOL ret;
673 
674     ret = SetupAddToDiskSpaceListA(NULL, "C:\\some-file.dat", 0, FILEOP_COPY, 0, 0);
675     ok(!ret, "Expected SetupAddToDiskSpaceListA to return FALSE, got %d\n", ret);
676     ok(GetLastError() == ERROR_INVALID_HANDLE,
677        "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n", GetLastError());
678 
679     handle = SetupCreateDiskSpaceListA(NULL, 0, 0);
680     ok(handle != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
681 
682     ret = SetupAddToDiskSpaceListA(handle, NULL, 0, FILEOP_COPY, 0, 0);
683     ok(ret || broken(!ret) /* >= Vista */, "Expected SetupAddToDiskSpaceListA to succeed\n");
684 
685     ret = SetupAddToDiskSpaceListA(handle, "C:\\some-file.dat", -20, FILEOP_COPY, 0, 0);
686     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
687 
688     ret = SetupAddToDiskSpaceListA(handle, "C:\\some-file.dat", 0, FILEOP_RENAME, 0, 0);
689     ok(!ret, "Expected SetupAddToDiskSpaceListA to return FALSE\n");
690     ok(GetLastError() == ERROR_INVALID_PARAMETER,
691        "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
692 
693     ret = SetupAddToDiskSpaceListA(handle, NULL, 0, FILEOP_RENAME, 0, 0);
694     ok(ret || broken(!ret) /* >= Vista */, "Expected SetupAddToDiskSpaceListA to succeed\n");
695 
696     ret = SetupAddToDiskSpaceListA(NULL, NULL, 0, FILEOP_RENAME, 0, 0);
697     ok(ret || broken(!ret) /* >= Vista */, "Expected SetupAddToDiskSpaceListA to succeed\n");
698 
699     ok(SetupDestroyDiskSpaceList(handle),
700        "Expected SetupDestroyDiskSpaceList to succeed\n");
701 }
702 
test_SetupQueryDrivesInDiskSpaceListA(void)703 static void test_SetupQueryDrivesInDiskSpaceListA(void)
704 {
705     char buffer[MAX_PATH];
706     HDSKSPC handle;
707     DWORD size;
708     BOOL ret;
709 
710     handle = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
711     ok(handle != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
712 
713     ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, NULL);
714     ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n");
715 
716     size = 0;
717     ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, &size);
718     ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n");
719     ok(size == 1, "Expected size 1, got %u\n", size);
720 
721     ret = SetupAddToDiskSpaceListA(handle, "F:\\random-file.dat", 0, FILEOP_COPY, 0, 0);
722     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
723 
724     ret = SetupAddToDiskSpaceListA(handle, "G:\\random-file.dat", 0, FILEOP_COPY, 0, 0);
725     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
726 
727     ret = SetupAddToDiskSpaceListA(handle, "G:\\random-file2.dat", 0, FILEOP_COPY, 0, 0);
728     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
729 
730     ret = SetupAddToDiskSpaceListA(handle, "X:\\random-file.dat", 0, FILEOP_COPY, 0, 0);
731     ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n");
732 
733     size = 0;
734     ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, &size);
735     ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n");
736     ok(size == 10, "Expected size 10, got %u\n", size);
737 
738     size = 0;
739     ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 0, &size);
740     ok(!ret, "Expected SetupQueryDrivesInDiskSpaceListA to fail\n");
741     ok(size == 4, "Expected size 4, got %u\n", size);
742     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
743        "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
744 
745     size = 0;
746     ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 4, &size);
747     ok(!ret, "Expected SetupQueryDrivesInDiskSpaceListA to fail\n");
748     ok(size == 7, "Expected size 7, got %u\n", size);
749     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
750        "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
751 
752     size = 0;
753     ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 7, &size);
754     ok(!ret, "Expected SetupQueryDrivesInDiskSpaceListA to fail\n");
755     ok(size == 10, "Expected size 10, got %u\n", size);
756     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
757        "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
758 
759     size = 0;
760     memset(buffer, 0xff, sizeof(buffer));
761     ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, sizeof(buffer), &size);
762     ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n");
763     ok(size == 10, "Expected size 10, got %u\n", size);
764     ok(!memcmp("f:\0g:\0x:\0\0", buffer, 10), "Device list does not match\n");
765 
766     memset(buffer, 0xff, sizeof(buffer));
767     ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, sizeof(buffer), NULL);
768     ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n");
769     ok(!memcmp("f:\0g:\0x:\0\0", buffer, 10), "Device list does not match\n");
770 
771     ok(SetupDestroyDiskSpaceList(handle),
772        "Expected SetupDestroyDiskSpaceList to succeed\n");
773 }
774 
775 struct device_usage
776 {
777     const char *dev;
778     LONGLONG usage;
779 };
780 
781 struct section
782 {
783     const char *name;
784     UINT fileop;
785     BOOL result;
786     DWORD error_code;
787 };
788 
789 static const struct
790 {
791     const char *data;
792     struct section sections[2];
793     const char *devices;
794     int device_length;
795     struct device_usage usage[2];
796 }
797 section_test[] =
798 {
799     /* 0 */
800     {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
801      {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
802      "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
803     /* 1 */
804     {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
805      {{"a", FILEOP_DELETE, TRUE, 0}, {NULL, 0, TRUE, 0}},
806      "c:\00", sizeof("c:\00"), {{"c:", 0}, {NULL, 0}}},
807     /* 2 */
808     {STD_HEADER "[a]\ntest,,,\n\r\n",
809      {{"a", FILEOP_COPY, FALSE, ERROR_LINE_NOT_FOUND}, {NULL, 0, TRUE, 0}},
810      "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
811     /* 3 */
812     {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nDefaultDestDir=-1,F:\\test\r\n",
813      {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
814      "f:\00", sizeof("f:\00"), {{"f:", 4096}, {NULL, 0}}},
815     /* 4 */
816     {STD_HEADER "[a]\ntest,test2,,\n[SourceDisksFiles]\ntest2=1,,4096\r\n",
817      {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
818      "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
819     /* 5 */
820     {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
821      {{"b", FILEOP_COPY, FALSE, ERROR_SECTION_NOT_FOUND}, {NULL, 0, TRUE, 0}},
822      "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
823     /* 6 */
824     {STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
825      {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
826      "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
827     /* 7 */
828     {STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nb=-1,F:\\test\r\n",
829      {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
830      "c:\00f:\00", sizeof("c:\00f:\00"), {{"c:", 4096}, {"f:", 4096}}},
831     /* 8 */
832     {STD_HEADER "[a]\ntest,test1,,\n[b]\ntest,test2,,\n[SourceDisksFiles]\ntest1=1,,4096\ntest2=1,,8192\r\n",
833      {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
834      "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
835     /* 9 */
836     {STD_HEADER "[a]\ntest1,test,,\n[b]\ntest2,test,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
837      {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
838      "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
839 };
840 
test_SetupAddSectionToDiskSpaceListA(void)841 static void test_SetupAddSectionToDiskSpaceListA(void)
842 {
843     char tmp[MAX_PATH];
844     char tmpfilename[MAX_PATH];
845     char buffer[MAX_PATH];
846     HDSKSPC diskspace;
847     UINT err_line;
848     LONGLONG space;
849     BOOL ret;
850     int i, j;
851     HINF inf;
852 
853     if (!GetTempPathA(MAX_PATH, tmp))
854     {
855         win_skip("GetTempPath failed with error %d\n", GetLastError());
856         return;
857     }
858 
859     if (!GetTempFileNameA(tmp, "inftest", 0, tmpfilename))
860     {
861         win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
862         return;
863     }
864 
865     inf = inf_open_file_content(tmpfilename, STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", &err_line);
866     ok(!!inf, "Failed to open inf file (%d, line %d)\n", GetLastError(), err_line);
867 
868     diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
869     ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
870 
871     ret = SetupAddSectionToDiskSpaceListA(diskspace, NULL, NULL, "a", FILEOP_COPY, 0, 0);
872     ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
873     ok(GetLastError() == ERROR_SECTION_NOT_FOUND, "Expected ERROR_SECTION_NOT_FOUND as error, got %u\n",
874        GetLastError());
875 
876     ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "a", FILEOP_COPY, 0, 0);
877     ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
878     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %u\n",
879        GetLastError());
880 
881     ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "b", FILEOP_COPY, 0, 0);
882     ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
883     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %u\n",
884        GetLastError());
885 
886     ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, "a", 0, 0, 0);
887     ok(ret, "Expected SetupAddSectionToDiskSpaceListA to succeed (%u)\n", GetLastError());
888 
889     ok(SetupDestroyDiskSpaceList(diskspace),
890        "Expected SetupDestroyDiskSpaceList to succeed\n");
891 
892     for (i = 0; i < sizeof(section_test) / sizeof(section_test[0]); i++)
893     {
894         err_line = 0;
895 
896         inf = inf_open_file_content(tmpfilename, section_test[i].data, &err_line);
897         ok(!!inf, "test %d: Failed to open inf file (%d, line %d)\n", i, GetLastError(), err_line);
898         if (!inf) continue;
899 
900         diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
901         ok(diskspace != NULL, "Expected SetupCreateDiskSpaceListA to return a valid handle\n");
902 
903         for (j = 0; j < 2; j++)
904         {
905             const struct section *section = &section_test[i].sections[j];
906             if (!section->name)
907                 continue;
908 
909             SetLastError(0xdeadbeef);
910             ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, section->name, section->fileop, 0, 0);
911             if (section->result)
912                 ok(ret, "test %d: Expected adding section %d to succeed (%u)\n", i, j, GetLastError());
913             else
914             {
915                 ok(!ret, "test %d: Expected adding section %d to fail\n", i, j);
916                 ok(GetLastError() == section->error_code, "test %d: Expected %u as error, got %u\n",
917                    i, section->error_code, GetLastError());
918             }
919         }
920 
921         memset(buffer, 0x0, sizeof(buffer));
922         ret = SetupQueryDrivesInDiskSpaceListA(diskspace, buffer, sizeof(buffer), NULL);
923         ok(ret, "test %d: Expected SetupQueryDrivesInDiskSpaceListA to succeed (%u)\n", i, GetLastError());
924         ok(!memcmp(section_test[i].devices, buffer, section_test[i].device_length),
925            "test %d: Device list (%s) does not match\n", i, buffer);
926 
927         for (j = 0; j < 2; j++)
928         {
929             const struct device_usage *usage = &section_test[i].usage[j];
930             if (!usage->dev)
931                 continue;
932 
933             space = 0;
934             ret = SetupQuerySpaceRequiredOnDriveA(diskspace, usage->dev, &space, NULL, 0);
935             ok(ret, "test %d: Expected SetupQuerySpaceRequiredOnDriveA to succeed for device %s (%u)\n",
936                i, usage->dev, GetLastError());
937             ok(space == usage->usage, "test %d: Expected size %u for device %s, got %u\n",
938                i, (DWORD)usage->usage, usage->dev, (DWORD)space);
939         }
940 
941         ok(SetupDestroyDiskSpaceList(diskspace),
942            "Expected SetupDestroyDiskSpaceList to succeed\n");
943 
944         SetupCloseInfFile(inf);
945     }
946 
947     DeleteFileA(tmpfilename);
948 }
949 
950 struct section_i
951 {
952     const char *name;
953     BOOL result;
954     DWORD error_code;
955 };
956 
957 static const struct
958 {
959     const char *data;
960     struct section_i sections[2];
961     const char *devices;
962     int device_length;
963     struct device_usage usage[2];
964 }
965 section_test_i[] =
966 {
967     /* 0 */
968     {STD_HEADER "[a.Install]\nCopyFiles=a.CopyFiles\n"
969                 "[a.CopyFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
970      {{"a.Install", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
971     /* 1 */
972     {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\n"
973                 "[a.CopyFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
974      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
975     /* 2 */
976     {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\nCopyFiles=a.CopyFiles2\n"
977                 "[a.CopyFiles]\ntest,,,\n[a.CopyFiles2]\ntest2,,,\n"
978                 "[SourceDisksFiles]\ntest=1,,4096\ntest2=1,,4096\r\n",
979      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
980     /* 3 */
981     {STD_HEADER "[a]\nCopyFiles=a.CopyFiles,a.CopyFiles2\n"
982                 "[a.CopyFiles]\ntest,,,\n[a.CopyFiles2]\ntest2,,,\n"
983                 "[SourceDisksFiles]\ntest=1,,4096\ntest2=1,,4096\r\n",
984      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
985     /* 4 */
986     {STD_HEADER "[a]\r\n",
987      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
988     /* 5 */
989     {STD_HEADER "[a]\nDelFiles=a.DelFiles\n"
990                 "[a.nDelFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
991      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
992     /* 6 */
993     {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\nDelFiles=a.DelFiles\n"
994                 "[a.CopyFiles]\ntest,,,\n[a.DelFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
995      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
996     /* 7 */
997     {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\n[b]\nDelFiles=b.DelFiles\n"
998                 "[a.CopyFiles]\ntest,,,\n[b.DelFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
999      {{"a", TRUE, 0}, {"b", TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
1000     /* 7 */
1001     {STD_HEADER "[a]\nCopyFiles=\r\n",
1002      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
1003     /* 8 */
1004     {STD_HEADER "[a]\nCopyFiles=something\r\n",
1005      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
1006     /* 9 */
1007     {STD_HEADER "[a]\nCopyFiles=a.CopyFiles,b.CopyFiles\n[a.CopyFiles]\ntest,,,\n[b.CopyFiles]\ntest,,,\n"
1008                 "[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nb.CopyFiles=-1,F:\\test\r\n",
1009      {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00f:\00", sizeof("c:\00f:\00"), {{"c:", 4096}, {"f:", 4096}}},
1010 };
1011 
test_SetupAddInstallSectionToDiskSpaceListA(void)1012 static void test_SetupAddInstallSectionToDiskSpaceListA(void)
1013 {
1014     char tmp[MAX_PATH];
1015     char tmpfilename[MAX_PATH];
1016     char buffer[MAX_PATH];
1017     HDSKSPC diskspace;
1018     LONGLONG space;
1019     UINT err_line;
1020     BOOL ret;
1021     int i, j;
1022     HINF inf;
1023 
1024     if (!GetTempPathA(MAX_PATH, tmp))
1025     {
1026         win_skip("GetTempPath failed with error %d\n", GetLastError());
1027         return;
1028     }
1029 
1030     if (!GetTempFileNameA(tmp, "inftest", 0, tmpfilename))
1031     {
1032         win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
1033         return;
1034     }
1035 
1036     inf = inf_open_file_content(tmpfilename, STD_HEADER "[a]\nCopyFiles=b\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", &err_line);
1037     ok(!!inf, "Failed to open inf file (%d, line %d)\n", GetLastError(), err_line);
1038 
1039     diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
1040     ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
1041 
1042     ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, NULL, NULL, "a", 0, 0);
1043     ok(ret, "Expected SetupAddInstallSectionToDiskSpaceListA to succeed\n");
1044 
1045     ret = SetupAddInstallSectionToDiskSpaceListA(NULL, inf, NULL, "a", 0, 0);
1046     ok(!ret, "Expected SetupAddInstallSectionToDiskSpaceListA to fail\n");
1047     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %u\n",
1048        GetLastError());
1049 
1050     ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, inf, NULL, NULL, 0, 0);
1051     ok(!ret || broken(ret), "Expected SetupAddSectionToDiskSpaceListA to fail\n");
1052     ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(ret),
1053        "Expected ERROR_INVALID_PARAMETER as error, got %u\n", GetLastError());
1054 
1055     ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, inf, NULL, "", 0, 0);
1056     ok(ret, "Expected SetupAddInstallSectionToDiskSpaceListA to succeed (%u)\n", GetLastError());
1057 
1058     ok(SetupDestroyDiskSpaceList(diskspace),
1059        "Expected SetupDestroyDiskSpaceList to succeed\n");
1060 
1061     for (i = 0; i < sizeof(section_test_i) / sizeof(section_test_i[0]); i++)
1062     {
1063         err_line = 0;
1064 
1065         inf = inf_open_file_content(tmpfilename, section_test_i[i].data, &err_line);
1066         ok(!!inf, "test %d: Failed to open inf file (%d, line %d)\n", i, GetLastError(), err_line);
1067         if (!inf) continue;
1068 
1069         diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
1070         ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
1071 
1072         for (j = 0; j < 2; j++)
1073         {
1074             const struct section_i *section = &section_test_i[i].sections[j];
1075             if (!section->name)
1076                 continue;
1077 
1078             SetLastError(0xdeadbeef);
1079             ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, inf, NULL, section->name, 0, 0);
1080             if (section->result)
1081                 ok(ret, "test %d: Expected adding section %d to succeed (%u)\n", i, j, GetLastError());
1082             else
1083             {
1084                 ok(!ret, "test %d: Expected adding section %d to fail\n", i, j);
1085                 ok(GetLastError() == section->error_code, "test %d: Expected %u as error, got %u\n",
1086                    i, section->error_code, GetLastError());
1087             }
1088         }
1089 
1090         memset(buffer, 0x0, sizeof(buffer));
1091         ret = SetupQueryDrivesInDiskSpaceListA(diskspace, buffer, sizeof(buffer), NULL);
1092         ok(ret, "test %d: Expected SetupQueryDrivesInDiskSpaceListA to succeed (%u)\n", i, GetLastError());
1093         ok(!memcmp(section_test_i[i].devices, buffer, section_test_i[i].device_length),
1094            "test %d: Device list (%s) does not match\n", i, buffer);
1095 
1096         for (j = 0; j < 2; j++)
1097         {
1098             const struct device_usage *usage = &section_test_i[i].usage[j];
1099             if (!usage->dev)
1100                 continue;
1101 
1102             space = 0;
1103             ret = SetupQuerySpaceRequiredOnDriveA(diskspace, usage->dev, &space, NULL, 0);
1104             ok(ret, "test %d: Expected SetupQuerySpaceRequiredOnDriveA to succeed for device %s (%u)\n",
1105                i, usage->dev, GetLastError());
1106             ok(space == usage->usage, "test %d: Expected size %u for device %s, got %u\n",
1107                i, (DWORD)usage->usage, usage->dev, (DWORD)space);
1108         }
1109 
1110         ok(SetupDestroyDiskSpaceList(diskspace),
1111            "Expected SetupDestroyDiskSpaceList to succeed\n");
1112 
1113         SetupCloseInfFile(inf);
1114     }
1115 
1116     DeleteFileA(tmpfilename);
1117 }
1118 
START_TEST(diskspace)1119 START_TEST(diskspace)
1120 {
1121     is_win9x = !SetupCreateDiskSpaceListW((void *)0xdeadbeef, 0xdeadbeef, 0) &&
1122                 GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1123     test_SetupCreateDiskSpaceListA();
1124     test_SetupCreateDiskSpaceListW();
1125     test_SetupDuplicateDiskSpaceListA();
1126     test_SetupDuplicateDiskSpaceListW();
1127     test_SetupQuerySpaceRequiredOnDriveA();
1128     test_SetupQuerySpaceRequiredOnDriveW();
1129     test_SetupAddToDiskSpaceListA();
1130     test_SetupQueryDrivesInDiskSpaceListA();
1131     test_SetupAddSectionToDiskSpaceListA();
1132     test_SetupAddInstallSectionToDiskSpaceListA();
1133 }
1134