1 /* 2 * Unit test for setupapi.dll install functions 3 * 4 * Copyright 2007 Misha Koshelev 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <assert.h> 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winnls.h" 29 #include "winuser.h" 30 #include "winreg.h" 31 #include "winsvc.h" 32 #include "setupapi.h" 33 #include "shlobj.h" 34 35 #include "wine/test.h" 36 37 static const char inffile[] = "test.inf"; 38 static const WCHAR inffileW[] = {'t','e','s','t','.','i','n','f',0}; 39 static char CURR_DIR[MAX_PATH]; 40 41 /* Notes on InstallHinfSectionA/W: 42 * - InstallHinfSectionA on WinXP seems to be a stub - it does not do anything 43 * and simply returns without displaying any error message or setting last 44 * error. 45 * - These functions do not return a value and do not always set last error to 46 * ERROR_SUCCESS when installation still occurs (e.g., unquoted inf file with 47 * spaces, registry keys are written but last error is 6). 48 * - On installation problems, a MessageBox() is displayed and a Beep() is 49 * issued. The MessageBox() is disabled with a CBT hook. 50 */ 51 52 /* 53 * Helpers 54 */ 55 56 static void create_inf_file(LPCSTR filename, const char *data) 57 { 58 DWORD res; 59 BOOL ret; 60 HANDLE handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, 61 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 62 assert(handle != INVALID_HANDLE_VALUE); 63 ret = WriteFile(handle, data, strlen(data), &res, NULL); 64 assert(ret != 0); 65 CloseHandle(handle); 66 } 67 68 /* CBT hook to ensure a window (e.g., MessageBox) cannot be created */ 69 static HHOOK hhook; 70 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 71 { 72 return nCode == HCBT_CREATEWND ? 1: CallNextHookEx(hhook, nCode, wParam, lParam); 73 } 74 75 /* 76 * Tests 77 */ 78 79 static const char *cmdline_inf = "[Version]\n" 80 "Signature=\"$Chicago$\"\n" 81 "[DefaultInstall]\n" 82 "AddReg=Add.Settings\n" 83 "[Add.Settings]\n" 84 "HKCU,Software\\Wine\\setupapitest,,\n"; 85 86 static void run_cmdline(LPCSTR section, int mode, LPCSTR path) 87 { 88 CHAR cmdline[MAX_PATH * 2]; 89 WCHAR cmdlinew[MAX_PATH * 2]; 90 91 sprintf(cmdline, "%s %d %s", section, mode, path); 92 MultiByteToWideChar(CP_ACP, 0, cmdline, -1, cmdlinew, MAX_PATH*2); 93 InstallHinfSectionW(NULL, NULL, cmdlinew, 0); 94 } 95 96 static void ok_registry(BOOL expectsuccess) 97 { 98 LONG ret; 99 100 /* Functional tests for success of install and clean up */ 101 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest"); 102 ok((expectsuccess && ret == ERROR_SUCCESS) || 103 (!expectsuccess && ret == ERROR_FILE_NOT_FOUND), 104 "Expected registry key Software\\Wine\\setupapitest to %s, RegDeleteKey returned %d\n", 105 expectsuccess ? "exist" : "not exist", 106 ret); 107 } 108 109 /* Test command line processing */ 110 static void test_cmdline(void) 111 { 112 static const char infwithspaces[] = "test file.inf"; 113 char path[MAX_PATH]; 114 BOOL ret; 115 116 create_inf_file(inffile, cmdline_inf); 117 sprintf(path, "%s\\%s", CURR_DIR, inffile); 118 run_cmdline("DefaultInstall", 128, path); 119 ok_registry(TRUE); 120 ret = DeleteFileA(inffile); 121 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError()); 122 123 /* Test handling of spaces in path, unquoted and quoted */ 124 create_inf_file(infwithspaces, cmdline_inf); 125 126 sprintf(path, "%s\\%s", CURR_DIR, infwithspaces); 127 run_cmdline("DefaultInstall", 128, path); 128 ok_registry(TRUE); 129 130 sprintf(path, "\"%s\\%s\"", CURR_DIR, infwithspaces); 131 run_cmdline("DefaultInstall", 128, path); 132 ok_registry(FALSE); 133 134 ret = DeleteFileA(infwithspaces); 135 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError()); 136 } 137 138 static const char *cmdline_inf_reg = "[Version]\n" 139 "Signature=\"$Chicago$\"\n" 140 "[DefaultInstall]\n" 141 "DelReg=Del.Settings\n" 142 "[Del.Settings]\n" 143 "HKCU,Software\\Wine\\setupapitest\n"; 144 145 static void test_registry(void) 146 { 147 HKEY key; 148 LONG res; 149 char path[MAX_PATH]; 150 BOOL ret; 151 152 /* First create a registry structure we would like to be deleted */ 153 ok(!RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key), 154 "Expected RegCreateKeyA to succeed\n"); 155 156 /* Doublecheck if the registry key is present */ 157 ok(!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key), 158 "Expected registry key to exist\n"); 159 160 create_inf_file(inffile, cmdline_inf_reg); 161 sprintf(path, "%s\\%s", CURR_DIR, inffile); 162 run_cmdline("DefaultInstall", 128, path); 163 164 /* Check if the registry key is recursively deleted */ 165 res = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key); 166 ok(res == ERROR_FILE_NOT_FOUND, "Didn't expect the registry key to exist\n"); 167 /* Just in case */ 168 if (res == ERROR_SUCCESS) 169 { 170 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest"); 171 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest"); 172 } 173 ret = DeleteFileA(inffile); 174 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError()); 175 } 176 177 static void test_install_svc_from(void) 178 { 179 char inf[2048]; 180 char path[MAX_PATH]; 181 HINF infhandle; 182 BOOL ret; 183 SC_HANDLE scm_handle, svc_handle; 184 185 /* Basic inf file to satisfy SetupOpenInfFileA */ 186 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n"); 187 create_inf_file(inffile, inf); 188 sprintf(path, "%s\\%s", CURR_DIR, inffile); 189 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 190 191 /* Nothing but the Version section */ 192 SetLastError(0xdeadbeef); 193 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 194 ok(!ret, "Expected failure\n"); 195 ok(GetLastError() == ERROR_SECTION_NOT_FOUND, 196 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError()); 197 SetupCloseInfFile(infhandle); 198 DeleteFileA(inffile); 199 200 /* Add the section */ 201 strcat(inf, "[Winetest.Services]\n"); 202 create_inf_file(inffile, inf); 203 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 204 SetLastError(0xdeadbeef); 205 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 206 ok(!ret, "Expected failure\n"); 207 ok(GetLastError() == ERROR_SECTION_NOT_FOUND, 208 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError()); 209 SetupCloseInfFile(infhandle); 210 DeleteFileA(inffile); 211 212 /* Add a reference */ 213 strcat(inf, "AddService=Winetest,,Winetest.Service\n"); 214 create_inf_file(inffile, inf); 215 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 216 SetLastError(0xdeadbeef); 217 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 218 ok(!ret, "Expected failure\n"); 219 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 220 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError()); 221 SetupCloseInfFile(infhandle); 222 DeleteFileA(inffile); 223 224 /* Add the section */ 225 strcat(inf, "[Winetest.Service]\n"); 226 create_inf_file(inffile, inf); 227 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 228 SetLastError(0xdeadbeef); 229 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 230 ok(!ret, "Expected failure\n"); 231 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 232 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError()); 233 SetupCloseInfFile(infhandle); 234 DeleteFileA(inffile); 235 236 /* Just the ServiceBinary */ 237 strcat(inf, "ServiceBinary=%12%\\winetest.sys\n"); 238 create_inf_file(inffile, inf); 239 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 240 SetLastError(0xdeadbeef); 241 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 242 ok(!ret, "Expected failure\n"); 243 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 244 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError()); 245 SetupCloseInfFile(infhandle); 246 DeleteFileA(inffile); 247 248 /* Add the ServiceType */ 249 strcat(inf, "ServiceType=1\n"); 250 create_inf_file(inffile, inf); 251 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 252 SetLastError(0xdeadbeef); 253 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 254 ok(!ret, "Expected failure\n"); 255 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 256 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError()); 257 SetupCloseInfFile(infhandle); 258 DeleteFileA(inffile); 259 260 /* Add the StartType */ 261 strcat(inf, "StartType=4\n"); 262 create_inf_file(inffile, inf); 263 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 264 SetLastError(0xdeadbeef); 265 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 266 ok(!ret, "Expected failure\n"); 267 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT, 268 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError()); 269 SetupCloseInfFile(infhandle); 270 DeleteFileA(inffile); 271 272 /* This should be it, the minimal entries to install a service */ 273 strcat(inf, "ErrorControl=1"); 274 create_inf_file(inffile, inf); 275 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 276 SetLastError(0xdeadbeef); 277 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); 278 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 279 { 280 skip("Not enough rights to install the service\n"); 281 SetupCloseInfFile(infhandle); 282 DeleteFileA(inffile); 283 return; 284 } 285 ok(ret, "Expected success\n"); 286 ok(GetLastError() == ERROR_SUCCESS, 287 "Expected ERROR_SUCCESS, got %08x\n", GetLastError()); 288 SetupCloseInfFile(infhandle); 289 DeleteFileA(inffile); 290 291 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 292 293 /* Open the service to see if it's really there */ 294 svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE); 295 ok(svc_handle != NULL, "Service was not created\n"); 296 297 SetLastError(0xdeadbeef); 298 ret = DeleteService(svc_handle); 299 ok(ret, "Service could not be deleted : %d\n", GetLastError()); 300 301 CloseServiceHandle(svc_handle); 302 CloseServiceHandle(scm_handle); 303 304 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n"); 305 strcat(inf, "[XSP.InstallPerVer]\n"); 306 strcat(inf, "AddReg=AspEventlogMsg.Reg,Perf.Reg,AspVersions.Reg,FreeADO.Reg,IndexServer.Reg\n"); 307 create_inf_file(inffile, inf); 308 sprintf(path, "%s\\%s", CURR_DIR, inffile); 309 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); 310 311 SetLastError(0xdeadbeef); 312 ret = SetupInstallServicesFromInfSectionA(infhandle, "XSP.InstallPerVer", 0); 313 ok(ret, "Expected success\n"); 314 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", GetLastError()); 315 SetupCloseInfFile(infhandle); 316 DeleteFileA(inffile); 317 318 /* TODO: Test the Flags */ 319 } 320 321 static void test_driver_install(void) 322 { 323 HANDLE handle; 324 SC_HANDLE scm_handle, svc_handle; 325 BOOL ret; 326 char path[MAX_PATH], windir[MAX_PATH], driver[MAX_PATH]; 327 DWORD attrs; 328 /* Minimal stuff needed */ 329 static const char *inf = 330 "[Version]\n" 331 "Signature=\"$Chicago$\"\n" 332 "[DestinationDirs]\n" 333 "Winetest.DriverFiles=12\n" 334 "[DefaultInstall]\n" 335 "CopyFiles=Winetest.DriverFiles\n" 336 "[DefaultInstall.Services]\n" 337 "AddService=Winetest,,Winetest.Service\n" 338 "[Winetest.Service]\n" 339 "ServiceBinary=%12%\\winetest.sys\n" 340 "ServiceType=1\n" 341 "StartType=4\n" 342 "ErrorControl=1\n" 343 "[Winetest.DriverFiles]\n" 344 "winetest.sys"; 345 346 /* Bail out if we don't have enough rights */ 347 SetLastError(0xdeadbeef); 348 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 349 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 350 { 351 skip("Not enough rights to install the service\n"); 352 return; 353 } 354 CloseServiceHandle(scm_handle); 355 356 /* Place where we expect the driver to be installed */ 357 GetWindowsDirectoryA(windir, MAX_PATH); 358 lstrcpyA(driver, windir); 359 lstrcatA(driver, "\\system32\\drivers\\winetest.sys"); 360 361 /* Create a dummy driver file */ 362 handle = CreateFileA("winetest.sys", GENERIC_WRITE, 0, NULL, 363 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 364 CloseHandle(handle); 365 366 create_inf_file(inffile, inf); 367 sprintf(path, "%s\\%s", CURR_DIR, inffile); 368 run_cmdline("DefaultInstall", 128, path); 369 370 /* Driver should have been installed */ 371 attrs = GetFileAttributesA(driver); 372 ok(attrs != INVALID_FILE_ATTRIBUTES, "Expected driver to exist\n"); 373 374 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 375 376 /* Open the service to see if it's really there */ 377 svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE); 378 ok(svc_handle != NULL, "Service was not created\n"); 379 380 SetLastError(0xdeadbeef); 381 ret = DeleteService(svc_handle); 382 ok(ret, "Service could not be deleted : %d\n", GetLastError()); 383 384 CloseServiceHandle(svc_handle); 385 CloseServiceHandle(scm_handle); 386 387 /* File cleanup */ 388 DeleteFileA(inffile); 389 DeleteFileA("winetest.sys"); 390 DeleteFileA(driver); 391 } 392 393 static void test_profile_items(void) 394 { 395 char path[MAX_PATH], commonprogs[MAX_PATH]; 396 397 static const char *inf = 398 "[Version]\n" 399 "Signature=\"$Chicago$\"\n" 400 "[DefaultInstall]\n" 401 "ProfileItems=TestItem,TestItem2,TestGroup\n" 402 "[TestItem]\n" 403 "Name=TestItem\n" 404 "CmdLine=11,,notepad.exe\n" 405 "[TestItem2]\n" 406 "Name=TestItem2\n" 407 "CmdLine=11,,notepad.exe\n" 408 "SubDir=TestDir\n" 409 "[TestGroup]\n" 410 "Name=TestGroup,4\n" 411 ; 412 413 if (S_OK != SHGetFolderPathA(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, commonprogs)) 414 { 415 skip("No common program files directory exists\n"); 416 goto cleanup; 417 } 418 419 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs); 420 if (!CreateDirectoryA(path, NULL) && GetLastError() == ERROR_ACCESS_DENIED) 421 { 422 skip("need admin rights\n"); 423 return; 424 } 425 RemoveDirectoryA(path); 426 427 create_inf_file(inffile, inf); 428 sprintf(path, "%s\\%s", CURR_DIR, inffile); 429 run_cmdline("DefaultInstall", 128, path); 430 431 snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs); 432 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs); 433 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "directory not created\n"); 434 snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs); 435 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "link not created\n"); 436 snprintf(path, MAX_PATH, "%s\\TestGroup", commonprogs); 437 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "group not created\n"); 438 439 snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs); 440 DeleteFileA(path); 441 snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs); 442 DeleteFileA(path); 443 snprintf(path, MAX_PATH, "%s\\TestItem2.lnk", commonprogs); 444 DeleteFileA(path); 445 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs); 446 RemoveDirectoryA(path); 447 snprintf(path, MAX_PATH, "%s\\TestGroup", commonprogs); 448 RemoveDirectoryA(path); 449 450 cleanup: 451 DeleteFileA(inffile); 452 } 453 454 static void test_inffilelistA(void) 455 { 456 static const char inffile2[] = "test2.inf"; 457 static const char *inf = 458 "[Version]\n" 459 "Signature=\"$Chicago$\""; 460 461 char buffer[MAX_PATH] = { 0 }; 462 char dir[MAX_PATH], *p; 463 DWORD expected, outsize; 464 BOOL ret; 465 466 /* create a private directory, the temp directory may contain some 467 * inf files left over from old installations 468 */ 469 if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dir)) 470 { 471 win_skip("GetTempFileNameA failed with error %d\n", GetLastError()); 472 return; 473 } 474 if (!CreateDirectoryA(dir, NULL )) 475 { 476 win_skip("CreateDirectoryA(%s) failed with error %d\n", dir, GetLastError()); 477 return; 478 } 479 if (!SetCurrentDirectoryA(dir)) 480 { 481 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError()); 482 RemoveDirectoryA(dir); 483 return; 484 } 485 486 create_inf_file(inffile, inf); 487 create_inf_file(inffile2, inf); 488 489 /* mixed style 490 */ 491 expected = 3 + strlen(inffile) + strlen(inffile2); 492 ret = SetupGetInfFileListA(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer, 493 MAX_PATH, &outsize); 494 ok(ret, "expected SetupGetInfFileListA to succeed!\n"); 495 ok(expected == outsize, "expected required buffersize to be %d, got %d\n", 496 expected, outsize); 497 for(p = buffer; lstrlenA(p) && (outsize > (p - buffer)); p+=lstrlenA(p) + 1) 498 ok(!lstrcmpA(p,inffile2) || !lstrcmpA(p,inffile), 499 "unexpected filename %s\n",p); 500 501 DeleteFileA(inffile); 502 DeleteFileA(inffile2); 503 SetCurrentDirectoryA(CURR_DIR); 504 RemoveDirectoryA(dir); 505 } 506 507 static void test_inffilelist(void) 508 { 509 static const char inffile2[] = "test2.inf"; 510 static const WCHAR inffile2W[] = {'t','e','s','t','2','.','i','n','f',0}; 511 static const char invalid_inf[] = "invalid.inf"; 512 static const WCHAR invalid_infW[] = {'i','n','v','a','l','i','d','.','i','n','f',0}; 513 static const char *inf = 514 "[Version]\n" 515 "Signature=\"$Chicago$\""; 516 static const char *inf2 = 517 "[Version]\n" 518 "Signature=\"$CHICAGO$\""; 519 static const char *infNT = 520 "[Version]\n" 521 "Signature=\"$WINDOWS NT$\""; 522 523 WCHAR *p, *ptr; 524 char dirA[MAX_PATH]; 525 WCHAR dir[MAX_PATH] = { 0 }; 526 WCHAR buffer[MAX_PATH] = { 0 }; 527 DWORD expected, outsize; 528 BOOL ret; 529 530 /* NULL means %windir%\\inf 531 * get the value as reference 532 */ 533 expected = 0; 534 SetLastError(0xdeadbeef); 535 ret = SetupGetInfFileListW(NULL, INF_STYLE_WIN4, NULL, 0, &expected); 536 ok(ret, "expected SetupGetInfFileListW to succeed! Error: %d\n", GetLastError()); 537 ok(expected > 0, "expected required buffersize to be at least 1\n"); 538 539 /* check if an empty string doesn't behaves like NULL */ 540 outsize = 0; 541 SetLastError(0xdeadbeef); 542 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); 543 ok(!ret, "expected SetupGetInfFileListW to fail!\n"); 544 545 /* create a private directory, the temp directory may contain some 546 * inf files left over from old installations 547 */ 548 if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dirA)) 549 { 550 win_skip("GetTempFileNameA failed with error %d\n", GetLastError()); 551 return; 552 } 553 if (!CreateDirectoryA(dirA, NULL )) 554 { 555 win_skip("CreateDirectoryA(%s) failed with error %d\n", dirA, GetLastError()); 556 return; 557 } 558 if (!SetCurrentDirectoryA(dirA)) 559 { 560 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError()); 561 RemoveDirectoryA(dirA); 562 return; 563 } 564 565 MultiByteToWideChar(CP_ACP, 0, dirA, -1, dir, MAX_PATH); 566 /* check a not existing directory 567 */ 568 ptr = dir + lstrlenW(dir); 569 MultiByteToWideChar(CP_ACP, 0, "\\not_existent", -1, ptr, MAX_PATH - lstrlenW(dir)); 570 outsize = 0xffffffff; 571 SetLastError(0xdeadbeef); 572 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); 573 ok(ret, "expected SetupGetInfFileListW to succeed!\n"); 574 ok(outsize == 1, "expected required buffersize to be 1, got %d\n", outsize); 575 ok(ERROR_PATH_NOT_FOUND == GetLastError(), 576 "expected error ERROR_PATH_NOT_FOUND, got %d\n", GetLastError()); 577 578 create_inf_file(inffile, inf); 579 create_inf_file(inffile2, inf); 580 create_inf_file(invalid_inf, "This content does not match the inf file format"); 581 582 /* pass a filename instead of a directory 583 */ 584 *ptr = '\\'; 585 MultiByteToWideChar(CP_ACP, 0, invalid_inf, -1, ptr+1, MAX_PATH - lstrlenW(dir)); 586 outsize = 0xffffffff; 587 SetLastError(0xdeadbeef); 588 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); 589 ok(!ret, "expected SetupGetInfFileListW to fail!\n"); 590 ok(ERROR_DIRECTORY == GetLastError(), 591 "expected error ERROR_DIRECTORY, got %d\n", GetLastError()); 592 593 /* make the filename look like directory 594 */ 595 dir[1 + lstrlenW(dir)] = 0; 596 dir[lstrlenW(dir)] = '\\'; 597 SetLastError(0xdeadbeef); 598 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); 599 ok(!ret, "expected SetupGetInfFileListW to fail!\n"); 600 ok(ERROR_DIRECTORY == GetLastError(), 601 "expected error ERROR_DIRECTORY, got %d\n", GetLastError()); 602 603 /* now check the buffer contents of a valid call 604 */ 605 *ptr = 0; 606 expected = 3 + strlen(inffile) + strlen(inffile2); 607 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize); 608 ok(ret, "expected SetupGetInfFileListW to succeed!\n"); 609 ok(expected == outsize, "expected required buffersize to be %d, got %d\n", 610 expected, outsize); 611 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) 612 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW), 613 "unexpected filename %s\n",wine_dbgstr_w(p)); 614 615 /* upper case value 616 */ 617 create_inf_file(inffile2, inf2); 618 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize); 619 ok(ret, "expected SetupGetInfFileListW to succeed!\n"); 620 ok(expected == outsize, "expected required buffersize to be %d, got %d\n", 621 expected, outsize); 622 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) 623 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW), 624 "unexpected filename %s\n",wine_dbgstr_w(p)); 625 626 /* signature Windows NT is also inf style win4 627 */ 628 create_inf_file(inffile2, infNT); 629 expected = 3 + strlen(inffile) + strlen(inffile2); 630 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize); 631 ok(ret, "expected SetupGetInfFileListW to succeed!\n"); 632 ok(expected == outsize, "expected required buffersize to be %d, got %d\n", 633 expected, outsize); 634 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) 635 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW), 636 "unexpected filename %s\n",wine_dbgstr_w(p)); 637 638 /* old style 639 */ 640 expected = 2 + strlen(invalid_inf); 641 ret = SetupGetInfFileListW(dir, INF_STYLE_OLDNT, buffer, MAX_PATH, &outsize); 642 ok(ret, "expected SetupGetInfFileListW to succeed!\n"); 643 ok(expected == outsize, "expected required buffersize to be %d, got %d\n", 644 expected, outsize); 645 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) 646 ok(!lstrcmpW(p,invalid_infW), "unexpected filename %s\n",wine_dbgstr_w(p)); 647 648 /* mixed style 649 */ 650 expected = 4 + strlen(inffile) + strlen(inffile2) + strlen(invalid_inf); 651 ret = SetupGetInfFileListW(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer, 652 MAX_PATH, &outsize); 653 ok(ret, "expected SetupGetInfFileListW to succeed!\n"); 654 ok(expected == outsize, "expected required buffersize to be %d, got %d\n", 655 expected, outsize); 656 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) 657 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW) || !lstrcmpW(p,invalid_infW), 658 "unexpected filename %s\n",wine_dbgstr_w(p)); 659 660 DeleteFileA(inffile); 661 DeleteFileA(inffile2); 662 DeleteFileA(invalid_inf); 663 SetCurrentDirectoryA(CURR_DIR); 664 RemoveDirectoryA(dirA); 665 } 666 667 static const char dirid_inf[] = "[Version]\n" 668 "Signature=\"$Chicago$\"\n" 669 "[DefaultInstall]\n" 670 "AddReg=Add.Settings\n" 671 "[Add.Settings]\n" 672 "HKCU,Software\\Wine\\setupapitest,dirid,,%%%i%%\n"; 673 674 static void check_dirid(int dirid, LPCSTR expected) 675 { 676 char buffer[sizeof(dirid_inf)+11]; 677 char path[MAX_PATH], actual[MAX_PATH]; 678 LONG ret; 679 DWORD size, type; 680 HKEY key; 681 682 sprintf(buffer, dirid_inf, dirid); 683 684 create_inf_file(inffile, buffer); 685 686 sprintf(path, "%s\\%s", CURR_DIR, inffile); 687 run_cmdline("DefaultInstall", 128, path); 688 689 size = sizeof(actual); 690 actual[0] = '\0'; 691 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key); 692 if (ret == ERROR_SUCCESS) 693 { 694 ret = RegQueryValueExA(key, "dirid", NULL, &type, (BYTE*)&actual, &size); 695 RegCloseKey(key); 696 if (type != REG_SZ) 697 ret = ERROR_FILE_NOT_FOUND; 698 } 699 700 ok(ret == ERROR_SUCCESS, "Failed getting value for dirid %i, err=%d\n", dirid, ret); 701 ok(!strcmp(actual, expected), "Expected path for dirid %i was \"%s\", got \"%s\"\n", dirid, expected, actual); 702 703 ok_registry(TRUE); 704 ret = DeleteFileA(inffile); 705 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError()); 706 } 707 708 /* Test dirid values */ 709 static void test_dirid(void) 710 { 711 char expected[MAX_PATH]; 712 713 check_dirid(DIRID_NULL, ""); 714 715 GetWindowsDirectoryA(expected, MAX_PATH); 716 check_dirid(DIRID_WINDOWS, expected); 717 718 GetSystemDirectoryA(expected, MAX_PATH); 719 check_dirid(DIRID_SYSTEM, expected); 720 721 strcat(expected, "\\unknown"); 722 check_dirid(40, expected); 723 } 724 725 START_TEST(install) 726 { 727 char temp_path[MAX_PATH], prev_path[MAX_PATH]; 728 DWORD len; 729 730 GetCurrentDirectoryA(MAX_PATH, prev_path); 731 GetTempPathA(MAX_PATH, temp_path); 732 SetCurrentDirectoryA(temp_path); 733 734 strcpy(CURR_DIR, temp_path); 735 len = strlen(CURR_DIR); 736 if(len && (CURR_DIR[len - 1] == '\\')) 737 CURR_DIR[len - 1] = 0; 738 739 /* Set CBT hook to disallow MessageBox creation in current thread */ 740 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 741 assert(hhook != 0); 742 743 test_cmdline(); 744 test_registry(); 745 test_install_svc_from(); 746 test_driver_install(); 747 test_dirid(); 748 749 UnhookWindowsHookEx(hhook); 750 751 /* We have to run this test after the CBT hook is disabled because 752 ProfileItems needs to create a window on Windows XP. */ 753 test_profile_items(); 754 755 test_inffilelist(); 756 test_inffilelistA(); 757 758 SetCurrentDirectoryA(prev_path); 759 } 760