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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Userinit Logon Application
22 * FILE: subsys/system/userinit/userinit.c
23 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
24 * Hervé Poussineau (hpoussin@reactos.org)
32 #include <wine/debug.h>
33 #include <win32k/ntusrtyp.h>
35 WINE_DEFAULT_DEBUG_CHANNEL(userinit
);
37 #define CMP_MAGIC 0x01234567
39 /* GLOBALS ******************************************************************/
41 /* FUNCTIONS ****************************************************************/
54 TRACE("(%p, %s, %p)\n", hKey
, debugstr_w(pszKey
), pValue
);
56 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
57 if (rc
!= ERROR_SUCCESS
)
59 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey
), rc
);
64 WARN("Wrong registry data type (%u vs %u)\n", dwType
, REG_SZ
);
65 return ERROR_FILE_NOT_FOUND
;
67 Value
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
71 return ERROR_NOT_ENOUGH_MEMORY
;
73 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
74 if (rc
!= ERROR_SUCCESS
)
76 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey
), rc
);
77 HeapFree(GetProcessHeap(), 0, Value
);
80 /* NULL-terminate the string */
81 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
88 BOOL
IsConsoleShell(VOID
)
90 HKEY ControlKey
= NULL
;
91 LPWSTR SystemStartOptions
= NULL
;
92 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
100 REGSTR_PATH_CURRENT_CONTROL_SET
,
104 if (rc
!= ERROR_SUCCESS
)
106 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
110 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
111 if (rc
!= ERROR_SUCCESS
)
113 WARN("ReadRegSzKey() failed with error %lu\n", rc
);
117 /* Check for CONSOLE in SystemStartOptions */
118 CurrentOption
= SystemStartOptions
;
119 while (CurrentOption
)
121 NextOption
= wcschr(CurrentOption
, L
' ');
124 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
126 TRACE("Found 'CONSOLE' boot option\n");
130 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
134 if (ControlKey
!= NULL
)
135 RegCloseKey(ControlKey
);
136 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
137 TRACE("IsConsoleShell() returning %d\n", ret
);
143 OUT WCHAR
*CommandLine
, /* must be at least MAX_PATH long */
148 WCHAR Shell
[MAX_PATH
];
150 BOOL ConsoleShell
= IsConsoleShell();
153 TRACE("(%p, %p)\n", CommandLine
, hRootKey
);
155 rc
= RegOpenKeyExW(hRootKey
, L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
156 0, KEY_QUERY_VALUE
, &hKey
);
157 if (rc
== ERROR_SUCCESS
)
159 Size
= MAX_PATH
* sizeof(WCHAR
);
160 rc
= RegQueryValueExW(hKey
,
161 ConsoleShell
? L
"ConsoleShell" : L
"Shell",
166 if (rc
== ERROR_SUCCESS
)
168 if ((Type
== REG_SZ
) || (Type
== REG_EXPAND_SZ
))
170 TRACE("Found command line %s\n", debugstr_w(Shell
));
171 wcscpy(CommandLine
, Shell
);
175 WARN("Wrong type %lu (expected %u or %u)\n", Type
, REG_SZ
, REG_EXPAND_SZ
);
178 WARN("RegQueryValueEx() failed with error %lu\n", rc
);
182 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
188 StartAutoApplications(
191 WCHAR szPath
[MAX_PATH
] = {0};
194 WIN32_FIND_DATAW findData
;
195 SHELLEXECUTEINFOW ExecInfo
;
198 TRACE("(%d)\n", clsid
);
200 hResult
= SHGetFolderPathW(NULL
, clsid
, NULL
, SHGFP_TYPE_CURRENT
, szPath
);
201 len
= wcslen(szPath
);
202 if (!SUCCEEDED(hResult
) || len
== 0)
204 WARN("SHGetFolderPath() failed with error %lu\n", GetLastError());
208 wcscat(szPath
, L
"\\*");
209 hFind
= FindFirstFileW(szPath
, &findData
);
210 if (hFind
== INVALID_HANDLE_VALUE
)
212 WARN("FindFirstFile(%s) failed with error %lu\n", debugstr_w(szPath
), GetLastError());
219 if (!(findData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) && (findData
.nFileSizeHigh
|| findData
.nFileSizeLow
))
221 memset(&ExecInfo
, 0x0, sizeof(SHELLEXECUTEINFOW
));
222 ExecInfo
.cbSize
= sizeof(ExecInfo
);
223 ExecInfo
.lpVerb
= L
"open";
224 ExecInfo
.lpFile
= findData
.cFileName
;
225 ExecInfo
.lpDirectory
= szPath
;
226 TRACE("Executing %s in directory %s\n",
227 debugstr_w(findData
.cFileName
), debugstr_w(szPath
));
228 ShellExecuteExW(&ExecInfo
);
230 } while (FindNextFileW(hFind
, &findData
));
239 PROCESS_INFORMATION pi
;
240 WCHAR ExpandedShell
[MAX_PATH
];
242 TRACE("(%s)\n", debugstr_w(Shell
));
244 ZeroMemory(&si
, sizeof(STARTUPINFO
));
245 si
.cb
= sizeof(STARTUPINFO
);
246 ZeroMemory(&pi
, sizeof(PROCESS_INFORMATION
));
248 ExpandEnvironmentStrings(Shell
, ExpandedShell
, MAX_PATH
);
250 if (!CreateProcess(NULL
,
255 NORMAL_PRIORITY_CLASS
,
261 WARN("CreateProcess() failed with error %lu\n", GetLastError());
265 StartAutoApplications(CSIDL_STARTUP
);
266 StartAutoApplications(CSIDL_COMMON_STARTUP
);
267 CloseHandle(pi
.hProcess
);
268 CloseHandle(pi
.hThread
);
273 VOID
StartShell(VOID
)
275 WCHAR Shell
[MAX_PATH
];
276 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
280 /* Try to run shell in user key */
281 if (GetShell(Shell
, HKEY_CURRENT_USER
) && TryToStartShell(Shell
))
283 TRACE("Started shell from HKEY_CURRENT_USER\n");
287 /* Try to run shell in local machine key */
288 if (GetShell(Shell
, HKEY_LOCAL_MACHINE
) && TryToStartShell(Shell
))
290 TRACE("Started shell from HKEY_LOCAL_MACHINE\n");
294 /* Try default shell */
295 if (IsConsoleShell())
297 if (GetSystemDirectory(Shell
, MAX_PATH
- 8))
298 wcscat(Shell
, L
"\\cmd.exe");
300 wcscpy(Shell
, L
"cmd.exe");
304 if (GetWindowsDirectory(Shell
, MAX_PATH
- 13))
305 wcscat(Shell
, L
"\\explorer.exe");
307 wcscpy(Shell
, L
"explorer.exe");
309 if (!TryToStartShell(Shell
))
311 WARN("Failed to start default shell %s\n", debugstr_w(Shell
));
312 LoadString( GetModuleHandle(NULL
), STRING_USERINIT_FAIL
, szMsg
, sizeof(szMsg
) / sizeof(szMsg
[0]));
313 MessageBox(0, szMsg
, NULL
, 0);
317 const WCHAR g_RegColorNames
[][32] = {
318 L
"Scrollbar", /* 00 = COLOR_SCROLLBAR */
319 L
"Background", /* 01 = COLOR_DESKTOP */
320 L
"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
321 L
"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
322 L
"Menu", /* 04 = COLOR_MENU */
323 L
"Window", /* 05 = COLOR_WINDOW */
324 L
"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
325 L
"MenuText", /* 07 = COLOR_MENUTEXT */
326 L
"WindowText", /* 08 = COLOR_WINDOWTEXT */
327 L
"TitleText", /* 09 = COLOR_CAPTIONTEXT */
328 L
"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
329 L
"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
330 L
"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
331 L
"Hilight", /* 13 = COLOR_HIGHLIGHT */
332 L
"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
333 L
"ButtonFace", /* 15 = COLOR_BTNFACE */
334 L
"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
335 L
"GrayText", /* 17 = COLOR_GRAYTEXT */
336 L
"ButtonText", /* 18 = COLOR_BTNTEXT */
337 L
"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
338 L
"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
339 L
"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
340 L
"ButtonLight", /* 22 = COLOR_3DLIGHT */
341 L
"InfoText", /* 23 = COLOR_INFOTEXT */
342 L
"InfoWindow", /* 24 = COLOR_INFOBK */
343 L
"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
344 L
"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
345 L
"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
346 L
"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
347 L
"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
348 L
"MenuBar" /* 30 = COLOR_MENUBAR */
350 #define NUM_SYSCOLORS (sizeof(g_RegColorNames) / sizeof(g_RegColorNames[0]))
353 COLORREF
StrToColorref(
358 TRACE("(%s)\n", debugstr_w(lpszCol
));
360 rgb
[0] = StrToIntW(lpszCol
);
361 lpszCol
= StrChrW(lpszCol
, L
' ') + 1;
362 rgb
[1] = StrToIntW(lpszCol
);
363 lpszCol
= StrChrW(lpszCol
, L
' ') + 1;
364 rgb
[2] = StrToIntW(lpszCol
);
365 return RGB(rgb
[0], rgb
[1], rgb
[2]);
369 VOID
SetUserSysColors(VOID
)
380 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_COLORS
,
381 0, KEY_QUERY_VALUE
, &hKey
);
382 if (rc
!= ERROR_SUCCESS
)
384 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
387 for(i
= 0; i
< NUM_SYSCOLORS
; i
++)
389 Size
= sizeof(szColor
);
390 rc
= RegQueryValueEx(hKey
, g_RegColorNames
[i
], NULL
, &Type
,
391 (LPBYTE
)szColor
, &Size
);
392 if (rc
== ERROR_SUCCESS
&& Type
== REG_SZ
)
394 crColor
= StrToColorref(szColor
);
395 SetSysColors(1, &i
, &crColor
);
398 WARN("RegQueryValueEx(%s) failed with error %lu\n",
399 debugstr_w(g_RegColorNames
[i
]), rc
);
405 VOID
LoadUserFontSetting(
406 IN LPWSTR lpValueName
,
414 TRACE("(%s, %p)\n", debugstr_w(lpValueName
), pFont
);
416 Size
= sizeof(LOGFONTW
);
417 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_METRICS
,
418 0, KEY_QUERY_VALUE
, &hKey
);
419 if (rc
!= ERROR_SUCCESS
)
421 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
424 rc
= RegQueryValueEx(hKey
, lpValueName
, NULL
, &Type
, (LPBYTE
)&lfTemp
, &Size
);
425 if (rc
!= ERROR_SUCCESS
|| Type
!= REG_BINARY
)
427 WARN("RegQueryValueEx() failed with error %lu\n", rc
);
431 /* FIXME: Check if lfTemp is a valid font */
436 VOID
LoadUserMetricSetting(
437 IN LPWSTR lpValueName
,
445 TRACE("(%s, %p)\n", debugstr_w(lpValueName
), pValue
);
447 Size
= sizeof(strValue
);
448 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_METRICS
,
449 0, KEY_QUERY_VALUE
, &hKey
);
450 if (rc
!= ERROR_SUCCESS
)
452 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
455 rc
= RegQueryValueEx(hKey
, lpValueName
, NULL
, &Type
, (LPBYTE
)&strValue
, &Size
);
456 if (rc
!= ERROR_SUCCESS
|| Type
!= REG_SZ
)
458 WARN("RegQueryValueEx() failed with error %lu\n", rc
);
462 *pValue
= StrToInt(strValue
);
466 VOID
SetUserMetrics(VOID
)
468 NONCLIENTMETRICSW ncmetrics
;
469 MINIMIZEDMETRICS mmmetrics
;
473 ncmetrics
.cbSize
= sizeof(NONCLIENTMETRICSW
);
474 mmmetrics
.cbSize
= sizeof(MINIMIZEDMETRICS
);
475 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
, sizeof(NONCLIENTMETRICSW
), &ncmetrics
, 0);
476 SystemParametersInfoW(SPI_GETMINIMIZEDMETRICS
, sizeof(MINIMIZEDMETRICS
), &mmmetrics
, 0);
478 LoadUserFontSetting(L
"CaptionFont", &ncmetrics
.lfCaptionFont
);
479 LoadUserFontSetting(L
"SmCaptionFont", &ncmetrics
.lfSmCaptionFont
);
480 LoadUserFontSetting(L
"MenuFont", &ncmetrics
.lfMenuFont
);
481 LoadUserFontSetting(L
"StatusFont", &ncmetrics
.lfStatusFont
);
482 LoadUserFontSetting(L
"MessageFont", &ncmetrics
.lfMessageFont
);
483 /* FIXME: load icon font ? */
485 LoadUserMetricSetting(L
"BorderWidth", &ncmetrics
.iBorderWidth
);
486 LoadUserMetricSetting(L
"ScrollWidth", &ncmetrics
.iScrollWidth
);
487 LoadUserMetricSetting(L
"ScrollHeight", &ncmetrics
.iScrollHeight
);
488 LoadUserMetricSetting(L
"CaptionWidth", &ncmetrics
.iCaptionWidth
);
489 LoadUserMetricSetting(L
"CaptionHeight", &ncmetrics
.iCaptionHeight
);
490 LoadUserMetricSetting(L
"SmCaptionWidth", &ncmetrics
.iSmCaptionWidth
);
491 LoadUserMetricSetting(L
"SmCaptionHeight", &ncmetrics
.iSmCaptionHeight
);
492 LoadUserMetricSetting(L
"Menuwidth", &ncmetrics
.iMenuWidth
);
493 LoadUserMetricSetting(L
"MenuHeight", &ncmetrics
.iMenuHeight
);
495 SystemParametersInfoW(SPI_SETNONCLIENTMETRICS
, sizeof(NONCLIENTMETRICSW
), &ncmetrics
, 0);
499 VOID
SetUserWallpaper(VOID
)
503 WCHAR szWallpaper
[MAX_PATH
+ 1];
508 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_DESKTOP
,
509 0, KEY_QUERY_VALUE
, &hKey
);
510 if (rc
== ERROR_SUCCESS
)
512 Size
= sizeof(szWallpaper
);
513 rc
= RegQueryValueEx(hKey
,
519 if (rc
== ERROR_SUCCESS
&& Type
== REG_SZ
)
521 ExpandEnvironmentStrings(szWallpaper
, szWallpaper
, MAX_PATH
);
522 TRACE("Using wallpaper %s\n", debugstr_w(szWallpaper
));
524 /* Load and change the wallpaper */
525 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, szWallpaper
, SPIF_SENDCHANGE
);
529 /* remove the wallpaper */
530 TRACE("No wallpaper set in registry (error %lu)\n", rc
);
531 SystemParametersInfo(SPI_SETDESKWALLPAPER
, 0, NULL
, SPIF_SENDCHANGE
);
536 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
539 static VOID
SetUserPreference(UINT uiAction
,BOOL bValue
,UINT fWinIni
)
541 DWORD dwvalue
= bValue
;
542 SystemParametersInfo(uiAction
, 0, (PVOID
)&dwvalue
, fWinIni
);
545 static VOID
SetUserPreferences(VOID
)
550 USERPREFERENCESMASK Preferences
;
554 rc
= RegOpenKeyEx(HKEY_CURRENT_USER
, REGSTR_PATH_DESKTOP
,
555 0, KEY_QUERY_VALUE
, &hKey
);
556 if (rc
== ERROR_SUCCESS
)
558 Size
= sizeof(USERPREFERENCESMASK
);
559 ERR("USERPREFERENCESMASK size: %d\n",Size
);
561 rc
= RegQueryValueEx(hKey
,
562 L
"UserPreferencesMask",
565 (LPBYTE
)&Preferences
,
567 if (rc
== ERROR_SUCCESS
&& Type
== REG_BINARY
)
569 SetUserPreference(SPI_SETUIEFFECTS
, Preferences
.bUiEffects
, SPIF_SENDCHANGE
);
570 SetUserPreference(SPI_SETACTIVEWINDOWTRACKING
, Preferences
.bActiveWindowTracking
, SPIF_SENDCHANGE
);
571 SetUserPreference(SPI_SETMENUANIMATION
, Preferences
.bMenuAnimation
, SPIF_SENDCHANGE
);
572 SetUserPreference(SPI_SETCOMBOBOXANIMATION
, Preferences
.bComboBoxAnimation
, SPIF_SENDCHANGE
);
573 SetUserPreference(SPI_SETLISTBOXSMOOTHSCROLLING
, Preferences
.bListBoxSmoothScrolling
, SPIF_SENDCHANGE
);
574 SetUserPreference(SPI_SETGRADIENTCAPTIONS
, Preferences
.bGradientCaptions
, SPIF_SENDCHANGE
);
575 SetUserPreference(SPI_SETKEYBOARDCUES
, Preferences
.bKeyboardCues
, SPIF_SENDCHANGE
);
576 SetUserPreference(SPI_SETACTIVEWNDTRKZORDER
, Preferences
.bActiveWndTrkZorder
, SPIF_SENDCHANGE
);
577 SetUserPreference(SPI_SETHOTTRACKING
, Preferences
.bHotTracking
, SPIF_SENDCHANGE
);
578 SetUserPreference(SPI_SETMENUFADE
, Preferences
.bMenuFade
, SPIF_SENDCHANGE
);
579 SetUserPreference(SPI_SETSELECTIONFADE
, Preferences
.bSelectionFade
, SPIF_SENDCHANGE
);
580 SetUserPreference(SPI_SETTOOLTIPANIMATION
, Preferences
.bTooltipAnimation
, SPIF_SENDCHANGE
);
581 SetUserPreference(SPI_SETTOOLTIPFADE
, Preferences
.bTooltipFade
, SPIF_SENDCHANGE
);
582 SetUserPreference(SPI_SETCURSORSHADOW
, Preferences
.bCursorShadow
, SPIF_SENDCHANGE
);
586 ERR("No User Preferences set in registry or incorrect type (error %lu)\n", rc
);
591 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
595 VOID
SetUserSettings(VOID
)
602 SetUserPreferences();
605 typedef DWORD (WINAPI
*PCMP_REPORT_LOGON
)(DWORD
, DWORD
);
611 PCMP_REPORT_LOGON CMP_Report_LogOn
;
615 hModule
= LoadLibrary(L
"setupapi.dll");
618 CMP_Report_LogOn
= (PCMP_REPORT_LOGON
)GetProcAddress(hModule
, "CMP_Report_LogOn");
619 if (CMP_Report_LogOn
)
620 CMP_Report_LogOn(CMP_MAGIC
, GetCurrentProcessId());
622 WARN("GetProcAddress() failed\n");
624 FreeLibrary(hModule
);
627 WARN("LoadLibrary() failed with error %lu\n", GetLastError());
631 #pragma warning(disable : 4100)
632 #endif /* _MSC_VER */
635 wWinMain(IN HINSTANCE hInst
,
636 IN HINSTANCE hPrevInstance
,
637 IN LPWSTR lpszCmdLine
,