/* * 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" #include WINE_DEFAULT_DEBUG_CHANNEL(winlogon); /* GLOBALS ******************************************************************/ HINSTANCE hAppInstance; PWLSESSION WLSession = NULL; /* FUNCTIONS *****************************************************************/ DWORD WINAPI PlayLogonSoundThread( IN LPVOID lpParameter) { HKEY hKey; WCHAR szBuffer[MAX_PATH] = {0}; WCHAR szDest[MAX_PATH]; DWORD dwSize = sizeof(szBuffer); HMODULE hLibrary; SERVICE_STATUS_PROCESS Info; typedef BOOL (WINAPI *PLAYSOUNDW)(LPCWSTR,HMODULE,DWORD); PLAYSOUNDW Play; ULONG Index = 0; if (RegOpenKeyExW(HKEY_CURRENT_USER, L"AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current", 0, KEY_READ, &hKey) != ERROR_SUCCESS) { ExitThread(0); } if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)szBuffer, &dwSize) != ERROR_SUCCESS) { RegCloseKey(hKey); ExitThread(0); } RegCloseKey(hKey); if (!szBuffer[0]) ExitThread(0); szBuffer[MAX_PATH-1] = L'\0'; if (ExpandEnvironmentStringsW(szBuffer, szDest, MAX_PATH)) { SC_HANDLE hSCManager, hService; hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCManager) ExitThread(0);; hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ); if (!hService) { CloseServiceHandle(hSCManager); TRACE("WL: failed to open sysaudio Status %x\n", GetLastError()); ExitThread(0); } do { if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize)) { TRACE("WL: QueryServiceStatusEx failed %x\n", GetLastError()); break; } if (Info.dwCurrentState == SERVICE_RUNNING) break; Sleep(1000); }while(Index++ < 20); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); if (Info.dwCurrentState != SERVICE_RUNNING) ExitThread(0); hLibrary = LoadLibraryW(L"winmm.dll"); if (hLibrary) { Play = (PLAYSOUNDW)GetProcAddress(hLibrary, "PlaySoundW"); if (Play) { Play(szDest, NULL, SND_FILENAME); } FreeLibrary(hLibrary); } } ExitThread(0); } 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); } 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; HANDLE hThread; UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nShowCmd); hAppInstance = hInstance; if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE)) { ERR("WL: Could not register logon process\n"); HandleShutdown(NULL, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF); 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); 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); } /* 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); /* Wait for the LSA server */ WaitForLsass(); #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->LogonStatus = WKSTA_IS_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); /* Play logon sound */ hThread = CreateThread(NULL, 0, PlayLogonSoundThread, NULL, 0, NULL); if (hThread) { CloseHandle(hThread); } /* 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; }