1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Winlogon 4 * FILE: base/system/winlogon/winlogon.c 5 * PURPOSE: Logon 6 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net) 7 * Filip Navara 8 * Herv� Poussineau (hpoussin@reactos.org) 9 */ 10 11 /* INCLUDES *****************************************************************/ 12 13 #include "winlogon.h" 14 15 #include <ndk/cmfuncs.h> 16 17 /* GLOBALS ******************************************************************/ 18 19 HINSTANCE hAppInstance; 20 PWLSESSION WLSession = NULL; 21 22 /* FUNCTIONS *****************************************************************/ 23 24 static 25 BOOL 26 StartServicesManager(VOID) 27 { 28 STARTUPINFOW StartupInfo; 29 PROCESS_INFORMATION ProcessInformation; 30 LPCWSTR ServiceString = L"services.exe"; 31 BOOL res; 32 33 /* Start the service control manager (services.exe) */ 34 ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW)); 35 StartupInfo.cb = sizeof(StartupInfo); 36 StartupInfo.lpReserved = NULL; 37 StartupInfo.lpDesktop = NULL; 38 StartupInfo.lpTitle = NULL; 39 StartupInfo.dwFlags = 0; 40 StartupInfo.cbReserved2 = 0; 41 StartupInfo.lpReserved2 = 0; 42 43 TRACE("WL: Creating new process - %S\n", ServiceString); 44 45 res = CreateProcessW(ServiceString, 46 NULL, 47 NULL, 48 NULL, 49 FALSE, 50 DETACHED_PROCESS, 51 NULL, 52 NULL, 53 &StartupInfo, 54 &ProcessInformation); 55 if (!res) 56 { 57 ERR("WL: Failed to execute services (error %lu)\n", GetLastError()); 58 return FALSE; 59 } 60 61 TRACE("WL: Created new process - %S\n", ServiceString); 62 63 CloseHandle(ProcessInformation.hThread); 64 CloseHandle(ProcessInformation.hProcess); 65 66 TRACE("WL: StartServicesManager() done.\n"); 67 68 return TRUE; 69 } 70 71 72 static 73 BOOL 74 StartLsass(VOID) 75 { 76 STARTUPINFOW StartupInfo; 77 PROCESS_INFORMATION ProcessInformation; 78 LPCWSTR ServiceString = L"lsass.exe"; 79 BOOL res; 80 81 /* Start the local security authority subsystem (lsass.exe) */ 82 ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW)); 83 StartupInfo.cb = sizeof(StartupInfo); 84 StartupInfo.lpReserved = NULL; 85 StartupInfo.lpDesktop = NULL; 86 StartupInfo.lpTitle = NULL; 87 StartupInfo.dwFlags = 0; 88 StartupInfo.cbReserved2 = 0; 89 StartupInfo.lpReserved2 = 0; 90 91 TRACE("WL: Creating new process - %S\n", ServiceString); 92 93 res = CreateProcessW(ServiceString, 94 NULL, 95 NULL, 96 NULL, 97 FALSE, 98 DETACHED_PROCESS, 99 NULL, 100 NULL, 101 &StartupInfo, 102 &ProcessInformation); 103 104 TRACE("WL: Created new process - %S\n", ServiceString); 105 106 CloseHandle(ProcessInformation.hThread); 107 CloseHandle(ProcessInformation.hProcess); 108 109 return res; 110 } 111 112 113 static 114 VOID 115 WaitForLsass(VOID) 116 { 117 HANDLE hEvent; 118 DWORD dwError; 119 120 hEvent = CreateEventW(NULL, 121 TRUE, 122 FALSE, 123 L"LSA_RPC_SERVER_ACTIVE"); 124 if (hEvent == NULL) 125 { 126 dwError = GetLastError(); 127 TRACE("WL: Failed to create the notification event (Error %lu)\n", dwError); 128 129 if (dwError == ERROR_ALREADY_EXISTS) 130 { 131 hEvent = OpenEventW(SYNCHRONIZE, 132 FALSE, 133 L"LSA_RPC_SERVER_ACTIVE"); 134 if (hEvent == NULL) 135 { 136 ERR("WL: Could not open the notification event (Error %lu)\n", GetLastError()); 137 return; 138 } 139 } 140 } 141 142 TRACE("WL: Wait for the LSA server!\n"); 143 WaitForSingleObject(hEvent, INFINITE); 144 TRACE("WL: LSA server running!\n"); 145 146 CloseHandle(hEvent); 147 } 148 149 150 static 151 BOOL 152 InitKeyboardLayouts(VOID) 153 { 154 WCHAR wszKeyName[12], wszKLID[10]; 155 DWORD dwSize = sizeof(wszKLID), dwType, i = 1; 156 HKEY hKey; 157 UINT Flags; 158 BOOL bRet = FALSE; 159 160 /* Open registry key with preloaded layouts */ 161 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_READ, &hKey) == ERROR_SUCCESS) 162 { 163 while (TRUE) 164 { 165 /* Read values with integer names only */ 166 swprintf(wszKeyName, L"%d", i++); 167 if (RegQueryValueExW(hKey, wszKeyName, NULL, &dwType, (LPBYTE)wszKLID, &dwSize) != ERROR_SUCCESS) 168 { 169 /* There is no more entries */ 170 break; 171 } 172 173 /* Only REG_SZ values are valid */ 174 if (dwType != REG_SZ) 175 { 176 ERR("Wrong type: %ws!\n", wszKLID); 177 continue; 178 } 179 180 /* Load keyboard layout with given locale id */ 181 Flags = KLF_SUBSTITUTE_OK; 182 if (i > 1) 183 Flags |= KLF_NOTELLSHELL|KLF_REPLACELANG; 184 else // First layout 185 Flags |= KLF_ACTIVATE; // |0x40000000 186 if (!LoadKeyboardLayoutW(wszKLID, Flags)) 187 { 188 ERR("LoadKeyboardLayoutW(%ws) failed!\n", wszKLID); 189 continue; 190 } 191 else 192 { 193 /* We loaded at least one layout - success */ 194 bRet = TRUE; 195 } 196 } 197 198 /* Close the key now */ 199 RegCloseKey(hKey); 200 } 201 else 202 WARN("RegOpenKeyExW(Keyboard Layout\\Preload) failed!\n"); 203 204 if (!bRet) 205 { 206 /* If we failed, load US keyboard layout */ 207 if (LoadKeyboardLayoutW(L"00000409", 0x04090409)) 208 bRet = TRUE; 209 } 210 211 return bRet; 212 } 213 214 215 BOOL 216 DisplayStatusMessage( 217 IN PWLSESSION Session, 218 IN HDESK hDesktop, 219 IN UINT ResourceId) 220 { 221 WCHAR StatusMsg[MAX_PATH]; 222 223 if (Session->Gina.Version < WLX_VERSION_1_3) 224 return TRUE; 225 226 if (Session->SuppressStatus) 227 return TRUE; 228 229 if (LoadStringW(hAppInstance, ResourceId, StatusMsg, MAX_PATH) == 0) 230 return FALSE; 231 232 return Session->Gina.Functions.WlxDisplayStatusMessage(Session->Gina.Context, hDesktop, 0, NULL, StatusMsg); 233 } 234 235 236 BOOL 237 RemoveStatusMessage( 238 IN PWLSESSION Session) 239 { 240 if (Session->Gina.Version < WLX_VERSION_1_3) 241 return TRUE; 242 243 return Session->Gina.Functions.WlxRemoveStatusMessage(Session->Gina.Context); 244 } 245 246 247 static 248 INT_PTR 249 CALLBACK 250 GinaLoadFailedWindowProc( 251 IN HWND hwndDlg, 252 IN UINT uMsg, 253 IN WPARAM wParam, 254 IN LPARAM lParam) 255 { 256 switch (uMsg) 257 { 258 case WM_COMMAND: 259 { 260 switch (LOWORD(wParam)) 261 { 262 case IDOK: 263 EndDialog(hwndDlg, IDOK); 264 return TRUE; 265 } 266 break; 267 } 268 269 case WM_INITDIALOG: 270 { 271 int len; 272 WCHAR templateText[MAX_PATH], text[MAX_PATH]; 273 274 len = GetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, templateText, MAX_PATH); 275 if (len) 276 { 277 wsprintfW(text, templateText, (LPWSTR)lParam); 278 SetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, text); 279 } 280 281 SetFocus(GetDlgItem(hwndDlg, IDOK)); 282 return TRUE; 283 } 284 285 case WM_CLOSE: 286 { 287 EndDialog(hwndDlg, IDCANCEL); 288 return TRUE; 289 } 290 } 291 292 return FALSE; 293 } 294 295 296 int 297 WINAPI 298 WinMain( 299 IN HINSTANCE hInstance, 300 IN HINSTANCE hPrevInstance, 301 IN LPSTR lpCmdLine, 302 IN int nShowCmd) 303 { 304 #if 0 305 LSA_STRING ProcessName, PackageName; 306 HANDLE LsaHandle; 307 LSA_OPERATIONAL_MODE Mode; 308 BOOLEAN Old; 309 ULONG AuthenticationPackage; 310 NTSTATUS Status; 311 #endif 312 ULONG HardErrorResponse; 313 MSG Msg; 314 315 UNREFERENCED_PARAMETER(hPrevInstance); 316 UNREFERENCED_PARAMETER(lpCmdLine); 317 UNREFERENCED_PARAMETER(nShowCmd); 318 319 hAppInstance = hInstance; 320 321 /* Make us critical */ 322 RtlSetProcessIsCritical(TRUE, NULL, FALSE); 323 RtlSetThreadIsCritical(TRUE, NULL, FALSE); 324 325 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE)) 326 { 327 ERR("WL: Could not register logon process\n"); 328 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 329 ExitProcess(1); 330 } 331 332 WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION)); 333 if (!WLSession) 334 { 335 ERR("WL: Could not allocate memory for winlogon instance\n"); 336 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 337 ExitProcess(1); 338 } 339 340 ZeroMemory(WLSession, sizeof(WLSESSION)); 341 WLSession->DialogTimeout = 120; /* 2 minutes */ 342 343 /* Initialize the dialog tracking list */ 344 InitDialogListHead(); 345 346 if (!CreateWindowStationAndDesktops(WLSession)) 347 { 348 ERR("WL: Could not create window station and desktops\n"); 349 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 350 ExitProcess(1); 351 } 352 353 LockWorkstation(WLSession); 354 355 /* Load default keyboard layouts */ 356 if (!InitKeyboardLayouts()) 357 { 358 ERR("WL: Could not preload keyboard layouts\n"); 359 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 360 ExitProcess(1); 361 } 362 363 if (!StartRpcServer()) 364 { 365 ERR("WL: Could not start the RPC server\n"); 366 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 367 ExitProcess(1); 368 } 369 370 if (!StartServicesManager()) 371 { 372 ERR("WL: Could not start services.exe\n"); 373 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 374 ExitProcess(1); 375 } 376 377 if (!StartLsass()) 378 { 379 ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError()); 380 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); 381 ExitProcess(1); 382 } 383 384 /* Wait for the LSA server */ 385 WaitForLsass(); 386 387 /* Init Notifications */ 388 InitNotifications(); 389 390 /* Load and initialize gina */ 391 if (!GinaInit(WLSession)) 392 { 393 ERR("WL: Failed to initialize Gina\n"); 394 // FIXME: Retrieve the real name of the GINA DLL we were trying to load. 395 // It is known only inside the GinaInit function... 396 DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"msgina.dll"); 397 HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT); 398 ExitProcess(1); 399 } 400 401 DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP); 402 403 #if 0 404 /* Connect to NetLogon service (lsass.exe) */ 405 /* Real winlogon uses "Winlogon" */ 406 RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon"); 407 Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); 408 if (Status == STATUS_PORT_CONNECTION_REFUSED) 409 { 410 /* Add the 'SeTcbPrivilege' privilege and try again */ 411 Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old); 412 if (!NT_SUCCESS(Status)) 413 { 414 ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status)); 415 return 1; 416 } 417 418 Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); 419 } 420 421 if (!NT_SUCCESS(Status)) 422 { 423 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status)); 424 return 1; 425 } 426 427 RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W); 428 Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage); 429 if (!NT_SUCCESS(Status)) 430 { 431 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status)); 432 LsaDeregisterLogonProcess(LsaHandle); 433 return 1; 434 } 435 #endif 436 437 CallNotificationDlls(WLSession, StartupHandler); 438 439 /* Create a hidden window to get SAS notifications */ 440 if (!InitializeSAS(WLSession)) 441 { 442 ERR("WL: Failed to initialize SAS\n"); 443 ExitProcess(2); 444 } 445 446 // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS); 447 // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS); 448 449 /* Display logged out screen */ 450 WLSession->LogonState = STATE_INIT; 451 RemoveStatusMessage(WLSession); 452 453 /* Check for pending setup */ 454 if (GetSetupType() != 0) 455 { 456 /* Run setup and reboot when done */ 457 TRACE("WL: Setup mode detected\n"); 458 RunSetup(); 459 } 460 else 461 { 462 PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0); 463 } 464 465 (void)LoadLibraryW(L"sfc_os.dll"); 466 467 /* Tell kernel that CurrentControlSet is good (needed 468 * to support Last good known configuration boot) */ 469 NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1); 470 471 /* Message loop for the SAS window */ 472 while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0)) 473 { 474 TranslateMessage(&Msg); 475 DispatchMessageW(&Msg); 476 } 477 478 CleanupNotifications(); 479 480 /* We never go there */ 481 482 return 0; 483 } 484