makefiles: Rename the SRCDIR, TOPSRCDIR and TOPOBJDIR variables to follow autoconf...
[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 laurence[] = {
365     'l','a','u','r','e','n','c','e','\r','\n'
366 };
367 static const BYTE comp_lzx[] = {
368     0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33, 0x41, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x00,
369     0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x3f, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64
370 };
371 static const BYTE comp_zip[] = {
372     0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11,
373     0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x15, 0x00, 0x77, 0x69,
374     0x6e, 0x65, 0x55, 0x54, 0x09, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46, 0xfd, 0x0d, 0x10, 0x46, 0x55,
375     0x78, 0x04, 0x00, 0xe8, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72,
376     0x65, 0x73, 0x73, 0x65, 0x64, 0x50, 0x4b, 0x01, 0x02, 0x17, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00,
377     0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11, 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
378     0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00,
379     0x00, 0x00, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x55, 0x54, 0x05, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46,
380     0x55, 0x78, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
381     0x3f, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00
382 };
383 static const BYTE comp_cab_lzx[] = {
384     0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
386     0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x0f, 0x0e, 0x00, 0x00, 0x00,
387     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x36, 0x86, 0x72, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
388     0x00, 0x19, 0xd0, 0x1a, 0xe3, 0x22, 0x00, 0x0e, 0x00, 0x5b, 0x80, 0x80, 0x8d, 0x00, 0x30, 0xe0,
389     0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x63,
390     0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x0d, 0x0a
391 };
392 static const BYTE comp_cab_zip[] =  {
393     0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
395     0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
396     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x36, 0x2f, 0xa5, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
397     0x00, 0x7c, 0x80, 0x26, 0x2b, 0x12, 0x00, 0x0e, 0x00, 0x43, 0x4b, 0x2b, 0xcd, 0x4b, 0xce, 0xcf,
398     0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0xe1, 0xe5, 0x02, 0x00
399 };
400 static const BYTE comp_cab_zip_multi[] = {
401     0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
403     0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00,
404     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x74, 0x72, 0x69, 0x73,
405     0x74, 0x72, 0x61, 0x6d, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1,
406     0x38, 0xf0, 0x48, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00,
407     0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x73, 0x68, 0x61, 0x6e, 0x64, 0x79,
408     0x00, 0x67, 0x2c, 0x03, 0x85, 0x23, 0x00, 0x20, 0x00, 0x43, 0x4b, 0xcb, 0x49, 0x2c, 0x2d, 0x4a,
409     0xcd, 0x4b, 0x4e, 0xe5, 0xe5, 0x2a, 0xcd, 0x4b, 0xce, 0xcf, 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e,
410     0x4d, 0xe1, 0xe5, 0x2a, 0x2e, 0x49, 0x2d, 0xca, 0x03, 0x8a, 0x02, 0x00
411 };
412
413 static void test_SetupGetFileCompressionInfo(void)
414 {
415     DWORD ret, source_size, target_size;
416     char source[MAX_PATH], temp[MAX_PATH], *name;
417     UINT type;
418
419     GetTempPathA(sizeof(temp), temp);
420     GetTempFileNameA(temp, "fci", 0, source);
421
422     create_source_file(source, uncompressed, sizeof(uncompressed));
423
424     ret = SetupGetFileCompressionInfoA(NULL, NULL, NULL, NULL, NULL);
425     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
426
427     ret = SetupGetFileCompressionInfoA(source, NULL, NULL, NULL, NULL);
428     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
429
430     ret = SetupGetFileCompressionInfoA(source, &name, NULL, NULL, NULL);
431     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
432
433     ret = SetupGetFileCompressionInfoA(source, &name, &source_size, NULL, NULL);
434     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
435
436     ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, NULL);
437     ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
438
439     name = NULL;
440     source_size = target_size = 0;
441     type = 5;
442
443     ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, &type);
444     ok(!ret, "SetupGetFileCompressionInfo failed unexpectedly\n");
445     ok(name && !lstrcmpA(name, source), "got %s, expected %s\n", name, source);
446     ok(source_size == sizeof(uncompressed), "got %d\n", source_size);
447     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
448     ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
449
450     MyFree(name);
451     DeleteFileA(source);
452 }
453
454 static void test_SetupGetFileCompressionInfoEx(void)
455 {
456     BOOL ret;
457     DWORD required_len, source_size, target_size;
458     char source[MAX_PATH], temp[MAX_PATH], name[MAX_PATH];
459     UINT type;
460
461     GetTempPathA(sizeof(temp), temp);
462     GetTempFileNameA(temp, "doc", 0, source);
463
464     ret = pSetupGetFileCompressionInfoExA(NULL, NULL, 0, NULL, NULL, NULL, NULL);
465     ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
466
467     ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, NULL, NULL, NULL, NULL);
468     ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
469
470     ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, &required_len, NULL, NULL, NULL);
471     ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
472     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
473
474     create_source_file(source, comp_lzx, sizeof(comp_lzx));
475
476     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
477     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
478     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
479     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
480     ok(source_size == sizeof(comp_lzx), "got %d\n", source_size);
481     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
482     ok(type == FILE_COMPRESSION_WINLZA, "got %d, expected FILE_COMPRESSION_WINLZA\n", type);
483     DeleteFileA(source);
484
485     create_source_file(source, comp_zip, sizeof(comp_zip));
486
487     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
488     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
489     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
490     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
491     ok(source_size == sizeof(comp_zip), "got %d\n", source_size);
492     ok(target_size == sizeof(comp_zip), "got %d\n", target_size);
493     ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
494     DeleteFileA(source);
495
496     create_source_file(source, comp_cab_lzx, sizeof(comp_cab_lzx));
497
498     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
499     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
500     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
501     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
502     ok(source_size == sizeof(comp_cab_lzx), "got %d\n", source_size);
503     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
504     ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
505     DeleteFileA(source);
506
507     create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
508
509     ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
510     ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
511     ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
512     ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
513     ok(source_size == sizeof(comp_cab_zip), "got %d\n", source_size);
514     ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
515     ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
516     DeleteFileA(source);
517 }
518
519 static void test_SetupDecompressOrCopyFile(void)
520 {
521     DWORD ret;
522     char source[MAX_PATH], target[MAX_PATH], temp[MAX_PATH], *p;
523     UINT type;
524     int i;
525
526     const struct
527     {
528         PCSTR source;
529         PCSTR target;
530         PUINT type;
531     } invalid_parameters[] =
532     {
533         {NULL,   NULL,   NULL},
534         {NULL,   NULL,   &type},
535         {NULL,   target, NULL},
536         {NULL,   target, &type},
537         {source, NULL,   NULL},
538         {source, NULL,   &type},
539     };
540
541     const struct
542     {
543         const char *filename;
544         const BYTE *expected_buffer;
545         const size_t buffer_size;
546     } zip_multi_tests[] =
547     {
548         {"tristram",     laurence, sizeof(laurence)},
549         {"tristram.txt", laurence, sizeof(laurence)},
550         {"wine",         laurence, sizeof(laurence)},
551         {"wine.txt",     laurence, sizeof(laurence)},
552         {"shandy",       laurence, sizeof(laurence)},
553         {"shandy.txt",   laurence, sizeof(laurence)},
554         {"deadbeef",     laurence, sizeof(laurence)},
555         {"deadbeef.txt", laurence, sizeof(laurence)},
556     };
557
558     GetTempPathA(sizeof(temp), temp);
559     GetTempFileNameA(temp, "doc", 0, source);
560     GetTempFileNameA(temp, "doc", 0, target);
561
562     /* parameter tests */
563
564     create_source_file(source, uncompressed, sizeof(uncompressed));
565
566     for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
567     {
568         type = FILE_COMPRESSION_NONE;
569         ret = SetupDecompressOrCopyFileA(invalid_parameters[i].source,
570                                          invalid_parameters[i].target,
571                                          invalid_parameters[i].type);
572         ok(ret == ERROR_INVALID_PARAMETER,
573            "[%d] Expected SetupDecompressOrCopyFileA to return ERROR_INVALID_PARAMETER, got %u\n",
574            i, ret);
575
576         /* try an invalid compression type */
577         type = 5;
578         ret = SetupDecompressOrCopyFileA(invalid_parameters[i].source,
579                                          invalid_parameters[i].target,
580                                          invalid_parameters[i].type);
581         ok(ret == ERROR_INVALID_PARAMETER,
582            "[%d] Expected SetupDecompressOrCopyFileA to return ERROR_INVALID_PARAMETER, got %u\n",
583            i, ret);
584     }
585
586     type = 5; /* try an invalid compression type */
587     ret = SetupDecompressOrCopyFileA(source, target, &type);
588     ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
589
590     DeleteFileA(target);
591
592     /* no compression tests */
593
594     ret = SetupDecompressOrCopyFileA(source, target, NULL);
595     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
596     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
597
598     /* try overwriting existing file */
599     ret = SetupDecompressOrCopyFileA(source, target, NULL);
600     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
601     DeleteFileA(target);
602
603     type = FILE_COMPRESSION_NONE;
604     ret = SetupDecompressOrCopyFileA(source, target, &type);
605     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
606     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
607     DeleteFileA(target);
608
609     type = FILE_COMPRESSION_WINLZA;
610     ret = SetupDecompressOrCopyFileA(source, target, &type);
611     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
612     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
613     DeleteFileA(target);
614
615     /* lz compression tests */
616
617     create_source_file(source, comp_lzx, sizeof(comp_lzx));
618
619     ret = SetupDecompressOrCopyFileA(source, target, NULL);
620     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
621     DeleteFileA(target);
622
623     /* zip compression tests */
624
625     create_source_file(source, comp_zip, sizeof(comp_zip));
626
627     ret = SetupDecompressOrCopyFileA(source, target, NULL);
628     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
629     ok(compare_file_data(target, comp_zip, sizeof(comp_zip)), "incorrect target file\n");
630     DeleteFileA(target);
631
632     /* cabinet compression tests */
633
634     create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
635
636     p = strrchr(target, '\\');
637     lstrcpyA(p + 1, "wine");
638
639     ret = SetupDecompressOrCopyFileA(source, target, NULL);
640     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
641     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
642
643     /* try overwriting existing file */
644     ret = SetupDecompressOrCopyFileA(source, target, NULL);
645     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
646
647     /* try zip compression */
648     type = FILE_COMPRESSION_MSZIP;
649     ret = SetupDecompressOrCopyFileA(source, target, &type);
650     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
651     ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
652
653     /* try no compression */
654     type = FILE_COMPRESSION_NONE;
655     ret = SetupDecompressOrCopyFileA(source, target, &type);
656     ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
657     ok(compare_file_data(target, comp_cab_zip, sizeof(comp_cab_zip)), "incorrect target file\n");
658
659     /* Show that SetupDecompressOrCopyFileA simply extracts the first file it
660      * finds within the compressed cabinet. Contents are:
661      * tristram -> "laurence\r\n"
662      * wine     -> "uncompressed\r\n"
663      * shandy   -> "sterne\r\n" */
664
665     create_source_file(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
666
667     p = strrchr(target, '\\');
668
669     for (i = 0; i < sizeof(zip_multi_tests)/sizeof(zip_multi_tests[0]); i++)
670     {
671         lstrcpyA(p + 1, zip_multi_tests[i].filename);
672
673         ret = SetupDecompressOrCopyFileA(source, target, NULL);
674         ok(!ret, "[%d] SetupDecompressOrCopyFile failed unexpectedly: %d\n", i, ret);
675         ok(compare_file_data(target, zip_multi_tests[i].expected_buffer, zip_multi_tests[i].buffer_size),
676            "[%d] incorrect target file\n", i);
677         DeleteFileA(target);
678     }
679
680     DeleteFileA(source);
681 }
682
683 static void test_SetupUninstallOEMInf(void)
684 {
685     BOOL ret;
686
687     SetLastError(0xdeadbeef);
688     ret = pSetupUninstallOEMInfA(NULL, 0, NULL);
689     ok(!ret, "Expected failure\n");
690     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
691
692     SetLastError(0xdeadbeef);
693     ret = pSetupUninstallOEMInfA("", 0, NULL);
694     todo_wine
695     {
696     ok(!ret, "Expected failure\n");
697     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
698     }
699
700     SetLastError(0xdeadbeef);
701     ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL);
702     todo_wine
703     {
704     ok(!ret, "Expected failure\n");
705     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
706     }
707 }
708
709 START_TEST(misc)
710 {
711     HMODULE hsetupapi = GetModuleHandle("setupapi.dll");
712
713     pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA");
714     pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA");
715     pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA");
716     pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA");
717
718     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
719
720     if (pSetupCopyOEMInfA)
721         test_SetupCopyOEMInf();
722     else
723         win_skip("SetupCopyOEMInfA is not available\n");
724
725     test_SetupGetFileCompressionInfo();
726
727     if (pSetupGetFileCompressionInfoExA)
728         test_SetupGetFileCompressionInfoEx();
729     else
730         win_skip("SetupGetFileCompressionInfoExA is not available\n");
731
732     test_SetupDecompressOrCopyFile();
733
734     if (pSetupUninstallOEMInfA)
735         test_SetupUninstallOEMInf();
736     else
737         win_skip("SetupUninstallOEMInfA is not available\n");
738 }