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