/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Winlogon * FILE: base/system/winlogon/winlogon.c * PURPOSE: Logon * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net) * Filip Navara * Hervé Poussineau (hpoussin@reactos.org) */ /* INCLUDES *****************************************************************/ #include "winlogon.h" WINE_DEFAULT_DEBUG_CHANNEL(winlogon); /* GLOBALS ******************************************************************/ HINSTANCE hAppInstance; PWLSESSION WLSession = NULL; /* FUNCTIONS *****************************************************************/ static BOOL StartServicesManager(VOID) { STARTUPINFOW StartupInfo; PROCESS_INFORMATION ProcessInformation; LPCWSTR ServiceString = L"services.exe"; BOOL res; /* Start the service control manager (services.exe) */ ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW)); StartupInfo.cb = sizeof(StartupInfo); StartupInfo.lpReserved = NULL; StartupInfo.lpDesktop = NULL; StartupInfo.lpTitle = NULL; StartupInfo.dwFlags = 0; StartupInfo.cbReserved2 = 0; StartupInfo.lpReserved2 = 0; TRACE("WL: Creating new process - %S\n", ServiceString); res = CreateProcessW(ServiceString, NULL, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &StartupInfo, &ProcessInformation); if (!res) { ERR("WL: Failed to execute services (error %lu)\n", GetLastError()); return FALSE; } TRACE("WL: Created new process - %S\n", ServiceString); CloseHandle(ProcessInformation.hThread); CloseHandle(ProcessInformation.hProcess); TRACE("WL: StartServicesManager() done.\n"); return TRUE; } static BOOL StartLsass(VOID) { STARTUPINFOW StartupInfo; PROCESS_INFORMATION ProcessInformation; LPCWSTR ServiceString = L"lsass.exe"; BOOL res; /* Start the local security authority subsystem (lsass.exe) */ ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW)); StartupInfo.cb = sizeof(StartupInfo); StartupInfo.lpReserved = NULL; StartupInfo.lpDesktop = NULL; StartupInfo.lpTitle = NULL; StartupInfo.dwFlags = 0; StartupInfo.cbReserved2 = 0; StartupInfo.lpReserved2 = 0; TRACE("WL: Creating new process - %S\n", ServiceString); res = CreateProcessW(ServiceString, NULL, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &StartupInfo, &ProcessInformation); TRACE("WL: Created new process - %S\n", ServiceString); CloseHandle(ProcessInformation.hThread); CloseHandle(ProcessInformation.hProcess); return res; } static VOID WaitForLsass(VOID) { HANDLE hEvent; DWORD dwError; hEvent = CreateEventW(NULL, TRUE, FALSE, L"LSA_RPC_SERVER_ACTIVE"); if (hEvent == NULL) { dwError = GetLastError(); TRACE("WL: Failed to create the notication event (Error %lu)\n", dwError); if (dwError == ERROR_ALREADY_EXISTS) { hEvent = OpenEventW(SYNCHRONIZE, FALSE, L"LSA_RPC_SERVER_ACTIVE"); if (hEvent == NULL) { ERR("WL: Could not open the notification event (Error %lu)\n", GetLastError()); return; } } } TRACE("WL: Wait for the LSA server!\n"); WaitForSingleObject(hEvent, INFINITE); TRACE("WL: LSA server running!\n"); CloseHandle(hEvent); } static BOOL InitKeyboardLayouts(VOID) { WCHAR wszKeyName[12], wszKLID[10]; DWORD dwSize = sizeof(wszKLID), dwType, i = 1; HKEY hKey; UINT Flags; BOOL bRet = FALSE; /* Open registry key with preloaded layouts */ if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { while(TRUE) { /* Read values with integer names only */ swprintf(wszKeyName, L"%d", i++); if (RegQueryValueExW(hKey, wszKeyName, NULL, &dwType, (LPBYTE)wszKLID, &dwSize) != ERROR_SUCCESS) { /* There is no more entries */ break; } /* Only REG_SZ values are valid */ if (dwType != REG_SZ) { ERR("Wrong type: %ws!\n", wszKLID); continue; } /* Load keyboard layout with given locale id */ Flags = KLF_SUBSTITUTE_OK; if (i > 1) Flags |= KLF_NOTELLSHELL|KLF_REPLACELANG; else // First layout Flags |= KLF_ACTIVATE; // |0x40000000 if (!LoadKeyboardLayoutW(wszKLID, Flags)) { ERR("LoadKeyboardLayoutW(%ws) failed!\n", wszKLID); continue; } else { /* We loaded at least one layout - success */ bRet = TRUE; } } /* Close the key now */ RegCloseKey(hKey); } else WARN("RegOpenKeyExW(Keyboard Layout\\Preload) failed!\n"); if (!bRet) { /* If we failed, load US keyboard layout */ if (LoadKeyboardLayoutW(L"00000409", 0x04090409)) bRet = TRUE; } return bRet; } BOOL DisplayStatusMessage(IN PWLSESSION Session, IN HDESK hDesktop, IN UINT ResourceId) { WCHAR StatusMsg[MAX_PATH]; if (Session->Gina.Version < WLX_VERSION_1_3) return TRUE; if (Session->SuppressStatus) return TRUE; if (LoadStringW(hAppInstance, ResourceId, StatusMsg, MAX_PATH) == 0) return FALSE; return Session->Gina.Functions.WlxDisplayStatusMessage(Session->Gina.Context, hDesktop, 0, NULL, StatusMsg); } BOOL RemoveStatusMessage(IN PWLSESSION Session) { if (Session->Gina.Version < WLX_VERSION_1_3) return TRUE; return Session->Gina.Functions.WlxRemoveStatusMessage(Session->Gina.Context); } static INT_PTR CALLBACK GinaLoadFailedWindowProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { switch (uMsg) { case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: EndDialog(hwndDlg, IDOK); return TRUE; } break; } case WM_INITDIALOG: { int len; WCHAR templateText[MAX_PATH], text[MAX_PATH]; len = GetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, templateText, MAX_PATH); if (len) { wsprintfW(text, templateText, (LPWSTR)lParam); SetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, text); } SetFocus(GetDlgItem(hwndDlg, IDOK)); return TRUE; } case WM_CLOSE: { EndDialog(hwndDlg, IDCANCEL); return TRUE; } } return FALSE; } int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd) { #if 0 LSA_STRING ProcessName, PackageName; HANDLE LsaHandle; LSA_OPERATIONAL_MODE Mode; BOOLEAN Old; ULONG AuthenticationPackage; NTSTATUS Status; #endif ULONG HardErrorResponse; MSG Msg; UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nShowCmd); hAppInstance = hInstance; if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE)) { ERR("WL: Could not register logon process\n"); NtShutdownSystem(ShutdownNoReboot); ExitProcess(0); } WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION)); if (!WLSession) { ERR("WL: Could not allocate memory for winlogon instance\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } ZeroMemory(WLSession, sizeof(WLSESSION)); WLSession->DialogTimeout = 120; /* 2 minutes */ if (!CreateWindowStationAndDesktops(WLSession)) { ERR("WL: Could not create window station and desktops\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } LockWorkstation(WLSession); /* Load default keyboard layouts */ if (!InitKeyboardLayouts()) { ERR("WL: Could not preload keyboard layouts\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartServicesManager()) { ERR("WL: Could not start services.exe\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartLsass()) { ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError()); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, OptionOk, &HardErrorResponse); ExitProcess(1); } /* Wait for the LSA server */ WaitForLsass(); /* Load and initialize gina */ if (!GinaInit(WLSession)) { ERR("WL: Failed to initialize Gina\n"); DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L""); HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT); ExitProcess(1); } DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP); #if 0 /* Connect to NetLogon service (lsass.exe) */ /* Real winlogon uses "Winlogon" */ RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon"); Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); if (Status == STATUS_PORT_CONNECTION_REFUSED) { /* Add the 'SeTcbPrivilege' privilege and try again */ Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old); if (!NT_SUCCESS(Status)) { ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status)); return 1; } Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); } if (!NT_SUCCESS(Status)) { ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status)); return 1; } RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W); Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage); if (!NT_SUCCESS(Status)) { ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status)); LsaDeregisterLogonProcess(LsaHandle); return 1; } #endif /* Create a hidden window to get SAS notifications */ if (!InitializeSAS(WLSession)) { ERR("WL: Failed to initialize SAS\n"); ExitProcess(2); } //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS); //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS); /* Display logged out screen */ WLSession->LogonState = STATE_LOGGED_OFF; RemoveStatusMessage(WLSession); /* Check for pending setup */ if (GetSetupType() != 0) { TRACE("WL: Setup mode detected\n"); /* Run setup and reboot when done */ SwitchDesktop(WLSession->ApplicationDesktop); RunSetup(); } else PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_TIMEOUT, 0); /* Tell kernel that CurrentControlSet is good (needed * to support Last good known configuration boot) */ NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1); /* Message loop for the SAS window */ while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); } /* We never go there */ return 0; }