2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winlogon
4 * FILE: services/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 /* GLOBALS ******************************************************************/
19 HINSTANCE hAppInstance
;
20 PWLSESSION WLSession
= NULL
;
22 /* FUNCTIONS *****************************************************************/
24 static INT_PTR CALLBACK
25 ShutdownComputerWindowProc(
35 switch (LOWORD(wParam
))
37 case IDC_BTNSHTDOWNCOMPUTER
:
38 EndDialog(hwndDlg
, IDC_BTNSHTDOWNCOMPUTER
);
45 RemoveMenu(GetSystemMenu(hwndDlg
, FALSE
), SC_CLOSE
, MF_BYCOMMAND
);
46 SetFocus(GetDlgItem(hwndDlg
, IDC_BTNSHTDOWNCOMPUTER
));
50 return DefWindowProc(hwndDlg
, uMsg
, wParam
, lParam
);
54 StartServicesManager(void)
56 HANDLE ServicesInitEvent
;
58 STARTUPINFO StartupInfo
;
59 PROCESS_INFORMATION ProcessInformation
;
61 WCHAR ServiceString
[] = L
"services.exe";
63 /* Start the service control manager (services.exe) */
65 StartupInfo
.cb
= sizeof(StartupInfo
);
66 StartupInfo
.lpReserved
= NULL
;
67 StartupInfo
.lpDesktop
= NULL
;
68 StartupInfo
.lpTitle
= NULL
;
69 StartupInfo
.dwFlags
= 0;
70 StartupInfo
.cbReserved2
= 0;
71 StartupInfo
.lpReserved2
= 0;
74 DPRINT1(L
"WL: Creating new process - \"services.exe\".\n");
77 Result
= CreateProcess(NULL
,
89 DPRINT1("WL: Failed to execute services\n");
93 /* wait for event creation (by SCM) for max. 20 seconds */
94 for (Count
= 0; Count
< 20; Count
++)
98 DPRINT("WL: Attempting to open event \"SvcctrlStartEvent_A3725DX\"\n");
99 ServicesInitEvent
= OpenEvent(EVENT_ALL_ACCESS
, //SYNCHRONIZE,
101 L
"SvcctrlStartEvent_A3725DX");
102 if (ServicesInitEvent
!= NULL
)
108 if (ServicesInitEvent
== NULL
)
110 DPRINT1("WL: Failed to open event \"SvcctrlStartEvent_A3725DX\"\n");
114 /* wait for event signalization */
115 DPRINT("WL: Waiting forever on event handle: %x\n", ServicesInitEvent
);
116 WaitForSingleObject(ServicesInitEvent
, INFINITE
);
117 DPRINT("WL: Closing event object \"SvcctrlStartEvent_A3725DX\"\n");
118 CloseHandle(ServicesInitEvent
);
119 DPRINT("WL: StartServicesManager() Done.\n");
126 IN LPCWSTR ServiceName
)
128 SC_HANDLE hSCManager
= NULL
;
129 SC_HANDLE hService
= NULL
;
132 hSCManager
= OpenSCManager(NULL
, NULL
, 0);
136 hService
= OpenService(hSCManager
, ServiceName
, SERVICE_START
);
140 if (!StartService(hService
, 0, NULL
))
148 CloseServiceHandle(hService
);
150 CloseServiceHandle(hSCManager
);
157 HANDLE LsassInitEvent
;
159 LsassInitEvent
= CreateEvent(
163 L
"Global\\SECURITY_SERVICES_STARTED");
166 ERR("WL: Failed to create lsass notification event (error %lu)\n", GetLastError());
170 /* Start the local security authority subsystem (Netlogon service) */
171 if (!StartCustomService(L
"Netlogon"))
173 ERR("WL: Failed to start NetLogon service (error %lu)\n", GetLastError());
178 WaitForSingleObject(LsassInitEvent
, INFINITE
);
180 CloseHandle(LsassInitEvent
);
187 OUT HKEY
*WinLogonKey
)
189 return ERROR_SUCCESS
== RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
190 L
"SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\WinLogon",
208 if (OpenRegistryKey(&WinLogonKey
))
210 Size
= sizeof(DWORD
);
211 if (ERROR_SUCCESS
== RegQueryValueEx(WinLogonKey
,
215 (LPBYTE
) &StartValue
,
218 if (REG_DWORD
== Type
)
220 StartIt
= (0 != StartValue
);
223 RegCloseKey(WinLogonKey
);
231 static BOOL RestartShell(void)
234 DWORD Type, Size, Value;
236 if(OpenRegistryKey(&WinLogonKey))
238 Size = sizeof(DWORD);
239 if(ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
246 if(Type == REG_DWORD)
248 RegCloseKey(WinLogonKey);
252 RegCloseKey(WinLogonKey);
260 OUT WCHAR
*CommandLine
,
261 IN DWORD BufferLength
)
267 WCHAR Shell
[_MAX_PATH
];
269 GotCommandLine
= FALSE
;
270 if (OpenRegistryKey(&WinLogonKey
))
273 if (ERROR_SUCCESS
== RegQueryValueEx(WinLogonKey
,
280 if (REG_EXPAND_SZ
== Type
)
282 ExpandEnvironmentStrings(Shell
, CommandLine
, _MAX_PATH
);
283 GotCommandLine
= TRUE
;
285 else if (REG_SZ
== Type
)
287 wcscpy(CommandLine
, Shell
);
288 GotCommandLine
= TRUE
;
291 RegCloseKey(WinLogonKey
);
294 if (! GotCommandLine
)
296 GetSystemDirectory(CommandLine
, MAX_PATH
- 15);
297 wcscat(CommandLine
, L
"\\userinit.exe");
306 IN PWLSESSION WLSession
,
307 IN PWLX_MPR_NOTIFY_INFO pMprNotifyInfo
)
309 PROCESS_INFORMATION ProcessInformation
;
310 STARTUPINFO StartupInfo
;
311 WCHAR CommandLine
[MAX_PATH
];
312 WCHAR CurrentDirectory
[MAX_PATH
];
313 PROFILEINFOW ProfileInfo
;
315 LPVOID lpEnvironment
= NULL
;
319 SwitchDesktop(WLSession
->ApplicationDesktop
);
321 /* Load the user profile */
322 ProfileInfo
.dwSize
= sizeof(PROFILEINFOW
);
323 ProfileInfo
.dwFlags
= 0;
324 ProfileInfo
.lpUserName
= pMprNotifyInfo
->pszUserName
;
325 ProfileInfo
.lpProfilePath
= NULL
;
326 ProfileInfo
.lpDefaultPath
= NULL
;
327 ProfileInfo
.lpServerName
= NULL
;
328 ProfileInfo
.lpPolicyPath
= NULL
;
329 ProfileInfo
.hProfile
= NULL
;
331 if (!LoadUserProfileW (WLSession
->UserToken
,
334 DPRINT1 ("WL: LoadUserProfileW() failed\n");
335 CloseHandle (WLSession
->UserToken
);
336 RtlDestroyEnvironment (lpEnvironment
);
340 if (!CreateEnvironmentBlock (&lpEnvironment
,
341 WLSession
->UserToken
,
344 DPRINT1("WL: CreateEnvironmentBlock() failed\n");
348 if (ImpersonateLoggedOnUser(WLSession
->UserToken
))
350 UpdatePerUserSystemParameters(0, TRUE
);
354 GetWindowsDirectoryW (CurrentDirectory
, MAX_PATH
);
356 StartupInfo
.cb
= sizeof(StartupInfo
);
357 StartupInfo
.lpReserved
= NULL
;
358 StartupInfo
.lpDesktop
= NULL
;
359 StartupInfo
.lpTitle
= NULL
;
360 StartupInfo
.dwFlags
= 0;
361 StartupInfo
.cbReserved2
= 0;
362 StartupInfo
.lpReserved2
= 0;
365 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
367 Result
= CreateProcessAsUserW(
368 WLSession
->UserToken
,
370 GetUserInit (CommandLine
, MAX_PATH
),
374 CREATE_UNICODE_ENVIRONMENT
,
378 &ProcessInformation
);
381 DPRINT1("WL: Failed to execute user shell %ws\n", CommandLine
);
382 if (ImpersonateLoggedOnUser(WLSession
->UserToken
))
384 UpdatePerUserSystemParameters(0, FALSE
);
387 UnloadUserProfile (WLSession
->UserToken
,
388 ProfileInfo
.hProfile
);
389 CloseHandle (WLSession
->UserToken
);
390 DestroyEnvironmentBlock (lpEnvironment
);
393 /*WLSession->MsGina.Functions.WlxActivateUserShell(WLSession->MsGina.Context,
398 while (WaitForSingleObject (ProcessInformation
.hProcess
, 100) != WAIT_OBJECT_0
)
400 if (PeekMessage(&Msg
, WLSession
->SASWindow
, 0, 0, PM_REMOVE
))
402 TranslateMessage(&Msg
);
403 DispatchMessage(&Msg
);
407 CloseHandle (ProcessInformation
.hProcess
);
408 CloseHandle (ProcessInformation
.hThread
);
410 if (ImpersonateLoggedOnUser(WLSession
->UserToken
))
412 UpdatePerUserSystemParameters(0, FALSE
);
416 /* Unload user profile */
417 UnloadUserProfile (WLSession
->UserToken
,
418 ProfileInfo
.hProfile
);
420 CloseHandle (WLSession
->UserToken
);
422 RtlDestroyEnvironment (lpEnvironment
);
428 DisplayStatusMessage(
429 IN PWLSESSION Session
,
433 WCHAR StatusMsg
[MAX_PATH
];
435 if (Session
->SuppressStatus
)
438 if (LoadString(hAppInstance
, ResourceId
, StatusMsg
, MAX_PATH
) == 0)
441 return Session
->MsGina
.Functions
.WlxDisplayStatusMessage(Session
->MsGina
.Context
, hDesktop
, 0, NULL
, StatusMsg
);
448 /*WCHAR StatusMsg[256];
450 LoadString(hAppInstance, IDS_REACTOSISSTARTINGUP, StatusMsg, 256 * sizeof(WCHAR));
451 DisplayStatusMessage(WLSession, WLSession->ApplicationDesktop, 0, NULL, StatusMsg);*/
453 /* start system processes (services.exe & lsass.exe) */
454 if(StartProcess(L
"StartServices"))
456 if(!StartServicesManager())
458 DPRINT1("WL: Failed to start Services (0x%X)\n", GetLastError());
463 DPRINT1("WL: StartProcess() failed!\n");
473 IN OUT PWLSESSION Session
)
475 DWORD WlxAction
, Options
;
476 WLX_MPR_NOTIFY_INFO MprNotifyInfo
;
477 PWLX_PROFILE_V2_0 Profile
;
478 PSID LogonSid
= NULL
;
481 /* FIXME - Create a Logon Sid
482 if(!(LogonSid = CreateUserLogonSid(NULL)))
484 return WLX_SAS_ACTION_NONE;
489 WlxAction
= Session
->MsGina
.Functions
.WlxLoggedOutSAS(Session
->MsGina
.Context
,
498 if (WlxAction
== WLX_SAS_ACTION_LOGON
)
500 Session
->UserToken
= Token
;
501 if (!DoBrokenLogonUser(Session
, &MprNotifyInfo
))
502 WlxAction
= WLX_SAS_ACTION_NONE
;
510 IN OUT PWLSESSION Session
)
512 //WCHAR StatusMsg[256];
513 //HANDLE hShutdownEvent;
516 Session
->LogonStatus
= WKSTA_IS_LOGGED_OFF
;
517 RemoveStatusMessage(Session
);
518 DispatchSAS(Session
, WLX_SAS_TYPE_TIMEOUT
);
520 /* Message loop for the SAS window */
521 while (GetMessage(&Msg
, WLSession
->SASWindow
, 0, 0))
523 TranslateMessage(&Msg
);
524 DispatchMessage(&Msg
);
527 /* Don't go there! */
530 /* FIXME - don't leave the loop when suspending the computer */
531 if(WLX_SUSPENDING(WlxAction
))
533 Session
->LogonStatus
= LOGON_NONE
;
534 WlxAction
= WLX_SAS_ACTION_NONE
;
535 /* don't leave the loop */
539 if(WLX_SHUTTINGDOWN(WlxAction
))
541 Session
->LogonStatus
= LOGON_SHUTDOWN
;
542 /* leave the loop here */
548 LoadString(hAppInstance, IDS_PREPARENETWORKCONNECTIONS, StatusMsg, 256 * sizeof(WCHAR));
549 MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
558 LoadString(hAppInstance, IDS_APPLYINGCOMPUTERSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
559 MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
568 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
569 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
570 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
575 LoadString(hAppInstance, IDS_LOADINGYOURPERSONALSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
576 MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
584 LoadString(hAppInstance, IDS_APPLYINGYOURPERSONALSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
585 MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
594 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
595 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
597 if(!MsGinaInst->Functions->WlxActivateUserShell(MsGinaInst->Context,
602 LoadString(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, 256 * sizeof(WCHAR));
603 MessageBox(0, StatusMsg, NULL, MB_ICONERROR);
604 SetEvent(hShutdownEvent);
608 WaitForSingleObject(hShutdownEvent, INFINITE);
609 CloseHandle(hShutdownEvent);
611 LoadString(hAppInstance, IDS_SAVEYOURSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
612 MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
621 MsGinaInst->Functions->WlxShutdown(MsGinaInst->Context, WLX_SAS_ACTION_SHUTDOWN);
623 LoadString(hAppInstance, IDS_REACTOSISSHUTTINGDOWN, StatusMsg, 256 * sizeof(WCHAR));
624 MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
633 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
634 MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
640 IN HINSTANCE hInstance
,
641 IN HINSTANCE hPrevInstance
,
646 LSA_STRING ProcessName
, PackageName
;
648 LSA_OPERATIONAL_MODE Mode
;
650 ULONG AuthenticationPackage
;
654 hAppInstance
= hInstance
;
656 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE
))
658 ERR("WL: Could not register logon process\n");
659 NtShutdownSystem(ShutdownNoReboot
);
664 WLSession
= (PWLSESSION
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WLSESSION
));
667 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, 0, 0, 0);
672 if (!CreateWindowStationAndDesktops(WLSession
))
674 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, 0, 0, 0);
679 /* Check for pending setup */
680 if (GetSetupType() != 0)
682 DPRINT("Winlogon: CheckForSetup() in setup mode\n");
684 /* Run setup and reboot when done */
685 SwitchDesktop(WLSession
->ApplicationDesktop
);
688 NtShutdownSystem(ShutdownReboot
);
693 /* Load and initialize gina */
694 if (!GinaInit(WLSession
))
696 ERR("WL: Failed to initialize Gina\n");
697 NtShutdownSystem(ShutdownNoReboot
);
702 DisplayStatusMessage(WLSession
, WLSession
->WinlogonDesktop
, IDS_REACTOSISSTARTINGUP
);
704 if (!StartServicesManager())
706 ERR("WL: Could not start services.exe\n");
707 NtShutdownSystem(ShutdownNoReboot
);
714 DPRINT1("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
719 /* Connect to NetLogon service (lsass.exe) */
720 /* Real winlogon uses "Winlogon" */
721 RtlInitUnicodeString((PUNICODE_STRING
)&ProcessName
, L
"Winlogon");
722 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
723 if (Status
== STATUS_PORT_CONNECTION_REFUSED
)
725 /* Add the 'SeTcbPrivilege' privilege and try again */
726 RtlAdjustPrivilege(SE_TCB_PRIVILEGE
, TRUE
, TRUE
, &Old
);
727 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
729 if (!NT_SUCCESS(Status
))
731 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status
));
735 RtlInitUnicodeString((PUNICODE_STRING
)&PackageName
, MICROSOFT_KERBEROS_NAME_W
);
736 Status
= LsaLookupAuthenticationPackage(LsaHandle
, &PackageName
, &AuthenticationPackage
);
737 if (!NT_SUCCESS(Status
))
739 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status
));
740 LsaDeregisterLogonProcess(LsaHandle
);
745 /* Create a hidden window to get SAS notifications */
746 if (!InitializeSAS(WLSession
))
748 ERR("WL: Failed to initialize SAS\n");
754 SessionLoop(WLSession
);
756 /* FIXME - Flush disks and registry, ... */
758 if(WLSession
->LogonStatus
== 0)
760 /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */
761 switch(DialogBox(hInstance
, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER
), 0, ShutdownComputerWindowProc
))
763 case IDC_BTNSHTDOWNCOMPUTER
:
764 NtShutdownSystem(ShutdownReboot
);
767 NtShutdownSystem(ShutdownNoReboot
);
774 DPRINT1("WL: LogonStatus != LOGON_SHUTDOWN!!!\n");