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