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: subsys/system/userinit/userinit.c 23 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net) 24 * Herv� Poussineau (hpoussin@reactos.org) 25 */ 26 #include <windows.h> 27 #include <cfgmgr32.h> 28 #include <regstr.h> 29 #include <shlobj.h> 30 #include <shlwapi.h> 31 #include <undocuser.h> 32 #include "resource.h" 33 #include <wine/debug.h> 34 #include <win32k/ntusrtyp.h> 35 36 WINE_DEFAULT_DEBUG_CHANNEL(userinit); 37 38 #define CMP_MAGIC 0x01234567 39 40 /* GLOBALS ******************************************************************/ 41 42 /* FUNCTIONS ****************************************************************/ 43 44 static LONG 45 ReadRegSzKey( 46 IN HKEY hKey, 47 IN LPCWSTR pszKey, 48 OUT LPWSTR* pValue) 49 { 50 LONG rc; 51 DWORD dwType; 52 DWORD cbData = 0; 53 LPWSTR Value; 54 55 TRACE("(%p, %s, %p)\n", hKey, debugstr_w(pszKey), pValue); 56 57 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData); 58 if (rc != ERROR_SUCCESS) 59 { 60 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey), rc); 61 return rc; 62 } 63 if (dwType != REG_SZ) 64 { 65 WARN("Wrong registry data type (%u vs %u)\n", dwType, REG_SZ); 66 return ERROR_FILE_NOT_FOUND; 67 } 68 Value = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); 69 if (!Value) 70 { 71 WARN("No memory\n"); 72 return ERROR_NOT_ENOUGH_MEMORY; 73 } 74 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData); 75 if (rc != ERROR_SUCCESS) 76 { 77 WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey), rc); 78 HeapFree(GetProcessHeap(), 0, Value); 79 return rc; 80 } 81 /* NULL-terminate the string */ 82 Value[cbData / sizeof(WCHAR)] = '\0'; 83 84 *pValue = Value; 85 return ERROR_SUCCESS; 86 } 87 88 static 89 BOOL IsConsoleShell(VOID) 90 { 91 HKEY ControlKey = NULL; 92 LPWSTR SystemStartOptions = NULL; 93 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */ 94 LONG rc; 95 BOOL ret = FALSE; 96 97 TRACE("()\n"); 98 99 rc = RegOpenKeyEx( 100 HKEY_LOCAL_MACHINE, 101 REGSTR_PATH_CURRENT_CONTROL_SET, 102 0, 103 KEY_QUERY_VALUE, 104 &ControlKey); 105 if (rc != ERROR_SUCCESS) 106 { 107 WARN("RegOpenKeyEx() failed with error %lu\n", rc); 108 goto cleanup; 109 } 110 111 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions); 112 if (rc != ERROR_SUCCESS) 113 { 114 WARN("ReadRegSzKey() failed with error %lu\n", rc); 115 goto cleanup; 116 } 117 118 /* Check for CONSOLE in SystemStartOptions */ 119 CurrentOption = SystemStartOptions; 120 while (CurrentOption) 121 { 122 NextOption = wcschr(CurrentOption, L' '); 123 if (NextOption) 124 *NextOption = L'\0'; 125 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0) 126 { 127 TRACE("Found 'CONSOLE' boot option\n"); 128 ret = TRUE; 129 goto cleanup; 130 } 131 CurrentOption = NextOption ? NextOption + 1 : NULL; 132 } 133 134 cleanup: 135 if (ControlKey != NULL) 136 RegCloseKey(ControlKey); 137 HeapFree(GetProcessHeap(), 0, SystemStartOptions); 138 TRACE("IsConsoleShell() returning %d\n", ret); 139 return ret; 140 } 141 142 static 143 BOOL GetShell( 144 OUT WCHAR *CommandLine, /* must be at least MAX_PATH long */ 145 IN HKEY hRootKey) 146 { 147 HKEY hKey; 148 DWORD Type, Size; 149 WCHAR Shell[MAX_PATH]; 150 BOOL Ret = FALSE; 151 BOOL ConsoleShell = IsConsoleShell(); 152 LONG rc; 153 154 TRACE("(%p, %p)\n", CommandLine, hRootKey); 155 156 rc = RegOpenKeyExW(hRootKey, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 157 0, KEY_QUERY_VALUE, &hKey); 158 if (rc == ERROR_SUCCESS) 159 { 160 Size = MAX_PATH * sizeof(WCHAR); 161 rc = RegQueryValueExW(hKey, 162 ConsoleShell ? L"ConsoleShell" : L"Shell", 163 NULL, 164 &Type, 165 (LPBYTE)Shell, 166 &Size); 167 if (rc == ERROR_SUCCESS) 168 { 169 if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ)) 170 { 171 TRACE("Found command line %s\n", debugstr_w(Shell)); 172 wcscpy(CommandLine, Shell); 173 Ret = TRUE; 174 } 175 else 176 WARN("Wrong type %lu (expected %u or %u)\n", Type, REG_SZ, REG_EXPAND_SZ); 177 } 178 else 179 WARN("RegQueryValueEx() failed with error %lu\n", rc); 180 RegCloseKey(hKey); 181 } 182 else 183 WARN("RegOpenKeyEx() failed with error %lu\n", rc); 184 185 return Ret; 186 } 187 188 static VOID 189 StartAutoApplications( 190 IN INT clsid) 191 { 192 WCHAR szPath[MAX_PATH] = {0}; 193 HRESULT hResult; 194 HANDLE hFind; 195 WIN32_FIND_DATAW findData; 196 SHELLEXECUTEINFOW ExecInfo; 197 size_t len; 198 199 TRACE("(%d)\n", clsid); 200 201 hResult = SHGetFolderPathW(NULL, clsid, NULL, SHGFP_TYPE_CURRENT, szPath); 202 len = wcslen(szPath); 203 if (!SUCCEEDED(hResult) || len == 0) 204 { 205 WARN("SHGetFolderPath() failed with error %lu\n", GetLastError()); 206 return; 207 } 208 209 wcscat(szPath, L"\\*"); 210 hFind = FindFirstFileW(szPath, &findData); 211 if (hFind == INVALID_HANDLE_VALUE) 212 { 213 WARN("FindFirstFile(%s) failed with error %lu\n", debugstr_w(szPath), GetLastError()); 214 return; 215 } 216 217 do 218 { 219 if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (findData.nFileSizeHigh || findData.nFileSizeLow)) 220 { 221 memset(&ExecInfo, 0x0, sizeof(SHELLEXECUTEINFOW)); 222 ExecInfo.cbSize = sizeof(ExecInfo); 223 wcscpy(&szPath[len+1], findData.cFileName); 224 ExecInfo.lpVerb = L"open"; 225 ExecInfo.lpFile = szPath; 226 ExecInfo.lpDirectory = NULL; 227 TRACE("Executing %s in directory %s\n", 228 debugstr_w(findData.cFileName), debugstr_w(szPath)); 229 ShellExecuteExW(&ExecInfo); 230 } 231 } while (FindNextFileW(hFind, &findData)); 232 FindClose(hFind); 233 } 234 235 static BOOL 236 TryToStartShell( 237 IN LPCWSTR Shell) 238 { 239 STARTUPINFO si; 240 PROCESS_INFORMATION pi; 241 WCHAR ExpandedShell[MAX_PATH]; 242 243 TRACE("(%s)\n", debugstr_w(Shell)); 244 245 ZeroMemory(&si, sizeof(STARTUPINFO)); 246 si.cb = sizeof(STARTUPINFO); 247 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 248 249 ExpandEnvironmentStrings(Shell, ExpandedShell, MAX_PATH); 250 251 if (!CreateProcess(NULL, 252 ExpandedShell, 253 NULL, 254 NULL, 255 FALSE, 256 NORMAL_PRIORITY_CLASS, 257 NULL, 258 NULL, 259 &si, 260 &pi)) 261 { 262 WARN("CreateProcess() failed with error %lu\n", GetLastError()); 263 return FALSE; 264 } 265 266 StartAutoApplications(CSIDL_STARTUP); 267 StartAutoApplications(CSIDL_COMMON_STARTUP); 268 CloseHandle(pi.hProcess); 269 CloseHandle(pi.hThread); 270 return TRUE; 271 } 272 273 static 274 VOID StartShell(VOID) 275 { 276 WCHAR Shell[MAX_PATH]; 277 TCHAR szMsg[RC_STRING_MAX_SIZE]; 278 DWORD Type, Size; 279 DWORD Value = 0; 280 LONG rc; 281 HKEY hKey; 282 283 TRACE("()\n"); 284 285 /* Safe Mode shell run */ 286 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 287 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option", 288 0, KEY_QUERY_VALUE, &hKey); 289 if(rc == ERROR_SUCCESS) 290 { 291 Size = sizeof(Value); 292 rc = RegQueryValueExW(hKey, L"UseAlternateShell", NULL, 293 &Type, (LPBYTE)&Value, &Size); 294 if(rc == ERROR_SUCCESS) 295 { 296 RegCloseKey(hKey); 297 if(Type == REG_DWORD) 298 { 299 if(Value) 300 { 301 /* Safe Mode Alternate Shell required */ 302 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 303 L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot", 304 0, KEY_READ, &hKey); 305 if(rc == ERROR_SUCCESS) 306 { 307 Size = MAX_PATH * sizeof(WCHAR); 308 rc = RegQueryValueExW(hKey, L"AlternateShell", NULL, 309 &Type, (LPBYTE)Shell, &Size); 310 if(rc == ERROR_SUCCESS) 311 { 312 RegCloseKey(hKey); 313 if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ)) 314 { 315 TRACE("Key located - %s\n", debugstr_w(Shell)); 316 /* Try to run alternate shell */ 317 if (TryToStartShell(Shell)) 318 { 319 TRACE("Alternate shell started (Safe Mode)\n"); 320 return; 321 } 322 } 323 else 324 { 325 WARN("Wrong type %lu (expected %u or %u)\n", 326 Type, REG_SZ, REG_EXPAND_SZ); 327 } 328 } 329 else 330 { 331 WARN("Alternate shell in Safe Mode required but not specified."); 332 } 333 } 334 } 335 } 336 else 337 { 338 WARN("Wrong type %lu (expected %u)\n", Type, REG_DWORD); 339 } 340 } 341 } 342 /* Try to run shell in user key */ 343 if (GetShell(Shell, HKEY_CURRENT_USER) && TryToStartShell(Shell)) 344 { 345 TRACE("Started shell from HKEY_CURRENT_USER\n"); 346 return; 347 } 348 349 /* Try to run shell in local machine key */ 350 if (GetShell(Shell, HKEY_LOCAL_MACHINE) && TryToStartShell(Shell)) 351 { 352 TRACE("Started shell from HKEY_LOCAL_MACHINE\n"); 353 return; 354 } 355 356 /* Try default shell */ 357 if (IsConsoleShell()) 358 { 359 if (GetSystemDirectory(Shell, MAX_PATH - 8)) 360 wcscat(Shell, L"\\cmd.exe"); 361 else 362 wcscpy(Shell, L"cmd.exe"); 363 } 364 else 365 { 366 if (GetWindowsDirectory(Shell, MAX_PATH - 13)) 367 wcscat(Shell, L"\\explorer.exe"); 368 else 369 wcscpy(Shell, L"explorer.exe"); 370 } 371 if (!TryToStartShell(Shell)) 372 { 373 WARN("Failed to start default shell %s\n", debugstr_w(Shell)); 374 LoadString( GetModuleHandle(NULL), STRING_USERINIT_FAIL, szMsg, sizeof(szMsg) / sizeof(szMsg[0])); 375 MessageBox(0, szMsg, NULL, 0); 376 } 377 } 378 379 const WCHAR g_RegColorNames[][32] = { 380 L"Scrollbar", /* 00 = COLOR_SCROLLBAR */ 381 L"Background", /* 01 = COLOR_DESKTOP */ 382 L"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */ 383 L"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */ 384 L"Menu", /* 04 = COLOR_MENU */ 385 L"Window", /* 05 = COLOR_WINDOW */ 386 L"WindowFrame", /* 06 = COLOR_WINDOWFRAME */ 387 L"MenuText", /* 07 = COLOR_MENUTEXT */ 388 L"WindowText", /* 08 = COLOR_WINDOWTEXT */ 389 L"TitleText", /* 09 = COLOR_CAPTIONTEXT */ 390 L"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */ 391 L"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */ 392 L"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */ 393 L"Hilight", /* 13 = COLOR_HIGHLIGHT */ 394 L"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */ 395 L"ButtonFace", /* 15 = COLOR_BTNFACE */ 396 L"ButtonShadow", /* 16 = COLOR_BTNSHADOW */ 397 L"GrayText", /* 17 = COLOR_GRAYTEXT */ 398 L"ButtonText", /* 18 = COLOR_BTNTEXT */ 399 L"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */ 400 L"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */ 401 L"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */ 402 L"ButtonLight", /* 22 = COLOR_3DLIGHT */ 403 L"InfoText", /* 23 = COLOR_INFOTEXT */ 404 L"InfoWindow", /* 24 = COLOR_INFOBK */ 405 L"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */ 406 L"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */ 407 L"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */ 408 L"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */ 409 L"MenuHilight", /* 29 = COLOR_MENUHILIGHT */ 410 L"MenuBar" /* 30 = COLOR_MENUBAR */ 411 }; 412 #define NUM_SYSCOLORS (sizeof(g_RegColorNames) / sizeof(g_RegColorNames[0])) 413 414 static 415 COLORREF StrToColorref( 416 IN LPWSTR lpszCol) 417 { 418 BYTE rgb[3]; 419 420 TRACE("(%s)\n", debugstr_w(lpszCol)); 421 422 rgb[0] = StrToIntW(lpszCol); 423 lpszCol = StrChrW(lpszCol, L' ') + 1; 424 rgb[1] = StrToIntW(lpszCol); 425 lpszCol = StrChrW(lpszCol, L' ') + 1; 426 rgb[2] = StrToIntW(lpszCol); 427 return RGB(rgb[0], rgb[1], rgb[2]); 428 } 429 430 static 431 VOID SetUserSysColors(VOID) 432 { 433 HKEY hKey; 434 INT i; 435 WCHAR szColor[20]; 436 DWORD Type, Size; 437 COLORREF crColor; 438 LONG rc; 439 440 TRACE("()\n"); 441 442 rc = RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_COLORS, 443 0, KEY_QUERY_VALUE, &hKey); 444 if (rc != ERROR_SUCCESS) 445 { 446 WARN("RegOpenKeyEx() failed with error %lu\n", rc); 447 return; 448 } 449 for(i = 0; i < NUM_SYSCOLORS; i++) 450 { 451 Size = sizeof(szColor); 452 rc = RegQueryValueEx(hKey, g_RegColorNames[i], NULL, &Type, 453 (LPBYTE)szColor, &Size); 454 if (rc == ERROR_SUCCESS && Type == REG_SZ) 455 { 456 crColor = StrToColorref(szColor); 457 SetSysColors(1, &i, &crColor); 458 } 459 else 460 WARN("RegQueryValueEx(%s) failed with error %lu\n", 461 debugstr_w(g_RegColorNames[i]), rc); 462 } 463 RegCloseKey(hKey); 464 } 465 466 static 467 VOID SetUserWallpaper(VOID) 468 { 469 HKEY hKey; 470 DWORD Type, Size; 471 WCHAR szWallpaper[MAX_PATH + 1]; 472 LONG rc; 473 474 TRACE("()\n"); 475 476 rc = RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, 477 0, KEY_QUERY_VALUE, &hKey); 478 if (rc == ERROR_SUCCESS) 479 { 480 Size = sizeof(szWallpaper); 481 rc = RegQueryValueEx(hKey, 482 L"Wallpaper", 483 NULL, 484 &Type, 485 (LPBYTE)szWallpaper, 486 &Size); 487 if (rc == ERROR_SUCCESS && Type == REG_SZ) 488 { 489 ExpandEnvironmentStrings(szWallpaper, szWallpaper, MAX_PATH); 490 TRACE("Using wallpaper %s\n", debugstr_w(szWallpaper)); 491 492 /* Load and change the wallpaper */ 493 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, szWallpaper, SPIF_SENDCHANGE); 494 } 495 else 496 { 497 /* remove the wallpaper */ 498 TRACE("No wallpaper set in registry (error %lu)\n", rc); 499 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE); 500 } 501 RegCloseKey(hKey); 502 } 503 else 504 WARN("RegOpenKeyEx() failed with error %lu\n", rc); 505 } 506 507 static 508 VOID SetUserSettings(VOID) 509 { 510 TRACE("()\n"); 511 512 UpdatePerUserSystemParameters(1, TRUE); 513 SetUserSysColors(); 514 SetUserWallpaper(); 515 } 516 517 typedef DWORD (WINAPI *PCMP_REPORT_LOGON)(DWORD, DWORD); 518 519 static VOID 520 NotifyLogon(VOID) 521 { 522 HINSTANCE hModule; 523 PCMP_REPORT_LOGON CMP_Report_LogOn; 524 525 TRACE("()\n"); 526 527 hModule = LoadLibrary(L"setupapi.dll"); 528 if (hModule) 529 { 530 CMP_Report_LogOn = (PCMP_REPORT_LOGON)GetProcAddress(hModule, "CMP_Report_LogOn"); 531 if (CMP_Report_LogOn) 532 CMP_Report_LogOn(CMP_MAGIC, GetCurrentProcessId()); 533 else 534 WARN("GetProcAddress() failed\n"); 535 536 FreeLibrary(hModule); 537 } 538 else 539 WARN("LoadLibrary() failed with error %lu\n", GetLastError()); 540 } 541 542 #ifdef _MSC_VER 543 #pragma warning(disable : 4100) 544 #endif /* _MSC_VER */ 545 546 int WINAPI 547 wWinMain(IN HINSTANCE hInst, 548 IN HINSTANCE hPrevInstance, 549 IN LPWSTR lpszCmdLine, 550 IN int nCmdShow) 551 { 552 SetUserSettings(); 553 StartShell(); 554 NotifyLogon(); 555 return 0; 556 } 557 558 /* EOF */ 559