3 * Copyright (C) 2001, 2002 ReactOS Team
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.
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.
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.
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)
29 #define CMP_MAGIC 0x01234567
31 /* GLOBALS ******************************************************************/
36 /* FUNCTIONS ****************************************************************/
49 TRACE("(%p, %s, %p)\n", hKey
, debugstr_w(pszKey
), pValue
);
51 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
52 if (rc
!= ERROR_SUCCESS
)
54 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey
), rc
);
59 WARN("Wrong registry data type (%u vs %u)\n", dwType
, REG_SZ
);
60 return ERROR_FILE_NOT_FOUND
;
62 Value
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
66 return ERROR_NOT_ENOUGH_MEMORY
;
68 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
69 if (rc
!= ERROR_SUCCESS
)
71 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey
), rc
);
72 HeapFree(GetProcessHeap(), 0, Value
);
75 /* NULL-terminate the string */
76 Value
[cbData
/ sizeof(WCHAR
)] = L
'\0';
85 HKEY ControlKey
= NULL
;
86 LPWSTR SystemStartOptions
= NULL
;
87 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
95 REGSTR_PATH_CURRENT_CONTROL_SET
,
99 if (rc
!= ERROR_SUCCESS
)
101 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
105 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
106 if (rc
!= ERROR_SUCCESS
)
108 WARN("ReadRegSzKey() failed with error %lu\n", rc
);
112 /* Check for CONSOLE switch in SystemStartOptions */
113 CurrentOption
= SystemStartOptions
;
114 while (CurrentOption
)
116 NextOption
= wcschr(CurrentOption
, L
' ');
119 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
121 TRACE("Found 'CONSOLE' boot option\n");
125 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
129 if (ControlKey
!= NULL
)
130 RegCloseKey(ControlKey
);
131 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
132 TRACE("IsConsoleShell() returning %d\n", ret
);
138 OUT WCHAR
*CommandLine
, /* must be at least MAX_PATH long */
143 WCHAR Shell
[MAX_PATH
];
144 BOOL ConsoleShell
= IsConsoleShell();
147 TRACE("(%p, %p)\n", CommandLine
, hRootKey
);
149 rc
= RegOpenKeyExW(hRootKey
, L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
150 0, KEY_QUERY_VALUE
, &hKey
);
151 if (rc
!= ERROR_SUCCESS
)
153 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
157 Size
= sizeof(Shell
);
158 rc
= RegQueryValueExW(hKey
,
159 ConsoleShell
? L
"ConsoleShell" : L
"Shell",
166 if (rc
!= ERROR_SUCCESS
)
168 WARN("RegQueryValueEx() failed with error %lu\n", rc
);
172 if ((Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
))
174 TRACE("Found command line %s\n", debugstr_w(Shell
));
175 wcscpy(CommandLine
, Shell
);
180 WARN("Wrong type %lu (expected %u or %u)\n", Type
, REG_SZ
, REG_EXPAND_SZ
);
190 PROCESS_INFORMATION pi
;
191 WCHAR ExpandedShell
[MAX_PATH
];
193 TRACE("(%s)\n", debugstr_w(Shell
));
195 ZeroMemory(&si
, sizeof(si
));
197 si
.dwFlags
= STARTF_USESHOWWINDOW
;
198 si
.wShowWindow
= SW_SHOWNORMAL
;
199 ZeroMemory(&pi
, sizeof(pi
));
201 ExpandEnvironmentStringsW(Shell
, ExpandedShell
, ARRAYSIZE(ExpandedShell
));
203 if (!CreateProcessW(NULL
,
208 NORMAL_PRIORITY_CLASS
,
214 WARN("CreateProcess() failed with error %lu\n", GetLastError());
218 CloseHandle(pi
.hProcess
);
219 CloseHandle(pi
.hThread
);
226 WCHAR Shell
[MAX_PATH
];
227 WCHAR szMsg
[RC_STRING_MAX_SIZE
];
235 /* Safe Mode shell run */
236 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
237 L
"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
238 0, KEY_QUERY_VALUE
, &hKey
);
239 if (rc
== ERROR_SUCCESS
)
241 Size
= sizeof(Value
);
242 rc
= RegQueryValueExW(hKey
, L
"UseAlternateShell", NULL
,
243 &Type
, (LPBYTE
)&Value
, &Size
);
246 if (rc
== ERROR_SUCCESS
)
248 if (Type
== REG_DWORD
)
252 /* Safe Mode Alternate Shell required */
253 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
254 L
"SYSTEM\\CurrentControlSet\\Control\\SafeBoot",
256 if (rc
== ERROR_SUCCESS
)
258 Size
= sizeof(Shell
);
259 rc
= RegQueryValueExW(hKey
, L
"AlternateShell", NULL
,
260 &Type
, (LPBYTE
)Shell
, &Size
);
263 if (rc
== ERROR_SUCCESS
)
265 if ((Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
))
267 TRACE("Key located - %s\n", debugstr_w(Shell
));
269 /* Try to run alternate shell */
270 if (TryToStartShell(Shell
))
272 TRACE("Alternate shell started (Safe Mode)\n");
278 WARN("Wrong type %lu (expected %u or %u)\n",
279 Type
, REG_SZ
, REG_EXPAND_SZ
);
284 WARN("Alternate shell in Safe Mode required but not specified.");
291 WARN("Wrong type %lu (expected %u)\n", Type
, REG_DWORD
);
296 /* Try to run shell in user key */
297 if (GetShell(Shell
, HKEY_CURRENT_USER
) && TryToStartShell(Shell
))
299 TRACE("Started shell from HKEY_CURRENT_USER\n");
303 /* Try to run shell in local machine key */
304 if (GetShell(Shell
, HKEY_LOCAL_MACHINE
) && TryToStartShell(Shell
))
306 TRACE("Started shell from HKEY_LOCAL_MACHINE\n");
310 /* Try default shell */
311 if (IsConsoleShell())
313 if (GetSystemDirectoryW(Shell
, ARRAYSIZE(Shell
) - 8))
314 wcscat(Shell
, L
"\\cmd.exe");
316 wcscpy(Shell
, L
"cmd.exe");
320 if (GetWindowsDirectoryW(Shell
, ARRAYSIZE(Shell
) - 13))
321 wcscat(Shell
, L
"\\explorer.exe");
323 wcscpy(Shell
, L
"explorer.exe");
326 if (!TryToStartShell(Shell
))
328 WARN("Failed to start default shell %s\n", debugstr_w(Shell
));
329 LoadStringW(GetModuleHandle(NULL
), IDS_SHELL_FAIL
, szMsg
, ARRAYSIZE(szMsg
));
330 MessageBoxW(NULL
, szMsg
, NULL
, MB_OK
);
336 const WCHAR g_RegColorNames
[][32] = {
337 L
"Scrollbar", /* 00 = COLOR_SCROLLBAR */
338 L
"Background", /* 01 = COLOR_DESKTOP */
339 L
"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
340 L
"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
341 L
"Menu", /* 04 = COLOR_MENU */
342 L
"Window", /* 05 = COLOR_WINDOW */
343 L
"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
344 L
"MenuText", /* 07 = COLOR_MENUTEXT */
345 L
"WindowText", /* 08 = COLOR_WINDOWTEXT */
346 L
"TitleText", /* 09 = COLOR_CAPTIONTEXT */
347 L
"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
348 L
"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
349 L
"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
350 L
"Hilight", /* 13 = COLOR_HIGHLIGHT */
351 L
"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
352 L
"ButtonFace", /* 15 = COLOR_BTNFACE */
353 L
"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
354 L
"GrayText", /* 17 = COLOR_GRAYTEXT */
355 L
"ButtonText", /* 18 = COLOR_BTNTEXT */
356 L
"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
357 L
"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
358 L
"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
359 L
"ButtonLight", /* 22 = COLOR_3DLIGHT */
360 L
"InfoText", /* 23 = COLOR_INFOTEXT */
361 L
"InfoWindow", /* 24 = COLOR_INFOBK */
362 L
"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
363 L
"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
364 L
"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
365 L
"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
366 L
"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
367 L
"MenuBar" /* 30 = COLOR_MENUBAR */
376 TRACE("(%s)\n", debugstr_w(lpszCol
));
378 rgb
[0] = (BYTE
)wcstoul(lpszCol
, &lpszCol
, 10);
379 rgb
[1] = (BYTE
)wcstoul(lpszCol
, &lpszCol
, 10);
380 rgb
[2] = (BYTE
)wcstoul(lpszCol
, &lpszCol
, 10);
381 return RGB(rgb
[0], rgb
[1], rgb
[2]);
385 SetUserSysColors(VOID
)
396 rc
= RegOpenKeyExW(HKEY_CURRENT_USER
, REGSTR_PATH_COLORS
,
397 0, KEY_QUERY_VALUE
, &hKey
);
398 if (rc
!= ERROR_SUCCESS
)
400 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
404 for (i
= 0; i
< ARRAYSIZE(g_RegColorNames
); i
++)
406 Size
= sizeof(szColor
);
407 rc
= RegQueryValueExW(hKey
, g_RegColorNames
[i
], NULL
, &Type
,
408 (LPBYTE
)szColor
, &Size
);
409 if (rc
== ERROR_SUCCESS
&& Type
== REG_SZ
)
411 crColor
= StrToColorref(szColor
);
412 SetSysColors(1, &i
, &crColor
);
416 WARN("RegQueryValueEx(%s) failed with error %lu\n",
417 debugstr_w(g_RegColorNames
[i
]), rc
);
425 SetUserWallpaper(VOID
)
429 WCHAR szWallpaper
[MAX_PATH
+ 1];
434 rc
= RegOpenKeyExW(HKEY_CURRENT_USER
, REGSTR_PATH_DESKTOP
,
435 0, KEY_QUERY_VALUE
, &hKey
);
436 if (rc
!= ERROR_SUCCESS
)
438 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
442 Size
= sizeof(szWallpaper
);
443 rc
= RegQueryValueExW(hKey
,
451 if (rc
== ERROR_SUCCESS
&& Type
== REG_SZ
)
453 ExpandEnvironmentStringsW(szWallpaper
, szWallpaper
, ARRAYSIZE(szWallpaper
));
454 TRACE("Using wallpaper %s\n", debugstr_w(szWallpaper
));
456 /* Load and change the wallpaper */
457 SystemParametersInfoW(SPI_SETDESKWALLPAPER
, 0, szWallpaper
, SPIF_SENDCHANGE
);
461 /* Remove the wallpaper */
462 TRACE("No wallpaper set in registry (error %lu)\n", rc
);
463 SystemParametersInfoW(SPI_SETDESKWALLPAPER
, 0, NULL
, SPIF_SENDCHANGE
);
468 SetUserSettings(VOID
)
472 UpdatePerUserSystemParameters(1, TRUE
);
477 typedef DWORD (WINAPI
*PCMP_REPORT_LOGON
)(DWORD
, DWORD
);
483 PCMP_REPORT_LOGON CMP_Report_LogOn
;
487 hModule
= LoadLibraryW(L
"setupapi.dll");
490 WARN("LoadLibrary() failed with error %lu\n", GetLastError());
494 CMP_Report_LogOn
= (PCMP_REPORT_LOGON
)GetProcAddress(hModule
, "CMP_Report_LogOn");
495 if (CMP_Report_LogOn
)
496 CMP_Report_LogOn(CMP_MAGIC
, GetCurrentProcessId());
498 WARN("GetProcAddress() failed\n");
500 FreeLibrary(hModule
);
506 WCHAR Shell
[MAX_PATH
];
507 WCHAR szMsg
[RC_STRING_MAX_SIZE
];
509 if (GetWindowsDirectoryW(Shell
, ARRAYSIZE(Shell
) - 12))
510 wcscat(Shell
, L
"\\reactos.exe");
512 wcscpy(Shell
, L
"reactos.exe");
514 if (!TryToStartShell(Shell
))
516 WARN("Failed to start the installer: %s\n", debugstr_w(Shell
));
517 LoadStringW(GetModuleHandle(NULL
), IDS_INSTALLER_FAIL
, szMsg
, ARRAYSIZE(szMsg
));
518 MessageBoxW(NULL
, szMsg
, NULL
, MB_OK
);
524 /* Used to get the shutdown privilege */
526 EnablePrivilege(LPCWSTR lpszPrivilegeName
, BOOL bEnablePrivilege
)
532 Success
= OpenProcessToken(GetCurrentProcess(),
533 TOKEN_ADJUST_PRIVILEGES
,
535 if (!Success
) return Success
;
537 Success
= LookupPrivilegeValueW(NULL
,
539 &tp
.Privileges
[0].Luid
);
540 if (!Success
) goto Quit
;
542 tp
.PrivilegeCount
= 1;
543 tp
.Privileges
[0].Attributes
= (bEnablePrivilege
? SE_PRIVILEGE_ENABLED
: 0);
545 Success
= AdjustTokenPrivileges(hToken
, FALSE
, &tp
, 0, NULL
, NULL
);
554 wWinMain(IN HINSTANCE hInst
,
555 IN HINSTANCE hPrevInstance
,
556 IN LPWSTR lpszCmdLine
,
559 BOOL bIsLiveCD
, Success
= TRUE
;
564 bIsLiveCD
= IsLiveCD();
571 State
.NextPage
= LOCALEPAGE
;
576 State
.NextPage
= DONE
;
580 if (State
.NextPage
!= DONE
) // && bIsLiveCD
588 Success
= StartShell();
594 Success
= StartInstaller();
599 EnablePrivilege(SE_SHUTDOWN_NAME
, TRUE
);
600 ExitWindowsEx(EWX_REBOOT
, 0);
601 EnablePrivilege(SE_SHUTDOWN_NAME
, FALSE
);
612 * In LiveCD mode, go back to the main menu if we failed
613 * to either start the shell or the installer.
615 if (bIsLiveCD
&& !Success
)