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