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