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