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 hWnd, hItem; 556 MSG Msg; 557 UNREFERENCED_PARAMETER(lpParameter); 558 559 hWnd = CreateDialogParam(hDllInstance, 560 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG), 561 GetDesktopWindow(), 562 StatusMessageWindowProc, 563 (LPARAM)NULL); 564 if (!hWnd) 565 return 0; 566 567 ShowWindow(hWnd, SW_SHOW); 568 569 hItem = GetDlgItem(hWnd, IDC_STATUSPROGRESS); 570 if (hItem) 571 { 572 PostMessage(hItem, PBM_SETMARQUEE, TRUE, 40); 573 } 574 575 /* Message loop for the Status window */ 576 while (GetMessage(&Msg, NULL, 0, 0)) 577 { 578 TranslateMessage(&Msg); 579 DispatchMessage(&Msg); 580 } 581 582 EndDialog(hWnd, 0); 583 584 return 0; 585 } 586 587 static LONG 588 ReadRegSzKey( 589 IN HKEY hKey, 590 IN LPCWSTR pszKey, 591 OUT LPWSTR* pValue) 592 { 593 LONG rc; 594 DWORD dwType; 595 DWORD cbData = 0; 596 LPWSTR pwszValue; 597 598 if (!pValue) 599 return ERROR_INVALID_PARAMETER; 600 601 *pValue = NULL; 602 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData); 603 if (rc != ERROR_SUCCESS) 604 return rc; 605 if (dwType != REG_SZ) 606 return ERROR_FILE_NOT_FOUND; 607 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); 608 if (!pwszValue) 609 return ERROR_NOT_ENOUGH_MEMORY; 610 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData); 611 if (rc != ERROR_SUCCESS) 612 { 613 HeapFree(GetProcessHeap(), 0, pwszValue); 614 return rc; 615 } 616 /* NULL-terminate the string */ 617 pwszValue[cbData / sizeof(WCHAR)] = '\0'; 618 619 *pValue = pwszValue; 620 return ERROR_SUCCESS; 621 } 622 623 static BOOL 624 IsConsoleBoot(VOID) 625 { 626 HKEY hControlKey = NULL; 627 LPWSTR pwszSystemStartOptions = NULL; 628 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */ 629 BOOL bConsoleBoot = FALSE; 630 LONG rc; 631 632 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 633 L"SYSTEM\\CurrentControlSet\\Control", 634 0, 635 KEY_QUERY_VALUE, 636 &hControlKey); 637 if (rc != ERROR_SUCCESS) 638 goto cleanup; 639 640 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions); 641 if (rc != ERROR_SUCCESS) 642 goto cleanup; 643 644 /* Check for CONSOLE switch in SystemStartOptions */ 645 pwszCurrentOption = pwszSystemStartOptions; 646 while (pwszCurrentOption) 647 { 648 pwszNextOption = wcschr(pwszCurrentOption, L' '); 649 if (pwszNextOption) 650 *pwszNextOption = L'\0'; 651 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0) 652 { 653 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption); 654 bConsoleBoot = TRUE; 655 goto cleanup; 656 } 657 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL; 658 } 659 660 cleanup: 661 if (hControlKey != NULL) 662 RegCloseKey(hControlKey); 663 if (pwszSystemStartOptions) 664 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions); 665 return bConsoleBoot; 666 } 667 668 static BOOL 669 CommonInstall(VOID) 670 { 671 HANDLE hThread = NULL; 672 BOOL bResult = FALSE; 673 674 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf", 675 NULL, 676 INF_STYLE_WIN4, 677 NULL); 678 if (hSysSetupInf == INVALID_HANDLE_VALUE) 679 { 680 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError()); 681 return FALSE; 682 } 683 684 if (!InstallSysSetupInfDevices()) 685 { 686 FatalError("InstallSysSetupInfDevices() failed!\n"); 687 goto Exit; 688 } 689 690 if(!InstallSysSetupInfComponents()) 691 { 692 FatalError("InstallSysSetupInfComponents() failed!\n"); 693 goto Exit; 694 } 695 696 if (!IsConsoleBoot()) 697 { 698 hThread = CreateThread(NULL, 699 0, 700 ShowStatusMessageThread, 701 NULL, 702 0, 703 NULL); 704 } 705 706 if (!EnableUserModePnpManager()) 707 { 708 FatalError("EnableUserModePnpManager() failed!\n"); 709 goto Exit; 710 } 711 712 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0) 713 { 714 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n"); 715 goto Exit; 716 } 717 718 bResult = TRUE; 719 720 Exit: 721 722 if (bResult == FALSE) 723 { 724 SetupCloseInfFile(hSysSetupInf); 725 } 726 727 if (hThread != NULL) 728 { 729 PostThreadMessage(GetThreadId(hThread), WM_QUIT, 0, 0); 730 WaitForSingleObject(hThread, INFINITE); 731 CloseHandle(hThread); 732 } 733 734 return bResult; 735 } 736 737 static 738 DWORD 739 InstallLiveCD(VOID) 740 { 741 STARTUPINFOW StartupInfo; 742 PROCESS_INFORMATION ProcessInformation; 743 BOOL bRes; 744 745 if (!CommonInstall()) 746 goto error; 747 748 /* Install the TCP/IP protocol driver */ 749 bRes = InstallNetworkComponent(L"MS_TCPIP"); 750 if (!bRes && GetLastError() != ERROR_FILE_NOT_FOUND) 751 { 752 DPRINT("InstallNetworkComponent() failed with error 0x%lx\n", GetLastError()); 753 } 754 else 755 { 756 /* Start the TCP/IP protocol driver */ 757 SetupStartService(L"Tcpip", FALSE); 758 SetupStartService(L"Dhcp", FALSE); 759 SetupStartService(L"Dnscache", FALSE); 760 } 761 762 /* Register components */ 763 _SEH2_TRY 764 { 765 if (!SetupInstallFromInfSectionW(NULL, 766 hSysSetupInf, L"RegistrationPhase2", 767 SPINST_ALL, 768 0, NULL, 0, NULL, NULL, NULL, NULL)) 769 { 770 DPRINT1("SetupInstallFromInfSectionW failed!\n"); 771 } 772 773 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries"); 774 } 775 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 776 { 777 DPRINT1("Catching exception\n"); 778 } 779 _SEH2_END; 780 781 SetupCloseInfFile(hSysSetupInf); 782 783 /* Run the shell */ 784 ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 785 StartupInfo.cb = sizeof(StartupInfo); 786 bRes = CreateProcessW(L"userinit.exe", 787 NULL, 788 NULL, 789 NULL, 790 FALSE, 791 0, 792 NULL, 793 NULL, 794 &StartupInfo, 795 &ProcessInformation); 796 if (!bRes) 797 goto error; 798 799 CloseHandle(ProcessInformation.hThread); 800 CloseHandle(ProcessInformation.hProcess); 801 802 return 0; 803 804 error: 805 MessageBoxW( 806 NULL, 807 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.", 808 L"ReactOS LiveCD", 809 MB_OK); 810 return 0; 811 } 812 813 814 static BOOL 815 SetSetupType(DWORD dwSetupType) 816 { 817 DWORD dwError; 818 HKEY hKey; 819 820 dwError = RegOpenKeyExW( 821 HKEY_LOCAL_MACHINE, 822 L"SYSTEM\\Setup", 823 0, 824 KEY_SET_VALUE, 825 &hKey); 826 if (dwError != ERROR_SUCCESS) 827 return FALSE; 828 829 dwError = RegSetValueExW( 830 hKey, 831 L"SetupType", 832 0, 833 REG_DWORD, 834 (LPBYTE)&dwSetupType, 835 sizeof(DWORD)); 836 RegCloseKey(hKey); 837 if (dwError != ERROR_SUCCESS) 838 return FALSE; 839 840 return TRUE; 841 } 842 843 static DWORD CALLBACK 844 HotkeyThread(LPVOID Parameter) 845 { 846 ATOM hotkey; 847 MSG msg; 848 849 DPRINT("HotkeyThread start\n"); 850 851 hotkey = GlobalAddAtomW(L"Setup Shift+F10 Hotkey"); 852 853 if (!RegisterHotKey(NULL, hotkey, MOD_SHIFT, VK_F10)) 854 DPRINT1("RegisterHotKey failed with %lu\n", GetLastError()); 855 856 while (GetMessage(&msg, NULL, 0, 0)) 857 { 858 if (msg.hwnd == NULL && msg.message == WM_HOTKEY && msg.wParam == hotkey) 859 { 860 STARTUPINFOW si = { sizeof(si) }; 861 PROCESS_INFORMATION pi; 862 863 if (CreateProcessW(L"cmd.exe", 864 NULL, 865 NULL, 866 NULL, 867 FALSE, 868 CREATE_NEW_CONSOLE, 869 NULL, 870 NULL, 871 &si, 872 &pi)) 873 { 874 CloseHandle(pi.hProcess); 875 CloseHandle(pi.hThread); 876 } 877 else 878 { 879 DPRINT1("Failed to launch command prompt: %lu\n", GetLastError()); 880 } 881 } 882 } 883 884 UnregisterHotKey(NULL, hotkey); 885 GlobalDeleteAtom(hotkey); 886 887 DPRINT("HotkeyThread terminate\n"); 888 return 0; 889 } 890 891 892 static 893 BOOL 894 InitializeProgramFilesDir(VOID) 895 { 896 LONG Error; 897 HKEY hKey; 898 DWORD dwLength; 899 WCHAR szProgramFilesDirPath[MAX_PATH]; 900 WCHAR szCommonFilesDirPath[MAX_PATH]; 901 WCHAR szBuffer[MAX_PATH]; 902 903 /* Load 'Program Files' location */ 904 if (!LoadStringW(hDllInstance, 905 IDS_PROGRAMFILES, 906 szBuffer, 907 ARRAYSIZE(szBuffer))) 908 { 909 DPRINT1("Error: %lu\n", GetLastError()); 910 return FALSE; 911 } 912 913 if (!LoadStringW(hDllInstance, 914 IDS_COMMONFILES, 915 szCommonFilesDirPath, 916 ARRAYSIZE(szCommonFilesDirPath))) 917 { 918 DPRINT1("Warning: %lu\n", GetLastError()); 919 } 920 921 /* Expand it */ 922 if (!ExpandEnvironmentStringsW(szBuffer, 923 szProgramFilesDirPath, 924 ARRAYSIZE(szProgramFilesDirPath))) 925 { 926 DPRINT1("Error: %lu\n", GetLastError()); 927 return FALSE; 928 } 929 930 wcscpy(szBuffer, szProgramFilesDirPath); 931 wcscat(szBuffer, L"\\"); 932 wcscat(szBuffer, szCommonFilesDirPath); 933 934 if (!ExpandEnvironmentStringsW(szBuffer, 935 szCommonFilesDirPath, 936 ARRAYSIZE(szCommonFilesDirPath))) 937 { 938 DPRINT1("Warning: %lu\n", GetLastError()); 939 } 940 941 /* Store it */ 942 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 943 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 944 0, 945 KEY_SET_VALUE, 946 &hKey); 947 if (Error != ERROR_SUCCESS) 948 { 949 DPRINT1("Error: %lu\n", Error); 950 return FALSE; 951 } 952 953 dwLength = (wcslen(szProgramFilesDirPath) + 1) * sizeof(WCHAR); 954 Error = RegSetValueExW(hKey, 955 L"ProgramFilesDir", 956 0, 957 REG_SZ, 958 (LPBYTE)szProgramFilesDirPath, 959 dwLength); 960 if (Error != ERROR_SUCCESS) 961 { 962 DPRINT1("Error: %lu\n", Error); 963 RegCloseKey(hKey); 964 return FALSE; 965 } 966 967 dwLength = (wcslen(szCommonFilesDirPath) + 1) * sizeof(WCHAR); 968 Error = RegSetValueExW(hKey, 969 L"CommonFilesDir", 970 0, 971 REG_SZ, 972 (LPBYTE)szCommonFilesDirPath, 973 dwLength); 974 if (Error != ERROR_SUCCESS) 975 { 976 DPRINT1("Warning: %lu\n", Error); 977 } 978 979 RegCloseKey(hKey); 980 981 /* Create directory */ 982 // FIXME: Security! 983 if (!CreateDirectoryW(szProgramFilesDirPath, NULL)) 984 { 985 if (GetLastError() != ERROR_ALREADY_EXISTS) 986 { 987 DPRINT1("Error: %lu\n", GetLastError()); 988 return FALSE; 989 } 990 } 991 992 /* Create directory */ 993 // FIXME: Security! 994 if (!CreateDirectoryW(szCommonFilesDirPath, NULL)) 995 { 996 if (GetLastError() != ERROR_ALREADY_EXISTS) 997 { 998 DPRINT1("Warning: %lu\n", GetLastError()); 999 // return FALSE; 1000 } 1001 } 1002 1003 return TRUE; 1004 } 1005 1006 1007 static 1008 VOID 1009 InitializeDefaultUserLocale(VOID) 1010 { 1011 WCHAR szBuffer[80]; 1012 PWSTR ptr; 1013 HKEY hLocaleKey; 1014 DWORD ret; 1015 DWORD dwSize; 1016 LCID lcid; 1017 INT i; 1018 1019 struct {LCTYPE LCType; PWSTR pValue;} LocaleData[] = { 1020 /* Number */ 1021 {LOCALE_SDECIMAL, L"sDecimal"}, 1022 {LOCALE_STHOUSAND, L"sThousand"}, 1023 {LOCALE_SNEGATIVESIGN, L"sNegativeSign"}, 1024 {LOCALE_SPOSITIVESIGN, L"sPositiveSign"}, 1025 {LOCALE_SGROUPING, L"sGrouping"}, 1026 {LOCALE_SLIST, L"sList"}, 1027 {LOCALE_SNATIVEDIGITS, L"sNativeDigits"}, 1028 {LOCALE_INEGNUMBER, L"iNegNumber"}, 1029 {LOCALE_IDIGITS, L"iDigits"}, 1030 {LOCALE_ILZERO, L"iLZero"}, 1031 {LOCALE_IMEASURE, L"iMeasure"}, 1032 {LOCALE_IDIGITSUBSTITUTION, L"NumShape"}, 1033 1034 /* Currency */ 1035 {LOCALE_SCURRENCY, L"sCurrency"}, 1036 {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"}, 1037 {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"}, 1038 {LOCALE_SMONGROUPING, L"sMonGrouping"}, 1039 {LOCALE_ICURRENCY, L"iCurrency"}, 1040 {LOCALE_INEGCURR, L"iNegCurr"}, 1041 {LOCALE_ICURRDIGITS, L"iCurrDigits"}, 1042 1043 /* Time */ 1044 {LOCALE_STIMEFORMAT, L"sTimeFormat"}, 1045 {LOCALE_STIME, L"sTime"}, 1046 {LOCALE_S1159, L"s1159"}, 1047 {LOCALE_S2359, L"s2359"}, 1048 {LOCALE_ITIME, L"iTime"}, 1049 {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"}, 1050 {LOCALE_ITLZERO, L"iTLZero"}, 1051 1052 /* Date */ 1053 {LOCALE_SLONGDATE, L"sLongDate"}, 1054 {LOCALE_SSHORTDATE, L"sShortDate"}, 1055 {LOCALE_SDATE, L"sDate"}, 1056 {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"}, 1057 {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"}, 1058 {LOCALE_IDATE, L"iDate"}, 1059 {LOCALE_ICALENDARTYPE, L"iCalendarType"}, 1060 1061 /* Misc */ 1062 {LOCALE_SCOUNTRY, L"sCountry"}, 1063 {LOCALE_SABBREVLANGNAME, L"sLanguage"}, 1064 {LOCALE_ICOUNTRY, L"iCountry"}, 1065 {0, NULL}}; 1066 1067 ret = RegOpenKeyExW(HKEY_USERS, 1068 L".DEFAULT\\Control Panel\\International", 1069 0, 1070 KEY_READ | KEY_WRITE, 1071 &hLocaleKey); 1072 if (ret != ERROR_SUCCESS) 1073 { 1074 return; 1075 } 1076 1077 dwSize = 9 * sizeof(WCHAR); 1078 ret = RegQueryValueExW(hLocaleKey, 1079 L"Locale", 1080 NULL, 1081 NULL, 1082 (PBYTE)szBuffer, 1083 &dwSize); 1084 if (ret != ERROR_SUCCESS) 1085 goto done; 1086 1087 lcid = (LCID)wcstoul(szBuffer, &ptr, 16); 1088 if (lcid == 0) 1089 goto done; 1090 1091 i = 0; 1092 while (LocaleData[i].pValue != NULL) 1093 { 1094 if (GetLocaleInfoW(lcid, 1095 LocaleData[i].LCType | LOCALE_NOUSEROVERRIDE, 1096 szBuffer, 1097 ARRAYSIZE(szBuffer))) 1098 { 1099 RegSetValueExW(hLocaleKey, 1100 LocaleData[i].pValue, 1101 0, 1102 REG_SZ, 1103 (PBYTE)szBuffer, 1104 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1105 } 1106 1107 i++; 1108 } 1109 1110 done: 1111 RegCloseKey(hLocaleKey); 1112 } 1113 1114 1115 static 1116 DWORD 1117 SaveDefaultUserHive(VOID) 1118 { 1119 WCHAR szDefaultUserHive[MAX_PATH]; 1120 HKEY hUserKey = NULL; 1121 DWORD cchSize; 1122 DWORD dwError; 1123 1124 DPRINT("SaveDefaultUserHive()\n"); 1125 1126 cchSize = ARRAYSIZE(szDefaultUserHive); 1127 GetDefaultUserProfileDirectoryW(szDefaultUserHive, &cchSize); 1128 1129 wcscat(szDefaultUserHive, L"\\ntuser.dat"); 1130 1131 dwError = RegOpenKeyExW(HKEY_USERS, 1132 L".DEFAULT", 1133 0, 1134 KEY_READ, 1135 &hUserKey); 1136 if (dwError != ERROR_SUCCESS) 1137 { 1138 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError); 1139 return dwError; 1140 } 1141 1142 pSetupEnablePrivilege(L"SeBackupPrivilege", TRUE); 1143 1144 /* Save the Default hive */ 1145 dwError = RegSaveKeyExW(hUserKey, 1146 szDefaultUserHive, 1147 NULL, 1148 REG_STANDARD_FORMAT); 1149 if (dwError == ERROR_ALREADY_EXISTS) 1150 { 1151 WCHAR szBackupHive[MAX_PATH]; 1152 1153 /* Build the backup hive file name by replacing the extension */ 1154 wcscpy(szBackupHive, szDefaultUserHive); 1155 wcscpy(&szBackupHive[wcslen(szBackupHive) - 4], L".bak"); 1156 1157 /* Back up the existing default user hive by renaming it, replacing any possible existing old backup */ 1158 if (!MoveFileExW(szDefaultUserHive, 1159 szBackupHive, 1160 MOVEFILE_REPLACE_EXISTING)) 1161 { 1162 dwError = GetLastError(); 1163 DPRINT1("Failed to create a default-user hive backup '%S', MoveFileExW failed (Error %lu)\n", 1164 szBackupHive, dwError); 1165 } 1166 else 1167 { 1168 /* The backup has been done, retry saving the Default hive */ 1169 dwError = RegSaveKeyExW(hUserKey, 1170 szDefaultUserHive, 1171 NULL, 1172 REG_STANDARD_FORMAT); 1173 } 1174 } 1175 if (dwError != ERROR_SUCCESS) 1176 { 1177 DPRINT1("RegSaveKeyExW() failed (Error %lu)\n", dwError); 1178 } 1179 1180 pSetupEnablePrivilege(L"SeBackupPrivilege", FALSE); 1181 1182 RegCloseKey(hUserKey); 1183 1184 return dwError; 1185 } 1186 1187 1188 static 1189 DWORD 1190 InstallReactOS(VOID) 1191 { 1192 WCHAR szBuffer[MAX_PATH]; 1193 HANDLE token; 1194 TOKEN_PRIVILEGES privs; 1195 HKEY hKey; 1196 HINF hShortcutsInf; 1197 HANDLE hHotkeyThread; 1198 BOOL ret; 1199 1200 InitializeSetupActionLog(FALSE); 1201 LogItem(NULL, L"Installing ReactOS"); 1202 1203 CreateTempDir(L"TEMP"); 1204 CreateTempDir(L"TMP"); 1205 1206 if (!InitializeProgramFilesDir()) 1207 { 1208 FatalError("InitializeProgramFilesDir() failed"); 1209 return 0; 1210 } 1211 1212 if (!InitializeProfiles()) 1213 { 1214 FatalError("InitializeProfiles() failed"); 1215 return 0; 1216 } 1217 1218 InitializeDefaultUserLocale(); 1219 1220 if (GetWindowsDirectoryW(szBuffer, ARRAYSIZE(szBuffer))) 1221 { 1222 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1223 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1224 0, 1225 KEY_WRITE, 1226 &hKey) == ERROR_SUCCESS) 1227 { 1228 RegSetValueExW(hKey, 1229 L"PathName", 1230 0, 1231 REG_SZ, 1232 (LPBYTE)szBuffer, 1233 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1234 1235 RegSetValueExW(hKey, 1236 L"SystemRoot", 1237 0, 1238 REG_SZ, 1239 (LPBYTE)szBuffer, 1240 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1241 1242 RegCloseKey(hKey); 1243 } 1244 1245 PathAddBackslash(szBuffer); 1246 wcscat(szBuffer, L"system"); 1247 CreateDirectory(szBuffer, NULL); 1248 } 1249 1250 if (SaveDefaultUserHive() != ERROR_SUCCESS) 1251 { 1252 FatalError("SaveDefaultUserHive() failed"); 1253 return 0; 1254 } 1255 1256 if (!CopySystemProfile(0)) 1257 { 1258 FatalError("CopySystemProfile() failed"); 1259 return 0; 1260 } 1261 1262 hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL); 1263 1264 if (!CommonInstall()) 1265 return 0; 1266 1267 /* Install the TCP/IP protocol driver */ 1268 ret = InstallNetworkComponent(L"MS_TCPIP"); 1269 if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND) 1270 { 1271 DPRINT("InstallNetworkComponent() failed with error 0x%lx\n", GetLastError()); 1272 } 1273 else 1274 { 1275 /* Start the TCP/IP protocol driver */ 1276 SetupStartService(L"Tcpip", FALSE); 1277 SetupStartService(L"Dhcp", FALSE); 1278 SetupStartService(L"Dnscache", FALSE); 1279 } 1280 1281 InstallWizard(); 1282 1283 InstallSecurity(); 1284 1285 SetAutoAdminLogon(); 1286 1287 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf", 1288 NULL, 1289 INF_STYLE_WIN4, 1290 NULL); 1291 if (hShortcutsInf == INVALID_HANDLE_VALUE) 1292 { 1293 FatalError("Failed to open shortcuts.inf"); 1294 return 0; 1295 } 1296 1297 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders")) 1298 { 1299 FatalError("CreateShortcuts() failed"); 1300 return 0; 1301 } 1302 1303 SetupCloseInfFile(hShortcutsInf); 1304 1305 hShortcutsInf = SetupOpenInfFileW(L"rosapps_shortcuts.inf", 1306 NULL, 1307 INF_STYLE_WIN4, 1308 NULL); 1309 if (hShortcutsInf != INVALID_HANDLE_VALUE) 1310 { 1311 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders")) 1312 { 1313 FatalError("CreateShortcuts(rosapps) failed"); 1314 return 0; 1315 } 1316 SetupCloseInfFile(hShortcutsInf); 1317 } 1318 1319 SetupCloseInfFile(hSysSetupInf); 1320 SetSetupType(0); 1321 1322 if (hHotkeyThread) 1323 { 1324 PostThreadMessage(GetThreadId(hHotkeyThread), WM_QUIT, 0, 0); 1325 CloseHandle(hHotkeyThread); 1326 } 1327 1328 LogItem(NULL, L"Installing ReactOS done"); 1329 TerminateSetupActionLog(); 1330 1331 if (AdminInfo.Name != NULL) 1332 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name); 1333 1334 if (AdminInfo.Domain != NULL) 1335 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain); 1336 1337 if (AdminInfo.Password != NULL) 1338 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password); 1339 1340 /* Get shutdown privilege */ 1341 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) 1342 { 1343 FatalError("OpenProcessToken() failed!"); 1344 return 0; 1345 } 1346 if (!LookupPrivilegeValue(NULL, 1347 SE_SHUTDOWN_NAME, 1348 &privs.Privileges[0].Luid)) 1349 { 1350 FatalError("LookupPrivilegeValue() failed!"); 1351 return 0; 1352 } 1353 privs.PrivilegeCount = 1; 1354 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1355 if (AdjustTokenPrivileges(token, 1356 FALSE, 1357 &privs, 1358 0, 1359 (PTOKEN_PRIVILEGES)NULL, 1360 NULL) == 0) 1361 { 1362 FatalError("AdjustTokenPrivileges() failed!"); 1363 return 0; 1364 } 1365 1366 ExitWindowsEx(EWX_REBOOT, 0); 1367 return 0; 1368 } 1369 1370 1371 /* 1372 * Standard Windows-compatible export, which dispatches 1373 * to either 'InstallReactOS' or 'InstallLiveCD'. 1374 */ 1375 INT 1376 WINAPI 1377 InstallWindowsNt(INT argc, WCHAR** argv) 1378 { 1379 INT i; 1380 PWSTR p; 1381 1382 for (i = 0; i < argc; ++i) 1383 { 1384 p = argv[i]; 1385 if (*p == L'-') 1386 { 1387 p++; 1388 1389 // NOTE: On Windows, "mini" means "minimal UI", and can be used 1390 // in addition to "newsetup"; these options are not exclusive. 1391 if (_wcsicmp(p, L"newsetup") == 0) 1392 return (INT)InstallReactOS(); 1393 else if (_wcsicmp(p, L"mini") == 0) 1394 return (INT)InstallLiveCD(); 1395 1396 /* Add support for other switches */ 1397 } 1398 } 1399 1400 return 0; 1401 } 1402 1403 1404 /* 1405 * @unimplemented 1406 */ 1407 DWORD WINAPI 1408 SetupChangeFontSize( 1409 IN HANDLE hWnd, 1410 IN LPCWSTR lpszFontSize) 1411 { 1412 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1413 return FALSE; 1414 } 1415 1416 /* 1417 * @unimplemented 1418 */ 1419 DWORD WINAPI 1420 SetupChangeLocaleEx(HWND hWnd, 1421 LCID Lcid, 1422 LPCWSTR lpSrcRootPath, 1423 char Unknown, 1424 DWORD dwUnused1, 1425 DWORD dwUnused2) 1426 { 1427 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1428 return FALSE; 1429 } 1430 1431 /* 1432 * @implemented 1433 */ 1434 DWORD WINAPI 1435 SetupChangeLocale(HWND hWnd, LCID Lcid) 1436 { 1437 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0); 1438 } 1439 1440 1441 DWORD 1442 WINAPI 1443 SetupStartService( 1444 LPCWSTR lpServiceName, 1445 BOOL bWait) 1446 { 1447 SC_HANDLE hManager = NULL; 1448 SC_HANDLE hService = NULL; 1449 DWORD dwError = ERROR_SUCCESS; 1450 1451 hManager = OpenSCManagerW(NULL, 1452 NULL, 1453 SC_MANAGER_ALL_ACCESS); 1454 if (hManager == NULL) 1455 { 1456 dwError = GetLastError(); 1457 goto done; 1458 } 1459 1460 hService = OpenServiceW(hManager, 1461 lpServiceName, 1462 SERVICE_START); 1463 if (hService == NULL) 1464 { 1465 dwError = GetLastError(); 1466 goto done; 1467 } 1468 1469 if (!StartService(hService, 0, NULL)) 1470 { 1471 dwError = GetLastError(); 1472 goto done; 1473 } 1474 1475 done: 1476 if (hService != NULL) 1477 CloseServiceHandle(hService); 1478 1479 if (hManager != NULL) 1480 CloseServiceHandle(hManager); 1481 1482 return dwError; 1483 } 1484