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 <wine/debug.h>
17 WINE_DEFAULT_DEBUG_CHANNEL(winlogon
);
19 /* GLOBALS ******************************************************************/
21 HINSTANCE hAppInstance
;
22 PWLSESSION WLSession
= NULL
;
24 /* FUNCTIONS *****************************************************************/
29 IN LPVOID lpParameter
)
32 WCHAR szBuffer
[MAX_PATH
] = {0};
33 WCHAR szDest
[MAX_PATH
];
34 DWORD dwSize
= sizeof(szBuffer
);
36 SERVICE_STATUS_PROCESS Info
;
37 typedef BOOL (WINAPI
*PLAYSOUNDW
)(LPCWSTR
,HMODULE
,DWORD
);
41 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
46 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)szBuffer
, &dwSize
) != ERROR_SUCCESS
)
59 szBuffer
[MAX_PATH
-1] = L
'\0';
60 if (ExpandEnvironmentStringsW(szBuffer
, szDest
, MAX_PATH
))
62 SC_HANDLE hSCManager
, hService
;
64 hSCManager
= OpenSCManager(NULL
, NULL
, SC_MANAGER_CONNECT
);
68 hService
= OpenServiceW(hSCManager
, L
"wdmaud", GENERIC_READ
);
71 CloseServiceHandle(hSCManager
);
72 TRACE("WL: failed to open sysaudio Status %x\n", GetLastError());
78 if (!QueryServiceStatusEx(hService
, SC_STATUS_PROCESS_INFO
, (LPBYTE
)&Info
, sizeof(SERVICE_STATUS_PROCESS
), &dwSize
))
80 TRACE("WL: QueryServiceStatusEx failed %x\n", GetLastError());
84 if (Info
.dwCurrentState
== SERVICE_RUNNING
)
91 CloseServiceHandle(hService
);
92 CloseServiceHandle(hSCManager
);
94 if (Info
.dwCurrentState
!= SERVICE_RUNNING
)
98 hLibrary
= LoadLibraryW(L
"winmm.dll");
101 Play
= (PLAYSOUNDW
)GetProcAddress(hLibrary
, "PlaySoundW");
104 Play(szDest
, NULL
, SND_FILENAME
);
106 FreeLibrary(hLibrary
);
115 StartServicesManager(VOID
)
117 STARTUPINFOW StartupInfo
;
118 PROCESS_INFORMATION ProcessInformation
;
119 LPCWSTR ServiceString
= L
"services.exe";
122 /* Start the service control manager (services.exe) */
123 ZeroMemory(&StartupInfo
, sizeof(STARTUPINFOW
));
124 StartupInfo
.cb
= sizeof(StartupInfo
);
125 StartupInfo
.lpReserved
= NULL
;
126 StartupInfo
.lpDesktop
= NULL
;
127 StartupInfo
.lpTitle
= NULL
;
128 StartupInfo
.dwFlags
= 0;
129 StartupInfo
.cbReserved2
= 0;
130 StartupInfo
.lpReserved2
= 0;
132 TRACE("WL: Creating new process - %S\n", ServiceString
);
134 res
= CreateProcessW(
144 &ProcessInformation
);
147 ERR("WL: Failed to execute services (error %lu)\n", GetLastError());
151 TRACE("WL: Created new process - %S\n", ServiceString
);
153 CloseHandle(ProcessInformation
.hThread
);
154 CloseHandle(ProcessInformation
.hProcess
);
156 TRACE("WL: StartServicesManager() done.\n");
165 STARTUPINFOW StartupInfo
;
166 PROCESS_INFORMATION ProcessInformation
;
167 LPCWSTR ServiceString
= L
"lsass.exe";
170 /* Start the local security authority subsystem (lsass.exe) */
171 ZeroMemory(&StartupInfo
, sizeof(STARTUPINFOW
));
172 StartupInfo
.cb
= sizeof(StartupInfo
);
173 StartupInfo
.lpReserved
= NULL
;
174 StartupInfo
.lpDesktop
= NULL
;
175 StartupInfo
.lpTitle
= NULL
;
176 StartupInfo
.dwFlags
= 0;
177 StartupInfo
.cbReserved2
= 0;
178 StartupInfo
.lpReserved2
= 0;
180 TRACE("WL: Creating new process - %S\n", ServiceString
);
182 res
= CreateProcessW(
192 &ProcessInformation
);
194 TRACE("WL: Created new process - %S\n", ServiceString
);
196 CloseHandle(ProcessInformation
.hThread
);
197 CloseHandle(ProcessInformation
.hProcess
);
209 hEvent
= CreateEventW(NULL
,
212 L
"LSA_RPC_SERVER_ACTIVE");
215 dwError
= GetLastError();
216 TRACE("WL: Failed to create the notication event (Error %lu)\n", dwError
);
218 if (dwError
== ERROR_ALREADY_EXISTS
)
220 hEvent
= OpenEventW(SYNCHRONIZE
,
222 L
"LSA_RPC_SERVER_ACTIVE");
225 ERR("WL: Could not open the notification event (Error %lu)\n", GetLastError());
231 TRACE("WL: Wait for the LSA server!\n");
232 WaitForSingleObject(hEvent
, INFINITE
);
233 TRACE("WL: LSA server running!\n");
240 DisplayStatusMessage(
241 IN PWLSESSION Session
,
245 WCHAR StatusMsg
[MAX_PATH
];
247 if (Session
->Gina
.Version
< WLX_VERSION_1_3
)
250 if (Session
->SuppressStatus
)
253 if (LoadStringW(hAppInstance
, ResourceId
, StatusMsg
, MAX_PATH
) == 0)
256 return Session
->Gina
.Functions
.WlxDisplayStatusMessage(Session
->Gina
.Context
, hDesktop
, 0, NULL
, StatusMsg
);
261 IN PWLSESSION Session
)
263 if (Session
->Gina
.Version
< WLX_VERSION_1_3
)
266 return Session
->Gina
.Functions
.WlxRemoveStatusMessage(Session
->Gina
.Context
);
269 static INT_PTR CALLBACK
270 GinaLoadFailedWindowProc(
280 switch (LOWORD(wParam
))
283 EndDialog(hwndDlg
, IDOK
);
291 WCHAR templateText
[MAX_PATH
], text
[MAX_PATH
];
293 len
= GetDlgItemTextW(hwndDlg
, IDC_GINALOADFAILED
, templateText
, MAX_PATH
);
296 wsprintfW(text
, templateText
, (LPWSTR
)lParam
);
297 SetDlgItemTextW(hwndDlg
, IDC_GINALOADFAILED
, text
);
299 SetFocus(GetDlgItem(hwndDlg
, IDOK
));
304 EndDialog(hwndDlg
, IDCANCEL
);
314 IN HINSTANCE hInstance
,
315 IN HINSTANCE hPrevInstance
,
320 LSA_STRING ProcessName
, PackageName
;
322 LSA_OPERATIONAL_MODE Mode
;
324 ULONG AuthenticationPackage
;
327 ULONG HardErrorResponse
;
331 UNREFERENCED_PARAMETER(hPrevInstance
);
332 UNREFERENCED_PARAMETER(lpCmdLine
);
333 UNREFERENCED_PARAMETER(nShowCmd
);
335 hAppInstance
= hInstance
;
337 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE
))
339 ERR("WL: Could not register logon process\n");
340 HandleShutdown(NULL
, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF
);
341 NtShutdownSystem(ShutdownNoReboot
);
345 WLSession
= (PWLSESSION
)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION
));
348 ERR("WL: Could not allocate memory for winlogon instance\n");
349 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
352 ZeroMemory(WLSession
, sizeof(WLSESSION
));
353 WLSession
->DialogTimeout
= 120; /* 2 minutes */
355 if (!CreateWindowStationAndDesktops(WLSession
))
357 ERR("WL: Could not create window station and desktops\n");
358 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
361 LockWorkstation(WLSession
);
363 if (!StartServicesManager())
365 ERR("WL: Could not start services.exe\n");
366 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
372 ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
373 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, 0, OptionOk
, &HardErrorResponse
);
377 /* Load and initialize gina */
378 if (!GinaInit(WLSession
))
380 ERR("WL: Failed to initialize Gina\n");
381 DialogBoxParam(hAppInstance
, MAKEINTRESOURCE(IDD_GINALOADFAILED
), GetDesktopWindow(), GinaLoadFailedWindowProc
, (LPARAM
)L
"");
382 HandleShutdown(WLSession
, WLX_SAS_ACTION_SHUTDOWN_REBOOT
);
386 DisplayStatusMessage(WLSession
, WLSession
->WinlogonDesktop
, IDS_REACTOSISSTARTINGUP
);
389 /* Wait for the LSA server */
393 /* Connect to NetLogon service (lsass.exe) */
394 /* Real winlogon uses "Winlogon" */
395 RtlInitUnicodeString((PUNICODE_STRING
)&ProcessName
, L
"Winlogon");
396 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
397 if (Status
== STATUS_PORT_CONNECTION_REFUSED
)
399 /* Add the 'SeTcbPrivilege' privilege and try again */
400 Status
= RtlAdjustPrivilege(SE_TCB_PRIVILEGE
, TRUE
, TRUE
, &Old
);
401 if (!NT_SUCCESS(Status
))
403 ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status
));
406 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
408 if (!NT_SUCCESS(Status
))
410 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status
));
414 RtlInitUnicodeString((PUNICODE_STRING
)&PackageName
, MICROSOFT_KERBEROS_NAME_W
);
415 Status
= LsaLookupAuthenticationPackage(LsaHandle
, &PackageName
, &AuthenticationPackage
);
416 if (!NT_SUCCESS(Status
))
418 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status
));
419 LsaDeregisterLogonProcess(LsaHandle
);
424 /* Create a hidden window to get SAS notifications */
425 if (!InitializeSAS(WLSession
))
427 ERR("WL: Failed to initialize SAS\n");
431 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
432 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);
434 /* Display logged out screen */
435 WLSession
->LogonStatus
= WKSTA_IS_LOGGED_OFF
;
436 RemoveStatusMessage(WLSession
);
438 /* Check for pending setup */
439 if (GetSetupType() != 0)
441 TRACE("WL: Setup mode detected\n");
443 /* Run setup and reboot when done */
444 SwitchDesktop(WLSession
->ApplicationDesktop
);
448 PostMessageW(WLSession
->SASWindow
, WLX_WM_SAS
, WLX_SAS_TYPE_TIMEOUT
, 0);
450 /* Play logon sound */
451 hThread
= CreateThread(NULL
, 0, PlayLogonSoundThread
, NULL
, 0, NULL
);
454 CloseHandle(hThread
);
457 /* Tell kernel that CurrentControlSet is good (needed
458 * to support Last good known configuration boot) */
459 NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED
| 1);
461 /* Message loop for the SAS window */
462 while (GetMessageW(&Msg
, WLSession
->SASWindow
, 0, 0))
464 TranslateMessage(&Msg
);
465 DispatchMessageW(&Msg
);
468 /* We never go there */