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 } 868