setupapi/tests: Add tests to show that SetupIterateCabinet handles callback exception...
[wine] / dlls / setupapi / tests / misc.c
1 /*
2  * Miscellaneous tests
3  *
4  * Copyright 2007 James Hawkins
5  * Copyright 2007 Hans Leidekker
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "setupapi.h"
32
33 #include "wine/test.h"
34
35 static CHAR CURR_DIR[MAX_PATH];
36
37 /* test:
38  *  - fails if not administrator
39  *  - what if it's not a .inf file?
40  *  - copied to %windir%/Inf
41  *  - SourceInfFileName should be a full path
42  *  - SourceInfFileName should be <= MAX_PATH
43  *  - copy styles
44  */
45
46 static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT);
47 static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *);
48 static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A);
49 static BOOL (WINAPI *pSetupUninstallOEMInfA)(PCSTR, DWORD, PVOID);
50
51 static void create_inf_file(LPCSTR filename)
52 {
53     DWORD dwNumberOfBytesWritten;
54     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
55                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
56
57     static const char data[] =
58         "[Version]\n"
59         "Signature=\"$Chicago$\"\n"
60         "AdvancedINF=2.5\n"
61         "[DefaultInstall]\n"
62         "RegisterOCXs=RegisterOCXsSection\n"
63         "[RegisterOCXsSection]\n"
64         "%%11%%\\ole32.dll\n";
65
66     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
67     CloseHandle(hf);
68 }
69
70 static void get_temp_filename(LPSTR path)
71 {
72     CHAR temp[MAX_PATH];
73     LPSTR ptr;
74
75     GetTempFileName(CURR_DIR, "set", 0, temp);
76     ptr = strrchr(temp, '\\');
77
78     lstrcpy(path, ptr + 1);
79 }
80
81 static BOOL file_exists(LPSTR path)
82 {
83     return GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES;
84 }
85
86 static BOOL check_format(LPSTR path, LPSTR inf)
87 {
88     CHAR check[MAX_PATH];
89     BOOL res;
90
91     static const CHAR format[] = "\\INF\\oem";
92
93     GetWindowsDirectory(check, MAX_PATH);
94     lstrcat(check, format);
95     res = CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, check, -1, path, lstrlen(check)) == CSTR_EQUAL &&
96           path[lstrlen(check)] != '\\';
97
98     return (!inf) ? res : res && (inf == path + lstrlen(check) - 3);
99 }
100
101 static void test_original_file_name(LPCSTR original, LPCSTR dest)
102 {
103     HINF hinf;
104     PSP_INF_INFORMATION pspii;
105     SP_ORIGINAL_FILE_INFO spofi;
106     BOOL res;
107     DWORD size;
108
109     if (!pSetupQueryInfOriginalFileInformationA)
110     {
111         win_skip("SetupQueryInfOriginalFileInformationA is not available\n");
112         return;
113     }
114
115     hinf = SetupOpenInfFileA(dest, NULL, INF_STYLE_WIN4, NULL);
116     ok(hinf != NULL, "SetupOpenInfFileA failed with error %d\n", GetLastError());
117
118     res = SetupGetInfInformation(hinf, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
119     ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError());
120
121     pspii = HeapAlloc(GetProcessHeap(), 0, size);
122
123     res = SetupGetInfInformation(hinf, INFINFO_INF_SPEC_IS_HINF, pspii, size, NULL);
124     ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError());
125
126     spofi.cbSize = 0;
127     res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi);
128     ok(!res && GetLastError() == ERROR_INVALID_USER_BUFFER,
129         "SetupQueryInfOriginalFileInformationA should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", GetLastError());
130
131     spofi.cbSize = sizeof(spofi);
132     res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi);
133     ok(res, "SetupQueryInfOriginalFileInformationA failed with error %d\n", GetLastError());
134     ok(!spofi.OriginalCatalogName[0], "spofi.OriginalCatalogName should have been \"\" instead of \"%s\"\n", spofi.OriginalCatalogName);
135     todo_wine
136     ok(!strcmp(original, spofi.OriginalInfName), "spofi.OriginalInfName of %s didn't match real original name %s\n", spofi.OriginalInfName, original);
137
138     HeapFree(GetProcessHeap(), 0, pspii);
139
140     SetupCloseInfFile(hinf);
141 }
142
143 static void test_SetupCopyOEMInf(void)
144 {
145     CHAR toolong[MAX_PATH * 2];
146     CHAR path[MAX_PATH], dest[MAX_PATH];
147     CHAR tmpfile[MAX_PATH], dest_save[MAX_PATH];
148     LPSTR inf = NULL;
149     DWORD size;
150     BOOL res;
151
152     /* try NULL SourceInfFileName */
153     SetLastError(0xdeadbeef);
154     res = pSetupCopyOEMInfA(NULL, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
155     ok(res == FALSE, "Expected FALSE, got %d\n", res);
156     ok(GetLastError() == ERROR_INVALID_PARAMETER,
157        "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
158
159     /* try empty SourceInfFileName */
160     SetLastError(0xdeadbeef);
161     res = pSetupCopyOEMInfA("", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
162     ok(res == FALSE, "Expected FALSE, got %d\n", res);
163     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
164        GetLastError() == ERROR_BAD_PATHNAME || /* Win98 */
165        GetLastError() == ERROR_INVALID_PARAMETER, /* Vista, W2K8 */
166        "Unexpected error : %d\n", GetLastError());
167
168     /* try a relative nonexistent SourceInfFileName */
169     SetLastError(0xdeadbeef);
170     res = pSetupCopyOEMInfA("nonexistent", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
171     ok(res == FALSE, "Expected FALSE, got %d\n", res);
172     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
173        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
174
175     /* try an absolute nonexistent SourceInfFileName */
176     lstrcpy(path, CURR_DIR);
177     lstrcat(path, "\\nonexistent");
178     SetLastError(0xdeadbeef);
179     res = pSetupCopyOEMInfA(path, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
180     ok(res == FALSE, "Expected FALSE, got %d\n", res);
181     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
182        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
183
184     /* try a long SourceInfFileName */
185     memset(toolong, 'a', MAX_PATH * 2);
186     toolong[MAX_PATH * 2 - 1] = '\0';
187     SetLastError(0xdeadbeef);
188     res = pSetupCopyOEMInfA(toolong, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
189     ok(res == FALSE, "Expected FALSE, got %d\n", res);
190     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
191        GetLastError() == ERROR_FILENAME_EXCED_RANGE, /* Win98 */
192        "Expected ERROR_FILE_NOT_FOUND or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
193
194     get_temp_filename(tmpfile);
195     create_inf_file(tmpfile);
196
197     /* try a relative SourceInfFileName */
198     SetLastError(0xdeadbeef);
199     res = pSetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
200     ok(res == FALSE ||
201        broken(res == TRUE), /* Win98 */
202        "Expected FALSE, got %d\n", res);
203     if (GetLastError() == ERROR_WRONG_INF_TYPE || GetLastError() == ERROR_UNSUPPORTED_TYPE /* Win7 */)
204     {
205        /* FIXME:
206         * Vista needs a [Manufacturer] entry in the inf file. Doing this will give some
207         * popups during the installation though as it also needs a catalog file (signed?).
208         */
209        win_skip("Needs a different inf file on Vista+\n");
210        DeleteFile(tmpfile);
211        return;
212     }
213
214     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
215        broken(GetLastError() == ERROR_SUCCESS), /* Win98 */
216        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
217     ok(file_exists(tmpfile), "Expected tmpfile to exist\n");
218
219     /* try SP_COPY_REPLACEONLY, dest does not exist */
220     SetLastError(0xdeadbeef);
221     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
222     ok(res == FALSE, "Expected FALSE, got %d\n", res);
223     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
224        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     ok(file_exists(tmpfile), "Expected source inf to exist\n");
226
227     /* try an absolute SourceInfFileName, without DestinationInfFileName */
228     lstrcpy(path, CURR_DIR);
229     lstrcat(path, "\\");
230     lstrcat(path, tmpfile);
231     SetLastError(0xdeadbeef);
232     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, NULL, 0, NULL, NULL);
233     ok(res == TRUE, "Expected TRUE, got %d\n", res);
234     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
235     ok(file_exists(path), "Expected source inf to exist\n");
236
237     /* try SP_COPY_REPLACEONLY, dest exists */
238     SetLastError(0xdeadbeef);
239     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
240     ok(res == TRUE, "Expected TRUE, got %d\n", res);
241     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
242     ok(file_exists(path), "Expected source inf to exist\n");
243
244     /* try SP_COPY_NOOVERWRITE */
245     SetLastError(0xdeadbeef);
246     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
247     ok(res == FALSE, "Expected FALSE, got %d\n", res);
248     ok(GetLastError() == ERROR_FILE_EXISTS,
249        "Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
250
251     /* get the DestinationInfFileName */
252     SetLastError(0xdeadbeef);
253     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, NULL, NULL);
254     ok(res == TRUE, "Expected TRUE, got %d\n", res);
255     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
256     ok(lstrlen(dest) != 0, "Expected a non-zero length string\n");
257     ok(file_exists(dest), "Expected destination inf to exist\n");
258     ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
259     ok(file_exists(path), "Expected source inf to exist\n");
260
261     lstrcpy(dest_save, dest);
262     DeleteFile(dest_save);
263
264     /* get the DestinationInfFileName, DestinationInfFileNameSize is too small
265      *   - inf is still copied
266      */
267     lstrcpy(dest, "aaa");
268     size = 0;
269     SetLastError(0xdeadbeef);
270     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, 5, &size, NULL);
271     ok(res == FALSE, "Expected FALSE, got %d\n", res);
272     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
273        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
274     ok(file_exists(path), "Expected source inf to exist\n");
275     ok(file_exists(dest_save), "Expected dest inf to exist\n");
276     ok(!lstrcmp(dest, "aaa"), "Expected dest to be unchanged\n");
277     ok(size == lstrlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
278
279     /* get the DestinationInfFileName and DestinationInfFileNameSize */
280     SetLastError(0xdeadbeef);
281     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, NULL);
282     ok(res == TRUE, "Expected TRUE, got %d\n", res);
283     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
284     ok(lstrlen(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlen(dest), size);
285     ok(file_exists(dest), "Expected destination inf to exist\n");
286     ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
287     ok(file_exists(path), "Expected source inf to exist\n");
288     ok(size == lstrlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
289
290     test_original_file_name(strrchr(path, '\\') + 1, dest);
291
292     /* get the DestinationInfFileName, DestinationInfFileNameSize, and DestinationInfFileNameComponent */
293     SetLastError(0xdeadbeef);
294     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, &inf);
295     ok(res == TRUE, "Expected TRUE, got %d\n", res);
296     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
297     ok(lstrlen(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlen(dest), size);
298     ok(file_exists(dest), "Expected destination inf to exist\n");
299     ok((inf && inf[0] != 0) ||
300        broken(!inf), /* Win98 */
301        "Expected inf to point to the filename\n");
302     ok(check_format(dest, inf), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
303     ok(file_exists(path), "Expected source inf to exist\n");
304     ok(size == lstrlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
305
306     /* try SP_COPY_DELETESOURCE */
307     SetLastError(0xdeadbeef);
308     res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_DELETESOURCE, NULL, 0, NULL, NULL);
309     ok(res == TRUE, "Expected TRUE, got %d\n", res);
310     ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
311     ok(!file_exists(path), "Expected source inf to not exist\n");
312
313     if (pSetupUninstallOEMInfA)
314     {
315         char *destfile = strrchr(dest, '\\') + 1;
316
317         SetLastError(0xdeadbeef);
318         ok(pSetupUninstallOEMInfA(destfile, 0, NULL), "Failed to uninstall '%s' : %d\n", destfile, GetLastError());
319     }
320     else
321     {
322         /* Win9x/WinMe */
323         SetLastError(0xdeadbeef);
324         ok(DeleteFileA(dest), "Failed to delete file '%s' : %d\n", dest, GetLastError());
325
326         /* On WinMe we also need to remove the .pnf file */
327         *(strrchr(dest, '.') + 1) = 'p';
328         DeleteFileA(dest);
329     }
330 }
331
332 static void create_source_file(LPSTR filename, const BYTE *data, DWORD size)
333 {
334     HANDLE handle;
335     DWORD written;
336
337     handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
338     WriteFile(handle, data, size, &written, NULL);
339     CloseHandle(handle);
340 }
341
342 static BOOL compare_file_data(LPSTR file, const BYTE *data, DWORD size)
343 {
344     DWORD read;
345     HANDLE handle;
346     BOOL ret = FALSE;
347     LPBYTE buffer;
348
349     handle = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
350     buffer = HeapAlloc(GetProcessHeap(), 0, size);
351     if (buffer)
352     {
353         ReadFile(handle, buffer, size, &read, NULL);
354         if (read == size && !memcmp(data, buffer, size)) ret = TRUE;
355         HeapFree(GetProcessHeap(), 0, buffer);
356     }
357     CloseHandle(handle);
358     return ret;
359 }
360
361 static const BYTE uncompressed[] = {
362     'u','n','c','o','m','p','r','e','s','s','e','d','\r','\n'
363 };
364 static const BYTE comp_lzx[] = {
365     0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33, 0x41, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x00,
366     0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x3f, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64
367 };
368 static const BYTE comp_zip[] = {
369     0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11,
370     0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x15, 0x00, 0x77, 0x69,
371     0x6e, 0x65, 0x55, 0x54, 0x09, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46, 0xfd, 0x0d, 0x10, 0x46, 0x55,
372     0x78, 0x04, 0x00, 0xe8, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72,
373     0x65, 0x73, 0x73, 0x65, 0x64, 0x50, 0x4b, 0x01, 0x02, 0x17, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00,
374     0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11, 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
375     0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00,
376     0x00, 0x00, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x55, 0x54, 0x05, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46,
377     0x55, 0x78, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
378     0x3f, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00
379 };
380 static const BYTE comp_cab_lzx[] = {
381     0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
383     0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x0f, 0x0e, 0x00, 0x00, 0x00,
384     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x36, 0x86, 0x72, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
385     0x00, 0x19, 0xd0, 0x1a, 0xe3, 0x22, 0x00, 0x0e, 0x00, 0x5b, 0x80, 0x80, 0x8d, 0x00, 0x30, 0xe0,
386     0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x63,
387     0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x0d, 0x0a
388 };
389 static const BYTE comp_cab_zip[] =  {
390     0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
392     0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
393     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x36, 0x2f, 0xa5, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
394     0x00, 0x7c, 0x80, 0x26, 0x2b, 0x12, 0x00, 0x0e, 0x00, 0x43, 0x4b, 0x2b, 0xcd, 0x4b, 0xce, 0xcf,
395     0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0xe1, 0xe5, 0x02, 0x00
396 };
397
398 static void test_SetupGetFileCompressionInfo(void)
399 {
400     DWORD ret, source_size, target_size;
401     char source[MAX_PATH], temp[MAX_PATH], *name;
402     UINT type;
403
404     GetTempPathA(sizeof(temp), temp);
405     GetTempFileNameA(temp, "fci", 0, source);
406
407     create_source_file(source, uncompressed, sizeof(uncompressed));
408
409     ret = SetupGetFileCompressionInfoA(NULL, NULL, NULL, NULL, NULL);
410     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
411
412     ret = SetupGetFileCompressionInfoA(source, NULL, NULL, NULL, NULL);
413     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
414
415     ret = SetupGetFileCompressionInfoA(source, &name, NULL, NULL, NULL);
416     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
417
418     ret = SetupGetFileCompressionInfoA(source, &name, &source_size, NULL, NULL);
419     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
420
421     ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, NULL);
422     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
423
424     name = NULL;
425     source_size = target_size = 0;
426     type = 5;
427
428     ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, &type);
429     ok(!ret, "SetupGetFileCompressionInfo failed unexpectedly\n");
430     ok(name && !lstrcmpA(name, source), "got %s, expected %s\n", name, source);
431     ok(source_size == sizeof(uncompressed), "got %d\n", source_size);
432     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
433     ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
434
435     MyFree(name);
436     DeleteFileA(source);
437 }
438
439 static void test_SetupGetFileCompressionInfoEx(void)
440 {
441     BOOL ret;
442     DWORD required_len, source_size, target_size;
443     char source[MAX_PATH], temp[MAX_PATH], name[MAX_PATH];
444     UINT type;
445
446     GetTempPathA(sizeof(temp), temp);
447     GetTempFileNameA(temp, "doc", 0, source);
448
449     ret = pSetupGetFileCompressionInfoExA(NULL, NULL, 0, NULL, NULL, NULL, NULL);
450     ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
451
452     ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, NULL, NULL, NULL, NULL);
453     ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
454
455     ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, &required_len, NULL, NULL, NULL);
456     ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
457     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
458
459     create_source_file(source, comp_lzx, sizeof(comp_lzx));
460
461     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
462     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
463     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
464     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
465     ok(source_size == sizeof(comp_lzx), "got %d\n", source_size);
466     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
467     ok(type == FILE_COMPRESSION_WINLZA, "got %d, expected FILE_COMPRESSION_WINLZA\n", type);
468     DeleteFileA(source);
469
470     create_source_file(source, comp_zip, sizeof(comp_zip));
471
472     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
473     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
474     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
475     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
476     ok(source_size == sizeof(comp_zip), "got %d\n", source_size);
477     ok(target_size == sizeof(comp_zip), "got %d\n", target_size);
478     ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
479     DeleteFileA(source);
480
481     create_source_file(source, comp_cab_lzx, sizeof(comp_cab_lzx));
482
483     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
484     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
485     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
486     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
487     ok(source_size == sizeof(comp_cab_lzx), "got %d\n", source_size);
488     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
489     ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
490     DeleteFileA(source);
491
492     create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
493
494     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
495     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
496     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
497     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
498     ok(source_size == sizeof(comp_cab_zip), "got %d\n", source_size);
499     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
500     ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
501     DeleteFileA(source);
502 }
503
504 static void test_SetupDecompressOrCopyFile(void)
505 {
506     DWORD ret;
507     char source[MAX_PATH], target[MAX_PATH], temp[MAX_PATH], *p;
508     UINT type;
509
510     GetTempPathA(sizeof(temp), temp);
511     GetTempFileNameA(temp, "doc", 0, source);
512     GetTempFileNameA(temp, "doc", 0, target);
513
514     /* parameter tests */
515
516     create_source_file(source, uncompressed, sizeof(uncompressed));
517
518     ret = SetupDecompressOrCopyFileA(NULL, NULL, NULL);
519     ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
520
521     type = FILE_COMPRESSION_NONE;
522     ret = SetupDecompressOrCopyFileA(NULL, target, &type);
523     ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
524
525     ret = SetupDecompressOrCopyFileA(source, NULL, &type);
526     ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
527
528     type = 5; /* try an invalid compression type */
529     ret = SetupDecompressOrCopyFileA(source, target, &type);
530     ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
531
532     DeleteFileA(target);
533
534     /* no compression tests */
535
536     ret = SetupDecompressOrCopyFileA(source, target, NULL);
537     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
538     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
539
540     /* try overwriting existing file */
541     ret = SetupDecompressOrCopyFileA(source, target, NULL);
542     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
543     DeleteFileA(target);
544
545     type = FILE_COMPRESSION_NONE;
546     ret = SetupDecompressOrCopyFileA(source, target, &type);
547     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
548     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
549     DeleteFileA(target);
550
551     type = FILE_COMPRESSION_WINLZA;
552     ret = SetupDecompressOrCopyFileA(source, target, &type);
553     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
554     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
555     DeleteFileA(target);
556
557     /* lz compression tests */
558
559     create_source_file(source, comp_lzx, sizeof(comp_lzx));
560
561     ret = SetupDecompressOrCopyFileA(source, target, NULL);
562     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
563     DeleteFileA(target);
564
565     /* zip compression tests */
566
567     create_source_file(source, comp_zip, sizeof(comp_zip));
568
569     ret = SetupDecompressOrCopyFileA(source, target, NULL);
570     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
571     ok(compare_file_data(target, comp_zip, sizeof(comp_zip)), "incorrect target file\n");
572     DeleteFileA(target);
573
574     /* cabinet compression tests */
575
576     create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
577
578     p = strrchr(target, '\\');
579     lstrcpyA(p + 1, "wine");
580
581     ret = SetupDecompressOrCopyFileA(source, target, NULL);
582     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
583     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
584
585     /* try overwriting existing file */
586     ret = SetupDecompressOrCopyFileA(source, target, NULL);
587     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
588
589     /* try zip compression */
590     type = FILE_COMPRESSION_MSZIP;
591     ret = SetupDecompressOrCopyFileA(source, target, &type);
592     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
593     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
594
595     /* try no compression */
596     type = FILE_COMPRESSION_NONE;
597     ret = SetupDecompressOrCopyFileA(source, target, &type);
598     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
599     ok(compare_file_data(target, comp_cab_zip, sizeof(comp_cab_zip)), "incorrect target file\n");
600
601     DeleteFileA(target);
602     DeleteFileA(source);
603 }
604
605 static void test_SetupUninstallOEMInf(void)
606 {
607     BOOL ret;
608
609     SetLastError(0xdeadbeef);
610     ret = pSetupUninstallOEMInfA(NULL, 0, NULL);
611     ok(!ret, "Expected failure\n");
612     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
613
614     SetLastError(0xdeadbeef);
615     ret = pSetupUninstallOEMInfA("", 0, NULL);
616     todo_wine
617     {
618     ok(!ret, "Expected failure\n");
619     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
620     }
621
622     SetLastError(0xdeadbeef);
623     ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL);
624     todo_wine
625     {
626     ok(!ret, "Expected failure\n");
627     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
628     }
629 }
630
631 START_TEST(misc)
632 {
633     HMODULE hsetupapi = GetModuleHandle("setupapi.dll");
634
635     pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA");
636     pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA");
637     pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA");
638     pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA");
639
640     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
641
642     if (pSetupCopyOEMInfA)
643         test_SetupCopyOEMInf();
644     else
645         win_skip("SetupCopyOEMInfA is not available\n");
646
647     test_SetupGetFileCompressionInfo();
648
649     if (pSetupGetFileCompressionInfoExA)
650         test_SetupGetFileCompressionInfoEx();
651     else
652         win_skip("SetupGetFileCompressionInfoExA is not available\n");
653
654     test_SetupDecompressOrCopyFile();
655
656     if (pSetupUninstallOEMInfA)
657         test_SetupUninstallOEMInf();
658     else
659         win_skip("SetupUninstallOEMInfA is not available\n");
660 }