Taken from GvGs blog on login and shutdown prcoesses.
Currently (Reactos 0.2.4 and lower) logout and shutdown isn't handled gracefully. User processes are not informed of the pending shutdown, only the kernel is properly shutdown. This needs to be rectified.
The collective minds of ros-kernel describe the logout/shutdown process as follows:
- App (usually explorer) calls ExitWindowsEx()
- ExitWindowsEx() sends a message to CSRSS
- CSRSS impersonates the caller and sends a message to a hidden WinLogon window
- WinLogon checks if the caller has the required privileges
- WinLogon enters pending log-out state
- WinLogon impersonates the interactive user and calls ExitWindowsEx() again,
passing some special internal flags
- CSRSS loops over all processes of the interactive user (sorted by their
SetProcessShutdownParameters() level), sending WM_QUERYENDSESSION and WM_ENDSESSION messages to its top-level windows. If the messages aren't processed within the timeout period (registry key HKCU\Control Panel\Desktop\HungAppTimeout) CSRSS will put up a dialog box asking if the process should be terminated. Using the registry key HKCU\Control Panel\Desktop\AutoEndTask you can specify that the dialog box shouldn't be shown and CSRSS should just terminate the thread. If the the WM_ENDSESSION message is processed but the thread doesn't terminate within the timeout specified by HKCU\Control Panel\Desktop\WaitToKillAppTimeout CSRSS will terminate the thread. When all the top-level windows have been destroyed CSRSS will terminate the process. If the process is a console process, CSRSS will send a CTRL_LOGOFF_EVENT to the console control handler on logoff. No event is sent on shutdown. If the handler doesn't respond in time the same activities as for GUI apps (i.e. display dialog box etc) take place. This also happens if the handler returns TRUE.
- This ends the processing for the first ExitWindowsEx() call from WinLogon.
Execution continues in WinLogon, which calls ExitWindowsEx() again to terminate COM processes in the interactive user's session.
- WinLogon stops impersonating the interactive user (whos processes are
all dead by now). and enters logged-out state
- If the ExitWindowsEx() request was for a logoff, WinLogon sends a SAS
event (to display the "press ctrl+alt+del") to the GINA. WinLogon then waits for the GINA to send a SAS event to login.
- If the ExitWindowsEx() request was for shutdown/restart, WinLogon calls
ExitWindowsEx() again in the system process context.
- CSRSS goes through the motions of sending WM_QUERYENDSESSION/WM_ENDSESSION
to GUI processes running in the system process context but won't display dialog boxes or kill threads/processes. Same for console processes, using the CTRL_SHUTDOWN_EVENT. The Service Control Manager is one of these console processes and has a special timeout value WaitToKillServiceTimeout.
- WinLogon issues a "InitiateSystemShutdown" request to the SM (SMSS API # 1)
- the SM propagates the shutdown request to every environment subsystem it
started since bootstrap time (still active ones, of course)
- each environment subsystem, on shutdown request, releases every resource
it aquired during its life (processes, memory etc), then dies
- when every environment subsystem has gone to bed, the SM actually initiates
the kernel and executive shutdown by calling NtShutdownSystem.
Although this is a pretty long list, I thought it wouldn't take long to implement. Boy, was I wrong :-) It's not really difficult, but it does use some stuff which isn't used very often by other parts of the system and which contained some buggy or unimplemented functions. On the bright side, I did learn a lot about security tokens, logon sessions etc. There are many details to work out, mostly by writing small test apps on MS Windows (Q: if you have an app with more than one top-level window, does each window get WM_QUERYENDSESSION notification? A: yes. Q: Are the timeouts reset for each notification or is there one big timeout for the process as a whole? A: one big timeout).
So, where are we at this moment (end of August 2004)? Well, the first few steps are implemented (basically notifying Winlogon about the end session request). I'm working on the notification of GUI applications right now, that's almost finished (it already puts up the "End Program Now?" dialog box). Notification of console apps shouldn't be that hard because of code reuse. Process termination is easy (just call TerminateProcess()...). I'm not sure about the next step (terminating COM processes running in the interactive user's session). How do I recognize those processes? I'll probably chicken out of this one for now and just put in a FIXME, since we don't have any COM processes running at this point anyway... I estimate it will take another month or so to finish this.
For the future, I want to do some work on winlogon, since it is rather messy at the moment to put it nicely. One of the improvements of ReactOS over Windows is that we have the capability to start up in console mode. Only when a GUI app is started will the screen switch to graphics mode. I'd like to consolidate this by introducing a "/CONSOLE" boot switch. When this switch is not present on the boot line, Winlogon will load the program specified by the "Shell" registry value, normally this will be (ROS) explorer, causing the screen to switch to graphics mode. With the boot switch present, Winlogon will load the program specified by the "ConsoleShell" registry value (to be added), which normally will be cmd.exe running in "blue screen" mode.
The same boot switch can also be used to prompt for login name and password. Our GINA (Graphical Identification and Authentication, the component which is responsible for the winlogon user interface) dll can check for the presence of the switch and present either a console-mode login prompt or a GUI prompt. Of course, since we don't have any proper security anyway, this will also be a good time to implement auto-login (using the "DefaultUserName" registry value), as I don't want to type a (mostly useless at this moment) username/password every time I boot ReactOS for testing.