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
)] = '\0';
83 BOOL
IsConsoleShell(VOID
)
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
];
145 BOOL ConsoleShell
= IsConsoleShell();
148 TRACE("(%p, %p)\n", CommandLine
, hRootKey
);
150 rc
= RegOpenKeyExW(hRootKey
, L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
151 0, KEY_QUERY_VALUE
, &hKey
);
152 if (rc
== ERROR_SUCCESS
)
154 Size
= MAX_PATH
* sizeof(WCHAR
);
155 rc
= RegQueryValueExW(hKey
,
156 ConsoleShell
? L
"ConsoleShell" : L
"Shell",
161 if (rc
== ERROR_SUCCESS
)
163 if ((Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
))
165 TRACE("Found command line %s\n", debugstr_w(Shell
));
166 wcscpy(CommandLine
, Shell
);
170 WARN("Wrong type %lu (expected %u or %u)\n", Type
, REG_SZ
, REG_EXPAND_SZ
);
173 WARN("RegQueryValueEx() failed with error %lu\n", rc
);
177 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
183 StartAutoApplications(
186 WCHAR szPath
[MAX_PATH
] = {0};
189 WIN32_FIND_DATAW findData
;
190 SHELLEXECUTEINFOW ExecInfo
;
193 TRACE("(%d)\n", clsid
);
195 hResult
= SHGetFolderPathW(NULL
, clsid
, NULL
, SHGFP_TYPE_CURRENT
, szPath
);
196 len
= wcslen(szPath
);
197 if (!SUCCEEDED(hResult
) || len
== 0)
199 WARN("SHGetFolderPath() failed with error %lu\n", GetLastError());
203 wcscat(szPath
, L
"\\*");
204 hFind
= FindFirstFileW(szPath
, &findData
);
205 if (hFind
== INVALID_HANDLE_VALUE
)
207 WARN("FindFirstFile(%s) failed with error %lu\n", debugstr_w(szPath
), GetLastError());
213 if (!(findData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) && (findData
.nFileSizeHigh
|| findData
.nFileSizeLow
))
215 ZeroMemory(&ExecInfo
, sizeof(SHELLEXECUTEINFOW
));
216 ExecInfo
.cbSize
= sizeof(ExecInfo
);
217 wcscpy(&szPath
[len
+1], findData
.cFileName
);
218 ExecInfo
.lpVerb
= L
"open";
219 ExecInfo
.lpFile
= szPath
;
220 ExecInfo
.lpDirectory
= NULL
;
221 TRACE("Executing %s in directory %s\n",
222 debugstr_w(findData
.cFileName
), debugstr_w(szPath
));
223 ShellExecuteExW(&ExecInfo
);
225 } while (FindNextFileW(hFind
, &findData
));
234 PROCESS_INFORMATION pi
;
235 WCHAR ExpandedShell
[MAX_PATH
];
237 TRACE("(%s)\n", debugstr_w(Shell
));
239 ZeroMemory(&si
, sizeof(si
));
241 si
.dwFlags
= STARTF_USESHOWWINDOW
;
242 si
.wShowWindow
= SW_SHOWNORMAL
;
243 ZeroMemory(&pi
, sizeof(pi
));
245 ExpandEnvironmentStrings(Shell
, ExpandedShell
, MAX_PATH
);
247 if (!CreateProcess(NULL
,
252 NORMAL_PRIORITY_CLASS
,
258 WARN("CreateProcess() failed with error %lu\n", GetLastError());
262 StartAutoApplications(CSIDL_STARTUP
);
263 StartAutoApplications(CSIDL_COMMON_STARTUP
);
264 CloseHandle(pi
.hProcess
);
265 CloseHandle(pi
.hThread
);
270 VOID
StartShell(VOID
)
272 WCHAR Shell
[MAX_PATH
];
273 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
281 /* Safe Mode shell run */
282 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
283 L
"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
284 0, KEY_QUERY_VALUE
, &hKey
);
285 if(rc
== ERROR_SUCCESS
)
287 Size
= sizeof(Value
);
288 rc
= RegQueryValueExW(hKey
, L
"UseAlternateShell", NULL
,
289 &Type
, (LPBYTE
)&Value
, &Size
);
290 if(rc
== ERROR_SUCCESS
)
293 if(Type
== REG_DWORD
)
297 /* Safe Mode Alternate Shell required */
298 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
299 L
"SYSTEM\\CurrentControlSet\\Control\\SafeBoot",
301 if(rc
== ERROR_SUCCESS
)
303 Size
= MAX_PATH
* sizeof(WCHAR
);
304 rc
= RegQueryValueExW(hKey
, L
"AlternateShell", NULL
,
305 &Type
, (LPBYTE
)Shell
, &Size
);
306 if(rc
== ERROR_SUCCESS
)
309 if ((Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
))
311 TRACE("Key located - %s\n", debugstr_w(Shell
));
312 /* Try to run alternate shell */
313 if (TryToStartShell(Shell
))
315 TRACE("Alternate shell started (Safe Mode)\n");
321 WARN("Wrong type %lu (expected %u or %u)\n",
322 Type
, REG_SZ
, REG_EXPAND_SZ
);
327 WARN("Alternate shell in Safe Mode required but not specified.");
334 WARN("Wrong type %lu (expected %u)\n", Type
, REG_DWORD
);
338 /* Try to run shell in user key */
339 if (GetShell(Shell
, HKEY_CURRENT_USER
) && TryToStartShell(Shell
))
341 TRACE("Started shell from HKEY_CURRENT_USER\n");
345 /* Try to run shell in local machine key */
346 if (GetShell(Shell
, HKEY_LOCAL_MACHINE
) && TryToStartShell(Shell
))
348 TRACE("Started shell from HKEY_LOCAL_MACHINE\n");
352 /* Try default shell */
353 if (IsConsoleShell())
355 if (GetSystemDirectory(Shell
, MAX_PATH
- 8))
356 wcscat(Shell
, L
"\\cmd.exe");
358 wcscpy(Shell
, L
"cmd.exe");
362 if (GetWindowsDirectory(Shell
, MAX_PATH
- 13))
363 wcscat(Shell
, L
"\\explorer.exe");
365 wcscpy(Shell
, L
"explorer.exe");
367 if (!TryToStartShell(Shell
))
369 WARN("Failed to start default shell %s\n", debugstr_w(Shell
));
370 LoadString( GetModuleHandle(NULL
), IDS_SHELL_FAIL
, szMsg
, sizeof(szMsg
) / sizeof(szMsg
[0]));
371 MessageBox(0, szMsg
, NULL
, 0);
375 const WCHAR g_RegColorNames
[][32] = {
376 L
"Scrollbar", /* 00 = COLOR_SCROLLBAR */
377 L
"Background", /* 01 = COLOR_DESKTOP */
378 L
"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
379 L
"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
380 L
"Menu", /* 04 = COLOR_MENU */
381 L
"Window", /* 05 = COLOR_WINDOW */
382 L
"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
383 L
"MenuText", /* 07 = COLOR_MENUTEXT */
384 L
"WindowText", /* 08 = COLOR_WINDOWTEXT */
385 L
"TitleText", /* 09 = COLOR_CAPTIONTEXT */
386 L
"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
387 L
"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
388 L
"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
389 L
"Hilight", /* 13 = COLOR_HIGHLIGHT */
390 L
"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
391 L
"ButtonFace", /* 15 = COLOR_BTNFACE */
392 L
"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
393 L
"GrayText", /* 17 = COLOR_GRAYTEXT */
394 L
"ButtonText", /* 18 = COLOR_BTNTEXT */
395 L
"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
396 L
"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
397 L
"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
398 L
"ButtonLight", /* 22 = COLOR_3DLIGHT */
399 L
"InfoText", /* 23 = COLOR_INFOTEXT */
400 L
"InfoWindow", /* 24 = COLOR_INFOBK */
401 L
"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
402 L
"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
403 L
"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
404 L
"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
405 L
"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
406 L
"MenuBar" /* 30 = COLOR_MENUBAR */
408 #define NUM_SYSCOLORS (sizeof(g_RegColorNames) / sizeof(g_RegColorNames[0]))
411 COLORREF
StrToColorref(
416 TRACE("(%s)\n", debugstr_w(lpszCol
));
418 rgb
[0] = (BYTE
)wcstoul(lpszCol
, &lpszCol
, 10);
419 rgb
[1] = (BYTE
)wcstoul(lpszCol
, &lpszCol
, 10);
420 rgb
[2] = (BYTE
)wcstoul(lpszCol
, &lpszCol
, 10);
421 return RGB(rgb
[0], rgb
[1], rgb
[2]);
425 VOID
SetUserSysColors(VOID
)
436 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_COLORS
,
437 0, KEY_QUERY_VALUE
, &hKey
);
438 if (rc
!= ERROR_SUCCESS
)
440 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
443 for(i
= 0; i
< NUM_SYSCOLORS
; i
++)
445 Size
= sizeof(szColor
);
446 rc
= RegQueryValueEx(hKey
, g_RegColorNames
[i
], NULL
, &Type
,
447 (LPBYTE
)szColor
, &Size
);
448 if (rc
== ERROR_SUCCESS
&& Type
== REG_SZ
)
450 crColor
= StrToColorref(szColor
);
451 SetSysColors(1, &i
, &crColor
);
454 WARN("RegQueryValueEx(%s) failed with error %lu\n",
455 debugstr_w(g_RegColorNames
[i
]), rc
);
461 VOID
SetUserWallpaper(VOID
)
465 WCHAR szWallpaper
[MAX_PATH
+ 1];
470 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_DESKTOP
,
471 0, KEY_QUERY_VALUE
, &hKey
);
472 if (rc
== ERROR_SUCCESS
)
474 Size
= sizeof(szWallpaper
);
475 rc
= RegQueryValueEx(hKey
,
481 if (rc
== ERROR_SUCCESS
&& Type
== REG_SZ
)
483 ExpandEnvironmentStrings(szWallpaper
, szWallpaper
, MAX_PATH
);
484 TRACE("Using wallpaper %s\n", debugstr_w(szWallpaper
));
486 /* Load and change the wallpaper */
487 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, szWallpaper
, SPIF_SENDCHANGE
);
491 /* remove the wallpaper */
492 TRACE("No wallpaper set in registry (error %lu)\n", rc
);
493 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, NULL
, SPIF_SENDCHANGE
);
498 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
502 VOID
SetUserSettings(VOID
)
506 UpdatePerUserSystemParameters(1, TRUE
);
511 typedef DWORD (WINAPI
*PCMP_REPORT_LOGON
)(DWORD
, DWORD
);
517 PCMP_REPORT_LOGON CMP_Report_LogOn
;
521 hModule
= LoadLibrary(L
"setupapi.dll");
524 CMP_Report_LogOn
= (PCMP_REPORT_LOGON
)GetProcAddress(hModule
, "CMP_Report_LogOn");
525 if (CMP_Report_LogOn
)
526 CMP_Report_LogOn(CMP_MAGIC
, GetCurrentProcessId());
528 WARN("GetProcAddress() failed\n");
530 FreeLibrary(hModule
);
533 WARN("LoadLibrary() failed with error %lu\n", GetLastError());
540 WCHAR Shell
[MAX_PATH
];
541 WCHAR szMsg
[RC_STRING_MAX_SIZE
];
543 if (GetWindowsDirectory(Shell
, MAX_PATH
- 12))
544 wcscat(Shell
, L
"\\reactos.exe");
546 wcscpy(Shell
, L
"reactos.exe");
548 if (!TryToStartShell(Shell
))
550 ERR("Failed to start the installer: %s\n", debugstr_w(Shell
));
551 LoadStringW(GetModuleHandle(NULL
), IDS_INSTALLER_FAIL
, szMsg
, sizeof(szMsg
) / sizeof(szMsg
[0]));
552 MessageBoxW(0, szMsg
, NULL
, 0);
558 #pragma warning(disable : 4100)
559 #endif /* _MSC_VER */
562 wWinMain(IN HINSTANCE hInst
,
563 IN HINSTANCE hPrevInstance
,
564 IN LPWSTR lpszCmdLine
,
575 State
.NextPage
= LOCALEPAGE
;
580 State
.NextPage
= DONE
;
584 if (State
.NextPage
!= DONE
)
589 if (State
.Run
== SHELL
)
594 else if (State
.Run
== INSTALLER
)