call the correct event on system boot
[reactos.git] / reactos / base / system / winlogon / winlogon.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winlogon
4 * FILE: services/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 #include "winlogon.h"
13
14 //#define YDEBUG
15 #include <wine/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 HINSTANCE hAppInstance;
20 PWLSESSION WLSession = NULL;
21
22 /* FUNCTIONS *****************************************************************/
23
24 static BOOL
25 StartServicesManager(VOID)
26 {
27 HANDLE ServicesInitEvent = NULL;
28 STARTUPINFOW StartupInfo;
29 PROCESS_INFORMATION ProcessInformation;
30 DWORD Count;
31 LPCWSTR ServiceString = L"services.exe";
32 BOOL res;
33
34 /* Start the service control manager (services.exe) */
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;
42
43 TRACE("WL: Creating new process - %S\n", ServiceString);
44
45 res = CreateProcessW(
46 ServiceString,
47 NULL,
48 NULL,
49 NULL,
50 FALSE,
51 DETACHED_PROCESS,
52 NULL,
53 NULL,
54 &StartupInfo,
55 &ProcessInformation);
56 if (!res)
57 {
58 ERR("WL: Failed to execute services (error %lu)\n", GetLastError());
59 return FALSE;
60 }
61
62 /* Wait for event creation (by SCM) for max. 20 seconds */
63 for (Count = 0; Count < 20; Count++)
64 {
65 Sleep(1000);
66
67 TRACE("WL: Attempting to open event \"SvcctrlStartEvent_A3752DX\"\n");
68 ServicesInitEvent = OpenEventW(
69 SYNCHRONIZE,
70 FALSE,
71 L"SvcctrlStartEvent_A3752DX");
72 if (ServicesInitEvent)
73 break;
74 }
75
76 if (!ServicesInitEvent)
77 {
78 ERR("WL: Failed to open event \"SvcctrlStartEvent_A3752DX\"\n");
79 return FALSE;
80 }
81
82 /* Wait for event signalization */
83 WaitForSingleObject(ServicesInitEvent, INFINITE);
84 CloseHandle(ServicesInitEvent);
85 TRACE("WL: StartServicesManager() done.\n");
86
87 return TRUE;
88 }
89
90 static BOOL
91 StartCustomService(
92 IN LPCWSTR ServiceName)
93 {
94 SC_HANDLE hSCManager = NULL;
95 SC_HANDLE hService = NULL;
96 BOOL ret = FALSE;
97
98 hSCManager = OpenSCManager(NULL, NULL, 0);
99 if (!hSCManager)
100 {
101 ERR("WL: Failed to OpenSCManager\n");
102 goto cleanup;
103 }
104
105 hService = OpenServiceW(hSCManager, ServiceName, SERVICE_START);
106 if (!hService)
107 {
108 ERR("WL: Failed to open the service\n");
109 goto cleanup;
110 }
111 if (!StartServiceW(hService, 0, NULL))
112 {
113 ERR("WL: Failed to start the service\n");
114 goto cleanup;
115 }
116
117 ret = TRUE;
118
119 cleanup:
120 if (hService)
121 CloseServiceHandle(hService);
122 if (hSCManager)
123 CloseServiceHandle(hSCManager);
124 return ret;
125 }
126
127 static BOOL
128 StartLsass(VOID)
129 {
130 HANDLE LsassInitEvent;
131
132 LsassInitEvent = CreateEventW(
133 NULL,
134 TRUE,
135 FALSE,
136 L"Global\\SECURITY_SERVICES_STARTED");
137 if (!LsassInitEvent)
138 {
139 ERR("WL: Failed to create lsass notification event (error %lu)\n", GetLastError());
140 return FALSE;
141 }
142
143 /* Start the local security authority subsystem (Netlogon service) */
144 if (!StartCustomService(L"Netlogon"))
145 {
146 ERR("WL: Failed to start NetLogon service (error %lu)\n", GetLastError());
147 return FALSE;
148 }
149
150 WaitForSingleObject(LsassInitEvent, INFINITE);
151 CloseHandle(LsassInitEvent);
152
153 return TRUE;
154 }
155
156 #if 0
157 static BOOL
158 OpenRegistryKey(
159 OUT HKEY *WinLogonKey)
160 {
161 return ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
162 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
163 0,
164 KEY_QUERY_VALUE,
165 WinLogonKey);
166 }
167 #endif
168
169 #if 0
170 static BOOL
171 StartProcess(
172 IN PWCHAR ValueName)
173 {
174 BOOL StartIt;
175 HKEY WinLogonKey;
176 DWORD Type;
177 DWORD Size;
178 DWORD StartValue;
179
180 StartIt = TRUE;
181 if (OpenRegistryKey(&WinLogonKey))
182 {
183 Size = sizeof(DWORD);
184 if (ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
185 ValueName,
186 NULL,
187 &Type,
188 (LPBYTE) &StartValue,
189 &Size))
190 {
191 if (REG_DWORD == Type)
192 {
193 StartIt = (0 != StartValue);
194 }
195 }
196 RegCloseKey(WinLogonKey);
197 }
198
199 return StartIt;
200 }
201 #endif
202
203 /*
204 static BOOL RestartShell(
205 IN OUT PWLSESSION Session)
206 {
207 HKEY WinLogonKey;
208 DWORD Type, Size, Value;
209
210 if(OpenRegistryKey(&WinLogonKey))
211 {
212 Size = sizeof(DWORD);
213 if(ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
214 L"AutoRestartShell",
215 NULL,
216 &Type,
217 (LPBYTE)&Value,
218 &Size))
219 {
220 if(Type == REG_DWORD)
221 {
222 RegCloseKey(WinLogonKey);
223 return (Value != 0);
224 }
225 }
226 RegCloseKey(WinLogonKey);
227 }
228 return FALSE;
229 }
230 */
231
232 #if 0
233 static PWCHAR
234 GetUserInit(
235 OUT WCHAR *CommandLine,
236 IN DWORD BufferLength)
237 {
238 HKEY WinLogonKey;
239 BOOL GotCommandLine;
240 DWORD Type;
241 DWORD Size;
242 WCHAR Shell[_MAX_PATH];
243
244 GotCommandLine = FALSE;
245 if (OpenRegistryKey(&WinLogonKey))
246 {
247 Size = MAX_PATH;
248 if (ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
249 L"UserInit",
250 NULL,
251 &Type,
252 (LPBYTE) Shell,
253 &Size))
254 {
255 if (REG_EXPAND_SZ == Type)
256 {
257 ExpandEnvironmentStrings(Shell, CommandLine, _MAX_PATH);
258 GotCommandLine = TRUE;
259 }
260 else if (REG_SZ == Type)
261 {
262 wcscpy(CommandLine, Shell);
263 GotCommandLine = TRUE;
264 }
265 }
266 RegCloseKey(WinLogonKey);
267 }
268
269 if (! GotCommandLine)
270 {
271 GetSystemDirectory(CommandLine, MAX_PATH - 15);
272 wcscat(CommandLine, L"\\userinit.exe");
273 }
274
275 return CommandLine;
276 }
277
278 #endif
279
280 BOOL
281 DisplayStatusMessage(
282 IN PWLSESSION Session,
283 IN HDESK hDesktop,
284 IN UINT ResourceId)
285 {
286 WCHAR StatusMsg[MAX_PATH];
287
288 if (Session->Gina.Version < WLX_VERSION_1_3)
289 return TRUE;
290
291 if (Session->SuppressStatus)
292 return TRUE;
293
294 if (LoadStringW(hAppInstance, ResourceId, StatusMsg, MAX_PATH) == 0)
295 return FALSE;
296
297 return Session->Gina.Functions.WlxDisplayStatusMessage(Session->Gina.Context, hDesktop, 0, NULL, StatusMsg);
298 }
299
300 BOOL
301 RemoveStatusMessage(
302 IN PWLSESSION Session)
303 {
304 if (Session->Gina.Version < WLX_VERSION_1_3)
305 return TRUE;
306
307 return Session->Gina.Functions.WlxRemoveStatusMessage(Session->Gina.Context);
308 }
309
310 static BOOL CALLBACK
311 GinaLoadFailedWindowProc(
312 IN HWND hwndDlg,
313 IN UINT uMsg,
314 IN WPARAM wParam,
315 IN LPARAM lParam)
316 {
317 switch (uMsg)
318 {
319 case WM_COMMAND:
320 {
321 switch (LOWORD(wParam))
322 {
323 case IDOK:
324 EndDialog(hwndDlg, IDOK);
325 return TRUE;
326 }
327 break;
328 }
329 case WM_INITDIALOG:
330 {
331 int len;
332 WCHAR templateText[MAX_PATH], text[MAX_PATH];
333
334 len = GetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, templateText, MAX_PATH);
335 if (len)
336 {
337 wsprintfW(text, templateText, (LPWSTR)lParam);
338 SetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, text);
339 }
340 SetFocus(GetDlgItem(hwndDlg, IDOK));
341 return TRUE;
342 }
343 case WM_CLOSE:
344 {
345 EndDialog(hwndDlg, IDCANCEL);
346 return TRUE;
347 }
348 }
349
350 return FALSE;
351 }
352
353 int WINAPI
354 WinMain(
355 IN HINSTANCE hInstance,
356 IN HINSTANCE hPrevInstance,
357 IN LPSTR lpCmdLine,
358 IN int nShowCmd)
359 {
360 #if 0
361 LSA_STRING ProcessName, PackageName;
362 HANDLE LsaHandle;
363 LSA_OPERATIONAL_MODE Mode;
364 BOOLEAN Old;
365 ULONG AuthenticationPackage;
366 NTSTATUS Status;
367 #endif
368 ULONG HardErrorResponse;
369 MSG Msg;
370
371 UNREFERENCED_PARAMETER(hPrevInstance);
372 UNREFERENCED_PARAMETER(lpCmdLine);
373 UNREFERENCED_PARAMETER(nShowCmd);
374
375 hAppInstance = hInstance;
376
377 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE))
378 {
379 ERR("WL: Could not register logon process\n");
380 HandleShutdown(NULL, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
381 NtShutdownSystem(ShutdownNoReboot);
382 ExitProcess(0);
383 }
384
385 WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION));
386 if (!WLSession)
387 {
388 ERR("WL: Could not allocate memory for winlogon instance\n");
389 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
390 ExitProcess(1);
391 }
392 ZeroMemory(WLSession, sizeof(WLSESSION));
393 WLSession->DialogTimeout = 120; /* 2 minutes */
394
395 if (!CreateWindowStationAndDesktops(WLSession))
396 {
397 ERR("WL: Could not create window station and desktops\n");
398 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
399 ExitProcess(1);
400 }
401 LockWorkstation(WLSession);
402
403 if (!StartServicesManager())
404 {
405 ERR("WL: Could not start services.exe\n");
406 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
407 ExitProcess(1);
408 }
409
410 /* Check for pending setup */
411 if (GetSetupType() != 0)
412 {
413 TRACE("WL: Setup mode detected\n");
414
415 /* Set locale */
416 SetDefaultLanguage(FALSE);
417
418 /* Run setup and reboot when done */
419 SwitchDesktop(WLSession->ApplicationDesktop);
420 RunSetup();
421
422 HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT);
423 ExitProcess(0);
424 }
425
426 if (!StartLsass())
427 {
428 DPRINT1("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
429 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, OptionOk, &HardErrorResponse);
430 ExitProcess(1);
431 }
432
433 /* Load and initialize gina */
434 if (!GinaInit(WLSession))
435 {
436 ERR("WL: Failed to initialize Gina\n");
437 DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"");
438 HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT);
439 ExitProcess(1);
440 }
441
442 DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP);
443
444 #if 0
445 /* Connect to NetLogon service (lsass.exe) */
446 /* Real winlogon uses "Winlogon" */
447 RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon");
448 Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
449 if (Status == STATUS_PORT_CONNECTION_REFUSED)
450 {
451 /* Add the 'SeTcbPrivilege' privilege and try again */
452 Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old);
453 if (!NT_SUCCESS(Status))
454 {
455 ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status));
456 return 1;
457 }
458 Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
459 }
460 if (!NT_SUCCESS(Status))
461 {
462 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status));
463 return 1;
464 }
465
466 RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W);
467 Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage);
468 if (!NT_SUCCESS(Status))
469 {
470 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status));
471 LsaDeregisterLogonProcess(LsaHandle);
472 return 1;
473 }
474 #endif
475
476 /* Create a hidden window to get SAS notifications */
477 if (!InitializeSAS(WLSession))
478 {
479 ERR("WL: Failed to initialize SAS\n");
480 ExitProcess(2);
481 }
482
483 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
484 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);
485
486 /* Display logged out screen */
487 WLSession->LogonStatus = WKSTA_IS_LOGGED_OFF;
488 RemoveStatusMessage(WLSession);
489 PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_TIMEOUT, 0);
490
491 /* Message loop for the SAS window */
492 while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0))
493 {
494 TranslateMessage(&Msg);
495 DispatchMessageW(&Msg);
496 }
497
498 /* We never go there */
499
500 return 0;
501 }