xref: /reactos/base/system/winlogon/sas.c (revision 1dfba2a6)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS Winlogon
4c2c66affSColin Finck  * FILE:            base/system/winlogon/sas.c
5c2c66affSColin Finck  * PURPOSE:         Secure Attention Sequence
6c2c66affSColin Finck  * PROGRAMMERS:     Thomas Weidenmueller (w3seek@users.sourceforge.net)
79d48f26dSThamatip Chitpong  *                  Hervé Poussineau (hpoussin@reactos.org)
85f033392SArnav Bhatt  *                  Arnav Bhatt (arnavbhatt288@gmail.com)
9c2c66affSColin Finck  * UPDATE HISTORY:
10c2c66affSColin Finck  *                  Created 28/03/2004
11c2c66affSColin Finck  */
12c2c66affSColin Finck 
13c2c66affSColin Finck /* INCLUDES *****************************************************************/
14c2c66affSColin Finck 
15c2c66affSColin Finck #include "winlogon.h"
16c2c66affSColin Finck 
17c2c66affSColin Finck #define WIN32_LEAN_AND_MEAN
18c2c66affSColin Finck #include <aclapi.h>
19c2c66affSColin Finck #include <mmsystem.h>
20c2c66affSColin Finck #include <userenv.h>
21c2c66affSColin Finck #include <ndk/setypes.h>
22c2c66affSColin Finck #include <ndk/sefuncs.h>
23c2c66affSColin Finck 
24c2c66affSColin Finck /* GLOBALS ******************************************************************/
25c2c66affSColin Finck 
26c2c66affSColin Finck #define WINLOGON_SAS_CLASS L"SAS Window class"
27c2c66affSColin Finck #define WINLOGON_SAS_TITLE L"SAS window"
28c2c66affSColin Finck 
29c2c66affSColin Finck #define HK_CTRL_ALT_DEL   0
30c2c66affSColin Finck #define HK_CTRL_SHIFT_ESC 1
31c2c66affSColin Finck 
32c2c66affSColin Finck // #define EWX_FLAGS_MASK  0x00000014
33c2c66affSColin Finck // #define EWX_ACTION_MASK ~EWX_FLAGS_MASK
34c2c66affSColin Finck 
35c2c66affSColin Finck // FIXME: At the moment we use this value (select the lowbyte flags and some highbytes ones).
36c2c66affSColin Finck // It should be set such that it makes winlogon accepting only valid flags.
37c2c66affSColin Finck #define EWX_ACTION_MASK 0x5C0F
38c2c66affSColin Finck 
39c2c66affSColin Finck typedef struct tagLOGOFF_SHUTDOWN_DATA
40c2c66affSColin Finck {
41c2c66affSColin Finck     UINT Flags;
42c2c66affSColin Finck     PWLSESSION Session;
43c2c66affSColin Finck } LOGOFF_SHUTDOWN_DATA, *PLOGOFF_SHUTDOWN_DATA;
44c2c66affSColin Finck 
45c2c66affSColin Finck static BOOL ExitReactOSInProgress = FALSE;
46c2c66affSColin Finck 
4702eee253SHermès Bélusca-Maïto LUID LuidNone = {0, 0};
4802eee253SHermès Bélusca-Maïto 
49*1dfba2a6SThamatip Chitpong typedef struct tagLOGON_SOUND_DATA
50*1dfba2a6SThamatip Chitpong {
51*1dfba2a6SThamatip Chitpong     HANDLE UserToken;
52*1dfba2a6SThamatip Chitpong     BOOL IsStartup;
53*1dfba2a6SThamatip Chitpong } LOGON_SOUND_DATA, *PLOGON_SOUND_DATA;
54*1dfba2a6SThamatip Chitpong 
55c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
56c2c66affSColin Finck 
57c2c66affSColin Finck static BOOL
StartTaskManager(IN OUT PWLSESSION Session)58c2c66affSColin Finck StartTaskManager(
59c2c66affSColin Finck     IN OUT PWLSESSION Session)
60c2c66affSColin Finck {
61c2c66affSColin Finck     LPVOID lpEnvironment;
62c2c66affSColin Finck     BOOL ret;
63c2c66affSColin Finck 
64c2c66affSColin Finck     if (!Session->Gina.Functions.WlxStartApplication)
65c2c66affSColin Finck         return FALSE;
66c2c66affSColin Finck 
67c2c66affSColin Finck     if (!CreateEnvironmentBlock(
68c2c66affSColin Finck         &lpEnvironment,
69c2c66affSColin Finck         Session->UserToken,
70c2c66affSColin Finck         TRUE))
71c2c66affSColin Finck     {
72c2c66affSColin Finck         return FALSE;
73c2c66affSColin Finck     }
74c2c66affSColin Finck 
75c2c66affSColin Finck     ret = Session->Gina.Functions.WlxStartApplication(
76c2c66affSColin Finck         Session->Gina.Context,
77c2c66affSColin Finck         L"Default",
78c2c66affSColin Finck         lpEnvironment,
79c2c66affSColin Finck         L"taskmgr.exe");
80c2c66affSColin Finck 
81c2c66affSColin Finck     DestroyEnvironmentBlock(lpEnvironment);
82c2c66affSColin Finck     return ret;
83c2c66affSColin Finck }
84c2c66affSColin Finck 
85c2c66affSColin Finck static BOOL
StartUserShell(IN OUT PWLSESSION Session)86c2c66affSColin Finck StartUserShell(
87c2c66affSColin Finck     IN OUT PWLSESSION Session)
88c2c66affSColin Finck {
89c2c66affSColin Finck     LPVOID lpEnvironment = NULL;
90c2c66affSColin Finck     BOOLEAN Old;
91c2c66affSColin Finck     BOOL ret;
92c2c66affSColin Finck 
93c2c66affSColin Finck     /* Create environment block for the user */
94c2c66affSColin Finck     if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE))
95c2c66affSColin Finck     {
96c2c66affSColin Finck         WARN("WL: CreateEnvironmentBlock() failed\n");
97c2c66affSColin Finck         return FALSE;
98c2c66affSColin Finck     }
99c2c66affSColin Finck 
100c2c66affSColin Finck     /* Get privilege */
101c2c66affSColin Finck     /* FIXME: who should do it? winlogon or gina? */
102c2c66affSColin Finck     /* FIXME: reverting to lower privileges after creating user shell? */
103c2c66affSColin Finck     RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old);
104c2c66affSColin Finck 
105c2c66affSColin Finck     ret = Session->Gina.Functions.WlxActivateUserShell(
106c2c66affSColin Finck                 Session->Gina.Context,
107c2c66affSColin Finck                 L"Default",
108c2c66affSColin Finck                 NULL, /* FIXME */
109c2c66affSColin Finck                 lpEnvironment);
110c2c66affSColin Finck 
111c2c66affSColin Finck     DestroyEnvironmentBlock(lpEnvironment);
112c2c66affSColin Finck     return ret;
113c2c66affSColin Finck }
114c2c66affSColin Finck 
115c2c66affSColin Finck 
116c2c66affSColin Finck BOOL
SetDefaultLanguage(IN PWLSESSION Session)117c2c66affSColin Finck SetDefaultLanguage(
118c2c66affSColin Finck     IN PWLSESSION Session)
119c2c66affSColin Finck {
120c2c66affSColin Finck     BOOL ret = FALSE;
121c2c66affSColin Finck     BOOL UserProfile;
122c2c66affSColin Finck     LONG rc;
123c2c66affSColin Finck     HKEY UserKey, hKey = NULL;
124c2c66affSColin Finck     LPCWSTR SubKey, ValueName;
125c2c66affSColin Finck     DWORD dwType, dwSize;
126c2c66affSColin Finck     LPWSTR Value = NULL;
127c2c66affSColin Finck     UNICODE_STRING ValueString;
128c2c66affSColin Finck     NTSTATUS Status;
129c2c66affSColin Finck     LCID Lcid;
130c2c66affSColin Finck 
131c2c66affSColin Finck     UserProfile = (Session && Session->UserToken);
132c2c66affSColin Finck 
133c2c66affSColin Finck     if (UserProfile && !ImpersonateLoggedOnUser(Session->UserToken))
134c2c66affSColin Finck     {
135c2c66affSColin Finck         ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
136c2c66affSColin Finck         return FALSE;
137c2c66affSColin Finck         // FIXME: ... or use the default language of the system??
138c2c66affSColin Finck         // UserProfile = FALSE;
139c2c66affSColin Finck     }
140c2c66affSColin Finck 
141c2c66affSColin Finck     if (UserProfile)
142c2c66affSColin Finck     {
143c2c66affSColin Finck         rc = RegOpenCurrentUser(MAXIMUM_ALLOWED, &UserKey);
144c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
145c2c66affSColin Finck         {
146c2c66affSColin Finck             TRACE("RegOpenCurrentUser() failed with error %lu\n", rc);
147c2c66affSColin Finck             goto cleanup;
148c2c66affSColin Finck         }
149c2c66affSColin Finck 
150c2c66affSColin Finck         SubKey = L"Control Panel\\International";
151c2c66affSColin Finck         ValueName = L"Locale";
152c2c66affSColin Finck     }
153c2c66affSColin Finck     else
154c2c66affSColin Finck     {
155c2c66affSColin Finck         UserKey = NULL;
156c2c66affSColin Finck         SubKey = L"System\\CurrentControlSet\\Control\\Nls\\Language";
157c2c66affSColin Finck         ValueName = L"Default";
158c2c66affSColin Finck     }
159c2c66affSColin Finck 
160c2c66affSColin Finck     rc = RegOpenKeyExW(UserKey ? UserKey : HKEY_LOCAL_MACHINE,
161c2c66affSColin Finck                        SubKey,
162c2c66affSColin Finck                        0,
163c2c66affSColin Finck                        KEY_READ,
164c2c66affSColin Finck                        &hKey);
165c2c66affSColin Finck 
166c2c66affSColin Finck     if (UserKey)
167c2c66affSColin Finck         RegCloseKey(UserKey);
168c2c66affSColin Finck 
169c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
170c2c66affSColin Finck     {
171c2c66affSColin Finck         TRACE("RegOpenKeyEx() failed with error %lu\n", rc);
172c2c66affSColin Finck         goto cleanup;
173c2c66affSColin Finck     }
174c2c66affSColin Finck 
175c2c66affSColin Finck     rc = RegQueryValueExW(hKey,
176c2c66affSColin Finck                           ValueName,
177c2c66affSColin Finck                           NULL,
178c2c66affSColin Finck                           &dwType,
179c2c66affSColin Finck                           NULL,
180c2c66affSColin Finck                           &dwSize);
181c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
182c2c66affSColin Finck     {
183c2c66affSColin Finck         TRACE("RegQueryValueEx() failed with error %lu\n", rc);
184c2c66affSColin Finck         goto cleanup;
185c2c66affSColin Finck     }
186c2c66affSColin Finck     else if (dwType != REG_SZ)
187c2c66affSColin Finck     {
188c2c66affSColin Finck         TRACE("Wrong type for %S\\%S registry entry (got 0x%lx, expected 0x%x)\n",
189c2c66affSColin Finck             SubKey, ValueName, dwType, REG_SZ);
190c2c66affSColin Finck         goto cleanup;
191c2c66affSColin Finck     }
192c2c66affSColin Finck 
193c2c66affSColin Finck     Value = HeapAlloc(GetProcessHeap(), 0, dwSize);
194c2c66affSColin Finck     if (!Value)
195c2c66affSColin Finck     {
196c2c66affSColin Finck         TRACE("HeapAlloc() failed\n");
197c2c66affSColin Finck         goto cleanup;
198c2c66affSColin Finck     }
199c2c66affSColin Finck     rc = RegQueryValueExW(hKey,
200c2c66affSColin Finck                           ValueName,
201c2c66affSColin Finck                           NULL,
202c2c66affSColin Finck                           NULL,
203c2c66affSColin Finck                           (LPBYTE)Value,
204c2c66affSColin Finck                           &dwSize);
205c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
206c2c66affSColin Finck     {
207c2c66affSColin Finck         TRACE("RegQueryValueEx() failed with error %lu\n", rc);
208c2c66affSColin Finck         goto cleanup;
209c2c66affSColin Finck     }
210c2c66affSColin Finck 
211c2c66affSColin Finck     /* Convert Value to a Lcid */
212c2c66affSColin Finck     ValueString.Length = ValueString.MaximumLength = (USHORT)dwSize;
213c2c66affSColin Finck     ValueString.Buffer = Value;
214c2c66affSColin Finck     Status = RtlUnicodeStringToInteger(&ValueString, 16, (PULONG)&Lcid);
215c2c66affSColin Finck     if (!NT_SUCCESS(Status))
216c2c66affSColin Finck     {
217c2c66affSColin Finck         TRACE("RtlUnicodeStringToInteger() failed with status 0x%08lx\n", Status);
218c2c66affSColin Finck         goto cleanup;
219c2c66affSColin Finck     }
220c2c66affSColin Finck 
221c2c66affSColin Finck     TRACE("%s language is 0x%08lx\n",
222c2c66affSColin Finck         UserProfile ? "User" : "System", Lcid);
223c2c66affSColin Finck     Status = NtSetDefaultLocale(UserProfile, Lcid);
224c2c66affSColin Finck     if (!NT_SUCCESS(Status))
225c2c66affSColin Finck     {
226c2c66affSColin Finck         TRACE("NtSetDefaultLocale() failed with status 0x%08lx\n", Status);
227c2c66affSColin Finck         goto cleanup;
228c2c66affSColin Finck     }
229c2c66affSColin Finck 
230c2c66affSColin Finck     ret = TRUE;
231c2c66affSColin Finck 
232c2c66affSColin Finck cleanup:
233c2c66affSColin Finck     if (Value)
234c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, Value);
235c2c66affSColin Finck 
236c2c66affSColin Finck     if (hKey)
237c2c66affSColin Finck         RegCloseKey(hKey);
238c2c66affSColin Finck 
239c2c66affSColin Finck     if (UserProfile)
240c2c66affSColin Finck         RevertToSelf();
241c2c66affSColin Finck 
242c2c66affSColin Finck     return ret;
243c2c66affSColin Finck }
244c2c66affSColin Finck 
245c2c66affSColin Finck BOOL
PlaySoundRoutine(IN LPCWSTR FileName,IN UINT bLogon,IN UINT Flags)246c2c66affSColin Finck PlaySoundRoutine(
247c2c66affSColin Finck     IN LPCWSTR FileName,
248c2c66affSColin Finck     IN UINT bLogon,
249c2c66affSColin Finck     IN UINT Flags)
250c2c66affSColin Finck {
251c2c66affSColin Finck     typedef BOOL (WINAPI *PLAYSOUNDW)(LPCWSTR,HMODULE,DWORD);
252c2c66affSColin Finck     typedef UINT (WINAPI *WAVEOUTGETNUMDEVS)(VOID);
253c2c66affSColin Finck     PLAYSOUNDW Play;
254c2c66affSColin Finck     WAVEOUTGETNUMDEVS waveOutGetNumDevs;
255c2c66affSColin Finck     UINT NumDevs;
256c2c66affSColin Finck     HMODULE hLibrary;
257c2c66affSColin Finck     BOOL Ret = FALSE;
258c2c66affSColin Finck 
259c2c66affSColin Finck     hLibrary = LoadLibraryW(L"winmm.dll");
260967f5b98SHermès Bélusca-Maïto     if (!hLibrary)
261967f5b98SHermès Bélusca-Maïto         return FALSE;
262967f5b98SHermès Bélusca-Maïto 
263c2c66affSColin Finck     waveOutGetNumDevs = (WAVEOUTGETNUMDEVS)GetProcAddress(hLibrary, "waveOutGetNumDevs");
264967f5b98SHermès Bélusca-Maïto     Play = (PLAYSOUNDW)GetProcAddress(hLibrary, "PlaySoundW");
265967f5b98SHermès Bélusca-Maïto 
266967f5b98SHermès Bélusca-Maïto     _SEH2_TRY
267967f5b98SHermès Bélusca-Maïto     {
268c2c66affSColin Finck         if (waveOutGetNumDevs)
269c2c66affSColin Finck         {
270c2c66affSColin Finck             NumDevs = waveOutGetNumDevs();
271c2c66affSColin Finck             if (!NumDevs)
272c2c66affSColin Finck             {
273c2c66affSColin Finck                 if (!bLogon)
274d811fca7SAdam Słaboń                     Beep(440, 125);
275967f5b98SHermès Bélusca-Maïto                 _SEH2_LEAVE;
276c2c66affSColin Finck             }
277c2c66affSColin Finck         }
278c2c66affSColin Finck 
279c2c66affSColin Finck         if (Play)
280c2c66affSColin Finck             Ret = Play(FileName, NULL, Flags);
281c2c66affSColin Finck     }
282967f5b98SHermès Bélusca-Maïto     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
283967f5b98SHermès Bélusca-Maïto     {
284967f5b98SHermès Bélusca-Maïto         ERR("WL: Exception while playing sound '%S', Status 0x%08lx\n",
285967f5b98SHermès Bélusca-Maïto             FileName ? FileName : L"(n/a)", _SEH2_GetExceptionCode());
286c2c66affSColin Finck     }
287967f5b98SHermès Bélusca-Maïto     _SEH2_END;
288967f5b98SHermès Bélusca-Maïto 
289967f5b98SHermès Bélusca-Maïto     FreeLibrary(hLibrary);
290c2c66affSColin Finck 
291c2c66affSColin Finck     return Ret;
292c2c66affSColin Finck }
293c2c66affSColin Finck 
29425579481SThamatip Chitpong static
295c2c66affSColin Finck DWORD
296c2c66affSColin Finck WINAPI
PlayLogonSoundThread(_In_ LPVOID lpParameter)297c2c66affSColin Finck PlayLogonSoundThread(
298*1dfba2a6SThamatip Chitpong     _In_ LPVOID lpParameter)
299c2c66affSColin Finck {
300*1dfba2a6SThamatip Chitpong     PLOGON_SOUND_DATA SoundData = (PLOGON_SOUND_DATA)lpParameter;
301c2c66affSColin Finck     SERVICE_STATUS_PROCESS Info;
3029d48f26dSThamatip Chitpong     DWORD dwSize;
303c2c66affSColin Finck     ULONG Index = 0;
304c2c66affSColin Finck     SC_HANDLE hSCManager, hService;
305c2c66affSColin Finck 
306c2c66affSColin Finck     /* Open the service manager */
307c2c66affSColin Finck     hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
308c2c66affSColin Finck     if (!hSCManager)
309c2c66affSColin Finck     {
310c2c66affSColin Finck         ERR("OpenSCManager failed (%x)\n", GetLastError());
311*1dfba2a6SThamatip Chitpong         goto Cleanup;
312c2c66affSColin Finck     }
313c2c66affSColin Finck 
314c2c66affSColin Finck     /* Open the wdmaud service */
315c2c66affSColin Finck     hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ);
316c2c66affSColin Finck     if (!hService)
317c2c66affSColin Finck     {
318c2c66affSColin Finck         /* The service is not installed */
319c2c66affSColin Finck         TRACE("Failed to open wdmaud service (%x)\n", GetLastError());
320c2c66affSColin Finck         CloseServiceHandle(hSCManager);
321*1dfba2a6SThamatip Chitpong         goto Cleanup;
322c2c66affSColin Finck     }
323c2c66affSColin Finck 
324c2c66affSColin Finck     /* Wait for wdmaud to start */
325c2c66affSColin Finck     do
326c2c66affSColin Finck     {
327c2c66affSColin Finck         if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize))
328c2c66affSColin Finck         {
329c2c66affSColin Finck             TRACE("QueryServiceStatusEx failed (%x)\n", GetLastError());
330c2c66affSColin Finck             break;
331c2c66affSColin Finck         }
332c2c66affSColin Finck 
333c2c66affSColin Finck         if (Info.dwCurrentState == SERVICE_RUNNING)
334c2c66affSColin Finck             break;
335c2c66affSColin Finck 
336c2c66affSColin Finck         Sleep(1000);
337c2c66affSColin Finck 
338c2c66affSColin Finck     } while (Index++ < 20);
339c2c66affSColin Finck 
340c2c66affSColin Finck     CloseServiceHandle(hService);
341c2c66affSColin Finck     CloseServiceHandle(hSCManager);
342c2c66affSColin Finck 
343c2c66affSColin Finck     /* If wdmaud is not running exit */
344c2c66affSColin Finck     if (Info.dwCurrentState != SERVICE_RUNNING)
345c2c66affSColin Finck     {
346c2c66affSColin Finck         WARN("wdmaud has not started!\n");
347*1dfba2a6SThamatip Chitpong         goto Cleanup;
348c2c66affSColin Finck     }
349c2c66affSColin Finck 
350c2c66affSColin Finck     /* Sound subsystem is running. Play logon sound. */
351*1dfba2a6SThamatip Chitpong     TRACE("Playing %s sound\n", SoundData->IsStartup ? "startup" : "logon");
352*1dfba2a6SThamatip Chitpong     if (!ImpersonateLoggedOnUser(SoundData->UserToken))
3539d48f26dSThamatip Chitpong     {
3549d48f26dSThamatip Chitpong         ERR("ImpersonateLoggedOnUser failed (%x)\n", GetLastError());
3559d48f26dSThamatip Chitpong     }
3569d48f26dSThamatip Chitpong     else
3579d48f26dSThamatip Chitpong     {
358*1dfba2a6SThamatip Chitpong         PlaySoundRoutine(SoundData->IsStartup ? L"SystemStart" : L"WindowsLogon",
35925579481SThamatip Chitpong                          TRUE,
36025579481SThamatip Chitpong                          SND_ALIAS | SND_NODEFAULT);
3619d48f26dSThamatip Chitpong         RevertToSelf();
3629d48f26dSThamatip Chitpong     }
363*1dfba2a6SThamatip Chitpong 
364*1dfba2a6SThamatip Chitpong Cleanup:
365*1dfba2a6SThamatip Chitpong     HeapFree(GetProcessHeap(), 0, SoundData);
366c2c66affSColin Finck     return 0;
367c2c66affSColin Finck }
368c2c66affSColin Finck 
369c2c66affSColin Finck static
370c2c66affSColin Finck VOID
PlayLogonSound(_In_ PWLSESSION Session)371c2c66affSColin Finck PlayLogonSound(
372*1dfba2a6SThamatip Chitpong     _In_ PWLSESSION Session)
373c2c66affSColin Finck {
374*1dfba2a6SThamatip Chitpong     PLOGON_SOUND_DATA SoundData;
375c2c66affSColin Finck     HANDLE hThread;
376c2c66affSColin Finck 
377*1dfba2a6SThamatip Chitpong     SoundData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGON_SOUND_DATA));
378*1dfba2a6SThamatip Chitpong     if (!SoundData)
379*1dfba2a6SThamatip Chitpong         return;
380*1dfba2a6SThamatip Chitpong 
381*1dfba2a6SThamatip Chitpong     SoundData->UserToken = Session->UserToken;
382*1dfba2a6SThamatip Chitpong     SoundData->IsStartup = IsFirstLogon(Session);
383*1dfba2a6SThamatip Chitpong 
384*1dfba2a6SThamatip Chitpong     hThread = CreateThread(NULL, 0, PlayLogonSoundThread, SoundData, 0, NULL);
385*1dfba2a6SThamatip Chitpong     if (!hThread)
386*1dfba2a6SThamatip Chitpong     {
387*1dfba2a6SThamatip Chitpong         HeapFree(GetProcessHeap(), 0, SoundData);
388*1dfba2a6SThamatip Chitpong         return;
389*1dfba2a6SThamatip Chitpong     }
390c2c66affSColin Finck     CloseHandle(hThread);
391c2c66affSColin Finck }
392c2c66affSColin Finck 
393c2c66affSColin Finck static
3944cf87fdbSPierre Schweitzer VOID
PlayLogoffShutdownSound(_In_ PWLSESSION Session,_In_ BOOL bShutdown)39537375fccSThamatip Chitpong PlayLogoffShutdownSound(
39637375fccSThamatip Chitpong     _In_ PWLSESSION Session,
39737375fccSThamatip Chitpong     _In_ BOOL bShutdown)
3989d48f26dSThamatip Chitpong {
3999d48f26dSThamatip Chitpong     if (!ImpersonateLoggedOnUser(Session->UserToken))
4009d48f26dSThamatip Chitpong         return;
4019d48f26dSThamatip Chitpong 
40237375fccSThamatip Chitpong     /* NOTE: Logoff and shutdown sounds play synchronously */
40337375fccSThamatip Chitpong     PlaySoundRoutine(bShutdown ? L"SystemExit" : L"WindowsLogoff",
40437375fccSThamatip Chitpong                      FALSE,
40537375fccSThamatip Chitpong                      SND_ALIAS | SND_NODEFAULT);
4069d48f26dSThamatip Chitpong 
4079d48f26dSThamatip Chitpong     RevertToSelf();
4089d48f26dSThamatip Chitpong }
4099d48f26dSThamatip Chitpong 
4109d48f26dSThamatip Chitpong static
4119d48f26dSThamatip Chitpong BOOL
PlayEventSound(_In_ PWLSESSION Session,_In_ LPCWSTR EventName)4129d48f26dSThamatip Chitpong PlayEventSound(
4139d48f26dSThamatip Chitpong     _In_ PWLSESSION Session,
4149d48f26dSThamatip Chitpong     _In_ LPCWSTR EventName)
4159d48f26dSThamatip Chitpong {
4169d48f26dSThamatip Chitpong     BOOL bRet;
4179d48f26dSThamatip Chitpong 
4189d48f26dSThamatip Chitpong     if (!ImpersonateLoggedOnUser(Session->UserToken))
4199d48f26dSThamatip Chitpong         return FALSE;
4209d48f26dSThamatip Chitpong 
4219d48f26dSThamatip Chitpong     bRet = PlaySoundRoutine(EventName, FALSE, SND_ALIAS | SND_ASYNC | SND_NODEFAULT);
4229d48f26dSThamatip Chitpong 
4239d48f26dSThamatip Chitpong     RevertToSelf();
4249d48f26dSThamatip Chitpong 
4259d48f26dSThamatip Chitpong     return bRet;
4269d48f26dSThamatip Chitpong }
4279d48f26dSThamatip Chitpong 
4289d48f26dSThamatip Chitpong static
4299d48f26dSThamatip Chitpong VOID
RestoreAllConnections(PWLSESSION Session)4304cf87fdbSPierre Schweitzer RestoreAllConnections(PWLSESSION Session)
4314cf87fdbSPierre Schweitzer {
4324cf87fdbSPierre Schweitzer     DWORD dRet;
4334cf87fdbSPierre Schweitzer     HANDLE hEnum;
4344cf87fdbSPierre Schweitzer     LPNETRESOURCE lpRes;
4354cf87fdbSPierre Schweitzer     DWORD dSize = 0x1000;
4364cf87fdbSPierre Schweitzer     DWORD dCount = -1;
4374cf87fdbSPierre Schweitzer     LPNETRESOURCE lpCur;
4384cf87fdbSPierre Schweitzer     BOOL UserProfile;
4394cf87fdbSPierre Schweitzer 
4404cf87fdbSPierre Schweitzer     UserProfile = (Session && Session->UserToken);
4414cf87fdbSPierre Schweitzer     if (!UserProfile)
4424cf87fdbSPierre Schweitzer     {
4434cf87fdbSPierre Schweitzer         return;
4444cf87fdbSPierre Schweitzer     }
4454cf87fdbSPierre Schweitzer 
4464cf87fdbSPierre Schweitzer     if (!ImpersonateLoggedOnUser(Session->UserToken))
4474cf87fdbSPierre Schweitzer     {
4484cf87fdbSPierre Schweitzer         ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
4494cf87fdbSPierre Schweitzer         return;
4504cf87fdbSPierre Schweitzer     }
4514cf87fdbSPierre Schweitzer 
4524cf87fdbSPierre Schweitzer     dRet = WNetOpenEnum(RESOURCE_REMEMBERED, RESOURCETYPE_DISK, 0, NULL, &hEnum);
4534cf87fdbSPierre Schweitzer     if (dRet != WN_SUCCESS)
4544cf87fdbSPierre Schweitzer     {
4554cf87fdbSPierre Schweitzer         ERR("Failed to open enumeration: %lu\n", dRet);
4564cf87fdbSPierre Schweitzer         goto quit;
4574cf87fdbSPierre Schweitzer     }
4584cf87fdbSPierre Schweitzer 
4594cf87fdbSPierre Schweitzer     lpRes = HeapAlloc(GetProcessHeap(), 0, dSize);
4604cf87fdbSPierre Schweitzer     if (!lpRes)
4614cf87fdbSPierre Schweitzer     {
4624cf87fdbSPierre Schweitzer         ERR("Failed to allocate memory\n");
4634cf87fdbSPierre Schweitzer         WNetCloseEnum(hEnum);
4644cf87fdbSPierre Schweitzer         goto quit;
4654cf87fdbSPierre Schweitzer     }
4664cf87fdbSPierre Schweitzer 
4674cf87fdbSPierre Schweitzer     do
4684cf87fdbSPierre Schweitzer     {
4694cf87fdbSPierre Schweitzer         dSize = 0x1000;
4704cf87fdbSPierre Schweitzer         dCount = -1;
4714cf87fdbSPierre Schweitzer 
4724cf87fdbSPierre Schweitzer         memset(lpRes, 0, dSize);
4734cf87fdbSPierre Schweitzer         dRet = WNetEnumResource(hEnum, &dCount, lpRes, &dSize);
4744cf87fdbSPierre Schweitzer         if (dRet == WN_SUCCESS || dRet == WN_MORE_DATA)
4754cf87fdbSPierre Schweitzer         {
4764cf87fdbSPierre Schweitzer             lpCur = lpRes;
4774cf87fdbSPierre Schweitzer             for (; dCount; dCount--)
4784cf87fdbSPierre Schweitzer             {
4794cf87fdbSPierre Schweitzer                 WNetAddConnection(lpCur->lpRemoteName, NULL, lpCur->lpLocalName);
4804cf87fdbSPierre Schweitzer                 lpCur++;
4814cf87fdbSPierre Schweitzer             }
4824cf87fdbSPierre Schweitzer         }
4834cf87fdbSPierre Schweitzer     } while (dRet != WN_NO_MORE_ENTRIES);
4844cf87fdbSPierre Schweitzer 
4854cf87fdbSPierre Schweitzer     HeapFree(GetProcessHeap(), 0, lpRes);
4864cf87fdbSPierre Schweitzer     WNetCloseEnum(hEnum);
4874cf87fdbSPierre Schweitzer 
4884cf87fdbSPierre Schweitzer quit:
4894cf87fdbSPierre Schweitzer     RevertToSelf();
4904cf87fdbSPierre Schweitzer }
4914cf87fdbSPierre Schweitzer 
4924cf87fdbSPierre Schweitzer static
493c2c66affSColin Finck BOOL
HandleLogon(IN OUT PWLSESSION Session)494c2c66affSColin Finck HandleLogon(
495c2c66affSColin Finck     IN OUT PWLSESSION Session)
496c2c66affSColin Finck {
497c2c66affSColin Finck     PROFILEINFOW ProfileInfo;
498c2c66affSColin Finck     BOOL ret = FALSE;
499c2c66affSColin Finck 
500c2c66affSColin Finck     /* Loading personal settings */
501c2c66affSColin Finck     DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOADINGYOURPERSONALSETTINGS);
502c2c66affSColin Finck     ProfileInfo.hProfile = INVALID_HANDLE_VALUE;
503c2c66affSColin Finck     if (0 == (Session->Options & WLX_LOGON_OPT_NO_PROFILE))
504c2c66affSColin Finck     {
505c2c66affSColin Finck         if (Session->Profile == NULL
506c2c66affSColin Finck          || (Session->Profile->dwType != WLX_PROFILE_TYPE_V1_0
507c2c66affSColin Finck           && Session->Profile->dwType != WLX_PROFILE_TYPE_V2_0))
508c2c66affSColin Finck         {
509c2c66affSColin Finck             ERR("WL: Wrong profile\n");
510c2c66affSColin Finck             goto cleanup;
511c2c66affSColin Finck         }
512c2c66affSColin Finck 
513c2c66affSColin Finck         /* Load the user profile */
514c2c66affSColin Finck         ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
515c2c66affSColin Finck         ProfileInfo.dwSize = sizeof(PROFILEINFOW);
516c2c66affSColin Finck         ProfileInfo.dwFlags = 0;
517c2c66affSColin Finck         ProfileInfo.lpUserName = Session->MprNotifyInfo.pszUserName;
518c2c66affSColin Finck         ProfileInfo.lpProfilePath = Session->Profile->pszProfile;
519c2c66affSColin Finck         if (Session->Profile->dwType >= WLX_PROFILE_TYPE_V2_0)
520c2c66affSColin Finck         {
521c2c66affSColin Finck             ProfileInfo.lpDefaultPath = Session->Profile->pszNetworkDefaultUserProfile;
522c2c66affSColin Finck             ProfileInfo.lpServerName = Session->Profile->pszServerName;
523c2c66affSColin Finck             ProfileInfo.lpPolicyPath = Session->Profile->pszPolicy;
524c2c66affSColin Finck         }
525c2c66affSColin Finck 
526c2c66affSColin Finck         if (!LoadUserProfileW(Session->UserToken, &ProfileInfo))
527c2c66affSColin Finck         {
528c2c66affSColin Finck             ERR("WL: LoadUserProfileW() failed\n");
529c2c66affSColin Finck             goto cleanup;
530c2c66affSColin Finck         }
531c2c66affSColin Finck     }
532c2c66affSColin Finck 
533c2c66affSColin Finck     /* Create environment block for the user */
534c2c66affSColin Finck     if (!CreateUserEnvironment(Session))
535c2c66affSColin Finck     {
536c2c66affSColin Finck         WARN("WL: SetUserEnvironment() failed\n");
537c2c66affSColin Finck         goto cleanup;
538c2c66affSColin Finck     }
539c2c66affSColin Finck 
540c2c66affSColin Finck     CallNotificationDlls(Session, LogonHandler);
541c2c66affSColin Finck 
542c2c66affSColin Finck     DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGYOURPERSONALSETTINGS);
543c2c66affSColin Finck     UpdatePerUserSystemParameters(0, TRUE);
544c2c66affSColin Finck 
545c2c66affSColin Finck     /* Set default user language */
546c2c66affSColin Finck     if (!SetDefaultLanguage(Session))
547c2c66affSColin Finck     {
548c2c66affSColin Finck         WARN("WL: SetDefaultLanguage() failed\n");
549c2c66affSColin Finck         goto cleanup;
550c2c66affSColin Finck     }
551c2c66affSColin Finck 
552f96c39f6SGeorge Bișoc     /* Allow winsta and desktop access for this session */
553f96c39f6SGeorge Bișoc     if (!AllowAccessOnSession(Session))
554f96c39f6SGeorge Bișoc     {
555f96c39f6SGeorge Bișoc         WARN("WL: AllowAccessOnSession() failed to give winsta & desktop access for this session\n");
556f96c39f6SGeorge Bișoc         goto cleanup;
557f96c39f6SGeorge Bișoc     }
55802eee253SHermès Bélusca-Maïto 
5594cf87fdbSPierre Schweitzer     /* Connect remote resources */
5604cf87fdbSPierre Schweitzer     RestoreAllConnections(Session);
5614cf87fdbSPierre Schweitzer 
562c2c66affSColin Finck     if (!StartUserShell(Session))
563c2c66affSColin Finck     {
564c2c66affSColin Finck         //WCHAR StatusMsg[256];
565c2c66affSColin Finck         WARN("WL: WlxActivateUserShell() failed\n");
566c2c66affSColin Finck         //LoadStringW(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, sizeof(StatusMsg) / sizeof(StatusMsg[0]));
567c2c66affSColin Finck         //MessageBoxW(0, StatusMsg, NULL, MB_ICONERROR);
568c2c66affSColin Finck         goto cleanup;
569c2c66affSColin Finck     }
570c2c66affSColin Finck 
571c2c66affSColin Finck     CallNotificationDlls(Session, StartShellHandler);
572c2c66affSColin Finck 
573c2c66affSColin Finck     if (!InitializeScreenSaver(Session))
574c2c66affSColin Finck         WARN("WL: Failed to initialize screen saver\n");
575c2c66affSColin Finck 
576c2c66affSColin Finck     Session->hProfileInfo = ProfileInfo.hProfile;
577c2c66affSColin Finck 
57840000a17SHermès Bélusca-Maïto     /* Logon has succeeded. Play sound. */
579c2c66affSColin Finck     PlayLogonSound(Session);
580c2c66affSColin Finck 
581*1dfba2a6SThamatip Chitpong     /* NOTE: The logon timestamp has to be set after calling PlayLogonSound
582*1dfba2a6SThamatip Chitpong      * to correctly detect the startup event (first logon) */
583*1dfba2a6SThamatip Chitpong     SetLogonTimestamp(Session);
584c2c66affSColin Finck     ret = TRUE;
585c2c66affSColin Finck 
586c2c66affSColin Finck cleanup:
587c2c66affSColin Finck     if (Session->Profile)
588c2c66affSColin Finck     {
589c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, Session->Profile->pszProfile);
590c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, Session->Profile);
591c2c66affSColin Finck     }
592c2c66affSColin Finck     Session->Profile = NULL;
593c2c66affSColin Finck     if (!ret && ProfileInfo.hProfile != INVALID_HANDLE_VALUE)
594c2c66affSColin Finck     {
595c2c66affSColin Finck         UnloadUserProfile(Session->UserToken, ProfileInfo.hProfile);
596c2c66affSColin Finck     }
597c2c66affSColin Finck     RemoveStatusMessage(Session);
598c2c66affSColin Finck     if (!ret)
599c2c66affSColin Finck     {
60002eee253SHermès Bélusca-Maïto         SetWindowStationUser(Session->InteractiveWindowStation,
60102eee253SHermès Bélusca-Maïto                              &LuidNone, NULL, 0);
602c2c66affSColin Finck         CloseHandle(Session->UserToken);
603c2c66affSColin Finck         Session->UserToken = NULL;
604c2c66affSColin Finck     }
605c2c66affSColin Finck 
606c2c66affSColin Finck     if (ret)
607c2c66affSColin Finck     {
608c2c66affSColin Finck         SwitchDesktop(Session->ApplicationDesktop);
609c2c66affSColin Finck         Session->LogonState = STATE_LOGGED_ON;
610c2c66affSColin Finck     }
611c2c66affSColin Finck 
612c2c66affSColin Finck     return ret;
613c2c66affSColin Finck }
614c2c66affSColin Finck 
615c2c66affSColin Finck 
616c2c66affSColin Finck static
617c2c66affSColin Finck DWORD
618c2c66affSColin Finck WINAPI
LogoffShutdownThread(LPVOID Parameter)619c2c66affSColin Finck LogoffShutdownThread(
620c2c66affSColin Finck     LPVOID Parameter)
621c2c66affSColin Finck {
622c2c66affSColin Finck     DWORD ret = 1;
623c2c66affSColin Finck     PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA)Parameter;
624c2c66affSColin Finck     UINT uFlags;
625c2c66affSColin Finck 
626c2c66affSColin Finck     if (LSData->Session->UserToken != NULL &&
627c2c66affSColin Finck         !ImpersonateLoggedOnUser(LSData->Session->UserToken))
628c2c66affSColin Finck     {
629c2c66affSColin Finck         ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
630c2c66affSColin Finck         return 0;
631c2c66affSColin Finck     }
632c2c66affSColin Finck 
633c2c66affSColin Finck     // FIXME: To be really fixed: need to check what needs to be kept and what needs to be removed there.
634c2c66affSColin Finck     //
635c2c66affSColin Finck     // uFlags = EWX_INTERNAL_KILL_USER_APPS | (LSData->Flags & EWX_FLAGS_MASK) |
636c2c66affSColin Finck              // ((LSData->Flags & EWX_ACTION_MASK) == EWX_LOGOFF ? EWX_CALLER_WINLOGON_LOGOFF : 0);
637c2c66affSColin Finck 
638c2c66affSColin Finck     uFlags = EWX_CALLER_WINLOGON | (LSData->Flags & 0x0F);
639c2c66affSColin Finck 
640c2c66affSColin Finck     TRACE("In LogoffShutdownThread with uFlags == 0x%x; exit_in_progress == %s\n",
641c2c66affSColin Finck         uFlags, ExitReactOSInProgress ? "true" : "false");
642c2c66affSColin Finck 
643c2c66affSColin Finck     ExitReactOSInProgress = TRUE;
644c2c66affSColin Finck 
645c2c66affSColin Finck     /* Close processes of the interactive user */
646c2c66affSColin Finck     if (!ExitWindowsEx(uFlags, 0))
647c2c66affSColin Finck     {
648c2c66affSColin Finck         ERR("Unable to kill user apps, error %lu\n", GetLastError());
649c2c66affSColin Finck         ret = 0;
650c2c66affSColin Finck     }
651c2c66affSColin Finck 
652cbff9a30SPierre Schweitzer     /* Cancel all the user connections */
6530dedb9b4SSerge Gautherie     WNetClearConnections(NULL);
654cbff9a30SPierre Schweitzer 
655c2c66affSColin Finck     if (LSData->Session->UserToken)
656c2c66affSColin Finck         RevertToSelf();
657c2c66affSColin Finck 
658c2c66affSColin Finck     return ret;
659c2c66affSColin Finck }
660c2c66affSColin Finck 
661c2c66affSColin Finck static
662c2c66affSColin Finck DWORD
663c2c66affSColin Finck WINAPI
KillComProcesses(LPVOID Parameter)664c2c66affSColin Finck KillComProcesses(
665c2c66affSColin Finck     LPVOID Parameter)
666c2c66affSColin Finck {
667c2c66affSColin Finck     DWORD ret = 1;
668c2c66affSColin Finck     PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA)Parameter;
669c2c66affSColin Finck 
670c2c66affSColin Finck     TRACE("In KillComProcesses\n");
671c2c66affSColin Finck 
672c2c66affSColin Finck     if (LSData->Session->UserToken != NULL &&
673c2c66affSColin Finck         !ImpersonateLoggedOnUser(LSData->Session->UserToken))
674c2c66affSColin Finck     {
675c2c66affSColin Finck         ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
676c2c66affSColin Finck         return 0;
677c2c66affSColin Finck     }
678c2c66affSColin Finck 
679c2c66affSColin Finck     /* Attempt to kill remaining processes. No notifications needed. */
680c2c66affSColin Finck     if (!ExitWindowsEx(EWX_CALLER_WINLOGON | EWX_NONOTIFY | EWX_FORCE | EWX_LOGOFF, 0))
681c2c66affSColin Finck     {
682c2c66affSColin Finck         ERR("Unable to kill COM apps, error %lu\n", GetLastError());
683c2c66affSColin Finck         ret = 0;
684c2c66affSColin Finck     }
685c2c66affSColin Finck 
686c2c66affSColin Finck     if (LSData->Session->UserToken)
687c2c66affSColin Finck         RevertToSelf();
688c2c66affSColin Finck 
689c2c66affSColin Finck     return ret;
690c2c66affSColin Finck }
691c2c66affSColin Finck 
692c2c66affSColin Finck static
693c2c66affSColin Finck NTSTATUS
CreateLogoffSecurityAttributes(OUT PSECURITY_ATTRIBUTES * ppsa)694c2c66affSColin Finck CreateLogoffSecurityAttributes(
695c2c66affSColin Finck     OUT PSECURITY_ATTRIBUTES* ppsa)
696c2c66affSColin Finck {
697c2c66affSColin Finck     /* The following code is not working yet and messy */
698c2c66affSColin Finck     /* Still, it gives some ideas about data types and functions involved and */
699c2c66affSColin Finck     /* required to set up a SECURITY_DESCRIPTOR for a SECURITY_ATTRIBUTES */
700c2c66affSColin Finck     /* instance for a thread, to allow that  thread to ImpersonateLoggedOnUser(). */
701c2c66affSColin Finck     /* Specifically THREAD_SET_THREAD_TOKEN is required. */
702c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
703c2c66affSColin Finck     PSECURITY_ATTRIBUTES psa = 0;
704c2c66affSColin Finck     BYTE* pMem;
705c2c66affSColin Finck     PACL pACL;
706c2c66affSColin Finck     EXPLICIT_ACCESS Access;
707c2c66affSColin Finck     PSID pEveryoneSID = NULL;
708c2c66affSColin Finck     static SID_IDENTIFIER_AUTHORITY WorldAuthority = { SECURITY_WORLD_SID_AUTHORITY };
709c2c66affSColin Finck 
710c2c66affSColin Finck     *ppsa = NULL;
711c2c66affSColin Finck 
712c2c66affSColin Finck     // Let's first try to enumerate what kind of data we need for this to ever work:
713c2c66affSColin Finck     // 1.  The Winlogon SID, to be able to give it THREAD_SET_THREAD_TOKEN.
714c2c66affSColin Finck     // 2.  The users SID (the user trying to logoff, or rather shut down the system).
715c2c66affSColin Finck     // 3.  At least two EXPLICIT_ACCESS instances:
716c2c66affSColin Finck     // 3.1 One for Winlogon itself, giving it the rights
717c2c66affSColin Finck     //     required to THREAD_SET_THREAD_TOKEN (as it's needed to successfully call
718c2c66affSColin Finck     //     ImpersonateLoggedOnUser).
719c2c66affSColin Finck     // 3.2 One for the user, to allow *that* thread to perform its work.
720c2c66affSColin Finck     // 4.  An ACL to hold the these EXPLICIT_ACCESS ACE's.
721c2c66affSColin Finck     // 5.  A SECURITY_DESCRIPTOR to hold the ACL, and finally.
722c2c66affSColin Finck     // 6.  A SECURITY_ATTRIBUTES instance to pull all of this required stuff
723c2c66affSColin Finck     //     together, to hand it to CreateThread.
724c2c66affSColin Finck     //
725c2c66affSColin Finck     // However, it seems struct LOGOFF_SHUTDOWN_DATA doesn't contain
726c2c66affSColin Finck     // these required SID's, why they'd have to be added.
727c2c66affSColin Finck     // The Winlogon's own SID should probably only be created once,
728c2c66affSColin Finck     // while the user's SID obviously must be created for each new user.
729c2c66affSColin Finck     // Might as well store it when the user logs on?
730c2c66affSColin Finck 
731c2c66affSColin Finck     if(!AllocateAndInitializeSid(&WorldAuthority,
732c2c66affSColin Finck                                  1,
733c2c66affSColin Finck                                  SECURITY_WORLD_RID,
734c2c66affSColin Finck                                  0, 0, 0, 0, 0, 0, 0,
735c2c66affSColin Finck                                  &pEveryoneSID))
736c2c66affSColin Finck     {
737c2c66affSColin Finck         ERR("Failed to initialize security descriptor for logoff thread!\n");
738c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
739c2c66affSColin Finck     }
740c2c66affSColin Finck 
741c2c66affSColin Finck     /* set up the required security attributes to be able to shut down */
742c2c66affSColin Finck     /* To save space and time, allocate a single block of memory holding */
743c2c66affSColin Finck     /* both SECURITY_ATTRIBUTES and SECURITY_DESCRIPTOR */
744c2c66affSColin Finck     pMem = HeapAlloc(GetProcessHeap(),
745c2c66affSColin Finck                      0,
746c2c66affSColin Finck                      sizeof(SECURITY_ATTRIBUTES) +
747c2c66affSColin Finck                      SECURITY_DESCRIPTOR_MIN_LENGTH +
748c2c66affSColin Finck                      sizeof(ACL));
749c2c66affSColin Finck     if (!pMem)
750c2c66affSColin Finck     {
751c2c66affSColin Finck         ERR("Failed to allocate memory for logoff security descriptor!\n");
752c2c66affSColin Finck         return STATUS_NO_MEMORY;
753c2c66affSColin Finck     }
754c2c66affSColin Finck 
755c2c66affSColin Finck     /* Note that the security descriptor needs to be in _absolute_ format, */
756c2c66affSColin Finck     /* meaning its members must be pointers to other structures, rather */
757c2c66affSColin Finck     /* than the relative format using offsets */
758c2c66affSColin Finck     psa = (PSECURITY_ATTRIBUTES)pMem;
759c2c66affSColin Finck     SecurityDescriptor = (PSECURITY_DESCRIPTOR)(pMem + sizeof(SECURITY_ATTRIBUTES));
760c2c66affSColin Finck     pACL = (PACL)(((PBYTE)SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH);
761c2c66affSColin Finck 
762c2c66affSColin Finck     // Initialize an EXPLICIT_ACCESS structure for an ACE.
763c2c66affSColin Finck     // The ACE will allow this thread to log off (and shut down the system, currently).
764c2c66affSColin Finck     ZeroMemory(&Access, sizeof(Access));
765c2c66affSColin Finck     Access.grfAccessPermissions = THREAD_SET_THREAD_TOKEN;
766c2c66affSColin Finck     Access.grfAccessMode = SET_ACCESS; // GRANT_ACCESS?
767c2c66affSColin Finck     Access.grfInheritance = NO_INHERITANCE;
768c2c66affSColin Finck     Access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
769c2c66affSColin Finck     Access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
770c2c66affSColin Finck     Access.Trustee.ptstrName = pEveryoneSID;
771c2c66affSColin Finck 
772c2c66affSColin Finck     if (SetEntriesInAcl(1, &Access, NULL, &pACL) != ERROR_SUCCESS)
773c2c66affSColin Finck     {
774c2c66affSColin Finck         ERR("Failed to set Access Rights for logoff thread. Logging out will most likely fail.\n");
775c2c66affSColin Finck 
776c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pMem);
777c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
778c2c66affSColin Finck     }
779c2c66affSColin Finck 
780c2c66affSColin Finck     if (!InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
781c2c66affSColin Finck     {
782c2c66affSColin Finck         ERR("Failed to initialize security descriptor for logoff thread!\n");
783c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pMem);
784c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
785c2c66affSColin Finck     }
786c2c66affSColin Finck 
787c2c66affSColin Finck     if (!SetSecurityDescriptorDacl(SecurityDescriptor,
788c2c66affSColin Finck                                    TRUE,     // bDaclPresent flag
789c2c66affSColin Finck                                    pACL,
790c2c66affSColin Finck                                    FALSE))   // not a default DACL
791c2c66affSColin Finck     {
792c2c66affSColin Finck         ERR("SetSecurityDescriptorDacl Error %lu\n", GetLastError());
793c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pMem);
794c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
795c2c66affSColin Finck     }
796c2c66affSColin Finck 
797c2c66affSColin Finck     psa->nLength = sizeof(SECURITY_ATTRIBUTES);
798c2c66affSColin Finck     psa->lpSecurityDescriptor = SecurityDescriptor;
799c2c66affSColin Finck     psa->bInheritHandle = FALSE;
800c2c66affSColin Finck 
801c2c66affSColin Finck     *ppsa = psa;
802c2c66affSColin Finck 
803c2c66affSColin Finck     return STATUS_SUCCESS;
804c2c66affSColin Finck }
805c2c66affSColin Finck 
806c2c66affSColin Finck static
807c2c66affSColin Finck VOID
DestroyLogoffSecurityAttributes(IN PSECURITY_ATTRIBUTES psa)808c2c66affSColin Finck DestroyLogoffSecurityAttributes(
809c2c66affSColin Finck     IN PSECURITY_ATTRIBUTES psa)
810c2c66affSColin Finck {
811c2c66affSColin Finck     if (psa)
812c2c66affSColin Finck     {
813c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, psa);
814c2c66affSColin Finck     }
815c2c66affSColin Finck }
816c2c66affSColin Finck 
817c2c66affSColin Finck 
818c2c66affSColin Finck static
819c2c66affSColin Finck NTSTATUS
HandleLogoff(_Inout_ PWLSESSION Session,_In_ DWORD wlxAction)820c2c66affSColin Finck HandleLogoff(
82177bfc12eSThamatip Chitpong     _Inout_ PWLSESSION Session,
82277bfc12eSThamatip Chitpong     _In_ DWORD wlxAction)
823c2c66affSColin Finck {
824c2c66affSColin Finck     PLOGOFF_SHUTDOWN_DATA LSData;
825c2c66affSColin Finck     PSECURITY_ATTRIBUTES psa;
826c2c66affSColin Finck     HANDLE hThread;
827c2c66affSColin Finck     DWORD exitCode;
828c2c66affSColin Finck     NTSTATUS Status;
829c2c66affSColin Finck 
830c2c66affSColin Finck     /* Prepare data for logoff thread */
831c2c66affSColin Finck     LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
832c2c66affSColin Finck     if (!LSData)
833c2c66affSColin Finck     {
834c2c66affSColin Finck         ERR("Failed to allocate mem for thread data\n");
835c2c66affSColin Finck         return STATUS_NO_MEMORY;
836c2c66affSColin Finck     }
83777bfc12eSThamatip Chitpong 
83877bfc12eSThamatip Chitpong     LSData->Flags = EWX_LOGOFF;
83977bfc12eSThamatip Chitpong     if (wlxAction == WLX_SAS_ACTION_FORCE_LOGOFF)
84077bfc12eSThamatip Chitpong     {
84177bfc12eSThamatip Chitpong         LSData->Flags |= EWX_FORCE;
84277bfc12eSThamatip Chitpong     }
84377bfc12eSThamatip Chitpong 
844c2c66affSColin Finck     LSData->Session = Session;
845c2c66affSColin Finck 
846c2c66affSColin Finck     Status = CreateLogoffSecurityAttributes(&psa);
847c2c66affSColin Finck     if (!NT_SUCCESS(Status))
848c2c66affSColin Finck     {
849c2c66affSColin Finck         ERR("Failed to create a required security descriptor. Status 0x%08lx\n", Status);
850c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, LSData);
851c2c66affSColin Finck         return Status;
852c2c66affSColin Finck     }
853c2c66affSColin Finck 
854c2c66affSColin Finck     /* Run logoff thread */
855c2c66affSColin Finck     hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
856c2c66affSColin Finck     if (!hThread)
857c2c66affSColin Finck     {
858c2c66affSColin Finck         ERR("Unable to create logoff thread, error %lu\n", GetLastError());
859c2c66affSColin Finck         DestroyLogoffSecurityAttributes(psa);
860c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, LSData);
861c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
862c2c66affSColin Finck     }
863c2c66affSColin Finck     WaitForSingleObject(hThread, INFINITE);
864c2c66affSColin Finck     if (!GetExitCodeThread(hThread, &exitCode))
865c2c66affSColin Finck     {
866c2c66affSColin Finck         ERR("Unable to get exit code of logoff thread (error %lu)\n", GetLastError());
867c2c66affSColin Finck         CloseHandle(hThread);
868c2c66affSColin Finck         DestroyLogoffSecurityAttributes(psa);
869c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, LSData);
870c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
871c2c66affSColin Finck     }
872c2c66affSColin Finck     CloseHandle(hThread);
873c2c66affSColin Finck     if (exitCode == 0)
874c2c66affSColin Finck     {
875c2c66affSColin Finck         ERR("Logoff thread returned failure\n");
876c2c66affSColin Finck         DestroyLogoffSecurityAttributes(psa);
877c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, LSData);
878c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
879c2c66affSColin Finck     }
880c2c66affSColin Finck 
881c2c66affSColin Finck     SwitchDesktop(Session->WinlogonDesktop);
882c2c66affSColin Finck 
88337375fccSThamatip Chitpong     PlayLogoffShutdownSound(Session, WLX_SHUTTINGDOWN(wlxAction));
88402eee253SHermès Bélusca-Maïto 
88502eee253SHermès Bélusca-Maïto     SetWindowStationUser(Session->InteractiveWindowStation,
88602eee253SHermès Bélusca-Maïto                          &LuidNone, NULL, 0);
88702eee253SHermès Bélusca-Maïto 
888c2c66affSColin Finck     // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOGGINGOFF);
889c2c66affSColin Finck 
890c2c66affSColin Finck     // FIXME: Closing network connections!
891c2c66affSColin Finck     // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_CLOSINGNETWORKCONNECTIONS);
892c2c66affSColin Finck 
893c2c66affSColin Finck     /* Kill remaining COM apps. Only at logoff! */
894c2c66affSColin Finck     hThread = CreateThread(psa, 0, KillComProcesses, (LPVOID)LSData, 0, NULL);
895c2c66affSColin Finck     if (hThread)
896c2c66affSColin Finck     {
897c2c66affSColin Finck         WaitForSingleObject(hThread, INFINITE);
898c2c66affSColin Finck         CloseHandle(hThread);
899c2c66affSColin Finck     }
900c2c66affSColin Finck 
901c2c66affSColin Finck     /* We're done with the SECURITY_DESCRIPTOR */
902c2c66affSColin Finck     DestroyLogoffSecurityAttributes(psa);
903c2c66affSColin Finck     psa = NULL;
904c2c66affSColin Finck 
905c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, LSData);
906c2c66affSColin Finck 
907c2c66affSColin Finck     DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_SAVEYOURSETTINGS);
908c2c66affSColin Finck 
909c2c66affSColin Finck     UnloadUserProfile(Session->UserToken, Session->hProfileInfo);
910c2c66affSColin Finck 
911c2c66affSColin Finck     CallNotificationDlls(Session, LogoffHandler);
912c2c66affSColin Finck 
913c2c66affSColin Finck     CloseHandle(Session->UserToken);
914c2c66affSColin Finck     UpdatePerUserSystemParameters(0, FALSE);
915c2c66affSColin Finck     Session->LogonState = STATE_LOGGED_OFF;
916c2c66affSColin Finck     Session->UserToken = NULL;
917c2c66affSColin Finck 
918c2c66affSColin Finck     return STATUS_SUCCESS;
919c2c66affSColin Finck }
920c2c66affSColin Finck 
921c2c66affSColin Finck static
922c2c66affSColin Finck INT_PTR
923c2c66affSColin Finck CALLBACK
ShutdownComputerWindowProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)924c2c66affSColin Finck ShutdownComputerWindowProc(
925c2c66affSColin Finck     IN HWND hwndDlg,
926c2c66affSColin Finck     IN UINT uMsg,
927c2c66affSColin Finck     IN WPARAM wParam,
928c2c66affSColin Finck     IN LPARAM lParam)
929c2c66affSColin Finck {
930c2c66affSColin Finck     UNREFERENCED_PARAMETER(lParam);
931c2c66affSColin Finck 
932c2c66affSColin Finck     switch (uMsg)
933c2c66affSColin Finck     {
934c2c66affSColin Finck         case WM_COMMAND:
935c2c66affSColin Finck         {
936c2c66affSColin Finck             switch (LOWORD(wParam))
937c2c66affSColin Finck             {
938c2c66affSColin Finck                 case IDC_BTNSHTDOWNCOMPUTER:
939c2c66affSColin Finck                     EndDialog(hwndDlg, IDC_BTNSHTDOWNCOMPUTER);
940c2c66affSColin Finck                     return TRUE;
941c2c66affSColin Finck             }
942c2c66affSColin Finck             break;
943c2c66affSColin Finck         }
944c2c66affSColin Finck         case WM_INITDIALOG:
945c2c66affSColin Finck         {
946c2c66affSColin Finck             RemoveMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND);
947c2c66affSColin Finck             SetFocus(GetDlgItem(hwndDlg, IDC_BTNSHTDOWNCOMPUTER));
948c2c66affSColin Finck             return TRUE;
949c2c66affSColin Finck         }
950c2c66affSColin Finck     }
951c2c66affSColin Finck     return FALSE;
952c2c66affSColin Finck }
953c2c66affSColin Finck 
954c2c66affSColin Finck static
955c2c66affSColin Finck VOID
UninitializeSAS(IN OUT PWLSESSION Session)956c2c66affSColin Finck UninitializeSAS(
957c2c66affSColin Finck     IN OUT PWLSESSION Session)
958c2c66affSColin Finck {
959c2c66affSColin Finck     if (Session->SASWindow)
960c2c66affSColin Finck     {
961c2c66affSColin Finck         DestroyWindow(Session->SASWindow);
962c2c66affSColin Finck         Session->SASWindow = NULL;
963c2c66affSColin Finck     }
964c2c66affSColin Finck     if (Session->hEndOfScreenSaverThread)
965c2c66affSColin Finck         SetEvent(Session->hEndOfScreenSaverThread);
966c2c66affSColin Finck     UnregisterClassW(WINLOGON_SAS_CLASS, hAppInstance);
967c2c66affSColin Finck }
968c2c66affSColin Finck 
969c2c66affSColin Finck NTSTATUS
HandleShutdown(IN OUT PWLSESSION Session,IN DWORD wlxAction)970c2c66affSColin Finck HandleShutdown(
971c2c66affSColin Finck     IN OUT PWLSESSION Session,
972c2c66affSColin Finck     IN DWORD wlxAction)
973c2c66affSColin Finck {
974c2c66affSColin Finck     PLOGOFF_SHUTDOWN_DATA LSData;
975c2c66affSColin Finck     HANDLE hThread;
976c2c66affSColin Finck     DWORD exitCode;
977c2c66affSColin Finck     BOOLEAN Old;
978c2c66affSColin Finck 
979c2c66affSColin Finck     // SwitchDesktop(Session->WinlogonDesktop);
9805f033392SArnav Bhatt 
9815f033392SArnav Bhatt     /* If the system is rebooting, show the appropriate string */
9825f033392SArnav Bhatt     if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT)
9835f033392SArnav Bhatt         DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISRESTARTING);
9845f033392SArnav Bhatt     else
985c2c66affSColin Finck         DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISSHUTTINGDOWN);
986c2c66affSColin Finck 
987c2c66affSColin Finck     /* Prepare data for shutdown thread */
988c2c66affSColin Finck     LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
989c2c66affSColin Finck     if (!LSData)
990c2c66affSColin Finck     {
991c2c66affSColin Finck         ERR("Failed to allocate mem for thread data\n");
992c2c66affSColin Finck         return STATUS_NO_MEMORY;
993c2c66affSColin Finck     }
994c2c66affSColin Finck     if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_POWER_OFF)
995c2c66affSColin Finck         LSData->Flags = EWX_POWEROFF;
996c2c66affSColin Finck     else if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT)
997c2c66affSColin Finck         LSData->Flags = EWX_REBOOT;
998c2c66affSColin Finck     else
999c2c66affSColin Finck         LSData->Flags = EWX_SHUTDOWN;
1000c2c66affSColin Finck     LSData->Session = Session;
1001c2c66affSColin Finck 
1002c2c66affSColin Finck     // FIXME: We may need to specify this flag to really force application kill
1003c2c66affSColin Finck     // (we are shutting down ReactOS, not just logging off so no hangs, etc...
1004c2c66affSColin Finck     // should be allowed).
1005c2c66affSColin Finck     // LSData->Flags |= EWX_FORCE;
1006c2c66affSColin Finck 
1007c2c66affSColin Finck     /* Run shutdown thread */
1008c2c66affSColin Finck     hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
1009c2c66affSColin Finck     if (!hThread)
1010c2c66affSColin Finck     {
1011c2c66affSColin Finck         ERR("Unable to create shutdown thread, error %lu\n", GetLastError());
1012c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, LSData);
1013c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
1014c2c66affSColin Finck     }
1015c2c66affSColin Finck     WaitForSingleObject(hThread, INFINITE);
1016c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, LSData);
1017c2c66affSColin Finck     if (!GetExitCodeThread(hThread, &exitCode))
1018c2c66affSColin Finck     {
1019c2c66affSColin Finck         ERR("Unable to get exit code of shutdown thread (error %lu)\n", GetLastError());
1020c2c66affSColin Finck         CloseHandle(hThread);
1021c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
1022c2c66affSColin Finck     }
1023c2c66affSColin Finck     CloseHandle(hThread);
1024c2c66affSColin Finck     if (exitCode == 0)
1025c2c66affSColin Finck     {
1026c2c66affSColin Finck         ERR("Shutdown thread returned failure\n");
1027c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
1028c2c66affSColin Finck     }
1029c2c66affSColin Finck 
1030c2c66affSColin Finck     CallNotificationDlls(Session, ShutdownHandler);
1031c2c66affSColin Finck 
1032c2c66affSColin Finck     /* Destroy SAS window */
1033c2c66affSColin Finck     UninitializeSAS(Session);
1034c2c66affSColin Finck 
1035c2c66affSColin Finck     /* Now we can shut down NT */
1036c2c66affSColin Finck     ERR("Shutting down NT...\n");
1037c2c66affSColin Finck     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
1038c2c66affSColin Finck     if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT)
1039c2c66affSColin Finck     {
1040c2c66affSColin Finck         NtShutdownSystem(ShutdownReboot);
1041c2c66affSColin Finck     }
1042c2c66affSColin Finck     else
1043c2c66affSColin Finck     {
1044c2c66affSColin Finck         if (FALSE)
1045c2c66affSColin Finck         {
1046c2c66affSColin Finck             /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */
1047c2c66affSColin Finck             DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER),
1048c2c66affSColin Finck                       GetDesktopWindow(), ShutdownComputerWindowProc);
1049c2c66affSColin Finck         }
1050c2c66affSColin Finck         NtShutdownSystem(ShutdownNoReboot);
1051c2c66affSColin Finck     }
1052c2c66affSColin Finck     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
1053c2c66affSColin Finck     return STATUS_SUCCESS;
1054c2c66affSColin Finck }
1055c2c66affSColin Finck 
1056c2c66affSColin Finck static
1057c2c66affSColin Finck VOID
DoGenericAction(IN OUT PWLSESSION Session,IN DWORD wlxAction)1058c2c66affSColin Finck DoGenericAction(
1059c2c66affSColin Finck     IN OUT PWLSESSION Session,
1060c2c66affSColin Finck     IN DWORD wlxAction)
1061c2c66affSColin Finck {
1062c2c66affSColin Finck     switch (wlxAction)
1063c2c66affSColin Finck     {
1064c2c66affSColin Finck         case WLX_SAS_ACTION_LOGON: /* 0x01 */
1065c2c66affSColin Finck             if (Session->LogonState == STATE_LOGGED_OFF_SAS)
1066c2c66affSColin Finck             {
1067c2c66affSColin Finck                 if (!HandleLogon(Session))
1068c2c66affSColin Finck                 {
1069c2c66affSColin Finck                     Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
1070c2c66affSColin Finck                     CallNotificationDlls(Session, LogonHandler);
1071c2c66affSColin Finck                 }
1072c2c66affSColin Finck             }
1073c2c66affSColin Finck             break;
1074c2c66affSColin Finck         case WLX_SAS_ACTION_NONE: /* 0x02 */
1075c2c66affSColin Finck             if (Session->LogonState == STATE_LOGGED_OFF_SAS)
1076c2c66affSColin Finck             {
1077c2c66affSColin Finck                 Session->LogonState = STATE_LOGGED_OFF;
1078c2c66affSColin Finck                 Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
1079c2c66affSColin Finck             }
1080c2c66affSColin Finck             else if (Session->LogonState == STATE_LOGGED_ON_SAS)
1081c2c66affSColin Finck             {
1082c2c66affSColin Finck                 Session->LogonState = STATE_LOGGED_ON;
1083c2c66affSColin Finck             }
1084c2c66affSColin Finck             else if (Session->LogonState == STATE_LOCKED_SAS)
1085c2c66affSColin Finck             {
1086c2c66affSColin Finck                 Session->LogonState = STATE_LOCKED;
1087c2c66affSColin Finck                 Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context);
1088c2c66affSColin Finck             }
1089c2c66affSColin Finck             break;
1090c2c66affSColin Finck         case WLX_SAS_ACTION_LOCK_WKSTA: /* 0x03 */
1091c2c66affSColin Finck             if (Session->Gina.Functions.WlxIsLockOk(Session->Gina.Context))
1092c2c66affSColin Finck             {
1093c2c66affSColin Finck                 SwitchDesktop(Session->WinlogonDesktop);
1094c2c66affSColin Finck                 Session->LogonState = STATE_LOCKED;
1095c2c66affSColin Finck                 Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context);
1096c2c66affSColin Finck                 CallNotificationDlls(Session, LockHandler);
1097c2c66affSColin Finck             }
1098c2c66affSColin Finck             break;
1099c2c66affSColin Finck         case WLX_SAS_ACTION_LOGOFF: /* 0x04 */
1100c2c66affSColin Finck         case WLX_SAS_ACTION_SHUTDOWN: /* 0x05 */
110122635479SCarl J. Bialorucki         case WLX_SAS_ACTION_FORCE_LOGOFF: /* 0x09 */
1102c2c66affSColin Finck         case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: /* 0x0a */
1103c2c66affSColin Finck         case WLX_SAS_ACTION_SHUTDOWN_REBOOT: /* 0x0b */
1104c2c66affSColin Finck             if (Session->LogonState != STATE_LOGGED_OFF)
1105c2c66affSColin Finck             {
1106c2c66affSColin Finck                 if (!Session->Gina.Functions.WlxIsLogoffOk(Session->Gina.Context))
1107c2c66affSColin Finck                     break;
110877bfc12eSThamatip Chitpong                 if (!NT_SUCCESS(HandleLogoff(Session, wlxAction)))
1109c2c66affSColin Finck                 {
1110c2c66affSColin Finck                     RemoveStatusMessage(Session);
1111c2c66affSColin Finck                     break;
1112c2c66affSColin Finck                 }
1113c2c66affSColin Finck                 Session->Gina.Functions.WlxLogoff(Session->Gina.Context);
1114c2c66affSColin Finck             }
1115c2c66affSColin Finck             if (WLX_SHUTTINGDOWN(wlxAction))
1116c2c66affSColin Finck             {
1117c2c66affSColin Finck                 // FIXME: WlxShutdown should be done from inside HandleShutdown,
1118c2c66affSColin Finck                 // after having displayed "ReactOS is shutting down" message.
1119c2c66affSColin Finck                 Session->Gina.Functions.WlxShutdown(Session->Gina.Context, wlxAction);
1120c2c66affSColin Finck                 if (!NT_SUCCESS(HandleShutdown(Session, wlxAction)))
1121c2c66affSColin Finck                 {
1122c2c66affSColin Finck                     RemoveStatusMessage(Session);
1123c2c66affSColin Finck                     Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
1124c2c66affSColin Finck                 }
1125c2c66affSColin Finck             }
1126c2c66affSColin Finck             else
1127c2c66affSColin Finck             {
1128c2c66affSColin Finck                 RemoveStatusMessage(Session);
1129c2c66affSColin Finck                 Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
1130c2c66affSColin Finck             }
1131c2c66affSColin Finck             break;
1132c2c66affSColin Finck         case WLX_SAS_ACTION_TASKLIST: /* 0x07 */
1133c2c66affSColin Finck             SwitchDesktop(Session->ApplicationDesktop);
1134c2c66affSColin Finck             Session->LogonState = STATE_LOGGED_ON;
1135c2c66affSColin Finck             StartTaskManager(Session);
1136c2c66affSColin Finck             break;
1137c2c66affSColin Finck         case WLX_SAS_ACTION_UNLOCK_WKSTA: /* 0x08 */
1138c2c66affSColin Finck             SwitchDesktop(Session->ApplicationDesktop);
1139c2c66affSColin Finck             Session->LogonState = STATE_LOGGED_ON;
1140c2c66affSColin Finck             CallNotificationDlls(Session, UnlockHandler);
1141c2c66affSColin Finck             break;
1142c2c66affSColin Finck         default:
1143c2c66affSColin Finck             WARN("Unknown SAS action 0x%lx\n", wlxAction);
1144c2c66affSColin Finck     }
1145c2c66affSColin Finck }
1146c2c66affSColin Finck 
1147c2c66affSColin Finck static
1148c2c66affSColin Finck VOID
DispatchSAS(IN OUT PWLSESSION Session,IN DWORD dwSasType)1149c2c66affSColin Finck DispatchSAS(
1150c2c66affSColin Finck     IN OUT PWLSESSION Session,
1151c2c66affSColin Finck     IN DWORD dwSasType)
1152c2c66affSColin Finck {
1153c2c66affSColin Finck     DWORD wlxAction = WLX_SAS_ACTION_NONE;
1154c2c66affSColin Finck     PSID LogonSid = NULL; /* FIXME */
1155c2c66affSColin Finck     BOOL bSecure = TRUE;
1156c2c66affSColin Finck 
1157c2c66affSColin Finck     switch (dwSasType)
1158c2c66affSColin Finck     {
1159c2c66affSColin Finck         case WLX_SAS_TYPE_CTRL_ALT_DEL:
1160c2c66affSColin Finck             switch (Session->LogonState)
1161c2c66affSColin Finck             {
1162c2c66affSColin Finck                 case STATE_INIT:
1163c2c66affSColin Finck                     Session->LogonState = STATE_LOGGED_OFF;
1164c2c66affSColin Finck                     Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
1165c2c66affSColin Finck                     return;
1166c2c66affSColin Finck 
1167c2c66affSColin Finck                 case STATE_LOGGED_OFF:
1168c2c66affSColin Finck                     Session->LogonState = STATE_LOGGED_OFF_SAS;
1169c2c66affSColin Finck 
117002f3cb53SEric Kohl                     CloseAllDialogWindows();
1171c2c66affSColin Finck 
1172c2c66affSColin Finck                     Session->Options = 0;
1173c2c66affSColin Finck 
1174c2c66affSColin Finck                     wlxAction = (DWORD)Session->Gina.Functions.WlxLoggedOutSAS(
1175c2c66affSColin Finck                         Session->Gina.Context,
1176c2c66affSColin Finck                         Session->SASAction,
1177c2c66affSColin Finck                         &Session->LogonId,
1178c2c66affSColin Finck                         LogonSid,
1179c2c66affSColin Finck                         &Session->Options,
1180c2c66affSColin Finck                         &Session->UserToken,
1181c2c66affSColin Finck                         &Session->MprNotifyInfo,
1182c2c66affSColin Finck                         (PVOID*)&Session->Profile);
1183c2c66affSColin Finck                     break;
1184c2c66affSColin Finck 
1185c2c66affSColin Finck                 case STATE_LOGGED_OFF_SAS:
1186c2c66affSColin Finck                     /* Ignore SAS if we are already in an SAS state */
1187c2c66affSColin Finck                     return;
1188c2c66affSColin Finck 
1189c2c66affSColin Finck                 case STATE_LOGGED_ON:
1190c2c66affSColin Finck                     Session->LogonState = STATE_LOGGED_ON_SAS;
1191c2c66affSColin Finck                     wlxAction = (DWORD)Session->Gina.Functions.WlxLoggedOnSAS(Session->Gina.Context, dwSasType, NULL);
1192c2c66affSColin Finck                     break;
1193c2c66affSColin Finck 
1194c2c66affSColin Finck                 case STATE_LOGGED_ON_SAS:
1195c2c66affSColin Finck                     /* Ignore SAS if we are already in an SAS state */
1196c2c66affSColin Finck                     return;
1197c2c66affSColin Finck 
1198c2c66affSColin Finck                 case STATE_LOCKED:
1199c2c66affSColin Finck                     Session->LogonState = STATE_LOCKED_SAS;
1200c2c66affSColin Finck 
120102f3cb53SEric Kohl                     CloseAllDialogWindows();
1202c2c66affSColin Finck 
1203c2c66affSColin Finck                     wlxAction = (DWORD)Session->Gina.Functions.WlxWkstaLockedSAS(Session->Gina.Context, dwSasType);
1204c2c66affSColin Finck                     break;
1205c2c66affSColin Finck 
1206c2c66affSColin Finck                 case STATE_LOCKED_SAS:
1207c2c66affSColin Finck                     /* Ignore SAS if we are already in an SAS state */
1208c2c66affSColin Finck                     return;
1209c2c66affSColin Finck 
1210c2c66affSColin Finck                 default:
1211c2c66affSColin Finck                     return;
1212c2c66affSColin Finck             }
1213c2c66affSColin Finck             break;
1214c2c66affSColin Finck 
1215c2c66affSColin Finck         case WLX_SAS_TYPE_TIMEOUT:
1216c2c66affSColin Finck             return;
1217c2c66affSColin Finck 
1218c2c66affSColin Finck         case WLX_SAS_TYPE_SCRNSVR_TIMEOUT:
1219c2c66affSColin Finck             if (!Session->Gina.Functions.WlxScreenSaverNotify(Session->Gina.Context, &bSecure))
1220c2c66affSColin Finck             {
1221c2c66affSColin Finck                 /* Skip start of screen saver */
1222c2c66affSColin Finck                 SetEvent(Session->hEndOfScreenSaver);
1223c2c66affSColin Finck             }
1224c2c66affSColin Finck             else
1225c2c66affSColin Finck             {
1226c2c66affSColin Finck                 StartScreenSaver(Session);
1227c2c66affSColin Finck                 if (bSecure)
1228c2c66affSColin Finck                 {
1229c2c66affSColin Finck                     wlxAction = WLX_SAS_ACTION_LOCK_WKSTA;
1230c2c66affSColin Finck //                    DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA);
1231c2c66affSColin Finck                 }
1232c2c66affSColin Finck             }
1233c2c66affSColin Finck             break;
1234c2c66affSColin Finck 
1235c2c66affSColin Finck         case WLX_SAS_TYPE_SCRNSVR_ACTIVITY:
1236c2c66affSColin Finck             SetEvent(Session->hUserActivity);
1237c2c66affSColin Finck             break;
1238c2c66affSColin Finck     }
1239c2c66affSColin Finck 
1240c2c66affSColin Finck     DoGenericAction(Session, wlxAction);
1241c2c66affSColin Finck }
1242c2c66affSColin Finck 
1243c2c66affSColin Finck static
1244c2c66affSColin Finck BOOL
RegisterHotKeys(IN PWLSESSION Session,IN HWND hwndSAS)1245c2c66affSColin Finck RegisterHotKeys(
1246c2c66affSColin Finck     IN PWLSESSION Session,
1247c2c66affSColin Finck     IN HWND hwndSAS)
1248c2c66affSColin Finck {
1249c2c66affSColin Finck     /* Register Ctrl+Alt+Del Hotkey */
1250c2c66affSColin Finck     if (!RegisterHotKey(hwndSAS, HK_CTRL_ALT_DEL, MOD_CONTROL | MOD_ALT, VK_DELETE))
1251c2c66affSColin Finck     {
1252c2c66affSColin Finck         ERR("WL: Unable to register Ctrl+Alt+Del hotkey!\n");
1253c2c66affSColin Finck         return FALSE;
1254c2c66affSColin Finck     }
1255c2c66affSColin Finck 
1256c2c66affSColin Finck     /* Register Ctrl+Shift+Esc (optional) */
1257c2c66affSColin Finck     Session->TaskManHotkey = RegisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC, MOD_CONTROL | MOD_SHIFT, VK_ESCAPE);
1258c2c66affSColin Finck     if (!Session->TaskManHotkey)
1259c2c66affSColin Finck         WARN("WL: Warning: Unable to register Ctrl+Alt+Esc hotkey!\n");
1260c2c66affSColin Finck     return TRUE;
1261c2c66affSColin Finck }
1262c2c66affSColin Finck 
1263c2c66affSColin Finck static
1264c2c66affSColin Finck BOOL
UnregisterHotKeys(IN PWLSESSION Session,IN HWND hwndSAS)1265c2c66affSColin Finck UnregisterHotKeys(
1266c2c66affSColin Finck     IN PWLSESSION Session,
1267c2c66affSColin Finck     IN HWND hwndSAS)
1268c2c66affSColin Finck {
1269c2c66affSColin Finck     /* Unregister hotkeys */
1270c2c66affSColin Finck     UnregisterHotKey(hwndSAS, HK_CTRL_ALT_DEL);
1271c2c66affSColin Finck 
1272c2c66affSColin Finck     if (Session->TaskManHotkey)
1273c2c66affSColin Finck         UnregisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC);
1274c2c66affSColin Finck 
1275c2c66affSColin Finck     return TRUE;
1276c2c66affSColin Finck }
1277c2c66affSColin Finck 
12789d48f26dSThamatip Chitpong static
1279c2c66affSColin Finck BOOL
HandleMessageBeep(_In_ PWLSESSION Session,_In_ UINT uType)12809d48f26dSThamatip Chitpong HandleMessageBeep(
12819d48f26dSThamatip Chitpong     _In_ PWLSESSION Session,
12829d48f26dSThamatip Chitpong     _In_ UINT uType)
1283c2c66affSColin Finck {
1284c2c66affSColin Finck     LPWSTR EventName;
1285c2c66affSColin Finck 
1286c2c66affSColin Finck     switch (uType)
1287c2c66affSColin Finck     {
1288c2c66affSColin Finck         case 0xFFFFFFFF:
1289c2c66affSColin Finck             EventName = NULL;
1290c2c66affSColin Finck             break;
1291c2c66affSColin Finck         case MB_OK:
1292c2c66affSColin Finck             EventName = L"SystemDefault";
1293c2c66affSColin Finck             break;
1294c2c66affSColin Finck         case MB_ICONASTERISK:
1295c2c66affSColin Finck             EventName = L"SystemAsterisk";
1296c2c66affSColin Finck             break;
1297c2c66affSColin Finck         case MB_ICONEXCLAMATION:
1298c2c66affSColin Finck             EventName = L"SystemExclamation";
1299c2c66affSColin Finck             break;
1300c2c66affSColin Finck         case MB_ICONHAND:
1301c2c66affSColin Finck             EventName = L"SystemHand";
1302c2c66affSColin Finck             break;
1303c2c66affSColin Finck         case MB_ICONQUESTION:
1304c2c66affSColin Finck             EventName = L"SystemQuestion";
1305c2c66affSColin Finck             break;
1306c2c66affSColin Finck         default:
1307c2c66affSColin Finck             WARN("Unhandled type %d\n", uType);
1308c2c66affSColin Finck             EventName = L"SystemDefault";
1309c2c66affSColin Finck     }
1310c2c66affSColin Finck 
13119d48f26dSThamatip Chitpong     return PlayEventSound(Session, EventName);
1312c2c66affSColin Finck }
1313c2c66affSColin Finck 
1314c2c66affSColin Finck static
1315c2c66affSColin Finck LRESULT
1316c2c66affSColin Finck CALLBACK
SASWindowProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)1317c2c66affSColin Finck SASWindowProc(
1318c2c66affSColin Finck     IN HWND hwndDlg,
1319c2c66affSColin Finck     IN UINT uMsg,
1320c2c66affSColin Finck     IN WPARAM wParam,
1321c2c66affSColin Finck     IN LPARAM lParam)
1322c2c66affSColin Finck {
1323c2c66affSColin Finck     PWLSESSION Session = (PWLSESSION)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
1324c2c66affSColin Finck 
1325c2c66affSColin Finck     switch (uMsg)
1326c2c66affSColin Finck     {
1327c2c66affSColin Finck         case WM_HOTKEY:
1328c2c66affSColin Finck         {
1329c2c66affSColin Finck             switch (lParam)
1330c2c66affSColin Finck             {
1331c2c66affSColin Finck                 case MAKELONG(MOD_CONTROL | MOD_ALT, VK_DELETE):
1332c2c66affSColin Finck                 {
1333c2c66affSColin Finck                     TRACE("SAS: CONTROL+ALT+DELETE\n");
1334c2c66affSColin Finck                     if (!Session->Gina.UseCtrlAltDelete)
1335c2c66affSColin Finck                         break;
1336c2c66affSColin Finck                     PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0);
1337c2c66affSColin Finck                     return TRUE;
1338c2c66affSColin Finck                 }
1339c2c66affSColin Finck                 case MAKELONG(MOD_CONTROL | MOD_SHIFT, VK_ESCAPE):
1340c2c66affSColin Finck                 {
1341c2c66affSColin Finck                     TRACE("SAS: CONTROL+SHIFT+ESCAPE\n");
134246dcab7aSEric Kohl                     if (Session->LogonState == STATE_LOGGED_ON)
1343c2c66affSColin Finck                         DoGenericAction(Session, WLX_SAS_ACTION_TASKLIST);
1344c2c66affSColin Finck                     return TRUE;
1345c2c66affSColin Finck                 }
1346c2c66affSColin Finck             }
1347c2c66affSColin Finck             break;
1348c2c66affSColin Finck         }
1349c2c66affSColin Finck         case WM_CREATE:
1350c2c66affSColin Finck         {
1351c2c66affSColin Finck             /* Get the session pointer from the create data */
1352c2c66affSColin Finck             Session = (PWLSESSION)((LPCREATESTRUCT)lParam)->lpCreateParams;
1353c2c66affSColin Finck 
1354c2c66affSColin Finck             /* Save the Session pointer */
1355c2c66affSColin Finck             SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)Session);
1356c2c66affSColin Finck             if (GetSetupType())
1357c2c66affSColin Finck                 return TRUE;
1358c2c66affSColin Finck             return RegisterHotKeys(Session, hwndDlg);
1359c2c66affSColin Finck         }
1360c2c66affSColin Finck         case WM_DESTROY:
1361c2c66affSColin Finck         {
1362c2c66affSColin Finck             if (!GetSetupType())
1363c2c66affSColin Finck                 UnregisterHotKeys(Session, hwndDlg);
1364c2c66affSColin Finck             return TRUE;
1365c2c66affSColin Finck         }
1366c2c66affSColin Finck         case WM_SETTINGCHANGE:
1367c2c66affSColin Finck         {
1368c2c66affSColin Finck             UINT uiAction = (UINT)wParam;
1369c2c66affSColin Finck             if (uiAction == SPI_SETSCREENSAVETIMEOUT
1370c2c66affSColin Finck              || uiAction == SPI_SETSCREENSAVEACTIVE)
1371c2c66affSColin Finck             {
1372c2c66affSColin Finck                 SetEvent(Session->hScreenSaverParametersChanged);
1373c2c66affSColin Finck             }
1374c2c66affSColin Finck             return TRUE;
1375c2c66affSColin Finck         }
1376c2c66affSColin Finck         case WM_LOGONNOTIFY:
1377c2c66affSColin Finck         {
1378c2c66affSColin Finck             switch(wParam)
1379c2c66affSColin Finck             {
1380c2c66affSColin Finck                 case LN_MESSAGE_BEEP:
1381c2c66affSColin Finck                 {
13829d48f26dSThamatip Chitpong                     return HandleMessageBeep(Session, lParam);
1383c2c66affSColin Finck                 }
1384c2c66affSColin Finck                 case LN_SHELL_EXITED:
1385c2c66affSColin Finck                 {
1386c2c66affSColin Finck                     /* lParam is the exit code */
13871f0fe386SEric Kohl                     if (lParam != 1 &&
13881f0fe386SEric Kohl                         Session->LogonState != STATE_LOGGED_OFF &&
13891f0fe386SEric Kohl                         Session->LogonState != STATE_LOGGED_OFF_SAS)
1390c2c66affSColin Finck                     {
1391c2c66affSColin Finck                         SetTimer(hwndDlg, 1, 1000, NULL);
1392c2c66affSColin Finck                     }
1393c2c66affSColin Finck                     break;
1394c2c66affSColin Finck                 }
1395c2c66affSColin Finck                 case LN_START_SCREENSAVE:
1396c2c66affSColin Finck                 {
1397c2c66affSColin Finck                     DispatchSAS(Session, WLX_SAS_TYPE_SCRNSVR_TIMEOUT);
1398c2c66affSColin Finck                     break;
1399c2c66affSColin Finck                 }
1400c2c66affSColin Finck                 case LN_LOCK_WORKSTATION:
1401c2c66affSColin Finck                 {
1402c2c66affSColin Finck                     DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA);
1403c2c66affSColin Finck                     break;
1404c2c66affSColin Finck                 }
1405c2c66affSColin Finck                 case LN_LOGOFF:
1406c2c66affSColin Finck                 {
1407c2c66affSColin Finck                     UINT Flags = (UINT)lParam;
1408c2c66affSColin Finck                     UINT Action = Flags & EWX_ACTION_MASK;
1409c2c66affSColin Finck                     DWORD wlxAction;
1410c2c66affSColin Finck 
1411c2c66affSColin Finck                     TRACE("\tFlags : 0x%lx\n", lParam);
1412c2c66affSColin Finck 
1413c2c66affSColin Finck                     /*
1414c2c66affSColin Finck                      * Our caller (USERSRV) should have added the shutdown flag
1415c2c66affSColin Finck                      * when setting also poweroff or reboot.
1416c2c66affSColin Finck                      */
1417c2c66affSColin Finck                     if (Action & (EWX_POWEROFF | EWX_REBOOT))
1418c2c66affSColin Finck                     {
1419c2c66affSColin Finck                         if ((Action & EWX_SHUTDOWN) == 0)
1420c2c66affSColin Finck                         {
1421c2c66affSColin Finck                             ERR("Missing EWX_SHUTDOWN flag for poweroff or reboot; action 0x%x\n", Action);
1422c2c66affSColin Finck                             return STATUS_INVALID_PARAMETER;
1423c2c66affSColin Finck                         }
1424c2c66affSColin Finck 
1425c2c66affSColin Finck                         /* Now we can locally remove it for performing checks */
1426c2c66affSColin Finck                         Action &= ~EWX_SHUTDOWN;
1427c2c66affSColin Finck                     }
1428c2c66affSColin Finck 
1429c2c66affSColin Finck                     /* Check parameters */
1430c2c66affSColin Finck                     if (Action & EWX_FORCE)
1431c2c66affSColin Finck                     {
1432c2c66affSColin Finck                         // FIXME!
1433c2c66affSColin Finck                         ERR("FIXME: EWX_FORCE present for Winlogon, what to do?\n");
1434c2c66affSColin Finck                         Action &= ~EWX_FORCE;
1435c2c66affSColin Finck                     }
1436c2c66affSColin Finck                     switch (Action)
1437c2c66affSColin Finck                     {
1438c2c66affSColin Finck                         case EWX_LOGOFF:
1439c2c66affSColin Finck                             wlxAction = WLX_SAS_ACTION_LOGOFF;
1440c2c66affSColin Finck                             break;
1441c2c66affSColin Finck                         case EWX_SHUTDOWN:
1442c2c66affSColin Finck                             wlxAction = WLX_SAS_ACTION_SHUTDOWN;
1443c2c66affSColin Finck                             break;
1444c2c66affSColin Finck                         case EWX_REBOOT:
1445c2c66affSColin Finck                             wlxAction = WLX_SAS_ACTION_SHUTDOWN_REBOOT;
1446c2c66affSColin Finck                             break;
1447c2c66affSColin Finck                         case EWX_POWEROFF:
1448c2c66affSColin Finck                             wlxAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF;
1449c2c66affSColin Finck                             break;
1450c2c66affSColin Finck 
1451c2c66affSColin Finck                         default:
1452c2c66affSColin Finck                         {
1453c2c66affSColin Finck                             ERR("Invalid ExitWindows action 0x%x\n", Action);
1454c2c66affSColin Finck                             return STATUS_INVALID_PARAMETER;
1455c2c66affSColin Finck                         }
1456c2c66affSColin Finck                     }
1457c2c66affSColin Finck 
1458c2c66affSColin Finck                     TRACE("In LN_LOGOFF, exit_in_progress == %s\n",
1459c2c66affSColin Finck                         ExitReactOSInProgress ? "true" : "false");
1460c2c66affSColin Finck 
1461c2c66affSColin Finck                     /*
1462c2c66affSColin Finck                      * In case a parallel shutdown request is done (while we are
1463c2c66affSColin Finck                      * being to shut down) and it was not done by Winlogon itself,
1464c2c66affSColin Finck                      * then just stop here.
1465c2c66affSColin Finck                      */
1466c2c66affSColin Finck #if 0
1467c2c66affSColin Finck // This code is commented at the moment (even if it's correct) because
1468c2c66affSColin Finck // our log-offs do not really work: the shell is restarted, no app is killed
1469c2c66affSColin Finck // etc... and as a result you just get explorer opening "My Documents". And
1470c2c66affSColin Finck // if you try now a shut down, it won't work because winlogon thinks it is
1471c2c66affSColin Finck // still in the middle of a shutdown.
1472c2c66affSColin Finck // Maybe we also need to reset ExitReactOSInProgress somewhere else??
1473c2c66affSColin Finck                     if (ExitReactOSInProgress && (lParam & EWX_CALLER_WINLOGON) == 0)
1474c2c66affSColin Finck                     {
1475c2c66affSColin Finck                         break;
1476c2c66affSColin Finck                     }
1477c2c66affSColin Finck #endif
1478c2c66affSColin Finck                     /* Now do the shutdown action proper */
1479c2c66affSColin Finck                     DoGenericAction(Session, wlxAction);
1480c2c66affSColin Finck                     return 1;
1481c2c66affSColin Finck                 }
1482c2c66affSColin Finck                 case LN_LOGOFF_CANCELED:
1483c2c66affSColin Finck                 {
1484c2c66affSColin Finck                     ERR("Logoff canceled!!, before: exit_in_progress == %s, after will be false\n",
1485c2c66affSColin Finck                         ExitReactOSInProgress ? "true" : "false");
1486c2c66affSColin Finck 
1487c2c66affSColin Finck                     ExitReactOSInProgress = FALSE;
1488c2c66affSColin Finck                     return 1;
1489c2c66affSColin Finck                 }
1490c2c66affSColin Finck                 default:
1491c2c66affSColin Finck                 {
1492c2c66affSColin Finck                     ERR("WM_LOGONNOTIFY case %d is unimplemented\n", wParam);
1493c2c66affSColin Finck                 }
1494c2c66affSColin Finck             }
1495c2c66affSColin Finck             return 0;
1496c2c66affSColin Finck         }
1497c2c66affSColin Finck         case WM_TIMER:
1498c2c66affSColin Finck         {
1499c2c66affSColin Finck             if (wParam == 1)
1500c2c66affSColin Finck             {
1501c2c66affSColin Finck                 KillTimer(hwndDlg, 1);
1502c2c66affSColin Finck                 StartUserShell(Session);
1503c2c66affSColin Finck             }
1504c2c66affSColin Finck             break;
1505c2c66affSColin Finck         }
1506c2c66affSColin Finck         case WLX_WM_SAS:
1507c2c66affSColin Finck         {
1508c2c66affSColin Finck             DispatchSAS(Session, (DWORD)wParam);
1509c2c66affSColin Finck             return TRUE;
1510c2c66affSColin Finck         }
1511c2c66affSColin Finck     }
1512c2c66affSColin Finck 
1513c2c66affSColin Finck     return DefWindowProc(hwndDlg, uMsg, wParam, lParam);
1514c2c66affSColin Finck }
1515c2c66affSColin Finck 
1516c2c66affSColin Finck BOOL
InitializeSAS(IN OUT PWLSESSION Session)1517c2c66affSColin Finck InitializeSAS(
1518c2c66affSColin Finck     IN OUT PWLSESSION Session)
1519c2c66affSColin Finck {
1520c2c66affSColin Finck     WNDCLASSEXW swc;
1521c2c66affSColin Finck     BOOL ret = FALSE;
1522c2c66affSColin Finck 
1523c2c66affSColin Finck     if (!SwitchDesktop(Session->WinlogonDesktop))
1524c2c66affSColin Finck     {
1525c2c66affSColin Finck         ERR("WL: Failed to switch to winlogon desktop\n");
1526c2c66affSColin Finck         goto cleanup;
1527c2c66affSColin Finck     }
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     /* Register SAS window class */
1530c2c66affSColin Finck     swc.cbSize = sizeof(WNDCLASSEXW);
1531c2c66affSColin Finck     swc.style = CS_SAVEBITS;
1532c2c66affSColin Finck     swc.lpfnWndProc = SASWindowProc;
1533c2c66affSColin Finck     swc.cbClsExtra = 0;
1534c2c66affSColin Finck     swc.cbWndExtra = 0;
1535c2c66affSColin Finck     swc.hInstance = hAppInstance;
1536c2c66affSColin Finck     swc.hIcon = NULL;
1537c2c66affSColin Finck     swc.hCursor = NULL;
1538c2c66affSColin Finck     swc.hbrBackground = NULL;
1539c2c66affSColin Finck     swc.lpszMenuName = NULL;
1540c2c66affSColin Finck     swc.lpszClassName = WINLOGON_SAS_CLASS;
1541c2c66affSColin Finck     swc.hIconSm = NULL;
1542c2c66affSColin Finck     if (RegisterClassExW(&swc) == 0)
1543c2c66affSColin Finck     {
1544c2c66affSColin Finck         ERR("WL: Failed to register SAS window class\n");
1545c2c66affSColin Finck         goto cleanup;
1546c2c66affSColin Finck     }
1547c2c66affSColin Finck 
1548c2c66affSColin Finck     /* Create invisible SAS window */
1549c2c66affSColin Finck     Session->SASWindow = CreateWindowExW(
1550c2c66affSColin Finck         0,
1551c2c66affSColin Finck         WINLOGON_SAS_CLASS,
1552c2c66affSColin Finck         WINLOGON_SAS_TITLE,
1553c2c66affSColin Finck         WS_POPUP,
1554c2c66affSColin Finck         0, 0, 0, 0, 0, 0,
1555c2c66affSColin Finck         hAppInstance, Session);
1556c2c66affSColin Finck     if (!Session->SASWindow)
1557c2c66affSColin Finck     {
1558c2c66affSColin Finck         ERR("WL: Failed to create SAS window\n");
1559c2c66affSColin Finck         goto cleanup;
1560c2c66affSColin Finck     }
1561c2c66affSColin Finck 
1562c2c66affSColin Finck     /* Register SAS window to receive SAS notifications */
1563c2c66affSColin Finck     if (!SetLogonNotifyWindow(Session->SASWindow))
1564c2c66affSColin Finck     {
1565c2c66affSColin Finck         ERR("WL: Failed to register SAS window\n");
1566c2c66affSColin Finck         goto cleanup;
1567c2c66affSColin Finck     }
1568c2c66affSColin Finck 
1569c2c66affSColin Finck     if (!SetDefaultLanguage(NULL))
1570c2c66affSColin Finck         return FALSE;
1571c2c66affSColin Finck 
1572c2c66affSColin Finck     ret = TRUE;
1573c2c66affSColin Finck 
1574c2c66affSColin Finck cleanup:
1575c2c66affSColin Finck     if (!ret)
1576c2c66affSColin Finck         UninitializeSAS(Session);
1577c2c66affSColin Finck     return ret;
1578c2c66affSColin Finck }
1579