Reactos
1/*
2 * ReactOS applications
3 * Copyright (C) 2001, 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19/*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Userinit Logon Application
22 * FILE: base/system/userinit/userinit.c
23 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
24 * Herv� Poussineau (hpoussin@reactos.org)
25 */
26
27#include "userinit.h"
28
29#define CMP_MAGIC 0x01234567
30
31/* GLOBALS ******************************************************************/
32
33HINSTANCE hInstance;
34
35/* FUNCTIONS ****************************************************************/
36
37LONG
38ReadRegSzKey(
39 IN HKEY hKey,
40 IN LPCWSTR pszKey,
41 OUT LPWSTR *pValue)
42{
43 LONG rc;
44 DWORD dwType;
45 DWORD cbData = 0;
46 LPWSTR Value;
47
48 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
49 if (rc != ERROR_SUCCESS)
50 {
51 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey), rc);
52 return rc;
53 }
54 if (dwType != REG_SZ)
55 {
56 WARN("Wrong registry data type (%u vs %u)\n", dwType, REG_SZ);
57 return ERROR_FILE_NOT_FOUND;
58 }
59 Value = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
60 if (!Value)
61 {
62 WARN("No memory\n");
63 return ERROR_NOT_ENOUGH_MEMORY;
64 }
65 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
66 if (rc != ERROR_SUCCESS)
67 {
68 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey), rc);
69 HeapFree(GetProcessHeap(), 0, Value);
70 return rc;
71 }
72 /* NULL-terminate the string */
73 Value[cbData / sizeof(WCHAR)] = L'\0';
74
75 *pValue = Value;
76 return ERROR_SUCCESS;
77}
78
79static BOOL
80IsConsoleShell(VOID)
81{
82 HKEY ControlKey = NULL;
83 LPWSTR SystemStartOptions = NULL;
84 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
85 LONG rc;
86 BOOL ret = FALSE;
87
88 rc = RegOpenKeyEx(
89 HKEY_LOCAL_MACHINE,
90 REGSTR_PATH_CURRENT_CONTROL_SET,
91 0,
92 KEY_QUERY_VALUE,
93 &ControlKey);
94 if (rc != ERROR_SUCCESS)
95 {
96 WARN("RegOpenKeyEx() failed with error %lu\n", rc);
97 goto cleanup;
98 }
99
100 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
101 if (rc != ERROR_SUCCESS)
102 {
103 WARN("ReadRegSzKey() failed with error %lu\n", rc);
104 goto cleanup;
105 }
106
107 /* Check for CONSOLE switch in SystemStartOptions */
108 CurrentOption = SystemStartOptions;
109 while (CurrentOption)
110 {
111 NextOption = wcschr(CurrentOption, L' ');
112 if (NextOption)
113 *NextOption = L'\0';
114 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
115 {
116 TRACE("Found 'CONSOLE' boot option\n");
117 ret = TRUE;
118 goto cleanup;
119 }
120 CurrentOption = NextOption ? NextOption + 1 : NULL;
121 }
122
123cleanup:
124 if (ControlKey != NULL)
125 RegCloseKey(ControlKey);
126 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
127
128 TRACE("IsConsoleShell() returning %u\n", ret);
129 return ret;
130}
131
132static BOOL
133GetShell(
134 OUT WCHAR *CommandLine, /* must be at least MAX_PATH long */
135 IN HKEY hRootKey)
136{
137 HKEY hKey;
138 DWORD Type, Size;
139 WCHAR Shell[MAX_PATH];
140 BOOL ConsoleShell = IsConsoleShell();
141 LONG rc;
142
143 rc = RegOpenKeyExW(hRootKey, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
144 0, KEY_QUERY_VALUE, &hKey);
145 if (rc != ERROR_SUCCESS)
146 {
147 WARN("RegOpenKeyEx() failed with error %lu\n", rc);
148 return FALSE;
149 }
150
151 Size = sizeof(Shell);
152 rc = RegQueryValueExW(hKey,
153 ConsoleShell ? L"ConsoleShell" : L"Shell",
154 NULL,
155 &Type,
156 (LPBYTE)Shell,
157 &Size);
158 RegCloseKey(hKey);
159
160 if (rc != ERROR_SUCCESS)
161 {
162 WARN("RegQueryValueEx() failed with error %lu\n", rc);
163 return FALSE;
164 }
165
166 if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ))
167 {
168 TRACE("Found command line %s\n", debugstr_w(Shell));
169 wcscpy(CommandLine, Shell);
170 return TRUE;
171 }
172 else
173 {
174 WARN("Wrong type %lu (expected %u or %u)\n", Type, REG_SZ, REG_EXPAND_SZ);
175 return FALSE;
176 }
177}
178
179static BOOL
180StartProcess(
181 IN LPCWSTR CommandLine)
182{
183 STARTUPINFO si;
184 PROCESS_INFORMATION pi;
185 WCHAR ExpandedCmdLine[MAX_PATH];
186
187 ExpandEnvironmentStringsW(CommandLine, ExpandedCmdLine, ARRAYSIZE(ExpandedCmdLine));
188
189 ZeroMemory(&si, sizeof(si));
190 si.cb = sizeof(si);
191 si.dwFlags = STARTF_USESHOWWINDOW;
192 si.wShowWindow = SW_SHOWNORMAL;
193 ZeroMemory(&pi, sizeof(pi));
194
195 if (!CreateProcessW(NULL,
196 ExpandedCmdLine,
197 NULL,
198 NULL,
199 FALSE,
200 NORMAL_PRIORITY_CLASS,
201 NULL,
202 NULL,
203 &si,
204 &pi))
205 {
206 WARN("CreateProcessW() failed with error %lu\n", GetLastError());
207 return FALSE;
208 }
209
210 CloseHandle(pi.hProcess);
211 CloseHandle(pi.hThread);
212 return TRUE;
213}
214
215static BOOL
216StartShell(VOID)
217{
218 WCHAR Shell[MAX_PATH];
219 WCHAR szMsg[RC_STRING_MAX_SIZE];
220 DWORD Type, Size;
221 DWORD Value = 0;
222 LONG rc;
223 HKEY hKey;
224
225 /* Safe Mode shell run */
226 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
227 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
228 0, KEY_QUERY_VALUE, &hKey);
229 if (rc == ERROR_SUCCESS)
230 {
231 Size = sizeof(Value);
232 rc = RegQueryValueExW(hKey, L"UseAlternateShell", NULL,
233 &Type, (LPBYTE)&Value, &Size);
234 RegCloseKey(hKey);
235
236 if (rc == ERROR_SUCCESS)
237 {
238 if (Type == REG_DWORD)
239 {
240 if (Value)
241 {
242 /* Safe Mode Alternate Shell required */
243 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
244 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot",
245 0, KEY_READ, &hKey);
246 if (rc == ERROR_SUCCESS)
247 {
248 Size = sizeof(Shell);
249 rc = RegQueryValueExW(hKey, L"AlternateShell", NULL,
250 &Type, (LPBYTE)Shell, &Size);
251 RegCloseKey(hKey);
252
253 if (rc == ERROR_SUCCESS)
254 {
255 if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ))
256 {
257 TRACE("Key located - %s\n", debugstr_w(Shell));
258
259 /* Try to run alternate shell */
260 if (StartProcess(Shell))
261 {
262 TRACE("Alternate shell started (Safe Mode)\n");
263 return TRUE;
264 }
265 }
266 else
267 {
268 WARN("Wrong type %lu (expected %u or %u)\n",
269 Type, REG_SZ, REG_EXPAND_SZ);
270 }
271 }
272 else
273 {
274 WARN("Alternate shell in Safe Mode required but not specified.\n");
275 }
276 }
277 }
278 }
279 else
280 {
281 WARN("Wrong type %lu (expected %u)\n", Type, REG_DWORD);
282 }
283 }
284 }
285
286 /* Try to run shell in user key */
287 if (GetShell(Shell, HKEY_CURRENT_USER) && StartProcess(Shell))
288 {
289 TRACE("Started shell from HKEY_CURRENT_USER\n");
290 return TRUE;
291 }
292
293 /* Try to run shell in local machine key */
294 if (GetShell(Shell, HKEY_LOCAL_MACHINE) && StartProcess(Shell))
295 {
296 TRACE("Started shell from HKEY_LOCAL_MACHINE\n");
297 return TRUE;
298 }
299
300 /* Try default shell */
301 if (IsConsoleShell())
302 {
303 *Shell = UNICODE_NULL;
304 if (GetSystemDirectoryW(Shell, ARRAYSIZE(Shell) - 8))
305 StringCchCatW(Shell, ARRAYSIZE(Shell), L"\\");
306 StringCchCatW(Shell, ARRAYSIZE(Shell), L"cmd.exe");
307 }
308 else
309 {
310 *Shell = UNICODE_NULL;
311 if (GetSystemWindowsDirectoryW(Shell, ARRAYSIZE(Shell) - 13))
312 StringCchCatW(Shell, ARRAYSIZE(Shell), L"\\");
313 StringCchCatW(Shell, ARRAYSIZE(Shell), L"explorer.exe");
314 }
315
316 if (!StartProcess(Shell))
317 {
318 WARN("Failed to start default shell '%s'\n", debugstr_w(Shell));
319 LoadStringW(GetModuleHandle(NULL), IDS_SHELL_FAIL, szMsg, ARRAYSIZE(szMsg));
320 MessageBoxW(NULL, szMsg, NULL, MB_OK);
321 return FALSE;
322 }
323 return TRUE;
324}
325
326const WCHAR g_RegColorNames[][32] = {
327 L"Scrollbar", /* 00 = COLOR_SCROLLBAR */
328 L"Background", /* 01 = COLOR_DESKTOP */
329 L"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
330 L"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
331 L"Menu", /* 04 = COLOR_MENU */
332 L"Window", /* 05 = COLOR_WINDOW */
333 L"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
334 L"MenuText", /* 07 = COLOR_MENUTEXT */
335 L"WindowText", /* 08 = COLOR_WINDOWTEXT */
336 L"TitleText", /* 09 = COLOR_CAPTIONTEXT */
337 L"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
338 L"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
339 L"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
340 L"Hilight", /* 13 = COLOR_HIGHLIGHT */
341 L"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
342 L"ButtonFace", /* 15 = COLOR_BTNFACE */
343 L"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
344 L"GrayText", /* 17 = COLOR_GRAYTEXT */
345 L"ButtonText", /* 18 = COLOR_BTNTEXT */
346 L"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
347 L"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
348 L"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
349 L"ButtonLight", /* 22 = COLOR_3DLIGHT */
350 L"InfoText", /* 23 = COLOR_INFOTEXT */
351 L"InfoWindow", /* 24 = COLOR_INFOBK */
352 L"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
353 L"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
354 L"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
355 L"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
356 L"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
357 L"MenuBar" /* 30 = COLOR_MENUBAR */
358};
359
360static COLORREF
361StrToColorref(
362 IN LPWSTR lpszCol)
363{
364 BYTE rgb[3];
365
366 rgb[0] = (BYTE)wcstoul(lpszCol, &lpszCol, 10);
367 rgb[1] = (BYTE)wcstoul(lpszCol, &lpszCol, 10);
368 rgb[2] = (BYTE)wcstoul(lpszCol, &lpszCol, 10);
369 return RGB(rgb[0], rgb[1], rgb[2]);
370}
371
372static VOID
373SetUserSysColors(VOID)
374{
375 HKEY hKey;
376 INT i;
377 WCHAR szColor[25];
378 DWORD Type, Size;
379 COLORREF crColor;
380 LONG rc;
381
382 rc = RegOpenKeyExW(HKEY_CURRENT_USER, REGSTR_PATH_COLORS,
383 0, KEY_QUERY_VALUE, &hKey);
384 if (rc != ERROR_SUCCESS)
385 {
386 WARN("RegOpenKeyEx() failed with error %lu\n", rc);
387 return;
388 }
389
390 for (i = 0; i < ARRAYSIZE(g_RegColorNames); i++)
391 {
392 Size = sizeof(szColor);
393 rc = RegQueryValueExW(hKey, g_RegColorNames[i], NULL, &Type,
394 (LPBYTE)szColor, &Size);
395 if (rc == ERROR_SUCCESS && Type == REG_SZ)
396 {
397 crColor = StrToColorref(szColor);
398 SetSysColors(1, &i, &crColor);
399 }
400 else
401 {
402 WARN("RegQueryValueEx(%s) failed with error %lu\n",
403 debugstr_w(g_RegColorNames[i]), rc);
404 }
405 }
406
407 RegCloseKey(hKey);
408}
409
410static VOID
411SetUserWallpaper(VOID)
412{
413 HKEY hKey;
414 DWORD Type, Size;
415 WCHAR szWallpaper[MAX_PATH + 1];
416 LONG rc;
417
418 rc = RegOpenKeyExW(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP,
419 0, KEY_QUERY_VALUE, &hKey);
420 if (rc != ERROR_SUCCESS)
421 {
422 WARN("RegOpenKeyEx() failed with error %lu\n", rc);
423 return;
424 }
425
426 Size = sizeof(szWallpaper);
427 rc = RegQueryValueExW(hKey,
428 L"Wallpaper",
429 NULL,
430 &Type,
431 (LPBYTE)szWallpaper,
432 &Size);
433 RegCloseKey(hKey);
434
435 if (rc == ERROR_SUCCESS && Type == REG_SZ)
436 {
437 ExpandEnvironmentStringsW(szWallpaper, szWallpaper, ARRAYSIZE(szWallpaper));
438 TRACE("Using wallpaper %s\n", debugstr_w(szWallpaper));
439
440 /* Load and change the wallpaper */
441 SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, szWallpaper, SPIF_SENDCHANGE);
442 }
443 else
444 {
445 /* Remove the wallpaper */
446 TRACE("No wallpaper set in registry (error %lu)\n", rc);
447 SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE);
448 }
449}
450
451static VOID
452SetUserSettings(VOID)
453{
454 UpdatePerUserSystemParameters(1, TRUE);
455 SetUserSysColors();
456 SetUserWallpaper();
457}
458
459typedef DWORD (WINAPI *PCMP_REPORT_LOGON)(DWORD, DWORD);
460
461static VOID
462NotifyLogon(VOID)
463{
464 HINSTANCE hModule;
465 PCMP_REPORT_LOGON CMP_Report_LogOn;
466
467 hModule = LoadLibraryW(L"setupapi.dll");
468 if (!hModule)
469 {
470 WARN("LoadLibrary() failed with error %lu\n", GetLastError());
471 return;
472 }
473
474 CMP_Report_LogOn = (PCMP_REPORT_LOGON)GetProcAddress(hModule, "CMP_Report_LogOn");
475 if (CMP_Report_LogOn)
476 CMP_Report_LogOn(CMP_MAGIC, GetCurrentProcessId());
477 else
478 WARN("GetProcAddress() failed\n");
479
480 FreeLibrary(hModule);
481}
482
483/*
484 * Expands the path for the ReactOS Installer "reactos.exe".
485 * See also base/setup/welcome/welcome.c!ExpandInstallerPath()
486 */
487BOOL
488ExpandInstallerPath(
489 IN LPCWSTR lpInstallerName,
490 OUT LPWSTR lpInstallerPath,
491 IN SIZE_T PathSize)
492{
493 SYSTEM_INFO SystemInfo;
494 SIZE_T cchInstallerNameLen;
495 PWSTR ptr;
496 DWORD dwAttribs;
497
498 cchInstallerNameLen = wcslen(lpInstallerName);
499 if (PathSize < cchInstallerNameLen)
500 {
501 /* The buffer is not large enough to contain the installer file name */
502 *lpInstallerPath = UNICODE_NULL;
503 return FALSE;
504 }
505
506 /*
507 * First, try to find the installer using the default drive, under
508 * the directory whose name corresponds to the currently-running
509 * CPU architecture.
510 */
511 GetSystemInfo(&SystemInfo);
512
513 *lpInstallerPath = UNICODE_NULL;
514 /* Alternatively one can use SharedUserData->NtSystemRoot */
515 GetSystemWindowsDirectoryW(lpInstallerPath, PathSize - cchInstallerNameLen - 1);
516 ptr = wcschr(lpInstallerPath, L'\\');
517 if (ptr)
518 *++ptr = UNICODE_NULL;
519 else
520 *lpInstallerPath = UNICODE_NULL;
521
522 /* Append the corresponding CPU architecture */
523 switch (SystemInfo.wProcessorArchitecture)
524 {
525 case PROCESSOR_ARCHITECTURE_INTEL:
526 StringCchCatW(lpInstallerPath, PathSize, L"I386");
527 break;
528
529 case PROCESSOR_ARCHITECTURE_MIPS:
530 StringCchCatW(lpInstallerPath, PathSize, L"MIPS");
531 break;
532
533 case PROCESSOR_ARCHITECTURE_ALPHA:
534 StringCchCatW(lpInstallerPath, PathSize, L"ALPHA");
535 break;
536
537 case PROCESSOR_ARCHITECTURE_PPC:
538 StringCchCatW(lpInstallerPath, PathSize, L"PPC");
539 break;
540
541 case PROCESSOR_ARCHITECTURE_SHX:
542 StringCchCatW(lpInstallerPath, PathSize, L"SHX");
543 break;
544
545 case PROCESSOR_ARCHITECTURE_ARM:
546 StringCchCatW(lpInstallerPath, PathSize, L"ARM");
547 break;
548
549 case PROCESSOR_ARCHITECTURE_IA64:
550 StringCchCatW(lpInstallerPath, PathSize, L"IA64");
551 break;
552
553 case PROCESSOR_ARCHITECTURE_ALPHA64:
554 StringCchCatW(lpInstallerPath, PathSize, L"ALPHA64");
555 break;
556
557 case PROCESSOR_ARCHITECTURE_AMD64:
558 StringCchCatW(lpInstallerPath, PathSize, L"AMD64");
559 break;
560
561 // case PROCESSOR_ARCHITECTURE_MSIL: /* .NET CPU-independent code */
562 case PROCESSOR_ARCHITECTURE_UNKNOWN:
563 default:
564 WARN("Unknown processor architecture %lu\n", SystemInfo.wProcessorArchitecture);
565 SystemInfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
566 break;
567 }
568
569 if (SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_UNKNOWN)
570 StringCchCatW(lpInstallerPath, PathSize, L"\\");
571 StringCchCatW(lpInstallerPath, PathSize, lpInstallerName);
572
573 dwAttribs = GetFileAttributesW(lpInstallerPath);
574 if ((dwAttribs != INVALID_FILE_ATTRIBUTES) &&
575 !(dwAttribs & FILE_ATTRIBUTE_DIRECTORY))
576 {
577 /* We have found the installer */
578 return TRUE;
579 }
580
581 WARN("Couldn't find the installer '%s', trying alternative.\n", debugstr_w(lpInstallerPath));
582
583 /*
584 * We failed. Try to find the installer from either the current
585 * ReactOS installation directory, or from our current directory.
586 */
587 *lpInstallerPath = UNICODE_NULL;
588 /* Alternatively one can use SharedUserData->NtSystemRoot */
589 if (GetSystemWindowsDirectoryW(lpInstallerPath, PathSize - cchInstallerNameLen - 1))
590 StringCchCatW(lpInstallerPath, PathSize, L"\\");
591 StringCchCatW(lpInstallerPath, PathSize, lpInstallerName);
592
593 dwAttribs = GetFileAttributesW(lpInstallerPath);
594 if ((dwAttribs != INVALID_FILE_ATTRIBUTES) &&
595 !(dwAttribs & FILE_ATTRIBUTE_DIRECTORY))
596 {
597 /* We have found the installer */
598 return TRUE;
599 }
600
601 /* Installer not found */
602 ERR("Couldn't find the installer '%s'.\n", debugstr_w(lpInstallerPath));
603 *lpInstallerPath = UNICODE_NULL;
604 return FALSE;
605}
606
607static BOOL
608StartInstaller(IN LPCWSTR lpInstallerName)
609{
610 WCHAR Installer[MAX_PATH];
611 WCHAR szMsg[RC_STRING_MAX_SIZE];
612
613 if (ExpandInstallerPath(lpInstallerName, Installer, ARRAYSIZE(Installer)))
614 {
615 /* We have found the installer */
616 if (StartProcess(Installer))
617 return TRUE;
618 }
619
620 /* We failed. Display an error message and quit. */
621 ERR("Failed to start the installer '%s'.\n", debugstr_w(Installer));
622 LoadStringW(GetModuleHandle(NULL), IDS_INSTALLER_FAIL, szMsg, ARRAYSIZE(szMsg));
623 MessageBoxW(NULL, szMsg, NULL, MB_OK);
624 return FALSE;
625}
626
627/* Used to get the shutdown privilege */
628static BOOL
629EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
630{
631 BOOL Success;
632 HANDLE hToken;
633 TOKEN_PRIVILEGES tp;
634
635 Success = OpenProcessToken(GetCurrentProcess(),
636 TOKEN_ADJUST_PRIVILEGES,
637 &hToken);
638 if (!Success) return Success;
639
640 Success = LookupPrivilegeValueW(NULL,
641 lpszPrivilegeName,
642 &tp.Privileges[0].Luid);
643 if (!Success) goto Quit;
644
645 tp.PrivilegeCount = 1;
646 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
647
648 Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
649
650Quit:
651 CloseHandle(hToken);
652 return Success;
653}
654
655
656int WINAPI
657wWinMain(IN HINSTANCE hInst,
658 IN HINSTANCE hPrevInstance,
659 IN LPWSTR lpszCmdLine,
660 IN int nCmdShow)
661{
662 BOOL bIsLiveCD, Success = TRUE;
663 STATE State;
664
665 hInstance = hInst;
666
667 bIsLiveCD = IsLiveCD();
668
669Restart:
670 SetUserSettings();
671
672 if (bIsLiveCD)
673 {
674 State.NextPage = LOCALEPAGE;
675 State.Run = SHELL;
676 }
677 else
678 {
679 State.NextPage = DONE;
680 State.Run = SHELL;
681 }
682
683 if (State.NextPage != DONE) // && bIsLiveCD
684 {
685 RunLiveCD(&State);
686 }
687
688 switch (State.Run)
689 {
690 case SHELL:
691 Success = StartShell();
692 if (Success)
693 NotifyLogon();
694 break;
695
696 case INSTALLER:
697 Success = StartInstaller(L"reactos.exe");
698 break;
699
700 case REBOOT:
701 {
702 EnablePrivilege(SE_SHUTDOWN_NAME, TRUE);
703 ExitWindowsEx(EWX_REBOOT, 0);
704 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
705 Success = TRUE;
706 break;
707 }
708
709 default:
710 Success = FALSE;
711 break;
712 }
713
714 /*
715 * In LiveCD mode, go back to the main menu if we failed
716 * to either start the shell or the installer.
717 */
718 if (bIsLiveCD && !Success)
719 goto Restart;
720
721 return 0;
722}
723
724/* EOF */