xref: /reactos/dll/win32/syssetup/install.c (revision 58588b76)
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