2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winlogon
4 * FILE: base/system/winlogon/winlogon.c
6 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES *****************************************************************/
15 #include <ndk/cmfuncs.h>
17 /* GLOBALS ******************************************************************/
19 HINSTANCE hAppInstance
;
20 PWLSESSION WLSession
= NULL
;
22 /* FUNCTIONS *****************************************************************/
26 StartServicesManager(VOID
)
28 STARTUPINFOW StartupInfo
;
29 PROCESS_INFORMATION ProcessInformation
;
30 LPCWSTR ServiceString
= L
"services.exe";
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;
43 TRACE("WL: Creating new process - %S\n", ServiceString
);
45 res
= CreateProcessW(ServiceString
,
57 ERR("WL: Failed to execute services (error %lu)\n", GetLastError());
61 TRACE("WL: Created new process - %S\n", ServiceString
);
63 CloseHandle(ProcessInformation
.hThread
);
64 CloseHandle(ProcessInformation
.hProcess
);
66 TRACE("WL: StartServicesManager() done.\n");
76 STARTUPINFOW StartupInfo
;
77 PROCESS_INFORMATION ProcessInformation
;
78 LPCWSTR ServiceString
= L
"lsass.exe";
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;
91 TRACE("WL: Creating new process - %S\n", ServiceString
);
93 res
= CreateProcessW(ServiceString
,
102 &ProcessInformation
);
104 TRACE("WL: Created new process - %S\n", ServiceString
);
106 CloseHandle(ProcessInformation
.hThread
);
107 CloseHandle(ProcessInformation
.hProcess
);
120 hEvent
= CreateEventW(NULL
,
123 L
"LSA_RPC_SERVER_ACTIVE");
126 dwError
= GetLastError();
127 TRACE("WL: Failed to create the notication event (Error %lu)\n", dwError
);
129 if (dwError
== ERROR_ALREADY_EXISTS
)
131 hEvent
= OpenEventW(SYNCHRONIZE
,
133 L
"LSA_RPC_SERVER_ACTIVE");
136 ERR("WL: Could not open the notification event (Error %lu)\n", GetLastError());
142 TRACE("WL: Wait for the LSA server!\n");
143 WaitForSingleObject(hEvent
, INFINITE
);
144 TRACE("WL: LSA server running!\n");
152 InitKeyboardLayouts(VOID
)
154 WCHAR wszKeyName
[12], wszKLID
[10];
155 DWORD dwSize
= sizeof(wszKLID
), dwType
, i
= 1;
160 /* Open registry key with preloaded layouts */
161 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Keyboard Layout\\Preload", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
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
)
169 /* There is no more entries */
173 /* Only REG_SZ values are valid */
174 if (dwType
!= REG_SZ
)
176 ERR("Wrong type: %ws!\n", wszKLID
);
180 /* Load keyboard layout with given locale id */
181 Flags
= KLF_SUBSTITUTE_OK
;
183 Flags
|= KLF_NOTELLSHELL
|KLF_REPLACELANG
;
185 Flags
|= KLF_ACTIVATE
; // |0x40000000
186 if (!LoadKeyboardLayoutW(wszKLID
, Flags
))
188 ERR("LoadKeyboardLayoutW(%ws) failed!\n", wszKLID
);
193 /* We loaded at least one layout - success */
198 /* Close the key now */
202 WARN("RegOpenKeyExW(Keyboard Layout\\Preload) failed!\n");
206 /* If we failed, load US keyboard layout */
207 if (LoadKeyboardLayoutW(L
"00000409", 0x04090409))
216 DisplayStatusMessage(
217 IN PWLSESSION Session
,
221 WCHAR StatusMsg
[MAX_PATH
];
223 if (Session
->Gina
.Version
< WLX_VERSION_1_3
)
226 if (Session
->SuppressStatus
)
229 if (LoadStringW(hAppInstance
, ResourceId
, StatusMsg
, MAX_PATH
) == 0)
232 return Session
->Gina
.Functions
.WlxDisplayStatusMessage(Session
->Gina
.Context
, hDesktop
, 0, NULL
, StatusMsg
);
238 IN PWLSESSION Session
)
240 if (Session
->Gina
.Version
< WLX_VERSION_1_3
)
243 return Session
->Gina
.Functions
.WlxRemoveStatusMessage(Session
->Gina
.Context
);
250 GinaLoadFailedWindowProc(
260 switch (LOWORD(wParam
))
263 EndDialog(hwndDlg
, IDOK
);
272 WCHAR templateText
[MAX_PATH
], text
[MAX_PATH
];
274 len
= GetDlgItemTextW(hwndDlg
, IDC_GINALOADFAILED
, templateText
, MAX_PATH
);
277 wsprintfW(text
, templateText
, (LPWSTR
)lParam
);
278 SetDlgItemTextW(hwndDlg
, IDC_GINALOADFAILED
, text
);
281 SetFocus(GetDlgItem(hwndDlg
, IDOK
));
287 EndDialog(hwndDlg
, IDCANCEL
);
299 IN HINSTANCE hInstance
,
300 IN HINSTANCE hPrevInstance
,
305 LSA_STRING ProcessName
, PackageName
;
307 LSA_OPERATIONAL_MODE Mode
;
309 ULONG AuthenticationPackage
;
312 ULONG HardErrorResponse
;
315 UNREFERENCED_PARAMETER(hPrevInstance
);
316 UNREFERENCED_PARAMETER(lpCmdLine
);
317 UNREFERENCED_PARAMETER(nShowCmd
);
319 hAppInstance
= hInstance
;
321 /* Make us critical */
322 RtlSetProcessIsCritical(TRUE
, NULL
, FALSE
);
323 RtlSetThreadIsCritical(TRUE
, NULL
, FALSE
);
325 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE
))
327 ERR("WL: Could not register logon process\n");
328 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
332 WLSession
= (PWLSESSION
)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION
));
335 ERR("WL: Could not allocate memory for winlogon instance\n");
336 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
340 ZeroMemory(WLSession
, sizeof(WLSESSION
));
341 WLSession
->DialogTimeout
= 120; /* 2 minutes */
343 /* Initialize the dialog tracking list */
344 InitDialogListHead();
346 if (!CreateWindowStationAndDesktops(WLSession
))
348 ERR("WL: Could not create window station and desktops\n");
349 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
353 LockWorkstation(WLSession
);
355 /* Load default keyboard layouts */
356 if (!InitKeyboardLayouts())
358 ERR("WL: Could not preload keyboard layouts\n");
359 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
363 if (!StartRpcServer())
365 ERR("WL: Could not start the RPC server\n");
366 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
370 if (!StartServicesManager())
372 ERR("WL: Could not start services.exe\n");
373 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
379 ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
380 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
384 /* Wait for the LSA server */
387 /* Init Notifications */
390 /* Load and initialize gina */
391 if (!GinaInit(WLSession
))
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
);
401 DisplayStatusMessage(WLSession
, WLSession
->WinlogonDesktop
, IDS_REACTOSISSTARTINGUP
);
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
)
410 /* Add the 'SeTcbPrivilege' privilege and try again */
411 Status
= RtlAdjustPrivilege(SE_TCB_PRIVILEGE
, TRUE
, TRUE
, &Old
);
412 if (!NT_SUCCESS(Status
))
414 ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status
));
418 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
421 if (!NT_SUCCESS(Status
))
423 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status
));
427 RtlInitUnicodeString((PUNICODE_STRING
)&PackageName
, MICROSOFT_KERBEROS_NAME_W
);
428 Status
= LsaLookupAuthenticationPackage(LsaHandle
, &PackageName
, &AuthenticationPackage
);
429 if (!NT_SUCCESS(Status
))
431 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status
));
432 LsaDeregisterLogonProcess(LsaHandle
);
437 CallNotificationDlls(WLSession
, StartupHandler
);
439 /* Create a hidden window to get SAS notifications */
440 if (!InitializeSAS(WLSession
))
442 ERR("WL: Failed to initialize SAS\n");
446 // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
447 // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);
449 /* Display logged out screen */
450 WLSession
->LogonState
= STATE_INIT
;
451 RemoveStatusMessage(WLSession
);
453 /* Check for pending setup */
454 if (GetSetupType() != 0)
456 TRACE("WL: Setup mode detected\n");
458 /* Run setup and reboot when done */
459 SwitchDesktop(WLSession
->ApplicationDesktop
);
463 PostMessageW(WLSession
->SASWindow
, WLX_WM_SAS
, WLX_SAS_TYPE_CTRL_ALT_DEL
, 0);
465 (void)LoadLibraryW(L
"sfc_os.dll");
467 /* Tell kernel that CurrentControlSet is good (needed
468 * to support Last good known configuration boot) */
469 NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED
| 1);
471 /* Message loop for the SAS window */
472 while (GetMessageW(&Msg
, WLSession
->SASWindow
, 0, 0))
474 TranslateMessage(&Msg
);
475 DispatchMessageW(&Msg
);
478 CleanupNotifications();
480 /* We never go there */