04b2171ff82d9afa1dc29ba956027499db409428
[reactos.git] / rostests / winetests / setupapi / 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 #include "cfgmgr32.h"
33
34 #include "wine/test.h"
35
36 static CHAR CURR_DIR[MAX_PATH];
37
38 /* test:
39 * - fails if not administrator
40 * - what if it's not a .inf file?
41 * - copied to %windir%/Inf
42 * - SourceInfFileName should be a full path
43 * - SourceInfFileName should be <= MAX_PATH
44 * - copy styles
45 */
46
47 static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT);
48 static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *);
49 static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A);
50 static BOOL (WINAPI *pSetupUninstallOEMInfA)(PCSTR, DWORD, PVOID);
51
52 static void create_inf_file(LPCSTR filename)
53 {
54 DWORD dwNumberOfBytesWritten;
55 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
56 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
57
58 static const char data[] =
59 "[Version]\n"
60 "Signature=\"$Chicago$\"\n"
61 "AdvancedINF=2.5\n"
62 "[DefaultInstall]\n"
63 "RegisterOCXs=RegisterOCXsSection\n"
64 "[RegisterOCXsSection]\n"
65 "%%11%%\\ole32.dll\n";
66
67 WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
68 CloseHandle(hf);
69 }
70
71 static void get_temp_filename(LPSTR path)
72 {
73 CHAR temp[MAX_PATH];
74 LPSTR ptr;
75
76 GetTempFileNameA(CURR_DIR, "set", 0, temp);
77 ptr = strrchr(temp, '\\');
78
79 strcpy(path, ptr + 1);
80 }
81
82 static BOOL file_exists(LPSTR path)
83 {
84 return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
85 }
86
87 static BOOL check_format(LPSTR path, LPSTR inf)
88 {
89 CHAR check[MAX_PATH];
90 BOOL res;
91
92 static const CHAR format[] = "\\INF\\oem";
93
94 GetWindowsDirectoryA(check, MAX_PATH);
95 strcat(check, format);
96 res = CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, check, -1, path, strlen(check)) == CSTR_EQUAL &&
97 path[strlen(check)] != '\\';
98
99 return (!inf) ? res : res && (inf == path + strlen(check) - 3);
100 }
101
102 static void test_original_file_name(LPCSTR original, LPCSTR dest)
103 {
104 HINF hinf;
105 PSP_INF_INFORMATION pspii;
106 SP_ORIGINAL_FILE_INFO_A spofi;
107 BOOL res;
108 DWORD size;
109
110 if (!pSetupQueryInfOriginalFileInformationA)
111 {
112 win_skip("SetupQueryInfOriginalFileInformationA is not available\n");
113 return;
114 }
115
116 hinf = SetupOpenInfFileA(dest, NULL, INF_STYLE_WIN4, NULL);
117 ok(hinf != NULL, "SetupOpenInfFileA failed with error %d\n", GetLastError());
118
119 res = SetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
120 ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError());
121
122 pspii = HeapAlloc(GetProcessHeap(), 0, size);
123
124 res = SetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, pspii, size, NULL);
125 ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError());
126
127 spofi.cbSize = 0;
128 res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi);
129 ok(!res && GetLastError() == ERROR_INVALID_USER_BUFFER,
130 "SetupQueryInfOriginalFileInformationA should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", GetLastError());
131
132 spofi.cbSize = sizeof(spofi);
133 res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi);
134 ok(res, "SetupQueryInfOriginalFileInformationA failed with error %d\n", GetLastError());
135 ok(!spofi.OriginalCatalogName[0], "spofi.OriginalCatalogName should have been \"\" instead of \"%s\"\n", spofi.OriginalCatalogName);
136 todo_wine
137 ok(!strcmp(original, spofi.OriginalInfName), "spofi.OriginalInfName of %s didn't match real original name %s\n", spofi.OriginalInfName, original);
138
139 HeapFree(GetProcessHeap(), 0, pspii);
140
141 SetupCloseInfFile(hinf);
142 }
143
144 static void test_SetupCopyOEMInf(void)
145 {
146 CHAR toolong[MAX_PATH * 2];
147 CHAR path[MAX_PATH], dest[MAX_PATH];
148 CHAR tmpfile[MAX_PATH], dest_save[MAX_PATH];
149 LPSTR inf = NULL;
150 DWORD size;
151 BOOL res;
152
153 /* try NULL SourceInfFileName */
154 SetLastError(0xdeadbeef);
155 res = pSetupCopyOEMInfA(NULL, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
156 ok(res == FALSE, "Expected FALSE, got %d\n", res);
157 ok(GetLastError() == ERROR_INVALID_PARAMETER,
158 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
159
160 /* try empty SourceInfFileName */
161 SetLastError(0xdeadbeef);
162 res = pSetupCopyOEMInfA("", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
163 ok(res == FALSE, "Expected FALSE, got %d\n", res);
164 ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
165 GetLastError() == ERROR_BAD_PATHNAME || /* Win98 */
166 GetLastError() == ERROR_INVALID_PARAMETER, /* Vista, W2K8 */
167 "Unexpected error : %d\n", GetLastError());
168
169 /* try a relative nonexistent SourceInfFileName */
170 SetLastError(0xdeadbeef);
171 res = pSetupCopyOEMInfA("nonexistent", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
172 ok(res == FALSE, "Expected FALSE, got %d\n", res);
173 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
174 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
175
176 /* try an absolute nonexistent SourceInfFileName */
177 strcpy(path, CURR_DIR);
178 strcat(path, "\\nonexistent");
179 SetLastError(0xdeadbeef);
180 res = pSetupCopyOEMInfA(path, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
181 ok(res == FALSE, "Expected FALSE, got %d\n", res);
182 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
183 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
184
185 /* try a long SourceInfFileName */
186 memset(toolong, 'a', MAX_PATH * 2);
187 toolong[MAX_PATH * 2 - 1] = '\0';
188 SetLastError(0xdeadbeef);
189 res = pSetupCopyOEMInfA(toolong, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
190 ok(res == FALSE, "Expected FALSE, got %d\n", res);
191 ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
192 GetLastError() == ERROR_FILENAME_EXCED_RANGE, /* Win98 */
193 "Expected ERROR_FILE_NOT_FOUND or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
194
195 get_temp_filename(tmpfile);
196 create_inf_file(tmpfile);
197
198 /* try a relative SourceInfFileName */
199 SetLastError(0xdeadbeef);
200 res = pSetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
201 ok(res == FALSE ||
202 broken(res == TRUE), /* Win98 */
203 "Expected FALSE, got %d\n", res);
204 if (GetLastError() == ERROR_WRONG_INF_TYPE || GetLastError() == ERROR_UNSUPPORTED_TYPE /* Win7 */)
205 {
206 /* FIXME:
207 * Vista needs a [Manufacturer] entry in the inf file. Doing this will give some
208 * popups during the installation though as it also needs a catalog file (signed?).
209 */
210 win_skip("Needs a different inf file on Vista+\n");
211 DeleteFileA(tmpfile);
212 return;
213 }
214
215 ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
216 broken(GetLastError() == ERROR_SUCCESS), /* Win98 */
217 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
218 ok(file_exists(tmpfile), "Expected tmpfile to exist\n");
219
220 /* try SP_COPY_REPLACEONLY, dest does not exist */
221 SetLastError(0xdeadbeef);
222 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
223 ok(res == FALSE, "Expected FALSE, got %d\n", res);
224 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
225 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
226 ok(file_exists(tmpfile), "Expected source inf to exist\n");
227
228 /* try an absolute SourceInfFileName, without DestinationInfFileName */
229 strcpy(path, CURR_DIR);
230 strcat(path, "\\");
231 strcat(path, tmpfile);
232 SetLastError(0xdeadbeef);
233 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, NULL, 0, NULL, NULL);
234 ok(res == TRUE, "Expected TRUE, got %d\n", res);
235 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
236 ok(file_exists(path), "Expected source inf to exist\n");
237
238 /* try SP_COPY_REPLACEONLY, dest exists */
239 SetLastError(0xdeadbeef);
240 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
241 ok(res == TRUE, "Expected TRUE, got %d\n", res);
242 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
243 ok(file_exists(path), "Expected source inf to exist\n");
244
245 /* try SP_COPY_NOOVERWRITE */
246 SetLastError(0xdeadbeef);
247 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
248 ok(res == FALSE, "Expected FALSE, got %d\n", res);
249 ok(GetLastError() == ERROR_FILE_EXISTS,
250 "Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
251
252 /* get the DestinationInfFileName */
253 SetLastError(0xdeadbeef);
254 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, NULL, NULL);
255 ok(res == TRUE, "Expected TRUE, got %d\n", res);
256 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
257 ok(strlen(dest) != 0, "Expected a non-zero length string\n");
258 ok(file_exists(dest), "Expected destination inf to exist\n");
259 ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
260 ok(file_exists(path), "Expected source inf to exist\n");
261
262 strcpy(dest_save, dest);
263 DeleteFileA(dest_save);
264
265 /* get the DestinationInfFileName, DestinationInfFileNameSize is too small
266 * - inf is still copied
267 */
268 strcpy(dest, "aaa");
269 size = 0;
270 SetLastError(0xdeadbeef);
271 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, 5, &size, NULL);
272 ok(res == FALSE, "Expected FALSE, got %d\n", res);
273 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
274 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
275 ok(file_exists(path), "Expected source inf to exist\n");
276 ok(file_exists(dest_save), "Expected dest inf to exist\n");
277 ok(!strcmp(dest, "aaa"), "Expected dest to be unchanged\n");
278 ok(size == strlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
279
280 /* get the DestinationInfFileName and DestinationInfFileNameSize */
281 SetLastError(0xdeadbeef);
282 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, NULL);
283 ok(res == TRUE, "Expected TRUE, got %d\n", res);
284 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
285 ok(lstrlenA(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlenA(dest), size);
286 ok(file_exists(dest), "Expected destination inf to exist\n");
287 ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
288 ok(file_exists(path), "Expected source inf to exist\n");
289 ok(size == lstrlenA(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
290
291 test_original_file_name(strrchr(path, '\\') + 1, dest);
292
293 /* get the DestinationInfFileName, DestinationInfFileNameSize, and DestinationInfFileNameComponent */
294 SetLastError(0xdeadbeef);
295 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, &inf);
296 ok(res == TRUE, "Expected TRUE, got %d\n", res);
297 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
298 ok(lstrlenA(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlenA(dest), size);
299 ok(file_exists(dest), "Expected destination inf to exist\n");
300 ok((inf && inf[0] != 0) ||
301 broken(!inf), /* Win98 */
302 "Expected inf to point to the filename\n");
303 ok(check_format(dest, inf), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
304 ok(file_exists(path), "Expected source inf to exist\n");
305 ok(size == lstrlenA(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
306
307 /* try SP_COPY_DELETESOURCE */
308 SetLastError(0xdeadbeef);
309 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_DELETESOURCE, NULL, 0, NULL, NULL);
310 ok(res == TRUE, "Expected TRUE, got %d\n", res);
311 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
312 ok(!file_exists(path), "Expected source inf to not exist\n");
313
314 if (pSetupUninstallOEMInfA)
315 {
316 char pnf[MAX_PATH];
317 char *pnffile;
318 char *destfile = strrchr(dest, '\\') + 1;
319
320 strcpy(pnf, dest);
321 *(strrchr(pnf, '.') + 1) = 'p';
322 pnffile = strrchr(pnf, '\\') + 1;
323
324 SetLastError(0xdeadbeef);
325 res = pSetupUninstallOEMInfA(destfile, 0, NULL);
326 if(!res)
327 res = pSetupUninstallOEMInfA(pnffile, 0, NULL);
328 ok(res, "Failed to uninstall '%s'/'%s' : %d\n", destfile,
329 pnffile, GetLastError());
330 todo_wine ok(!file_exists(dest), "Expected inf '%s' to not exist\n", dest);
331 if(file_exists(dest))
332 {
333 SetLastError(0xdeadbeef);
334 res = DeleteFileA(dest);
335 ok(res, "Failed to delete file '%s' : %d\n", dest, GetLastError());
336 }
337 ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf);
338 if(file_exists(pnf))
339 {
340 SetLastError(0xdeadbeef);
341 res = DeleteFileA(pnf);
342 ok(res, "Failed to delete file '%s' : %d\n", pnf, GetLastError());
343 }
344 }
345 else
346 {
347 /* Win9x/WinMe */
348 SetLastError(0xdeadbeef);
349 res = DeleteFileA(dest);
350 ok(res, "Failed to delete file '%s' : %d\n", dest, GetLastError());
351
352 /* On WinMe we also need to remove the .pnf file */
353 *(strrchr(dest, '.') + 1) = 'p';
354 DeleteFileA(dest);
355 }
356 }
357
358 static void create_source_file(LPSTR filename, const BYTE *data, DWORD size)
359 {
360 HANDLE handle;
361 DWORD written;
362
363 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
364 WriteFile(handle, data, size, &written, NULL);
365 CloseHandle(handle);
366 }
367
368 static BOOL compare_file_data(LPSTR file, const BYTE *data, DWORD size)
369 {
370 DWORD read;
371 HANDLE handle;
372 BOOL ret = FALSE;
373 LPBYTE buffer;
374
375 handle = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
376 buffer = HeapAlloc(GetProcessHeap(), 0, size);
377 if (buffer)
378 {
379 ReadFile(handle, buffer, size, &read, NULL);
380 if (read == size && !memcmp(data, buffer, size)) ret = TRUE;
381 HeapFree(GetProcessHeap(), 0, buffer);
382 }
383 CloseHandle(handle);
384 return ret;
385 }
386
387 static const BYTE uncompressed[] = {
388 'u','n','c','o','m','p','r','e','s','s','e','d','\r','\n'
389 };
390 static const BYTE laurence[] = {
391 'l','a','u','r','e','n','c','e','\r','\n'
392 };
393 static const BYTE comp_lzx[] = {
394 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33, 0x41, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x00,
395 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x3f, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64
396 };
397 static const BYTE comp_zip[] = {
398 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11,
399 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x15, 0x00, 0x77, 0x69,
400 0x6e, 0x65, 0x55, 0x54, 0x09, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46, 0xfd, 0x0d, 0x10, 0x46, 0x55,
401 0x78, 0x04, 0x00, 0xe8, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72,
402 0x65, 0x73, 0x73, 0x65, 0x64, 0x50, 0x4b, 0x01, 0x02, 0x17, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11, 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
404 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00,
405 0x00, 0x00, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x55, 0x54, 0x05, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46,
406 0x55, 0x78, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
407 0x3f, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00
408 };
409 static const BYTE comp_cab_lzx[] = {
410 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x0f, 0x0e, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x36, 0x86, 0x72, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
414 0x00, 0x19, 0xd0, 0x1a, 0xe3, 0x22, 0x00, 0x0e, 0x00, 0x5b, 0x80, 0x80, 0x8d, 0x00, 0x30, 0xe0,
415 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x63,
416 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x0d, 0x0a
417 };
418 static const BYTE comp_cab_zip[] = {
419 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x36, 0x2f, 0xa5, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
423 0x00, 0x7c, 0x80, 0x26, 0x2b, 0x12, 0x00, 0x0e, 0x00, 0x43, 0x4b, 0x2b, 0xcd, 0x4b, 0xce, 0xcf,
424 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0xe1, 0xe5, 0x02, 0x00
425 };
426 static const BYTE comp_cab_zip_multi[] = {
427 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x74, 0x72, 0x69, 0x73,
431 0x74, 0x72, 0x61, 0x6d, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1,
432 0x38, 0xf0, 0x48, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x73, 0x68, 0x61, 0x6e, 0x64, 0x79,
434 0x00, 0x67, 0x2c, 0x03, 0x85, 0x23, 0x00, 0x20, 0x00, 0x43, 0x4b, 0xcb, 0x49, 0x2c, 0x2d, 0x4a,
435 0xcd, 0x4b, 0x4e, 0xe5, 0xe5, 0x2a, 0xcd, 0x4b, 0xce, 0xcf, 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e,
436 0x4d, 0xe1, 0xe5, 0x2a, 0x2e, 0x49, 0x2d, 0xca, 0x03, 0x8a, 0x02, 0x00
437 };
438
439 static void test_SetupGetFileCompressionInfo(void)
440 {
441 DWORD ret, source_size, target_size;
442 char source[MAX_PATH], temp[MAX_PATH], *name;
443 UINT type;
444
445 GetTempPathA(sizeof(temp), temp);
446 GetTempFileNameA(temp, "fci", 0, source);
447
448 create_source_file(source, uncompressed, sizeof(uncompressed));
449
450 ret = SetupGetFileCompressionInfoA(NULL, NULL, NULL, NULL, NULL);
451 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
452
453 ret = SetupGetFileCompressionInfoA(source, NULL, NULL, NULL, NULL);
454 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
455
456 ret = SetupGetFileCompressionInfoA(source, &name, NULL, NULL, NULL);
457 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
458
459 ret = SetupGetFileCompressionInfoA(source, &name, &source_size, NULL, NULL);
460 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
461
462 ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, NULL);
463 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
464
465 name = NULL;
466 source_size = target_size = 0;
467 type = 5;
468
469 ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, &type);
470 ok(!ret, "SetupGetFileCompressionInfo failed unexpectedly\n");
471 ok(name && !lstrcmpA(name, source), "got %s, expected %s\n", name, source);
472 ok(source_size == sizeof(uncompressed), "got %d\n", source_size);
473 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
474 ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
475
476 MyFree(name);
477 DeleteFileA(source);
478 }
479
480 static void test_SetupGetFileCompressionInfoEx(void)
481 {
482 BOOL ret;
483 DWORD required_len, source_size, target_size;
484 char source[MAX_PATH], temp[MAX_PATH], name[MAX_PATH];
485 UINT type;
486
487 GetTempPathA(sizeof(temp), temp);
488 GetTempFileNameA(temp, "doc", 0, source);
489
490 ret = pSetupGetFileCompressionInfoExA(NULL, NULL, 0, NULL, NULL, NULL, NULL);
491 ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
492
493 ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, NULL, NULL, NULL, NULL);
494 ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
495
496 ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, &required_len, NULL, NULL, NULL);
497 ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
498 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
499
500 create_source_file(source, comp_lzx, sizeof(comp_lzx));
501
502 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
503 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
504 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
505 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
506 ok(source_size == sizeof(comp_lzx), "got %d\n", source_size);
507 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
508 ok(type == FILE_COMPRESSION_WINLZA, "got %d, expected FILE_COMPRESSION_WINLZA\n", type);
509 DeleteFileA(source);
510
511 create_source_file(source, comp_zip, sizeof(comp_zip));
512
513 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
514 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
515 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
516 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
517 ok(source_size == sizeof(comp_zip), "got %d\n", source_size);
518 ok(target_size == sizeof(comp_zip), "got %d\n", target_size);
519 ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
520 DeleteFileA(source);
521
522 create_source_file(source, comp_cab_lzx, sizeof(comp_cab_lzx));
523
524 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
525 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
526 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
527 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
528 ok(source_size == sizeof(comp_cab_lzx), "got %d\n", source_size);
529 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
530 ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
531 DeleteFileA(source);
532
533 create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
534
535 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
536 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
537 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
538 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
539 ok(source_size == sizeof(comp_cab_zip), "got %d\n", source_size);
540 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
541 ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
542 DeleteFileA(source);
543 }
544
545 static void test_SetupDecompressOrCopyFile(void)
546 {
547 DWORD ret;
548 char source[MAX_PATH], target[MAX_PATH], temp[MAX_PATH], *p;
549 UINT type;
550 int i;
551
552 const struct
553 {
554 PCSTR source;
555 PCSTR target;
556 PUINT type;
557 } invalid_parameters[] =
558 {
559 {NULL, NULL, NULL},
560 {NULL, NULL, &type},
561 {NULL, target, NULL},
562 {NULL, target, &type},
563 {source, NULL, NULL},
564 {source, NULL, &type},
565 };
566
567 const struct
568 {
569 const char *filename;
570 const BYTE *expected_buffer;
571 const size_t buffer_size;
572 } zip_multi_tests[] =
573 {
574 {"tristram", laurence, sizeof(laurence)},
575 {"tristram.txt", laurence, sizeof(laurence)},
576 {"wine", laurence, sizeof(laurence)},
577 {"wine.txt", laurence, sizeof(laurence)},
578 {"shandy", laurence, sizeof(laurence)},
579 {"shandy.txt", laurence, sizeof(laurence)},
580 {"deadbeef", laurence, sizeof(laurence)},
581 {"deadbeef.txt", laurence, sizeof(laurence)},
582 };
583
584 GetTempPathA(sizeof(temp), temp);
585 GetTempFileNameA(temp, "doc", 0, source);
586 GetTempFileNameA(temp, "doc", 0, target);
587
588 /* parameter tests */
589
590 create_source_file(source, uncompressed, sizeof(uncompressed));
591
592 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
593 {
594 type = FILE_COMPRESSION_NONE;
595 ret = SetupDecompressOrCopyFileA(invalid_parameters[i].source,
596 invalid_parameters[i].target,
597 invalid_parameters[i].type);
598 ok(ret == ERROR_INVALID_PARAMETER,
599 "[%d] Expected SetupDecompressOrCopyFileA to return ERROR_INVALID_PARAMETER, got %u\n",
600 i, ret);
601
602 /* try an invalid compression type */
603 type = 5;
604 ret = SetupDecompressOrCopyFileA(invalid_parameters[i].source,
605 invalid_parameters[i].target,
606 invalid_parameters[i].type);
607 ok(ret == ERROR_INVALID_PARAMETER,
608 "[%d] Expected SetupDecompressOrCopyFileA to return ERROR_INVALID_PARAMETER, got %u\n",
609 i, ret);
610 }
611
612 type = 5; /* try an invalid compression type */
613 ret = SetupDecompressOrCopyFileA(source, target, &type);
614 ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
615
616 DeleteFileA(target);
617
618 /* no compression tests */
619
620 ret = SetupDecompressOrCopyFileA(source, target, NULL);
621 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
622 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
623
624 /* try overwriting existing file */
625 ret = SetupDecompressOrCopyFileA(source, target, NULL);
626 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
627 DeleteFileA(target);
628
629 type = FILE_COMPRESSION_NONE;
630 ret = SetupDecompressOrCopyFileA(source, target, &type);
631 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
632 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
633 DeleteFileA(target);
634
635 type = FILE_COMPRESSION_WINLZA;
636 ret = SetupDecompressOrCopyFileA(source, target, &type);
637 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
638 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
639 DeleteFileA(target);
640
641 /* lz compression tests */
642
643 create_source_file(source, comp_lzx, sizeof(comp_lzx));
644
645 ret = SetupDecompressOrCopyFileA(source, target, NULL);
646 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
647 DeleteFileA(target);
648
649 /* zip compression tests */
650
651 create_source_file(source, comp_zip, sizeof(comp_zip));
652
653 ret = SetupDecompressOrCopyFileA(source, target, NULL);
654 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
655 ok(compare_file_data(target, comp_zip, sizeof(comp_zip)), "incorrect target file\n");
656 DeleteFileA(target);
657
658 /* cabinet compression tests */
659
660 create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
661
662 p = strrchr(target, '\\');
663 lstrcpyA(p + 1, "wine");
664
665 ret = SetupDecompressOrCopyFileA(source, target, NULL);
666 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
667 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
668
669 /* try overwriting existing file */
670 ret = SetupDecompressOrCopyFileA(source, target, NULL);
671 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
672
673 /* try zip compression */
674 type = FILE_COMPRESSION_MSZIP;
675 ret = SetupDecompressOrCopyFileA(source, target, &type);
676 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
677 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
678
679 /* try no compression */
680 type = FILE_COMPRESSION_NONE;
681 ret = SetupDecompressOrCopyFileA(source, target, &type);
682 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
683 ok(compare_file_data(target, comp_cab_zip, sizeof(comp_cab_zip)), "incorrect target file\n");
684
685 /* Show that SetupDecompressOrCopyFileA simply extracts the first file it
686 * finds within the compressed cabinet. Contents are:
687 * tristram -> "laurence\r\n"
688 * wine -> "uncompressed\r\n"
689 * shandy -> "sterne\r\n" */
690
691 create_source_file(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
692
693 p = strrchr(target, '\\');
694
695 for (i = 0; i < sizeof(zip_multi_tests)/sizeof(zip_multi_tests[0]); i++)
696 {
697 lstrcpyA(p + 1, zip_multi_tests[i].filename);
698
699 ret = SetupDecompressOrCopyFileA(source, target, NULL);
700 ok(!ret, "[%d] SetupDecompressOrCopyFile failed unexpectedly: %d\n", i, ret);
701 ok(compare_file_data(target, zip_multi_tests[i].expected_buffer, zip_multi_tests[i].buffer_size),
702 "[%d] incorrect target file\n", i);
703 DeleteFileA(target);
704 }
705
706 DeleteFileA(source);
707 }
708
709 static void test_SetupUninstallOEMInf(void)
710 {
711 BOOL ret;
712
713 SetLastError(0xdeadbeef);
714 ret = pSetupUninstallOEMInfA(NULL, 0, NULL);
715 ok(!ret, "Expected failure\n");
716 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
717
718 SetLastError(0xdeadbeef);
719 ret = pSetupUninstallOEMInfA("", 0, NULL);
720 todo_wine
721 {
722 ok(!ret, "Expected failure\n");
723 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
724 }
725
726 SetLastError(0xdeadbeef);
727 ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL);
728 todo_wine
729 {
730 ok(!ret, "Expected failure\n");
731 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
732 }
733 }
734
735 struct default_callback_context
736 {
737 DWORD magic;
738 HWND owner;
739 DWORD unk1[4];
740 DWORD_PTR unk2[7];
741 HWND progress;
742 UINT message;
743 DWORD_PTR unk3[5];
744 };
745
746 static void test_defaultcallback(void)
747 {
748 struct default_callback_context *ctxt;
749 static const DWORD magic = 0x43515053; /* "SPQC" */
750 HWND owner, progress;
751
752 owner = (HWND)0x123;
753 progress = (HWND)0x456;
754 ctxt = SetupInitDefaultQueueCallbackEx(owner, progress, WM_USER, 0, NULL);
755 ok(ctxt != NULL, "got %p\n", ctxt);
756
757 ok(ctxt->magic == magic || broken(ctxt->magic != magic) /* win2000 */, "got magic 0x%08x\n", ctxt->magic);
758 if (ctxt->magic == magic)
759 {
760 ok(ctxt->owner == owner, "got %p, expected %p\n", ctxt->owner, owner);
761 ok(ctxt->progress == progress, "got %p, expected %p\n", ctxt->progress, progress);
762 ok(ctxt->message == WM_USER, "got %d, expected %d\n", ctxt->message, WM_USER);
763 SetupTermDefaultQueueCallback(ctxt);
764 }
765 else
766 {
767 win_skip("Skipping tests on old systems.\n");
768 SetupTermDefaultQueueCallback(ctxt);
769 return;
770 }
771
772 ctxt = SetupInitDefaultQueueCallback(owner);
773 ok(ctxt->magic == magic, "got magic 0x%08x\n", ctxt->magic);
774 ok(ctxt->owner == owner, "got %p, expected %p\n", ctxt->owner, owner);
775 ok(ctxt->progress == NULL, "got %p, expected %p\n", ctxt->progress, progress);
776 ok(ctxt->message == 0, "got %d\n", ctxt->message);
777 SetupTermDefaultQueueCallback(ctxt);
778 }
779
780 static void test_SetupLogError(void)
781 {
782 BOOL ret;
783 DWORD error;
784
785 SetLastError(0xdeadbeef);
786 ret = SetupLogErrorA("Test without opening\r\n", LogSevInformation);
787 error = GetLastError();
788 ok(!ret, "SetupLogError succeeded\n");
789 ok(error == ERROR_FILE_INVALID, "got wrong error: %d\n", error);
790
791 SetLastError(0xdeadbeef);
792 ret = SetupOpenLog(FALSE);
793 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
794 {
795 win_skip("SetupOpenLog() failed on insufficient permissions\n");
796 return;
797 }
798 ok(ret, "SetupOpenLog failed, error %d\n", GetLastError());
799
800 SetLastError(0xdeadbeef);
801 ret = SetupLogErrorA("Test with wrong log severity\r\n", LogSevMaximum);
802 error = GetLastError();
803 ok(!ret, "SetupLogError succeeded\n");
804 ok(error == 0xdeadbeef, "got wrong error: %d\n", error);
805 ret = SetupLogErrorA("Test without EOL", LogSevInformation);
806 ok(ret, "SetupLogError failed\n");
807
808 SetLastError(0xdeadbeef);
809 ret = SetupLogErrorA(NULL, LogSevInformation);
810 ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_PARAMETER /* Win Vista+ */),
811 "SetupLogError failed: %08x\n", GetLastError());
812
813 SetLastError(0xdeadbeef);
814 ret = SetupOpenLog(FALSE);
815 ok(ret, "SetupOpenLog failed, error %d\n", GetLastError());
816
817 SetupCloseLog();
818 }
819
820 static void test_CM_Get_Version(void)
821 {
822 WORD ret;
823
824 ret = CM_Get_Version();
825 ok(ret == 0x0400, "got version %#x\n", ret);
826 }
827
828 START_TEST(misc)
829 {
830 HMODULE hsetupapi = GetModuleHandleA("setupapi.dll");
831
832 pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA");
833 pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA");
834 pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA");
835 pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA");
836
837 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
838
839 if (pSetupCopyOEMInfA)
840 test_SetupCopyOEMInf();
841 else
842 win_skip("SetupCopyOEMInfA is not available\n");
843
844 test_SetupGetFileCompressionInfo();
845
846 if (pSetupGetFileCompressionInfoExA)
847 test_SetupGetFileCompressionInfoEx();
848 else
849 win_skip("SetupGetFileCompressionInfoExA is not available\n");
850
851 test_SetupDecompressOrCopyFile();
852
853 if (pSetupUninstallOEMInfA)
854 test_SetupUninstallOEMInf();
855 else
856 win_skip("SetupUninstallOEMInfA is not available\n");
857
858 test_defaultcallback();
859
860 test_SetupLogError();
861 test_CM_Get_Version();
862 }