1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * PURPOSE: System setup 5 * FILE: dll/win32/syssetup/install.c 6 * PROGRAMER: Eric Kohl 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include "precomp.h" 12 13 #define COBJMACROS 14 15 #include <io.h> 16 #include <wincon.h> 17 #include <winnls.h> 18 #include <winsvc.h> 19 #include <userenv.h> 20 #include <shlobj.h> 21 #include <shlwapi.h> 22 #include <shobjidl.h> 23 #include <rpcproxy.h> 24 #include <ndk/cmfuncs.h> 25 26 #define NDEBUG 27 #include <debug.h> 28 29 DWORD WINAPI 30 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout); 31 32 DWORD WINAPI 33 SetupStartService(LPCWSTR lpServiceName, BOOL bWait); 34 35 /* GLOBALS ******************************************************************/ 36 37 HINF hSysSetupInf = INVALID_HANDLE_VALUE; 38 ADMIN_INFO AdminInfo; 39 40 /* FUNCTIONS ****************************************************************/ 41 42 static VOID 43 FatalError(char *pszFmt,...) 44 { 45 char szBuffer[512]; 46 va_list ap; 47 48 va_start(ap, pszFmt); 49 vsprintf(szBuffer, pszFmt, ap); 50 va_end(ap); 51 52 LogItem(NULL, L"Failed"); 53 54 strcat(szBuffer, "\nRebooting now!"); 55 MessageBoxA(NULL, 56 szBuffer, 57 "ReactOS Setup", 58 MB_OK); 59 } 60 61 static HRESULT 62 CreateShellLink( 63 LPCWSTR pszLinkPath, 64 LPCWSTR pszCmd, 65 LPCWSTR pszArg, 66 LPCWSTR pszDir, 67 LPCWSTR pszIconPath, 68 INT iIconNr, 69 LPCWSTR pszComment) 70 { 71 IShellLinkW *psl; 72 IPersistFile *ppf; 73 74 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl); 75 76 if (SUCCEEDED(hr)) 77 { 78 hr = IShellLinkW_SetPath(psl, pszCmd); 79 80 if (pszArg) 81 hr = IShellLinkW_SetArguments(psl, pszArg); 82 83 if (pszDir) 84 hr = IShellLinkW_SetWorkingDirectory(psl, pszDir); 85 86 if (pszIconPath) 87 hr = IShellLinkW_SetIconLocation(psl, pszIconPath, iIconNr); 88 89 if (pszComment) 90 hr = IShellLinkW_SetDescription(psl, pszComment); 91 92 hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf); 93 94 if (SUCCEEDED(hr)) 95 { 96 hr = IPersistFile_Save(ppf, pszLinkPath, TRUE); 97 IPersistFile_Release(ppf); 98 } 99 100 IShellLinkW_Release(psl); 101 } 102 103 return hr; 104 } 105 106 107 static BOOL 108 CreateShortcut( 109 LPCWSTR pszFolder, 110 LPCWSTR pszName, 111 LPCWSTR pszCommand, 112 LPCWSTR pszDescription, 113 INT iIconNr, 114 LPCWSTR pszWorkingDir) 115 { 116 DWORD dwLen; 117 LPWSTR Ptr; 118 LPWSTR lpFilePart; 119 WCHAR szPath[MAX_PATH]; 120 WCHAR szWorkingDirBuf[MAX_PATH]; 121 122 /* If no working directory is provided, try to compute a default one */ 123 if (pszWorkingDir == NULL || pszWorkingDir[0] == L'\0') 124 { 125 if (ExpandEnvironmentStringsW(pszCommand, szPath, ARRAYSIZE(szPath)) == 0) 126 wcscpy(szPath, pszCommand); 127 128 dwLen = GetFullPathNameW(szPath, 129 ARRAYSIZE(szWorkingDirBuf), 130 szWorkingDirBuf, 131 &lpFilePart); 132 if (dwLen != 0 && dwLen <= ARRAYSIZE(szWorkingDirBuf)) 133 { 134 /* Since those should only be called with (.exe) files, 135 lpFilePart has not to be NULL */ 136 ASSERT(lpFilePart != NULL); 137 138 /* We're only interested in the path. Cut the file name off. 139 Also remove the trailing backslash unless the working directory 140 is only going to be a drive, i.e. C:\ */ 141 *(lpFilePart--) = L'\0'; 142 if (!(lpFilePart - szWorkingDirBuf == 2 && 143 szWorkingDirBuf[1] == L':' && szWorkingDirBuf[2] == L'\\')) 144 { 145 *lpFilePart = L'\0'; 146 } 147 pszWorkingDir = szWorkingDirBuf; 148 } 149 } 150 151 /* If we failed to compute a working directory, just do not use one */ 152 if (pszWorkingDir && pszWorkingDir[0] == L'\0') 153 pszWorkingDir = NULL; 154 155 /* Build the shortcut file name */ 156 wcscpy(szPath, pszFolder); 157 Ptr = PathAddBackslash(szPath); 158 wcscpy(Ptr, pszName); 159 160 /* Create the shortcut */ 161 return SUCCEEDED(CreateShellLink(szPath, 162 pszCommand, 163 L"", 164 pszWorkingDir, 165 /* Special value to indicate no icon */ 166 (iIconNr != -1 ? pszCommand : NULL), 167 iIconNr, 168 pszDescription)); 169 } 170 171 172 static BOOL CreateShortcutsFromSection(HINF hinf, LPWSTR pszSection, LPCWSTR pszFolder) 173 { 174 INFCONTEXT Context; 175 DWORD dwFieldCount; 176 INT iIconNr; 177 WCHAR szCommand[MAX_PATH]; 178 WCHAR szName[MAX_PATH]; 179 WCHAR szDescription[MAX_PATH]; 180 WCHAR szDirectory[MAX_PATH]; 181 182 if (!SetupFindFirstLine(hinf, pszSection, NULL, &Context)) 183 return FALSE; 184 185 do 186 { 187 dwFieldCount = SetupGetFieldCount(&Context); 188 if (dwFieldCount < 3) 189 continue; 190 191 if (!SetupGetStringFieldW(&Context, 1, szCommand, ARRAYSIZE(szCommand), NULL)) 192 continue; 193 194 if (!SetupGetStringFieldW(&Context, 2, szName, ARRAYSIZE(szName), NULL)) 195 continue; 196 197 if (!SetupGetStringFieldW(&Context, 3, szDescription, ARRAYSIZE(szDescription), NULL)) 198 continue; 199 200 if (dwFieldCount < 4 || !SetupGetIntField(&Context, 4, &iIconNr)) 201 iIconNr = -1; /* Special value to indicate no icon */ 202 203 if (dwFieldCount < 5 || !SetupGetStringFieldW(&Context, 5, szDirectory, ARRAYSIZE(szDirectory), NULL)) 204 szDirectory[0] = L'\0'; 205 206 wcscat(szName, L".lnk"); 207 208 CreateShortcut(pszFolder, szName, szCommand, szDescription, iIconNr, szDirectory); 209 210 } while (SetupFindNextLine(&Context, &Context)); 211 212 return TRUE; 213 } 214 215 static BOOL CreateShortcuts(HINF hinf, LPCWSTR szSection) 216 { 217 INFCONTEXT Context; 218 WCHAR szPath[MAX_PATH]; 219 WCHAR szFolder[MAX_PATH]; 220 WCHAR szFolderSection[MAX_PATH]; 221 INT csidl; 222 223 CoInitialize(NULL); 224 225 if (!SetupFindFirstLine(hinf, szSection, NULL, &Context)) 226 return FALSE; 227 228 do 229 { 230 if (SetupGetFieldCount(&Context) < 2) 231 continue; 232 233 if (!SetupGetStringFieldW(&Context, 0, szFolderSection, ARRAYSIZE(szFolderSection), NULL)) 234 continue; 235 236 if (!SetupGetIntField(&Context, 1, &csidl)) 237 continue; 238 239 if (!SetupGetStringFieldW(&Context, 2, szFolder, ARRAYSIZE(szFolder), NULL)) 240 continue; 241 242 if (FAILED(SHGetFolderPathAndSubDirW(NULL, csidl|CSIDL_FLAG_CREATE, (HANDLE)-1, SHGFP_TYPE_DEFAULT, szFolder, szPath))) 243 continue; 244 245 CreateShortcutsFromSection(hinf, szFolderSection, szPath); 246 247 } while (SetupFindNextLine(&Context, &Context)); 248 249 CoUninitialize(); 250 251 return TRUE; 252 } 253 254 static VOID 255 CreateTempDir( 256 IN LPCWSTR VarName) 257 { 258 WCHAR szTempDir[MAX_PATH]; 259 WCHAR szBuffer[MAX_PATH]; 260 DWORD dwLength; 261 HKEY hKey; 262 263 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 264 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 265 0, 266 KEY_QUERY_VALUE, 267 &hKey) != ERROR_SUCCESS) 268 { 269 FatalError("Error: %lu\n", GetLastError()); 270 return; 271 } 272 273 /* Get temp dir */ 274 dwLength = sizeof(szBuffer); 275 if (RegQueryValueExW(hKey, 276 VarName, 277 NULL, 278 NULL, 279 (LPBYTE)szBuffer, 280 &dwLength) != ERROR_SUCCESS) 281 { 282 FatalError("Error: %lu\n", GetLastError()); 283 goto cleanup; 284 } 285 286 /* Expand it */ 287 if (!ExpandEnvironmentStringsW(szBuffer, szTempDir, ARRAYSIZE(szTempDir))) 288 { 289 FatalError("Error: %lu\n", GetLastError()); 290 goto cleanup; 291 } 292 293 /* Create profiles directory */ 294 if (!CreateDirectoryW(szTempDir, NULL)) 295 { 296 if (GetLastError() != ERROR_ALREADY_EXISTS) 297 { 298 FatalError("Error: %lu\n", GetLastError()); 299 goto cleanup; 300 } 301 } 302 303 cleanup: 304 RegCloseKey(hKey); 305 } 306 307 static BOOL 308 InstallSysSetupInfDevices(VOID) 309 { 310 INFCONTEXT InfContext; 311 WCHAR szLineBuffer[256]; 312 DWORD dwLineLength; 313 314 if (!SetupFindFirstLineW(hSysSetupInf, 315 L"DeviceInfsToInstall", 316 NULL, 317 &InfContext)) 318 { 319 return FALSE; 320 } 321 322 do 323 { 324 if (!SetupGetStringFieldW(&InfContext, 325 0, 326 szLineBuffer, 327 ARRAYSIZE(szLineBuffer), 328 &dwLineLength)) 329 { 330 return FALSE; 331 } 332 333 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL)) 334 { 335 return FALSE; 336 } 337 } 338 while (SetupFindNextLine(&InfContext, &InfContext)); 339 340 return TRUE; 341 } 342 343 static BOOL 344 InstallSysSetupInfComponents(VOID) 345 { 346 INFCONTEXT InfContext; 347 WCHAR szNameBuffer[256]; 348 WCHAR szSectionBuffer[256]; 349 HINF hComponentInf = INVALID_HANDLE_VALUE; 350 351 if (!SetupFindFirstLineW(hSysSetupInf, 352 L"Infs.Always", 353 NULL, 354 &InfContext)) 355 { 356 DPRINT("No Inf.Always section found\n"); 357 } 358 else 359 { 360 do 361 { 362 if (!SetupGetStringFieldW(&InfContext, 363 1, // Get the component name 364 szNameBuffer, 365 ARRAYSIZE(szNameBuffer), 366 NULL)) 367 { 368 FatalError("Error while trying to get component name \n"); 369 return FALSE; 370 } 371 372 if (!SetupGetStringFieldW(&InfContext, 373 2, // Get the component install section 374 szSectionBuffer, 375 ARRAYSIZE(szSectionBuffer), 376 NULL)) 377 { 378 FatalError("Error while trying to get component install section \n"); 379 return FALSE; 380 } 381 382 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer); 383 384 hComponentInf = SetupOpenInfFileW(szNameBuffer, 385 NULL, 386 INF_STYLE_WIN4, 387 NULL); 388 389 if (hComponentInf == INVALID_HANDLE_VALUE) 390 { 391 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError()); 392 return FALSE; 393 } 394 395 if (!SetupInstallFromInfSectionW(NULL, 396 hComponentInf, 397 szSectionBuffer, 398 SPINST_ALL, 399 NULL, 400 NULL, 401 SP_COPY_NEWER, 402 SetupDefaultQueueCallbackW, 403 NULL, 404 NULL, 405 NULL)) 406 { 407 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError()); 408 SetupCloseInfFile(hComponentInf); 409 return FALSE; 410 } 411 412 SetupCloseInfFile(hComponentInf); 413 } 414 while (SetupFindNextLine(&InfContext, &InfContext)); 415 } 416 417 return TRUE; 418 } 419 420 421 422 BOOL 423 RegisterTypeLibraries(HINF hinf, LPCWSTR szSection) 424 { 425 INFCONTEXT InfContext; 426 BOOL res; 427 WCHAR szName[MAX_PATH]; 428 WCHAR szPath[MAX_PATH]; 429 INT csidl; 430 LPWSTR p; 431 HMODULE hmod; 432 HRESULT hret; 433 434 /* Begin iterating the entries in the inf section */ 435 res = SetupFindFirstLine(hinf, szSection, NULL, &InfContext); 436 if (!res) return FALSE; 437 438 do 439 { 440 /* Get the name of the current type library */ 441 if (!SetupGetStringFieldW(&InfContext, 1, szName, ARRAYSIZE(szName), NULL)) 442 { 443 FatalError("SetupGetStringFieldW failed\n"); 444 continue; 445 } 446 447 if (!SetupGetIntField(&InfContext, 2, &csidl)) 448 csidl = CSIDL_SYSTEM; 449 450 hret = SHGetFolderPathW(NULL, csidl, NULL, 0, szPath); 451 if (FAILED(hret)) 452 { 453 FatalError("SHGetFolderPathW failed hret=0x%lx\n", hret); 454 continue; 455 } 456 457 p = PathAddBackslash(szPath); 458 wcscpy(p, szName); 459 460 hmod = LoadLibraryW(szName); 461 if (hmod == NULL) 462 { 463 FatalError("LoadLibraryW failed\n"); 464 continue; 465 } 466 467 __wine_register_resources(hmod); 468 469 } while (SetupFindNextLine(&InfContext, &InfContext)); 470 471 return TRUE; 472 } 473 474 static BOOL 475 EnableUserModePnpManager(VOID) 476 { 477 SC_HANDLE hSCManager = NULL; 478 SC_HANDLE hService = NULL; 479 BOOL bRet = FALSE; 480 481 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); 482 if (hSCManager == NULL) 483 { 484 DPRINT1("Unable to open the service control manager.\n"); 485 DPRINT1("Last Error %d\n", GetLastError()); 486 goto cleanup; 487 } 488 489 hService = OpenServiceW(hSCManager, 490 L"PlugPlay", 491 SERVICE_CHANGE_CONFIG | SERVICE_START); 492 if (hService == NULL) 493 { 494 DPRINT1("Unable to open PlugPlay service\n"); 495 goto cleanup; 496 } 497 498 bRet = ChangeServiceConfigW(hService, 499 SERVICE_NO_CHANGE, 500 SERVICE_AUTO_START, 501 SERVICE_NO_CHANGE, 502 NULL, NULL, NULL, 503 NULL, NULL, NULL, NULL); 504 if (!bRet) 505 { 506 DPRINT1("Unable to change the service configuration\n"); 507 goto cleanup; 508 } 509 510 bRet = StartServiceW(hService, 0, NULL); 511 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)) 512 { 513 DPRINT1("Unable to start service\n"); 514 goto cleanup; 515 } 516 517 bRet = TRUE; 518 519 cleanup: 520 if (hService != NULL) 521 CloseServiceHandle(hService); 522 if (hSCManager != NULL) 523 CloseServiceHandle(hSCManager); 524 return bRet; 525 } 526 527 static INT_PTR CALLBACK 528 StatusMessageWindowProc( 529 IN HWND hwndDlg, 530 IN UINT uMsg, 531 IN WPARAM wParam, 532 IN LPARAM lParam) 533 { 534 UNREFERENCED_PARAMETER(wParam); 535 536 switch (uMsg) 537 { 538 case WM_INITDIALOG: 539 { 540 WCHAR szMsg[256]; 541 542 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, ARRAYSIZE(szMsg))) 543 return FALSE; 544 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg); 545 return TRUE; 546 } 547 } 548 return FALSE; 549 } 550 551 static DWORD WINAPI 552 ShowStatusMessageThread( 553 IN LPVOID lpParameter) 554 { 555 HWND *phWnd = (HWND *)lpParameter; 556 HWND hWnd, hItem; 557 MSG Msg; 558 559 hWnd = CreateDialogParam(hDllInstance, 560 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG), 561 GetDesktopWindow(), 562 StatusMessageWindowProc, 563 (LPARAM)NULL); 564 if (!hWnd) 565 return 0; 566 *phWnd = hWnd; 567 568 ShowWindow(hWnd, SW_SHOW); 569 570 hItem = GetDlgItem(hWnd, IDC_STATUSPROGRESS); 571 if (hItem) 572 { 573 PostMessage(hItem, PBM_SETMARQUEE, TRUE, 40); 574 } 575 576 /* Message loop for the Status window */ 577 while (GetMessage(&Msg, NULL, 0, 0)) 578 { 579 TranslateMessage(&Msg); 580 DispatchMessage(&Msg); 581 } 582 583 return 0; 584 } 585 586 static LONG 587 ReadRegSzKey( 588 IN HKEY hKey, 589 IN LPCWSTR pszKey, 590 OUT LPWSTR* pValue) 591 { 592 LONG rc; 593 DWORD dwType; 594 DWORD cbData = 0; 595 LPWSTR pwszValue; 596 597 if (!pValue) 598 return ERROR_INVALID_PARAMETER; 599 600 *pValue = NULL; 601 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData); 602 if (rc != ERROR_SUCCESS) 603 return rc; 604 if (dwType != REG_SZ) 605 return ERROR_FILE_NOT_FOUND; 606 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); 607 if (!pwszValue) 608 return ERROR_NOT_ENOUGH_MEMORY; 609 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData); 610 if (rc != ERROR_SUCCESS) 611 { 612 HeapFree(GetProcessHeap(), 0, pwszValue); 613 return rc; 614 } 615 /* NULL-terminate the string */ 616 pwszValue[cbData / sizeof(WCHAR)] = '\0'; 617 618 *pValue = pwszValue; 619 return ERROR_SUCCESS; 620 } 621 622 static BOOL 623 IsConsoleBoot(VOID) 624 { 625 HKEY hControlKey = NULL; 626 LPWSTR pwszSystemStartOptions = NULL; 627 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */ 628 BOOL bConsoleBoot = FALSE; 629 LONG rc; 630 631 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 632 L"SYSTEM\\CurrentControlSet\\Control", 633 0, 634 KEY_QUERY_VALUE, 635 &hControlKey); 636 if (rc != ERROR_SUCCESS) 637 goto cleanup; 638 639 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions); 640 if (rc != ERROR_SUCCESS) 641 goto cleanup; 642 643 /* Check for CONSOLE switch in SystemStartOptions */ 644 pwszCurrentOption = pwszSystemStartOptions; 645 while (pwszCurrentOption) 646 { 647 pwszNextOption = wcschr(pwszCurrentOption, L' '); 648 if (pwszNextOption) 649 *pwszNextOption = L'\0'; 650 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0) 651 { 652 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption); 653 bConsoleBoot = TRUE; 654 goto cleanup; 655 } 656 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL; 657 } 658 659 cleanup: 660 if (hControlKey != NULL) 661 RegCloseKey(hControlKey); 662 if (pwszSystemStartOptions) 663 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions); 664 return bConsoleBoot; 665 } 666 667 static BOOL 668 CommonInstall(VOID) 669 { 670 HWND hWnd = NULL; 671 672 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf", 673 NULL, 674 INF_STYLE_WIN4, 675 NULL); 676 if (hSysSetupInf == INVALID_HANDLE_VALUE) 677 { 678 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError()); 679 return FALSE; 680 } 681 682 if (!InstallSysSetupInfDevices()) 683 { 684 FatalError("InstallSysSetupInfDevices() failed!\n"); 685 goto error; 686 } 687 688 if(!InstallSysSetupInfComponents()) 689 { 690 FatalError("InstallSysSetupInfComponents() failed!\n"); 691 goto error; 692 } 693 694 if (!IsConsoleBoot()) 695 { 696 HANDLE hThread; 697 698 hThread = CreateThread(NULL, 699 0, 700 ShowStatusMessageThread, 701 (LPVOID)&hWnd, 702 0, 703 NULL); 704 if (hThread) 705 CloseHandle(hThread); 706 } 707 708 if (!EnableUserModePnpManager()) 709 { 710 FatalError("EnableUserModePnpManager() failed!\n"); 711 goto error; 712 } 713 714 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0) 715 { 716 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n"); 717 goto error; 718 } 719 720 EndDialog(hWnd, 0); 721 return TRUE; 722 723 error: 724 if (hWnd) 725 EndDialog(hWnd, 0); 726 SetupCloseInfFile(hSysSetupInf); 727 return FALSE; 728 } 729 730 /* Install a section of a .inf file 731 * Returns TRUE if success, FALSE if failure. Error code can 732 * be retrieved with GetLastError() 733 */ 734 static 735 BOOL 736 InstallInfSection( 737 IN HWND hWnd, 738 IN LPCWSTR InfFile, 739 IN LPCWSTR InfSection OPTIONAL, 740 IN LPCWSTR InfService OPTIONAL) 741 { 742 WCHAR Buffer[MAX_PATH]; 743 HINF hInf = INVALID_HANDLE_VALUE; 744 UINT BufferSize; 745 PVOID Context = NULL; 746 BOOL ret = FALSE; 747 748 /* Get Windows directory */ 749 BufferSize = ARRAYSIZE(Buffer) - 5 - wcslen(InfFile); 750 if (GetWindowsDirectoryW(Buffer, BufferSize) > BufferSize) 751 { 752 /* Function failed */ 753 SetLastError(ERROR_GEN_FAILURE); 754 goto cleanup; 755 } 756 /* We have enough space to add some information in the buffer */ 757 if (Buffer[wcslen(Buffer) - 1] != '\\') 758 wcscat(Buffer, L"\\"); 759 wcscat(Buffer, L"Inf\\"); 760 wcscat(Buffer, InfFile); 761 762 /* Install specified section */ 763 hInf = SetupOpenInfFileW(Buffer, NULL, INF_STYLE_WIN4, NULL); 764 if (hInf == INVALID_HANDLE_VALUE) 765 goto cleanup; 766 767 Context = SetupInitDefaultQueueCallback(hWnd); 768 if (Context == NULL) 769 goto cleanup; 770 771 ret = TRUE; 772 if (ret && InfSection) 773 { 774 ret = SetupInstallFromInfSectionW( 775 hWnd, hInf, 776 InfSection, SPINST_ALL, 777 NULL, NULL, SP_COPY_NEWER, 778 SetupDefaultQueueCallbackW, Context, 779 NULL, NULL); 780 } 781 if (ret && InfService) 782 { 783 ret = SetupInstallServicesFromInfSectionW(hInf, InfService, 0); 784 } 785 786 cleanup: 787 if (Context) 788 SetupTermDefaultQueueCallback(Context); 789 if (hInf != INVALID_HANDLE_VALUE) 790 SetupCloseInfFile(hInf); 791 return ret; 792 } 793 794 static 795 DWORD 796 InstallLiveCD(VOID) 797 { 798 STARTUPINFOW StartupInfo; 799 PROCESS_INFORMATION ProcessInformation; 800 BOOL bRes; 801 802 /* Hack: Install TCP/IP protocol driver */ 803 bRes = InstallInfSection(NULL, 804 L"nettcpip.inf", 805 L"MS_TCPIP.PrimaryInstall", 806 L"MS_TCPIP.PrimaryInstall.Services"); 807 if (!bRes && GetLastError() != ERROR_FILE_NOT_FOUND) 808 { 809 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError()); 810 } 811 else 812 { 813 /* Start the TCP/IP protocol driver */ 814 SetupStartService(L"Tcpip", FALSE); 815 SetupStartService(L"Dhcp", FALSE); 816 } 817 818 if (!CommonInstall()) 819 goto error; 820 821 /* Register components */ 822 _SEH2_TRY 823 { 824 if (!SetupInstallFromInfSectionW(NULL, 825 hSysSetupInf, L"RegistrationPhase2", 826 SPINST_ALL, 827 0, NULL, 0, NULL, NULL, NULL, NULL)) 828 { 829 DPRINT1("SetupInstallFromInfSectionW failed!\n"); 830 } 831 832 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries"); 833 } 834 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 835 { 836 DPRINT1("Catching exception\n"); 837 } 838 _SEH2_END; 839 840 SetupCloseInfFile(hSysSetupInf); 841 842 /* Run the shell */ 843 ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 844 StartupInfo.cb = sizeof(StartupInfo); 845 bRes = CreateProcessW(L"userinit.exe", 846 NULL, 847 NULL, 848 NULL, 849 FALSE, 850 0, 851 NULL, 852 NULL, 853 &StartupInfo, 854 &ProcessInformation); 855 if (!bRes) 856 goto error; 857 858 CloseHandle(ProcessInformation.hThread); 859 CloseHandle(ProcessInformation.hProcess); 860 861 return 0; 862 863 error: 864 MessageBoxW( 865 NULL, 866 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.", 867 L"ReactOS LiveCD", 868 MB_OK); 869 return 0; 870 } 871 872 873 static BOOL 874 SetSetupType(DWORD dwSetupType) 875 { 876 DWORD dwError; 877 HKEY hKey; 878 879 dwError = RegOpenKeyExW( 880 HKEY_LOCAL_MACHINE, 881 L"SYSTEM\\Setup", 882 0, 883 KEY_SET_VALUE, 884 &hKey); 885 if (dwError != ERROR_SUCCESS) 886 return FALSE; 887 888 dwError = RegSetValueExW( 889 hKey, 890 L"SetupType", 891 0, 892 REG_DWORD, 893 (LPBYTE)&dwSetupType, 894 sizeof(DWORD)); 895 RegCloseKey(hKey); 896 if (dwError != ERROR_SUCCESS) 897 return FALSE; 898 899 return TRUE; 900 } 901 902 static DWORD CALLBACK 903 HotkeyThread(LPVOID Parameter) 904 { 905 ATOM hotkey; 906 MSG msg; 907 908 DPRINT("HotkeyThread start\n"); 909 910 hotkey = GlobalAddAtomW(L"Setup Shift+F10 Hotkey"); 911 912 if (!RegisterHotKey(NULL, hotkey, MOD_SHIFT, VK_F10)) 913 DPRINT1("RegisterHotKey failed with %lu\n", GetLastError()); 914 915 while (GetMessage(&msg, NULL, 0, 0)) 916 { 917 if (msg.hwnd == NULL && msg.message == WM_HOTKEY && msg.wParam == hotkey) 918 { 919 STARTUPINFOW si = { sizeof(si) }; 920 PROCESS_INFORMATION pi; 921 922 if (CreateProcessW(L"cmd.exe", 923 NULL, 924 NULL, 925 NULL, 926 FALSE, 927 CREATE_NEW_CONSOLE, 928 NULL, 929 NULL, 930 &si, 931 &pi)) 932 { 933 CloseHandle(pi.hProcess); 934 CloseHandle(pi.hThread); 935 } 936 else 937 { 938 DPRINT1("Failed to launch command prompt: %lu\n", GetLastError()); 939 } 940 } 941 } 942 943 UnregisterHotKey(NULL, hotkey); 944 GlobalDeleteAtom(hotkey); 945 946 DPRINT("HotkeyThread terminate\n"); 947 return 0; 948 } 949 950 951 static 952 BOOL 953 InitializeProgramFilesDir(VOID) 954 { 955 LONG Error; 956 HKEY hKey; 957 DWORD dwLength; 958 WCHAR szProgramFilesDirPath[MAX_PATH]; 959 WCHAR szCommonFilesDirPath[MAX_PATH]; 960 WCHAR szBuffer[MAX_PATH]; 961 962 /* Load 'Program Files' location */ 963 if (!LoadStringW(hDllInstance, 964 IDS_PROGRAMFILES, 965 szBuffer, 966 ARRAYSIZE(szBuffer))) 967 { 968 DPRINT1("Error: %lu\n", GetLastError()); 969 return FALSE; 970 } 971 972 if (!LoadStringW(hDllInstance, 973 IDS_COMMONFILES, 974 szCommonFilesDirPath, 975 ARRAYSIZE(szCommonFilesDirPath))) 976 { 977 DPRINT1("Warning: %lu\n", GetLastError()); 978 } 979 980 /* Expand it */ 981 if (!ExpandEnvironmentStringsW(szBuffer, 982 szProgramFilesDirPath, 983 ARRAYSIZE(szProgramFilesDirPath))) 984 { 985 DPRINT1("Error: %lu\n", GetLastError()); 986 return FALSE; 987 } 988 989 wcscpy(szBuffer, szProgramFilesDirPath); 990 wcscat(szBuffer, L"\\"); 991 wcscat(szBuffer, szCommonFilesDirPath); 992 993 if (!ExpandEnvironmentStringsW(szBuffer, 994 szCommonFilesDirPath, 995 ARRAYSIZE(szCommonFilesDirPath))) 996 { 997 DPRINT1("Warning: %lu\n", GetLastError()); 998 } 999 1000 /* Store it */ 1001 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1002 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 1003 0, 1004 KEY_SET_VALUE, 1005 &hKey); 1006 if (Error != ERROR_SUCCESS) 1007 { 1008 DPRINT1("Error: %lu\n", Error); 1009 return FALSE; 1010 } 1011 1012 dwLength = (wcslen(szProgramFilesDirPath) + 1) * sizeof(WCHAR); 1013 Error = RegSetValueExW(hKey, 1014 L"ProgramFilesDir", 1015 0, 1016 REG_SZ, 1017 (LPBYTE)szProgramFilesDirPath, 1018 dwLength); 1019 if (Error != ERROR_SUCCESS) 1020 { 1021 DPRINT1("Error: %lu\n", Error); 1022 RegCloseKey(hKey); 1023 return FALSE; 1024 } 1025 1026 dwLength = (wcslen(szCommonFilesDirPath) + 1) * sizeof(WCHAR); 1027 Error = RegSetValueExW(hKey, 1028 L"CommonFilesDir", 1029 0, 1030 REG_SZ, 1031 (LPBYTE)szCommonFilesDirPath, 1032 dwLength); 1033 if (Error != ERROR_SUCCESS) 1034 { 1035 DPRINT1("Warning: %lu\n", Error); 1036 } 1037 1038 RegCloseKey(hKey); 1039 1040 /* Create directory */ 1041 // FIXME: Security! 1042 if (!CreateDirectoryW(szProgramFilesDirPath, NULL)) 1043 { 1044 if (GetLastError() != ERROR_ALREADY_EXISTS) 1045 { 1046 DPRINT1("Error: %lu\n", GetLastError()); 1047 return FALSE; 1048 } 1049 } 1050 1051 /* Create directory */ 1052 // FIXME: Security! 1053 if (!CreateDirectoryW(szCommonFilesDirPath, NULL)) 1054 { 1055 if (GetLastError() != ERROR_ALREADY_EXISTS) 1056 { 1057 DPRINT1("Warning: %lu\n", GetLastError()); 1058 // return FALSE; 1059 } 1060 } 1061 1062 return TRUE; 1063 } 1064 1065 1066 static 1067 VOID 1068 InitializeDefaultUserLocale(VOID) 1069 { 1070 WCHAR szBuffer[80]; 1071 PWSTR ptr; 1072 HKEY hLocaleKey; 1073 DWORD ret; 1074 DWORD dwSize; 1075 LCID lcid; 1076 INT i; 1077 1078 struct {LCTYPE LCType; PWSTR pValue;} LocaleData[] = { 1079 /* Number */ 1080 {LOCALE_SDECIMAL, L"sDecimal"}, 1081 {LOCALE_STHOUSAND, L"sThousand"}, 1082 {LOCALE_SNEGATIVESIGN, L"sNegativeSign"}, 1083 {LOCALE_SPOSITIVESIGN, L"sPositiveSign"}, 1084 {LOCALE_SGROUPING, L"sGrouping"}, 1085 {LOCALE_SLIST, L"sList"}, 1086 {LOCALE_SNATIVEDIGITS, L"sNativeDigits"}, 1087 {LOCALE_INEGNUMBER, L"iNegNumber"}, 1088 {LOCALE_IDIGITS, L"iDigits"}, 1089 {LOCALE_ILZERO, L"iLZero"}, 1090 {LOCALE_IMEASURE, L"iMeasure"}, 1091 {LOCALE_IDIGITSUBSTITUTION, L"NumShape"}, 1092 1093 /* Currency */ 1094 {LOCALE_SCURRENCY, L"sCurrency"}, 1095 {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"}, 1096 {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"}, 1097 {LOCALE_SMONGROUPING, L"sMonGrouping"}, 1098 {LOCALE_ICURRENCY, L"iCurrency"}, 1099 {LOCALE_INEGCURR, L"iNegCurr"}, 1100 {LOCALE_ICURRDIGITS, L"iCurrDigits"}, 1101 1102 /* Time */ 1103 {LOCALE_STIMEFORMAT, L"sTimeFormat"}, 1104 {LOCALE_STIME, L"sTime"}, 1105 {LOCALE_S1159, L"s1159"}, 1106 {LOCALE_S2359, L"s2359"}, 1107 {LOCALE_ITIME, L"iTime"}, 1108 {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"}, 1109 {LOCALE_ITLZERO, L"iTLZero"}, 1110 1111 /* Date */ 1112 {LOCALE_SLONGDATE, L"sLongDate"}, 1113 {LOCALE_SSHORTDATE, L"sShortDate"}, 1114 {LOCALE_SDATE, L"sDate"}, 1115 {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"}, 1116 {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"}, 1117 {LOCALE_IDATE, L"iDate"}, 1118 {LOCALE_ICALENDARTYPE, L"iCalendarType"}, 1119 1120 /* Misc */ 1121 {LOCALE_SCOUNTRY, L"sCountry"}, 1122 {LOCALE_SABBREVLANGNAME, L"sLanguage"}, 1123 {LOCALE_ICOUNTRY, L"iCountry"}, 1124 {0, NULL}}; 1125 1126 ret = RegOpenKeyExW(HKEY_USERS, 1127 L".DEFAULT\\Control Panel\\International", 1128 0, 1129 KEY_READ | KEY_WRITE, 1130 &hLocaleKey); 1131 if (ret != ERROR_SUCCESS) 1132 { 1133 return; 1134 } 1135 1136 dwSize = 9 * sizeof(WCHAR); 1137 ret = RegQueryValueExW(hLocaleKey, 1138 L"Locale", 1139 NULL, 1140 NULL, 1141 (PBYTE)szBuffer, 1142 &dwSize); 1143 if (ret != ERROR_SUCCESS) 1144 goto done; 1145 1146 lcid = (LCID)wcstoul(szBuffer, &ptr, 16); 1147 if (lcid == 0) 1148 goto done; 1149 1150 i = 0; 1151 while (LocaleData[i].pValue != NULL) 1152 { 1153 if (GetLocaleInfoW(lcid, 1154 LocaleData[i].LCType | LOCALE_NOUSEROVERRIDE, 1155 szBuffer, 1156 ARRAYSIZE(szBuffer))) 1157 { 1158 RegSetValueExW(hLocaleKey, 1159 LocaleData[i].pValue, 1160 0, 1161 REG_SZ, 1162 (PBYTE)szBuffer, 1163 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1164 } 1165 1166 i++; 1167 } 1168 1169 done: 1170 RegCloseKey(hLocaleKey); 1171 } 1172 1173 1174 static 1175 DWORD 1176 InstallReactOS(VOID) 1177 { 1178 WCHAR szBuffer[MAX_PATH]; 1179 HANDLE token; 1180 TOKEN_PRIVILEGES privs; 1181 HKEY hKey; 1182 HINF hShortcutsInf; 1183 HANDLE hHotkeyThread; 1184 BOOL ret; 1185 1186 InitializeSetupActionLog(FALSE); 1187 LogItem(NULL, L"Installing ReactOS"); 1188 1189 CreateTempDir(L"TEMP"); 1190 CreateTempDir(L"TMP"); 1191 1192 if (!InitializeProgramFilesDir()) 1193 { 1194 FatalError("InitializeProgramFilesDir() failed"); 1195 return 0; 1196 } 1197 1198 if (!InitializeProfiles()) 1199 { 1200 FatalError("InitializeProfiles() failed"); 1201 return 0; 1202 } 1203 1204 InitializeDefaultUserLocale(); 1205 1206 if (GetWindowsDirectoryW(szBuffer, ARRAYSIZE(szBuffer))) 1207 { 1208 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1209 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1210 0, 1211 KEY_WRITE, 1212 &hKey) == ERROR_SUCCESS) 1213 { 1214 RegSetValueExW(hKey, 1215 L"PathName", 1216 0, 1217 REG_SZ, 1218 (LPBYTE)szBuffer, 1219 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1220 1221 RegSetValueExW(hKey, 1222 L"SystemRoot", 1223 0, 1224 REG_SZ, 1225 (LPBYTE)szBuffer, 1226 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1227 1228 RegCloseKey(hKey); 1229 } 1230 1231 PathAddBackslash(szBuffer); 1232 wcscat(szBuffer, L"system"); 1233 CreateDirectory(szBuffer, NULL); 1234 } 1235 1236 hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL); 1237 1238 /* Hack: Install TCP/IP protocol driver */ 1239 ret = InstallInfSection(NULL, 1240 L"nettcpip.inf", 1241 L"MS_TCPIP.PrimaryInstall", 1242 L"MS_TCPIP.PrimaryInstall.Services"); 1243 if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND) 1244 { 1245 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError()); 1246 } 1247 else 1248 { 1249 /* Start the TCP/IP protocol driver */ 1250 SetupStartService(L"Tcpip", FALSE); 1251 SetupStartService(L"Dhcp", FALSE); 1252 } 1253 1254 1255 if (!CommonInstall()) 1256 return 0; 1257 1258 InstallWizard(); 1259 1260 InstallSecurity(); 1261 1262 SetAutoAdminLogon(); 1263 1264 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf", 1265 NULL, 1266 INF_STYLE_WIN4, 1267 NULL); 1268 if (hShortcutsInf == INVALID_HANDLE_VALUE) 1269 { 1270 FatalError("Failed to open shortcuts.inf"); 1271 return 0; 1272 } 1273 1274 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders")) 1275 { 1276 FatalError("CreateShortcuts() failed"); 1277 return 0; 1278 } 1279 1280 SetupCloseInfFile(hShortcutsInf); 1281 1282 hShortcutsInf = SetupOpenInfFileW(L"rosapps_shortcuts.inf", 1283 NULL, 1284 INF_STYLE_WIN4, 1285 NULL); 1286 if (hShortcutsInf != INVALID_HANDLE_VALUE) 1287 { 1288 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders")) 1289 { 1290 FatalError("CreateShortcuts(rosapps) failed"); 1291 return 0; 1292 } 1293 SetupCloseInfFile(hShortcutsInf); 1294 } 1295 1296 SetupCloseInfFile(hSysSetupInf); 1297 SetSetupType(0); 1298 1299 if (hHotkeyThread) 1300 { 1301 PostThreadMessage(GetThreadId(hHotkeyThread), WM_QUIT, 0, 0); 1302 CloseHandle(hHotkeyThread); 1303 } 1304 1305 LogItem(NULL, L"Installing ReactOS done"); 1306 TerminateSetupActionLog(); 1307 1308 if (AdminInfo.Name != NULL) 1309 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name); 1310 1311 if (AdminInfo.Domain != NULL) 1312 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain); 1313 1314 if (AdminInfo.Password != NULL) 1315 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password); 1316 1317 /* Get shutdown privilege */ 1318 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) 1319 { 1320 FatalError("OpenProcessToken() failed!"); 1321 return 0; 1322 } 1323 if (!LookupPrivilegeValue(NULL, 1324 SE_SHUTDOWN_NAME, 1325 &privs.Privileges[0].Luid)) 1326 { 1327 FatalError("LookupPrivilegeValue() failed!"); 1328 return 0; 1329 } 1330 privs.PrivilegeCount = 1; 1331 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1332 if (AdjustTokenPrivileges(token, 1333 FALSE, 1334 &privs, 1335 0, 1336 (PTOKEN_PRIVILEGES)NULL, 1337 NULL) == 0) 1338 { 1339 FatalError("AdjustTokenPrivileges() failed!"); 1340 return 0; 1341 } 1342 1343 ExitWindowsEx(EWX_REBOOT, 0); 1344 return 0; 1345 } 1346 1347 1348 /* 1349 * Standard Windows-compatible export, which dispatches 1350 * to either 'InstallReactOS' or 'InstallLiveCD'. 1351 */ 1352 INT 1353 WINAPI 1354 InstallWindowsNt(INT argc, WCHAR** argv) 1355 { 1356 INT i; 1357 PWSTR p; 1358 1359 for (i = 0; i < argc; ++i) 1360 { 1361 p = argv[i]; 1362 if (*p == L'-') 1363 { 1364 p++; 1365 1366 // NOTE: On Windows, "mini" means "minimal UI", and can be used 1367 // in addition to "newsetup"; these options are not exclusive. 1368 if (_wcsicmp(p, L"newsetup") == 0) 1369 return (INT)InstallReactOS(); 1370 else if (_wcsicmp(p, L"mini") == 0) 1371 return (INT)InstallLiveCD(); 1372 1373 /* Add support for other switches */ 1374 } 1375 } 1376 1377 return 0; 1378 } 1379 1380 1381 /* 1382 * @unimplemented 1383 */ 1384 DWORD WINAPI 1385 SetupChangeFontSize( 1386 IN HANDLE hWnd, 1387 IN LPCWSTR lpszFontSize) 1388 { 1389 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1390 return FALSE; 1391 } 1392 1393 /* 1394 * @unimplemented 1395 */ 1396 DWORD WINAPI 1397 SetupChangeLocaleEx(HWND hWnd, 1398 LCID Lcid, 1399 LPCWSTR lpSrcRootPath, 1400 char Unknown, 1401 DWORD dwUnused1, 1402 DWORD dwUnused2) 1403 { 1404 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1405 return FALSE; 1406 } 1407 1408 /* 1409 * @implemented 1410 */ 1411 DWORD WINAPI 1412 SetupChangeLocale(HWND hWnd, LCID Lcid) 1413 { 1414 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0); 1415 } 1416 1417 1418 DWORD 1419 WINAPI 1420 SetupStartService( 1421 LPCWSTR lpServiceName, 1422 BOOL bWait) 1423 { 1424 SC_HANDLE hManager = NULL; 1425 SC_HANDLE hService = NULL; 1426 DWORD dwError = ERROR_SUCCESS; 1427 1428 hManager = OpenSCManagerW(NULL, 1429 NULL, 1430 SC_MANAGER_ALL_ACCESS); 1431 if (hManager == NULL) 1432 { 1433 dwError = GetLastError(); 1434 goto done; 1435 } 1436 1437 hService = OpenServiceW(hManager, 1438 lpServiceName, 1439 SERVICE_START); 1440 if (hService == NULL) 1441 { 1442 dwError = GetLastError(); 1443 goto done; 1444 } 1445 1446 if (!StartService(hService, 0, NULL)) 1447 { 1448 dwError = GetLastError(); 1449 goto done; 1450 } 1451 1452 done: 1453 if (hService != NULL) 1454 CloseServiceHandle(hService); 1455 1456 if (hManager != NULL) 1457 CloseServiceHandle(hManager); 1458 1459 return dwError; 1460 } 1461