dbe684bb295f723fed1a5373fcd660dd97225bd3
[reactos.git] / modules / 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 if (!res && GetLastError() == ERROR_ACCESS_DENIED)
235 {
236 skip("SetupCopyOEMInfA() failed on insufficient permissions\n");
237 return;
238 }
239 ok(res == TRUE, "Expected TRUE, got %d\n", res);
240 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
241 ok(file_exists(path), "Expected source inf to exist\n");
242
243 /* try SP_COPY_REPLACEONLY, dest exists */
244 SetLastError(0xdeadbeef);
245 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
246 ok(res == TRUE, "Expected TRUE, got %d\n", res);
247 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
248 ok(file_exists(path), "Expected source inf to exist\n");
249
250 /* try SP_COPY_NOOVERWRITE */
251 SetLastError(0xdeadbeef);
252 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
253 ok(res == FALSE, "Expected FALSE, got %d\n", res);
254 ok(GetLastError() == ERROR_FILE_EXISTS,
255 "Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
256
257 /* get the DestinationInfFileName */
258 SetLastError(0xdeadbeef);
259 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, NULL, NULL);
260 ok(res == TRUE, "Expected TRUE, got %d\n", res);
261 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
262 ok(strlen(dest) != 0, "Expected a non-zero length string\n");
263 ok(file_exists(dest), "Expected destination inf to exist\n");
264 ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
265 ok(file_exists(path), "Expected source inf to exist\n");
266
267 strcpy(dest_save, dest);
268 DeleteFileA(dest_save);
269
270 /* get the DestinationInfFileName, DestinationInfFileNameSize is too small
271 * - inf is still copied
272 */
273 strcpy(dest, "aaa");
274 size = 0;
275 SetLastError(0xdeadbeef);
276 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, 5, &size, NULL);
277 ok(res == FALSE, "Expected FALSE, got %d\n", res);
278 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
279 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
280 ok(file_exists(path), "Expected source inf to exist\n");
281 ok(file_exists(dest_save), "Expected dest inf to exist\n");
282 ok(!strcmp(dest, "aaa"), "Expected dest to be unchanged\n");
283 ok(size == strlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
284
285 /* get the DestinationInfFileName and DestinationInfFileNameSize */
286 SetLastError(0xdeadbeef);
287 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, NULL);
288 ok(res == TRUE, "Expected TRUE, got %d\n", res);
289 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
290 ok(lstrlenA(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlenA(dest), size);
291 ok(file_exists(dest), "Expected destination inf to exist\n");
292 ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
293 ok(file_exists(path), "Expected source inf to exist\n");
294 ok(size == lstrlenA(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
295
296 test_original_file_name(strrchr(path, '\\') + 1, dest);
297
298 /* get the DestinationInfFileName, DestinationInfFileNameSize, and DestinationInfFileNameComponent */
299 SetLastError(0xdeadbeef);
300 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, &inf);
301 ok(res == TRUE, "Expected TRUE, got %d\n", res);
302 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
303 ok(lstrlenA(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlenA(dest), size);
304 ok(file_exists(dest), "Expected destination inf to exist\n");
305 ok((inf && inf[0] != 0) ||
306 broken(!inf), /* Win98 */
307 "Expected inf to point to the filename\n");
308 ok(check_format(dest, inf), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
309 ok(file_exists(path), "Expected source inf to exist\n");
310 ok(size == lstrlenA(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
311
312 /* try SP_COPY_DELETESOURCE */
313 SetLastError(0xdeadbeef);
314 res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_DELETESOURCE, NULL, 0, NULL, NULL);
315 ok(res == TRUE, "Expected TRUE, got %d\n", res);
316 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
317 ok(!file_exists(path), "Expected source inf to not exist\n");
318
319 if (pSetupUninstallOEMInfA)
320 {
321 char pnf[MAX_PATH];
322 char *pnffile;
323 char *destfile = strrchr(dest, '\\') + 1;
324
325 strcpy(pnf, dest);
326 *(strrchr(pnf, '.') + 1) = 'p';
327 pnffile = strrchr(pnf, '\\') + 1;
328
329 SetLastError(0xdeadbeef);
330 res = pSetupUninstallOEMInfA(destfile, 0, NULL);
331 if(!res)
332 res = pSetupUninstallOEMInfA(pnffile, 0, NULL);
333 ok(res, "Failed to uninstall '%s'/'%s' : %d\n", destfile,
334 pnffile, GetLastError());
335 todo_wine ok(!file_exists(dest), "Expected inf '%s' to not exist\n", dest);
336 if(file_exists(dest))
337 {
338 SetLastError(0xdeadbeef);
339 res = DeleteFileA(dest);
340 ok(res, "Failed to delete file '%s' : %d\n", dest, GetLastError());
341 }
342 ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf);
343 if(file_exists(pnf))
344 {
345 SetLastError(0xdeadbeef);
346 res = DeleteFileA(pnf);
347 ok(res, "Failed to delete file '%s' : %d\n", pnf, GetLastError());
348 }
349 }
350 else
351 {
352 /* Win9x/WinMe */
353 SetLastError(0xdeadbeef);
354 res = DeleteFileA(dest);
355 ok(res, "Failed to delete file '%s' : %d\n", dest, GetLastError());
356
357 /* On WinMe we also need to remove the .pnf file */
358 *(strrchr(dest, '.') + 1) = 'p';
359 DeleteFileA(dest);
360 }
361 }
362
363 static void create_source_file(LPSTR filename, const BYTE *data, DWORD size)
364 {
365 HANDLE handle;
366 DWORD written;
367
368 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
369 WriteFile(handle, data, size, &written, NULL);
370 CloseHandle(handle);
371 }
372
373 static BOOL compare_file_data(LPSTR file, const BYTE *data, DWORD size)
374 {
375 DWORD read;
376 HANDLE handle;
377 BOOL ret = FALSE;
378 LPBYTE buffer;
379
380 handle = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
381 buffer = HeapAlloc(GetProcessHeap(), 0, size);
382 if (buffer)
383 {
384 ReadFile(handle, buffer, size, &read, NULL);
385 if (read == size && !memcmp(data, buffer, size)) ret = TRUE;
386 HeapFree(GetProcessHeap(), 0, buffer);
387 }
388 CloseHandle(handle);
389 return ret;
390 }
391
392 static const BYTE uncompressed[] = {
393 'u','n','c','o','m','p','r','e','s','s','e','d','\r','\n'
394 };
395 static const BYTE laurence[] = {
396 'l','a','u','r','e','n','c','e','\r','\n'
397 };
398 static const BYTE comp_lzx[] = {
399 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33, 0x41, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x00,
400 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x3f, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64
401 };
402 static const BYTE comp_zip[] = {
403 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11,
404 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x15, 0x00, 0x77, 0x69,
405 0x6e, 0x65, 0x55, 0x54, 0x09, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46, 0xfd, 0x0d, 0x10, 0x46, 0x55,
406 0x78, 0x04, 0x00, 0xe8, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72,
407 0x65, 0x73, 0x73, 0x65, 0x64, 0x50, 0x4b, 0x01, 0x02, 0x17, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00,
408 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11, 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
409 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00,
410 0x00, 0x00, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x55, 0x54, 0x05, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46,
411 0x55, 0x78, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
412 0x3f, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00
413 };
414 static const BYTE comp_cab_lzx[] = {
415 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x0f, 0x0e, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x36, 0x86, 0x72, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
419 0x00, 0x19, 0xd0, 0x1a, 0xe3, 0x22, 0x00, 0x0e, 0x00, 0x5b, 0x80, 0x80, 0x8d, 0x00, 0x30, 0xe0,
420 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x63,
421 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x0d, 0x0a
422 };
423 static const BYTE comp_cab_zip[] = {
424 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x36, 0x2f, 0xa5, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
428 0x00, 0x7c, 0x80, 0x26, 0x2b, 0x12, 0x00, 0x0e, 0x00, 0x43, 0x4b, 0x2b, 0xcd, 0x4b, 0xce, 0xcf,
429 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0xe1, 0xe5, 0x02, 0x00
430 };
431 static const BYTE comp_cab_zip_multi[] = {
432 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x74, 0x72, 0x69, 0x73,
436 0x74, 0x72, 0x61, 0x6d, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1,
437 0x38, 0xf0, 0x48, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x73, 0x68, 0x61, 0x6e, 0x64, 0x79,
439 0x00, 0x67, 0x2c, 0x03, 0x85, 0x23, 0x00, 0x20, 0x00, 0x43, 0x4b, 0xcb, 0x49, 0x2c, 0x2d, 0x4a,
440 0xcd, 0x4b, 0x4e, 0xe5, 0xe5, 0x2a, 0xcd, 0x4b, 0xce, 0xcf, 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e,
441 0x4d, 0xe1, 0xe5, 0x2a, 0x2e, 0x49, 0x2d, 0xca, 0x03, 0x8a, 0x02, 0x00
442 };
443
444 static void test_SetupGetFileCompressionInfo(void)
445 {
446 DWORD ret, source_size, target_size;
447 char source[MAX_PATH], temp[MAX_PATH], *name;
448 UINT type;
449
450 GetTempPathA(sizeof(temp), temp);
451 GetTempFileNameA(temp, "fci", 0, source);
452
453 create_source_file(source, uncompressed, sizeof(uncompressed));
454
455 ret = SetupGetFileCompressionInfoA(NULL, NULL, NULL, NULL, NULL);
456 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
457
458 ret = SetupGetFileCompressionInfoA(source, NULL, NULL, NULL, NULL);
459 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
460
461 ret = SetupGetFileCompressionInfoA(source, &name, NULL, NULL, NULL);
462 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
463
464 ret = SetupGetFileCompressionInfoA(source, &name, &source_size, NULL, NULL);
465 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
466
467 ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, NULL);
468 ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
469
470 name = NULL;
471 source_size = target_size = 0;
472 type = 5;
473
474 ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, &type);
475 ok(!ret, "SetupGetFileCompressionInfo failed unexpectedly\n");
476 ok(name && !lstrcmpA(name, source), "got %s, expected %s\n", name, source);
477 ok(source_size == sizeof(uncompressed), "got %d\n", source_size);
478 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
479 ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
480
481 MyFree(name);
482 DeleteFileA(source);
483 }
484
485 static void test_SetupGetFileCompressionInfoEx(void)
486 {
487 BOOL ret;
488 DWORD required_len, source_size, target_size;
489 char source[MAX_PATH], temp[MAX_PATH], name[MAX_PATH];
490 UINT type;
491
492 GetTempPathA(sizeof(temp), temp);
493 GetTempFileNameA(temp, "doc", 0, source);
494
495 ret = pSetupGetFileCompressionInfoExA(NULL, NULL, 0, NULL, NULL, NULL, NULL);
496 ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
497
498 ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, NULL, NULL, NULL, NULL);
499 ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
500
501 ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, &required_len, NULL, NULL, NULL);
502 ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
503 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
504
505 create_source_file(source, comp_lzx, sizeof(comp_lzx));
506
507 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
508 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
509 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
510 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
511 ok(source_size == sizeof(comp_lzx), "got %d\n", source_size);
512 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
513 ok(type == FILE_COMPRESSION_WINLZA, "got %d, expected FILE_COMPRESSION_WINLZA\n", type);
514 DeleteFileA(source);
515
516 create_source_file(source, comp_zip, sizeof(comp_zip));
517
518 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
519 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
520 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
521 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
522 ok(source_size == sizeof(comp_zip), "got %d\n", source_size);
523 ok(target_size == sizeof(comp_zip), "got %d\n", target_size);
524 ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
525 DeleteFileA(source);
526
527 create_source_file(source, comp_cab_lzx, sizeof(comp_cab_lzx));
528
529 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
530 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
531 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
532 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
533 ok(source_size == sizeof(comp_cab_lzx), "got %d\n", source_size);
534 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
535 ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
536 DeleteFileA(source);
537
538 create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
539
540 ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
541 ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
542 ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
543 ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
544 ok(source_size == sizeof(comp_cab_zip), "got %d\n", source_size);
545 ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
546 ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
547 DeleteFileA(source);
548 }
549
550 static void test_SetupDecompressOrCopyFile(void)
551 {
552 DWORD ret;
553 char source[MAX_PATH], target[MAX_PATH], temp[MAX_PATH], *p;
554 UINT type;
555 int i;
556
557 const struct
558 {
559 PCSTR source;
560 PCSTR target;
561 PUINT type;
562 } invalid_parameters[] =
563 {
564 {NULL, NULL, NULL},
565 {NULL, NULL, &type},
566 {NULL, target, NULL},
567 {NULL, target, &type},
568 {source, NULL, NULL},
569 {source, NULL, &type},
570 };
571
572 const struct
573 {
574 const char *filename;
575 const BYTE *expected_buffer;
576 const size_t buffer_size;
577 } zip_multi_tests[] =
578 {
579 {"tristram", laurence, sizeof(laurence)},
580 {"tristram.txt", laurence, sizeof(laurence)},
581 {"wine", laurence, sizeof(laurence)},
582 {"wine.txt", laurence, sizeof(laurence)},
583 {"shandy", laurence, sizeof(laurence)},
584 {"shandy.txt", laurence, sizeof(laurence)},
585 {"deadbeef", laurence, sizeof(laurence)},
586 {"deadbeef.txt", laurence, sizeof(laurence)},
587 };
588
589 GetTempPathA(sizeof(temp), temp);
590 GetTempFileNameA(temp, "doc", 0, source);
591 GetTempFileNameA(temp, "doc", 0, target);
592
593 /* parameter tests */
594
595 create_source_file(source, uncompressed, sizeof(uncompressed));
596
597 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
598 {
599 type = FILE_COMPRESSION_NONE;
600 ret = SetupDecompressOrCopyFileA(invalid_parameters[i].source,
601 invalid_parameters[i].target,
602 invalid_parameters[i].type);
603 ok(ret == ERROR_INVALID_PARAMETER,
604 "[%d] Expected SetupDecompressOrCopyFileA to return ERROR_INVALID_PARAMETER, got %u\n",
605 i, ret);
606
607 /* try an invalid compression type */
608 type = 5;
609 ret = SetupDecompressOrCopyFileA(invalid_parameters[i].source,
610 invalid_parameters[i].target,
611 invalid_parameters[i].type);
612 ok(ret == ERROR_INVALID_PARAMETER,
613 "[%d] Expected SetupDecompressOrCopyFileA to return ERROR_INVALID_PARAMETER, got %u\n",
614 i, ret);
615 }
616
617 type = 5; /* try an invalid compression type */
618 ret = SetupDecompressOrCopyFileA(source, target, &type);
619 ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
620
621 DeleteFileA(target);
622
623 /* no compression tests */
624
625 ret = SetupDecompressOrCopyFileA(source, target, NULL);
626 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
627 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
628
629 /* try overwriting existing file */
630 ret = SetupDecompressOrCopyFileA(source, target, NULL);
631 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
632 DeleteFileA(target);
633
634 type = FILE_COMPRESSION_NONE;
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 type = FILE_COMPRESSION_WINLZA;
641 ret = SetupDecompressOrCopyFileA(source, target, &type);
642 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
643 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
644 DeleteFileA(target);
645
646 /* lz compression tests */
647
648 create_source_file(source, comp_lzx, sizeof(comp_lzx));
649
650 ret = SetupDecompressOrCopyFileA(source, target, NULL);
651 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
652 DeleteFileA(target);
653
654 /* zip compression tests */
655
656 create_source_file(source, comp_zip, sizeof(comp_zip));
657
658 ret = SetupDecompressOrCopyFileA(source, target, NULL);
659 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
660 ok(compare_file_data(target, comp_zip, sizeof(comp_zip)), "incorrect target file\n");
661 DeleteFileA(target);
662
663 /* cabinet compression tests */
664
665 create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
666
667 p = strrchr(target, '\\');
668 lstrcpyA(p + 1, "wine");
669
670 ret = SetupDecompressOrCopyFileA(source, target, NULL);
671 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
672 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
673
674 /* try overwriting existing file */
675 ret = SetupDecompressOrCopyFileA(source, target, NULL);
676 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
677
678 /* try zip compression */
679 type = FILE_COMPRESSION_MSZIP;
680 ret = SetupDecompressOrCopyFileA(source, target, &type);
681 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
682 ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
683
684 /* try no compression */
685 type = FILE_COMPRESSION_NONE;
686 ret = SetupDecompressOrCopyFileA(source, target, &type);
687 ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
688 ok(compare_file_data(target, comp_cab_zip, sizeof(comp_cab_zip)), "incorrect target file\n");
689
690 /* Show that SetupDecompressOrCopyFileA simply extracts the first file it
691 * finds within the compressed cabinet. Contents are:
692 * tristram -> "laurence\r\n"
693 * wine -> "uncompressed\r\n"
694 * shandy -> "sterne\r\n" */
695
696 create_source_file(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi));
697
698 p = strrchr(target, '\\');
699
700 for (i = 0; i < sizeof(zip_multi_tests)/sizeof(zip_multi_tests[0]); i++)
701 {
702 lstrcpyA(p + 1, zip_multi_tests[i].filename);
703
704 ret = SetupDecompressOrCopyFileA(source, target, NULL);
705 ok(!ret, "[%d] SetupDecompressOrCopyFile failed unexpectedly: %d\n", i, ret);
706 ok(compare_file_data(target, zip_multi_tests[i].expected_buffer, zip_multi_tests[i].buffer_size),
707 "[%d] incorrect target file\n", i);
708 DeleteFileA(target);
709 }
710
711 DeleteFileA(source);
712 }
713
714 static void test_SetupUninstallOEMInf(void)
715 {
716 BOOL ret;
717
718 SetLastError(0xdeadbeef);
719 ret = pSetupUninstallOEMInfA(NULL, 0, NULL);
720 ok(!ret, "Expected failure\n");
721 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
722
723 SetLastError(0xdeadbeef);
724 ret = pSetupUninstallOEMInfA("", 0, NULL);
725 todo_wine
726 {
727 ok(!ret, "Expected failure\n");
728 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
729 }
730
731 SetLastError(0xdeadbeef);
732 ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL);
733 todo_wine
734 {
735 ok(!ret, "Expected failure\n");
736 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
737 }
738 }
739
740 struct default_callback_context
741 {
742 DWORD magic;
743 HWND owner;
744 DWORD unk1[4];
745 DWORD_PTR unk2[7];
746 HWND progress;
747 UINT message;
748 DWORD_PTR unk3[5];
749 };
750
751 static void test_defaultcallback(void)
752 {
753 struct default_callback_context *ctxt;
754 static const DWORD magic = 0x43515053; /* "SPQC" */
755 HWND owner, progress;
756
757 owner = (HWND)0x123;
758 progress = (HWND)0x456;
759 ctxt = SetupInitDefaultQueueCallbackEx(owner, progress, WM_USER, 0, NULL);
760 ok(ctxt != NULL, "got %p\n", ctxt);
761
762 ok(ctxt->magic == magic || broken(ctxt->magic != magic) /* win2000 */, "got magic 0x%08x\n", ctxt->magic);
763 if (ctxt->magic == magic)
764 {
765 ok(ctxt->owner == owner, "got %p, expected %p\n", ctxt->owner, owner);
766 ok(ctxt->progress == progress, "got %p, expected %p\n", ctxt->progress, progress);
767 ok(ctxt->message == WM_USER, "got %d, expected %d\n", ctxt->message, WM_USER);
768 SetupTermDefaultQueueCallback(ctxt);
769 }
770 else
771 {
772 win_skip("Skipping tests on old systems.\n");
773 SetupTermDefaultQueueCallback(ctxt);
774 return;
775 }
776
777 ctxt = SetupInitDefaultQueueCallback(owner);
778 ok(ctxt->magic == magic, "got magic 0x%08x\n", ctxt->magic);
779 ok(ctxt->owner == owner, "got %p, expected %p\n", ctxt->owner, owner);
780 ok(ctxt->progress == NULL, "got %p, expected %p\n", ctxt->progress, progress);
781 ok(ctxt->message == 0, "got %d\n", ctxt->message);
782 SetupTermDefaultQueueCallback(ctxt);
783 }
784
785 static void test_SetupLogError(void)
786 {
787 BOOL ret;
788 DWORD error;
789
790 SetLastError(0xdeadbeef);
791 ret = SetupLogErrorA("Test without opening\r\n", LogSevInformation);
792 error = GetLastError();
793 ok(!ret, "SetupLogError succeeded\n");
794 ok(error == ERROR_FILE_INVALID, "got wrong error: %d\n", error);
795
796 SetLastError(0xdeadbeef);
797 ret = SetupOpenLog(FALSE);
798 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
799 {
800 skip("SetupOpenLog() failed on insufficient permissions\n");
801 return;
802 }
803 ok(ret, "SetupOpenLog failed, error %d\n", GetLastError());
804
805 SetLastError(0xdeadbeef);
806 ret = SetupLogErrorA("Test with wrong log severity\r\n", LogSevMaximum);
807 error = GetLastError();
808 ok(!ret, "SetupLogError succeeded\n");
809 ok(error == 0xdeadbeef, "got wrong error: %d\n", error);
810 ret = SetupLogErrorA("Test without EOL", LogSevInformation);
811 ok(ret, "SetupLogError failed\n");
812
813 SetLastError(0xdeadbeef);
814 ret = SetupLogErrorA(NULL, LogSevInformation);
815 ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_PARAMETER /* Win Vista+ */),
816 "SetupLogError failed: %08x\n", GetLastError());
817
818 SetLastError(0xdeadbeef);
819 ret = SetupOpenLog(FALSE);
820 ok(ret, "SetupOpenLog failed, error %d\n", GetLastError());
821
822 SetupCloseLog();
823 }
824
825 static void test_CM_Get_Version(void)
826 {
827 WORD ret;
828
829 ret = CM_Get_Version();
830 ok(ret == 0x0400, "got version %#x\n", ret);
831 }
832
833 START_TEST(misc)
834 {
835 HMODULE hsetupapi = GetModuleHandleA("setupapi.dll");
836
837 pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA");
838 pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA");
839 pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA");
840 pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA");
841
842 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
843
844 if (pSetupCopyOEMInfA)
845 test_SetupCopyOEMInf();
846 else
847 win_skip("SetupCopyOEMInfA is not available\n");
848
849 test_SetupGetFileCompressionInfo();
850
851 if (pSetupGetFileCompressionInfoExA)
852 test_SetupGetFileCompressionInfoEx();
853 else
854 win_skip("SetupGetFileCompressionInfoExA is not available\n");
855
856 test_SetupDecompressOrCopyFile();
857
858 if (pSetupUninstallOEMInfA)
859 test_SetupUninstallOEMInf();
860 else
861 win_skip("SetupUninstallOEMInfA is not available\n");
862
863 test_defaultcallback();
864
865 test_SetupLogError();
866 test_CM_Get_Version();
867 }