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 SaveDefaultUserHive(VOID) 1177 { 1178 WCHAR szDefaultUserHive[MAX_PATH]; 1179 HKEY hUserKey = NULL; 1180 DWORD cchSize; 1181 DWORD dwError; 1182 1183 DPRINT("SaveDefaultUserHive()\n"); 1184 1185 cchSize = ARRAYSIZE(szDefaultUserHive); 1186 GetDefaultUserProfileDirectoryW(szDefaultUserHive, &cchSize); 1187 1188 wcscat(szDefaultUserHive, L"\\ntuser.dat"); 1189 1190 dwError = RegOpenKeyExW(HKEY_USERS, 1191 L".DEFAULT", 1192 0, 1193 KEY_READ, 1194 &hUserKey); 1195 if (dwError != ERROR_SUCCESS) 1196 { 1197 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError); 1198 return dwError; 1199 } 1200 1201 pSetupEnablePrivilege(L"SeBackupPrivilege", TRUE); 1202 1203 /* Save the Default hive */ 1204 dwError = RegSaveKeyExW(hUserKey, 1205 szDefaultUserHive, 1206 NULL, 1207 REG_STANDARD_FORMAT); 1208 if (dwError == ERROR_ALREADY_EXISTS) 1209 { 1210 WCHAR szBackupHive[MAX_PATH]; 1211 1212 /* Build the backup hive file name by replacing the extension */ 1213 wcscpy(szBackupHive, szDefaultUserHive); 1214 wcscpy(&szBackupHive[wcslen(szBackupHive) - 4], L".bak"); 1215 1216 /* Back up the existing default user hive by renaming it, replacing any possible existing old backup */ 1217 if (!MoveFileExW(szDefaultUserHive, 1218 szBackupHive, 1219 MOVEFILE_REPLACE_EXISTING)) 1220 { 1221 dwError = GetLastError(); 1222 DPRINT1("Failed to create a default-user hive backup '%S', MoveFileExW failed (Error %lu)\n", 1223 szBackupHive, dwError); 1224 } 1225 else 1226 { 1227 /* The backup has been done, retry saving the Default hive */ 1228 dwError = RegSaveKeyExW(hUserKey, 1229 szDefaultUserHive, 1230 NULL, 1231 REG_STANDARD_FORMAT); 1232 } 1233 } 1234 if (dwError != ERROR_SUCCESS) 1235 { 1236 DPRINT1("RegSaveKeyExW() failed (Error %lu)\n", dwError); 1237 } 1238 1239 pSetupEnablePrivilege(L"SeBackupPrivilege", FALSE); 1240 1241 RegCloseKey(hUserKey); 1242 1243 return dwError; 1244 } 1245 1246 1247 static 1248 DWORD 1249 InstallReactOS(VOID) 1250 { 1251 WCHAR szBuffer[MAX_PATH]; 1252 HANDLE token; 1253 TOKEN_PRIVILEGES privs; 1254 HKEY hKey; 1255 HINF hShortcutsInf; 1256 HANDLE hHotkeyThread; 1257 BOOL ret; 1258 1259 InitializeSetupActionLog(FALSE); 1260 LogItem(NULL, L"Installing ReactOS"); 1261 1262 CreateTempDir(L"TEMP"); 1263 CreateTempDir(L"TMP"); 1264 1265 if (!InitializeProgramFilesDir()) 1266 { 1267 FatalError("InitializeProgramFilesDir() failed"); 1268 return 0; 1269 } 1270 1271 if (!InitializeProfiles()) 1272 { 1273 FatalError("InitializeProfiles() failed"); 1274 return 0; 1275 } 1276 1277 InitializeDefaultUserLocale(); 1278 1279 if (GetWindowsDirectoryW(szBuffer, ARRAYSIZE(szBuffer))) 1280 { 1281 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1282 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1283 0, 1284 KEY_WRITE, 1285 &hKey) == ERROR_SUCCESS) 1286 { 1287 RegSetValueExW(hKey, 1288 L"PathName", 1289 0, 1290 REG_SZ, 1291 (LPBYTE)szBuffer, 1292 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1293 1294 RegSetValueExW(hKey, 1295 L"SystemRoot", 1296 0, 1297 REG_SZ, 1298 (LPBYTE)szBuffer, 1299 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 1300 1301 RegCloseKey(hKey); 1302 } 1303 1304 PathAddBackslash(szBuffer); 1305 wcscat(szBuffer, L"system"); 1306 CreateDirectory(szBuffer, NULL); 1307 } 1308 1309 if (SaveDefaultUserHive() != ERROR_SUCCESS) 1310 { 1311 FatalError("SaveDefaultUserHive() failed"); 1312 return 0; 1313 } 1314 1315 if (!CopySystemProfile(0)) 1316 { 1317 FatalError("CopySystemProfile() failed"); 1318 return 0; 1319 } 1320 1321 hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL); 1322 1323 /* Hack: Install TCP/IP protocol driver */ 1324 ret = InstallInfSection(NULL, 1325 L"nettcpip.inf", 1326 L"MS_TCPIP.PrimaryInstall", 1327 L"MS_TCPIP.PrimaryInstall.Services"); 1328 if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND) 1329 { 1330 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError()); 1331 } 1332 else 1333 { 1334 /* Start the TCP/IP protocol driver */ 1335 SetupStartService(L"Tcpip", FALSE); 1336 SetupStartService(L"Dhcp", FALSE); 1337 } 1338 1339 1340 if (!CommonInstall()) 1341 return 0; 1342 1343 InstallWizard(); 1344 1345 InstallSecurity(); 1346 1347 SetAutoAdminLogon(); 1348 1349 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf", 1350 NULL, 1351 INF_STYLE_WIN4, 1352 NULL); 1353 if (hShortcutsInf == INVALID_HANDLE_VALUE) 1354 { 1355 FatalError("Failed to open shortcuts.inf"); 1356 return 0; 1357 } 1358 1359 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders")) 1360 { 1361 FatalError("CreateShortcuts() failed"); 1362 return 0; 1363 } 1364 1365 SetupCloseInfFile(hShortcutsInf); 1366 1367 hShortcutsInf = SetupOpenInfFileW(L"rosapps_shortcuts.inf", 1368 NULL, 1369 INF_STYLE_WIN4, 1370 NULL); 1371 if (hShortcutsInf != INVALID_HANDLE_VALUE) 1372 { 1373 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders")) 1374 { 1375 FatalError("CreateShortcuts(rosapps) failed"); 1376 return 0; 1377 } 1378 SetupCloseInfFile(hShortcutsInf); 1379 } 1380 1381 SetupCloseInfFile(hSysSetupInf); 1382 SetSetupType(0); 1383 1384 if (hHotkeyThread) 1385 { 1386 PostThreadMessage(GetThreadId(hHotkeyThread), WM_QUIT, 0, 0); 1387 CloseHandle(hHotkeyThread); 1388 } 1389 1390 LogItem(NULL, L"Installing ReactOS done"); 1391 TerminateSetupActionLog(); 1392 1393 if (AdminInfo.Name != NULL) 1394 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name); 1395 1396 if (AdminInfo.Domain != NULL) 1397 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain); 1398 1399 if (AdminInfo.Password != NULL) 1400 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password); 1401 1402 /* Get shutdown privilege */ 1403 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) 1404 { 1405 FatalError("OpenProcessToken() failed!"); 1406 return 0; 1407 } 1408 if (!LookupPrivilegeValue(NULL, 1409 SE_SHUTDOWN_NAME, 1410 &privs.Privileges[0].Luid)) 1411 { 1412 FatalError("LookupPrivilegeValue() failed!"); 1413 return 0; 1414 } 1415 privs.PrivilegeCount = 1; 1416 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1417 if (AdjustTokenPrivileges(token, 1418 FALSE, 1419 &privs, 1420 0, 1421 (PTOKEN_PRIVILEGES)NULL, 1422 NULL) == 0) 1423 { 1424 FatalError("AdjustTokenPrivileges() failed!"); 1425 return 0; 1426 } 1427 1428 ExitWindowsEx(EWX_REBOOT, 0); 1429 return 0; 1430 } 1431 1432 1433 /* 1434 * Standard Windows-compatible export, which dispatches 1435 * to either 'InstallReactOS' or 'InstallLiveCD'. 1436 */ 1437 INT 1438 WINAPI 1439 InstallWindowsNt(INT argc, WCHAR** argv) 1440 { 1441 INT i; 1442 PWSTR p; 1443 1444 for (i = 0; i < argc; ++i) 1445 { 1446 p = argv[i]; 1447 if (*p == L'-') 1448 { 1449 p++; 1450 1451 // NOTE: On Windows, "mini" means "minimal UI", and can be used 1452 // in addition to "newsetup"; these options are not exclusive. 1453 if (_wcsicmp(p, L"newsetup") == 0) 1454 return (INT)InstallReactOS(); 1455 else if (_wcsicmp(p, L"mini") == 0) 1456 return (INT)InstallLiveCD(); 1457 1458 /* Add support for other switches */ 1459 } 1460 } 1461 1462 return 0; 1463 } 1464 1465 1466 /* 1467 * @unimplemented 1468 */ 1469 DWORD WINAPI 1470 SetupChangeFontSize( 1471 IN HANDLE hWnd, 1472 IN LPCWSTR lpszFontSize) 1473 { 1474 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1475 return FALSE; 1476 } 1477 1478 /* 1479 * @unimplemented 1480 */ 1481 DWORD WINAPI 1482 SetupChangeLocaleEx(HWND hWnd, 1483 LCID Lcid, 1484 LPCWSTR lpSrcRootPath, 1485 char Unknown, 1486 DWORD dwUnused1, 1487 DWORD dwUnused2) 1488 { 1489 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1490 return FALSE; 1491 } 1492 1493 /* 1494 * @implemented 1495 */ 1496 DWORD WINAPI 1497 SetupChangeLocale(HWND hWnd, LCID Lcid) 1498 { 1499 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0); 1500 } 1501 1502 1503 DWORD 1504 WINAPI 1505 SetupStartService( 1506 LPCWSTR lpServiceName, 1507 BOOL bWait) 1508 { 1509 SC_HANDLE hManager = NULL; 1510 SC_HANDLE hService = NULL; 1511 SERVICE_STATUS ServiceStatus; 1512 DWORD dwError = ERROR_SUCCESS; 1513 DWORD dwRetries = 0; 1514 1515 hManager = OpenSCManagerW(NULL, 1516 NULL, 1517 SC_MANAGER_ALL_ACCESS); 1518 if (hManager == NULL) 1519 { 1520 dwError = GetLastError(); 1521 goto done; 1522 } 1523 1524 hService = OpenServiceW(hManager, 1525 lpServiceName, 1526 SERVICE_START | (bWait) ? SERVICE_QUERY_STATUS : 0); 1527 if (hService == NULL) 1528 { 1529 dwError = GetLastError(); 1530 goto done; 1531 } 1532 1533 if (!StartService(hService, 0, NULL)) 1534 { 1535 dwError = GetLastError(); 1536 if (dwError != ERROR_SERVICE_ALREADY_RUNNING) 1537 goto done; 1538 1539 if (bWait) 1540 { 1541 for (;;) 1542 { 1543 if (!QueryServiceStatus(hService, &ServiceStatus)) 1544 break; 1545 1546 if (ServiceStatus.dwCurrentState != SERVICE_START_PENDING) 1547 break; 1548 1549 if (dwRetries == 30) 1550 break; 1551 1552 dwRetries++; 1553 1554 Sleep(5000); 1555 } 1556 } 1557 } 1558 1559 done: 1560 if (hService != NULL) 1561 CloseServiceHandle(hService); 1562 1563 if (hManager != NULL) 1564 CloseServiceHandle(hManager); 1565 1566 return dwError; 1567 } 1568