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