merge trunk head (37902)
[reactos.git] / reactos / base / system / winlogon / winlogon.c
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 <wine/debug.h>
16
17 WINE_DEFAULT_DEBUG_CHANNEL(winlogon);
18
19 /* GLOBALS ******************************************************************/
20
21 HINSTANCE hAppInstance;
22 PWLSESSION WLSession = NULL;
23
24 /* FUNCTIONS *****************************************************************/
25
26 static BOOL
27 StartServicesManager(VOID)
28 {
29 HANDLE ServicesInitEvent = NULL;
30 STARTUPINFOW StartupInfo;
31 PROCESS_INFORMATION ProcessInformation;
32 DWORD Count;
33 LPCWSTR ServiceString = L"services.exe";
34 BOOL res;
35
36 /* Start the service control manager (services.exe) */
37 StartupInfo.cb = sizeof(StartupInfo);
38 StartupInfo.lpReserved = NULL;
39 StartupInfo.lpDesktop = NULL;
40 StartupInfo.lpTitle = NULL;
41 StartupInfo.dwFlags = 0;
42 StartupInfo.cbReserved2 = 0;
43 StartupInfo.lpReserved2 = 0;
44
45 TRACE("WL: Creating new process - %S\n", ServiceString);
46
47 res = CreateProcessW(
48 ServiceString,
49 NULL,
50 NULL,
51 NULL,
52 FALSE,
53 DETACHED_PROCESS,
54 NULL,
55 NULL,
56 &StartupInfo,
57 &ProcessInformation);
58 if (!res)
59 {
60 ERR("WL: Failed to execute services (error %lu)\n", GetLastError());
61 return FALSE;
62 }
63
64 /* Wait for event creation (by SCM) for max. 20 seconds */
65 for (Count = 0; Count < 20; Count++)
66 {
67 Sleep(1000);
68
69 TRACE("WL: Attempting to open event \"SvcctrlStartEvent_A3752DX\"\n");
70 ServicesInitEvent = OpenEventW(
71 SYNCHRONIZE,
72 FALSE,
73 L"SvcctrlStartEvent_A3752DX");
74 if (ServicesInitEvent)
75 break;
76 }
77
78 if (!ServicesInitEvent)
79 {
80 ERR("WL: Failed to open event \"SvcctrlStartEvent_A3752DX\"\n");
81 return FALSE;
82 }
83
84 /* Wait for event signalization */
85 WaitForSingleObject(ServicesInitEvent, INFINITE);
86 CloseHandle(ServicesInitEvent);
87 TRACE("WL: StartServicesManager() done.\n");
88
89 return TRUE;
90 }
91
92 static BOOL
93 StartCustomService(
94 IN LPCWSTR ServiceName)
95 {
96 SC_HANDLE hSCManager = NULL;
97 SC_HANDLE hService = NULL;
98 BOOL ret = FALSE;
99
100 hSCManager = OpenSCManager(NULL, NULL, 0);
101 if (!hSCManager)
102 {
103 ERR("WL: Failed to OpenSCManager\n");
104 goto cleanup;
105 }
106
107 hService = OpenServiceW(hSCManager, ServiceName, SERVICE_START);
108 if (!hService)
109 {
110 ERR("WL: Failed to open the service\n");
111 goto cleanup;
112 }
113 if (!StartServiceW(hService, 0, NULL))
114 {
115 ERR("WL: Failed to start the service\n");
116 goto cleanup;
117 }
118
119 ret = TRUE;
120
121 cleanup:
122 if (hService)
123 CloseServiceHandle(hService);
124 if (hSCManager)
125 CloseServiceHandle(hSCManager);
126 return ret;
127 }
128
129 static BOOL
130 StartLsass(VOID)
131 {
132 HANDLE LsassInitEvent;
133
134 LsassInitEvent = CreateEventW(
135 NULL,
136 TRUE,
137 FALSE,
138 L"Global\\SECURITY_SERVICES_STARTED");
139 if (!LsassInitEvent)
140 {
141 ERR("WL: Failed to create lsass notification event (error %lu)\n", GetLastError());
142 return FALSE;
143 }
144
145 /* Start the local security authority subsystem (Netlogon service) */
146 if (!StartCustomService(L"Netlogon"))
147 {
148 ERR("WL: Failed to start NetLogon service (error %lu)\n", GetLastError());
149 return FALSE;
150 }
151
152 WaitForSingleObject(LsassInitEvent, INFINITE);
153 CloseHandle(LsassInitEvent);
154
155 return TRUE;
156 }
157
158 BOOL
159 DisplayStatusMessage(
160 IN PWLSESSION Session,
161 IN HDESK hDesktop,
162 IN UINT ResourceId)
163 {
164 WCHAR StatusMsg[MAX_PATH];
165
166 if (Session->Gina.Version < WLX_VERSION_1_3)
167 return TRUE;
168
169 if (Session->SuppressStatus)
170 return TRUE;
171
172 if (LoadStringW(hAppInstance, ResourceId, StatusMsg, MAX_PATH) == 0)
173 return FALSE;
174
175 return Session->Gina.Functions.WlxDisplayStatusMessage(Session->Gina.Context, hDesktop, 0, NULL, StatusMsg);
176 }
177
178 BOOL
179 RemoveStatusMessage(
180 IN PWLSESSION Session)
181 {
182 if (Session->Gina.Version < WLX_VERSION_1_3)
183 return TRUE;
184
185 return Session->Gina.Functions.WlxRemoveStatusMessage(Session->Gina.Context);
186 }
187
188 static INT_PTR CALLBACK
189 GinaLoadFailedWindowProc(
190 IN HWND hwndDlg,
191 IN UINT uMsg,
192 IN WPARAM wParam,
193 IN LPARAM lParam)
194 {
195 switch (uMsg)
196 {
197 case WM_COMMAND:
198 {
199 switch (LOWORD(wParam))
200 {
201 case IDOK:
202 EndDialog(hwndDlg, IDOK);
203 return TRUE;
204 }
205 break;
206 }
207 case WM_INITDIALOG:
208 {
209 int len;
210 WCHAR templateText[MAX_PATH], text[MAX_PATH];
211
212 len = GetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, templateText, MAX_PATH);
213 if (len)
214 {
215 wsprintfW(text, templateText, (LPWSTR)lParam);
216 SetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, text);
217 }
218 SetFocus(GetDlgItem(hwndDlg, IDOK));
219 return TRUE;
220 }
221 case WM_CLOSE:
222 {
223 EndDialog(hwndDlg, IDCANCEL);
224 return TRUE;
225 }
226 }
227
228 return FALSE;
229 }
230
231 int WINAPI
232 WinMain(
233 IN HINSTANCE hInstance,
234 IN HINSTANCE hPrevInstance,
235 IN LPSTR lpCmdLine,
236 IN int nShowCmd)
237 {
238 #if 0
239 LSA_STRING ProcessName, PackageName;
240 HANDLE LsaHandle;
241 LSA_OPERATIONAL_MODE Mode;
242 BOOLEAN Old;
243 ULONG AuthenticationPackage;
244 NTSTATUS Status;
245 #endif
246 ULONG HardErrorResponse;
247 MSG Msg;
248
249 UNREFERENCED_PARAMETER(hPrevInstance);
250 UNREFERENCED_PARAMETER(lpCmdLine);
251 UNREFERENCED_PARAMETER(nShowCmd);
252
253 hAppInstance = hInstance;
254
255 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE))
256 {
257 ERR("WL: Could not register logon process\n");
258 HandleShutdown(NULL, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
259 NtShutdownSystem(ShutdownNoReboot);
260 ExitProcess(0);
261 }
262
263 WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION));
264 if (!WLSession)
265 {
266 ERR("WL: Could not allocate memory for winlogon instance\n");
267 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
268 ExitProcess(1);
269 }
270 ZeroMemory(WLSession, sizeof(WLSESSION));
271 WLSession->DialogTimeout = 120; /* 2 minutes */
272
273 if (!CreateWindowStationAndDesktops(WLSession))
274 {
275 ERR("WL: Could not create window station and desktops\n");
276 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
277 ExitProcess(1);
278 }
279 LockWorkstation(WLSession);
280
281 if (!StartServicesManager())
282 {
283 ERR("WL: Could not start services.exe\n");
284 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
285 ExitProcess(1);
286 }
287
288 if (!StartLsass())
289 {
290 ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
291 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, OptionOk, &HardErrorResponse);
292 ExitProcess(1);
293 }
294
295 /* Load and initialize gina */
296 if (!GinaInit(WLSession))
297 {
298 ERR("WL: Failed to initialize Gina\n");
299 DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"");
300 HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT);
301 ExitProcess(1);
302 }
303
304 DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP);
305
306 #if 0
307 /* Connect to NetLogon service (lsass.exe) */
308 /* Real winlogon uses "Winlogon" */
309 RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon");
310 Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
311 if (Status == STATUS_PORT_CONNECTION_REFUSED)
312 {
313 /* Add the 'SeTcbPrivilege' privilege and try again */
314 Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old);
315 if (!NT_SUCCESS(Status))
316 {
317 ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status));
318 return 1;
319 }
320 Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
321 }
322 if (!NT_SUCCESS(Status))
323 {
324 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status));
325 return 1;
326 }
327
328 RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W);
329 Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage);
330 if (!NT_SUCCESS(Status))
331 {
332 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status));
333 LsaDeregisterLogonProcess(LsaHandle);
334 return 1;
335 }
336 #endif
337
338 /* Create a hidden window to get SAS notifications */
339 if (!InitializeSAS(WLSession))
340 {
341 ERR("WL: Failed to initialize SAS\n");
342 ExitProcess(2);
343 }
344
345 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
346 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);
347
348 /* Display logged out screen */
349 WLSession->LogonStatus = WKSTA_IS_LOGGED_OFF;
350 RemoveStatusMessage(WLSession);
351
352 /* Check for pending setup */
353 if (GetSetupType() != 0)
354 {
355 TRACE("WL: Setup mode detected\n");
356
357 /* Run setup and reboot when done */
358 SwitchDesktop(WLSession->ApplicationDesktop);
359 RunSetup();
360 }
361 else
362 PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_TIMEOUT, 0);
363
364 /* Tell kernel that CurrentControlSet is good (needed
365 * to support Last good known configuration boot) */
366 NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED);
367
368 /* Message loop for the SAS window */
369 while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0))
370 {
371 TranslateMessage(&Msg);
372 DispatchMessageW(&Msg);
373 }
374
375 /* We never go there */
376
377 return 0;
378 }