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) 7c2c66affSColin Finck * 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 49c2c66affSColin Finck /* FUNCTIONS ****************************************************************/ 50c2c66affSColin Finck 51c2c66affSColin Finck static BOOL 52c2c66affSColin Finck StartTaskManager( 53c2c66affSColin Finck IN OUT PWLSESSION Session) 54c2c66affSColin Finck { 55c2c66affSColin Finck LPVOID lpEnvironment; 56c2c66affSColin Finck BOOL ret; 57c2c66affSColin Finck 58c2c66affSColin Finck if (!Session->Gina.Functions.WlxStartApplication) 59c2c66affSColin Finck return FALSE; 60c2c66affSColin Finck 61c2c66affSColin Finck if (!CreateEnvironmentBlock( 62c2c66affSColin Finck &lpEnvironment, 63c2c66affSColin Finck Session->UserToken, 64c2c66affSColin Finck TRUE)) 65c2c66affSColin Finck { 66c2c66affSColin Finck return FALSE; 67c2c66affSColin Finck } 68c2c66affSColin Finck 69c2c66affSColin Finck ret = Session->Gina.Functions.WlxStartApplication( 70c2c66affSColin Finck Session->Gina.Context, 71c2c66affSColin Finck L"Default", 72c2c66affSColin Finck lpEnvironment, 73c2c66affSColin Finck L"taskmgr.exe"); 74c2c66affSColin Finck 75c2c66affSColin Finck DestroyEnvironmentBlock(lpEnvironment); 76c2c66affSColin Finck return ret; 77c2c66affSColin Finck } 78c2c66affSColin Finck 79c2c66affSColin Finck static BOOL 80c2c66affSColin Finck StartUserShell( 81c2c66affSColin Finck IN OUT PWLSESSION Session) 82c2c66affSColin Finck { 83c2c66affSColin Finck LPVOID lpEnvironment = NULL; 84c2c66affSColin Finck BOOLEAN Old; 85c2c66affSColin Finck BOOL ret; 86c2c66affSColin Finck 87c2c66affSColin Finck /* Create environment block for the user */ 88c2c66affSColin Finck if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE)) 89c2c66affSColin Finck { 90c2c66affSColin Finck WARN("WL: CreateEnvironmentBlock() failed\n"); 91c2c66affSColin Finck return FALSE; 92c2c66affSColin Finck } 93c2c66affSColin Finck 94c2c66affSColin Finck /* Get privilege */ 95c2c66affSColin Finck /* FIXME: who should do it? winlogon or gina? */ 96c2c66affSColin Finck /* FIXME: reverting to lower privileges after creating user shell? */ 97c2c66affSColin Finck RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old); 98c2c66affSColin Finck 99c2c66affSColin Finck ret = Session->Gina.Functions.WlxActivateUserShell( 100c2c66affSColin Finck Session->Gina.Context, 101c2c66affSColin Finck L"Default", 102c2c66affSColin Finck NULL, /* FIXME */ 103c2c66affSColin Finck lpEnvironment); 104c2c66affSColin Finck 105c2c66affSColin Finck DestroyEnvironmentBlock(lpEnvironment); 106c2c66affSColin Finck return ret; 107c2c66affSColin Finck } 108c2c66affSColin Finck 109c2c66affSColin Finck 110c2c66affSColin Finck BOOL 111c2c66affSColin Finck SetDefaultLanguage( 112c2c66affSColin Finck IN PWLSESSION Session) 113c2c66affSColin Finck { 114c2c66affSColin Finck BOOL ret = FALSE; 115c2c66affSColin Finck BOOL UserProfile; 116c2c66affSColin Finck LONG rc; 117c2c66affSColin Finck HKEY UserKey, hKey = NULL; 118c2c66affSColin Finck LPCWSTR SubKey, ValueName; 119c2c66affSColin Finck DWORD dwType, dwSize; 120c2c66affSColin Finck LPWSTR Value = NULL; 121c2c66affSColin Finck UNICODE_STRING ValueString; 122c2c66affSColin Finck NTSTATUS Status; 123c2c66affSColin Finck LCID Lcid; 124c2c66affSColin Finck 125c2c66affSColin Finck UserProfile = (Session && Session->UserToken); 126c2c66affSColin Finck 127c2c66affSColin Finck if (UserProfile && !ImpersonateLoggedOnUser(Session->UserToken)) 128c2c66affSColin Finck { 129c2c66affSColin Finck ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError()); 130c2c66affSColin Finck return FALSE; 131c2c66affSColin Finck // FIXME: ... or use the default language of the system?? 132c2c66affSColin Finck // UserProfile = FALSE; 133c2c66affSColin Finck } 134c2c66affSColin Finck 135c2c66affSColin Finck if (UserProfile) 136c2c66affSColin Finck { 137c2c66affSColin Finck rc = RegOpenCurrentUser(MAXIMUM_ALLOWED, &UserKey); 138c2c66affSColin Finck if (rc != ERROR_SUCCESS) 139c2c66affSColin Finck { 140c2c66affSColin Finck TRACE("RegOpenCurrentUser() failed with error %lu\n", rc); 141c2c66affSColin Finck goto cleanup; 142c2c66affSColin Finck } 143c2c66affSColin Finck 144c2c66affSColin Finck SubKey = L"Control Panel\\International"; 145c2c66affSColin Finck ValueName = L"Locale"; 146c2c66affSColin Finck } 147c2c66affSColin Finck else 148c2c66affSColin Finck { 149c2c66affSColin Finck UserKey = NULL; 150c2c66affSColin Finck SubKey = L"System\\CurrentControlSet\\Control\\Nls\\Language"; 151c2c66affSColin Finck ValueName = L"Default"; 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck rc = RegOpenKeyExW(UserKey ? UserKey : HKEY_LOCAL_MACHINE, 155c2c66affSColin Finck SubKey, 156c2c66affSColin Finck 0, 157c2c66affSColin Finck KEY_READ, 158c2c66affSColin Finck &hKey); 159c2c66affSColin Finck 160c2c66affSColin Finck if (UserKey) 161c2c66affSColin Finck RegCloseKey(UserKey); 162c2c66affSColin Finck 163c2c66affSColin Finck if (rc != ERROR_SUCCESS) 164c2c66affSColin Finck { 165c2c66affSColin Finck TRACE("RegOpenKeyEx() failed with error %lu\n", rc); 166c2c66affSColin Finck goto cleanup; 167c2c66affSColin Finck } 168c2c66affSColin Finck 169c2c66affSColin Finck rc = RegQueryValueExW(hKey, 170c2c66affSColin Finck ValueName, 171c2c66affSColin Finck NULL, 172c2c66affSColin Finck &dwType, 173c2c66affSColin Finck NULL, 174c2c66affSColin Finck &dwSize); 175c2c66affSColin Finck if (rc != ERROR_SUCCESS) 176c2c66affSColin Finck { 177c2c66affSColin Finck TRACE("RegQueryValueEx() failed with error %lu\n", rc); 178c2c66affSColin Finck goto cleanup; 179c2c66affSColin Finck } 180c2c66affSColin Finck else if (dwType != REG_SZ) 181c2c66affSColin Finck { 182c2c66affSColin Finck TRACE("Wrong type for %S\\%S registry entry (got 0x%lx, expected 0x%x)\n", 183c2c66affSColin Finck SubKey, ValueName, dwType, REG_SZ); 184c2c66affSColin Finck goto cleanup; 185c2c66affSColin Finck } 186c2c66affSColin Finck 187c2c66affSColin Finck Value = HeapAlloc(GetProcessHeap(), 0, dwSize); 188c2c66affSColin Finck if (!Value) 189c2c66affSColin Finck { 190c2c66affSColin Finck TRACE("HeapAlloc() failed\n"); 191c2c66affSColin Finck goto cleanup; 192c2c66affSColin Finck } 193c2c66affSColin Finck rc = RegQueryValueExW(hKey, 194c2c66affSColin Finck ValueName, 195c2c66affSColin Finck NULL, 196c2c66affSColin Finck NULL, 197c2c66affSColin Finck (LPBYTE)Value, 198c2c66affSColin Finck &dwSize); 199c2c66affSColin Finck if (rc != ERROR_SUCCESS) 200c2c66affSColin Finck { 201c2c66affSColin Finck TRACE("RegQueryValueEx() failed with error %lu\n", rc); 202c2c66affSColin Finck goto cleanup; 203c2c66affSColin Finck } 204c2c66affSColin Finck 205c2c66affSColin Finck /* Convert Value to a Lcid */ 206c2c66affSColin Finck ValueString.Length = ValueString.MaximumLength = (USHORT)dwSize; 207c2c66affSColin Finck ValueString.Buffer = Value; 208c2c66affSColin Finck Status = RtlUnicodeStringToInteger(&ValueString, 16, (PULONG)&Lcid); 209c2c66affSColin Finck if (!NT_SUCCESS(Status)) 210c2c66affSColin Finck { 211c2c66affSColin Finck TRACE("RtlUnicodeStringToInteger() failed with status 0x%08lx\n", Status); 212c2c66affSColin Finck goto cleanup; 213c2c66affSColin Finck } 214c2c66affSColin Finck 215c2c66affSColin Finck TRACE("%s language is 0x%08lx\n", 216c2c66affSColin Finck UserProfile ? "User" : "System", Lcid); 217c2c66affSColin Finck Status = NtSetDefaultLocale(UserProfile, Lcid); 218c2c66affSColin Finck if (!NT_SUCCESS(Status)) 219c2c66affSColin Finck { 220c2c66affSColin Finck TRACE("NtSetDefaultLocale() failed with status 0x%08lx\n", Status); 221c2c66affSColin Finck goto cleanup; 222c2c66affSColin Finck } 223c2c66affSColin Finck 224c2c66affSColin Finck ret = TRUE; 225c2c66affSColin Finck 226c2c66affSColin Finck cleanup: 227c2c66affSColin Finck if (Value) 228c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, Value); 229c2c66affSColin Finck 230c2c66affSColin Finck if (hKey) 231c2c66affSColin Finck RegCloseKey(hKey); 232c2c66affSColin Finck 233c2c66affSColin Finck if (UserProfile) 234c2c66affSColin Finck RevertToSelf(); 235c2c66affSColin Finck 236c2c66affSColin Finck return ret; 237c2c66affSColin Finck } 238c2c66affSColin Finck 239c2c66affSColin Finck BOOL 240c2c66affSColin Finck PlaySoundRoutine( 241c2c66affSColin Finck IN LPCWSTR FileName, 242c2c66affSColin Finck IN UINT bLogon, 243c2c66affSColin Finck IN UINT Flags) 244c2c66affSColin Finck { 245c2c66affSColin Finck typedef BOOL (WINAPI *PLAYSOUNDW)(LPCWSTR,HMODULE,DWORD); 246c2c66affSColin Finck typedef UINT (WINAPI *WAVEOUTGETNUMDEVS)(VOID); 247c2c66affSColin Finck PLAYSOUNDW Play; 248c2c66affSColin Finck WAVEOUTGETNUMDEVS waveOutGetNumDevs; 249c2c66affSColin Finck UINT NumDevs; 250c2c66affSColin Finck HMODULE hLibrary; 251c2c66affSColin Finck BOOL Ret = FALSE; 252c2c66affSColin Finck 253c2c66affSColin Finck hLibrary = LoadLibraryW(L"winmm.dll"); 254c2c66affSColin Finck if (hLibrary) 255c2c66affSColin Finck { 256c2c66affSColin Finck waveOutGetNumDevs = (WAVEOUTGETNUMDEVS)GetProcAddress(hLibrary, "waveOutGetNumDevs"); 257c2c66affSColin Finck if (waveOutGetNumDevs) 258c2c66affSColin Finck { 259c2c66affSColin Finck NumDevs = waveOutGetNumDevs(); 260c2c66affSColin Finck if (!NumDevs) 261c2c66affSColin Finck { 262c2c66affSColin Finck if (!bLogon) 263c2c66affSColin Finck { 264d811fca7SAdam Słaboń Beep(440, 125); 265c2c66affSColin Finck } 266c2c66affSColin Finck FreeLibrary(hLibrary); 267c2c66affSColin Finck return FALSE; 268c2c66affSColin Finck } 269c2c66affSColin Finck } 270c2c66affSColin Finck 271c2c66affSColin Finck Play = (PLAYSOUNDW)GetProcAddress(hLibrary, "PlaySoundW"); 272c2c66affSColin Finck if (Play) 273c2c66affSColin Finck { 274c2c66affSColin Finck Ret = Play(FileName, NULL, Flags); 275c2c66affSColin Finck } 276c2c66affSColin Finck FreeLibrary(hLibrary); 277c2c66affSColin Finck } 278c2c66affSColin Finck 279c2c66affSColin Finck return Ret; 280c2c66affSColin Finck } 281c2c66affSColin Finck 282c2c66affSColin Finck DWORD 283c2c66affSColin Finck WINAPI 284c2c66affSColin Finck PlayLogonSoundThread( 285c2c66affSColin Finck IN LPVOID lpParameter) 286c2c66affSColin Finck { 287c2c66affSColin Finck BYTE TokenUserBuffer[256]; 288c2c66affSColin Finck PTOKEN_USER pTokenUser = (TOKEN_USER*)TokenUserBuffer; 289c2c66affSColin Finck ULONG Length; 290c2c66affSColin Finck HKEY hKey; 291c2c66affSColin Finck WCHAR wszBuffer[MAX_PATH] = {0}; 292c2c66affSColin Finck WCHAR wszDest[MAX_PATH]; 293c2c66affSColin Finck DWORD dwSize = sizeof(wszBuffer), dwType; 294c2c66affSColin Finck SERVICE_STATUS_PROCESS Info; 295c2c66affSColin Finck UNICODE_STRING SidString; 296c2c66affSColin Finck NTSTATUS Status; 297c2c66affSColin Finck ULONG Index = 0; 298c2c66affSColin Finck SC_HANDLE hSCManager, hService; 299c2c66affSColin Finck 300c2c66affSColin Finck // 301c2c66affSColin Finck // FIXME: Isn't it possible to *JUST* impersonate the current user 302c2c66affSColin Finck // *AND* open its HKCU?? 303c2c66affSColin Finck // 304c2c66affSColin Finck 305c2c66affSColin Finck /* Get SID of current user */ 306c2c66affSColin Finck Status = NtQueryInformationToken((HANDLE)lpParameter, 307c2c66affSColin Finck TokenUser, 308c2c66affSColin Finck TokenUserBuffer, 309c2c66affSColin Finck sizeof(TokenUserBuffer), 310c2c66affSColin Finck &Length); 311c2c66affSColin Finck if (!NT_SUCCESS(Status)) 312c2c66affSColin Finck { 313c2c66affSColin Finck ERR("NtQueryInformationToken failed: %x!\n", Status); 314c2c66affSColin Finck return 0; 315c2c66affSColin Finck } 316c2c66affSColin Finck 317c2c66affSColin Finck /* Convert SID to string */ 318c2c66affSColin Finck RtlInitEmptyUnicodeString(&SidString, wszBuffer, sizeof(wszBuffer)); 319c2c66affSColin Finck Status = RtlConvertSidToUnicodeString(&SidString, pTokenUser->User.Sid, FALSE); 320c2c66affSColin Finck if (!NT_SUCCESS(Status)) 321c2c66affSColin Finck { 322c2c66affSColin Finck ERR("RtlConvertSidToUnicodeString failed: %x!\n", Status); 323c2c66affSColin Finck return 0; 324c2c66affSColin Finck } 325c2c66affSColin Finck 326c2c66affSColin Finck /* Build path to logon sound registry key. 327c2c66affSColin Finck Note: We can't use HKCU here, because Winlogon is owned by SYSTEM user */ 328c2c66affSColin Finck if (FAILED(StringCbCopyW(wszBuffer + SidString.Length/sizeof(WCHAR), 329c2c66affSColin Finck sizeof(wszBuffer) - SidString.Length, 330c2c66affSColin Finck L"\\AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current"))) 331c2c66affSColin Finck { 332c2c66affSColin Finck /* SID is too long. Should not happen. */ 333c2c66affSColin Finck ERR("StringCbCopyW failed!\n"); 334c2c66affSColin Finck return 0; 335c2c66affSColin Finck } 336c2c66affSColin Finck 337c2c66affSColin Finck /* Open registry key and query sound path */ 338c2c66affSColin Finck if (RegOpenKeyExW(HKEY_USERS, wszBuffer, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 339c2c66affSColin Finck { 340c2c66affSColin Finck ERR("RegOpenKeyExW(%ls) failed!\n", wszBuffer); 341c2c66affSColin Finck return 0; 342c2c66affSColin Finck } 343c2c66affSColin Finck 344c2c66affSColin Finck if (RegQueryValueExW(hKey, NULL, NULL, &dwType, 345c2c66affSColin Finck (LPBYTE)wszBuffer, &dwSize) != ERROR_SUCCESS || 346c2c66affSColin Finck (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 347c2c66affSColin Finck { 348c2c66affSColin Finck ERR("RegQueryValueExW failed!\n"); 349c2c66affSColin Finck RegCloseKey(hKey); 350c2c66affSColin Finck return 0; 351c2c66affSColin Finck } 352c2c66affSColin Finck 353c2c66affSColin Finck RegCloseKey(hKey); 354c2c66affSColin Finck 355c2c66affSColin Finck if (!wszBuffer[0]) 356c2c66affSColin Finck { 357c2c66affSColin Finck /* No sound has been set */ 358c2c66affSColin Finck ERR("No sound has been set\n"); 359c2c66affSColin Finck return 0; 360c2c66affSColin Finck } 361c2c66affSColin Finck 362c2c66affSColin Finck /* Expand environment variables */ 363c2c66affSColin Finck if (!ExpandEnvironmentStringsW(wszBuffer, wszDest, MAX_PATH)) 364c2c66affSColin Finck { 365c2c66affSColin Finck ERR("ExpandEnvironmentStringsW failed!\n"); 366c2c66affSColin Finck return 0; 367c2c66affSColin Finck } 368c2c66affSColin Finck 369c2c66affSColin Finck /* Open the service manager */ 370c2c66affSColin Finck hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 371c2c66affSColin Finck if (!hSCManager) 372c2c66affSColin Finck { 373c2c66affSColin Finck ERR("OpenSCManager failed (%x)\n", GetLastError()); 374c2c66affSColin Finck return 0; 375c2c66affSColin Finck } 376c2c66affSColin Finck 377c2c66affSColin Finck /* Open the wdmaud service */ 378c2c66affSColin Finck hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ); 379c2c66affSColin Finck if (!hService) 380c2c66affSColin Finck { 381c2c66affSColin Finck /* The service is not installed */ 382c2c66affSColin Finck TRACE("Failed to open wdmaud service (%x)\n", GetLastError()); 383c2c66affSColin Finck CloseServiceHandle(hSCManager); 384c2c66affSColin Finck return 0; 385c2c66affSColin Finck } 386c2c66affSColin Finck 387c2c66affSColin Finck /* Wait for wdmaud to start */ 388c2c66affSColin Finck do 389c2c66affSColin Finck { 390c2c66affSColin Finck if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize)) 391c2c66affSColin Finck { 392c2c66affSColin Finck TRACE("QueryServiceStatusEx failed (%x)\n", GetLastError()); 393c2c66affSColin Finck break; 394c2c66affSColin Finck } 395c2c66affSColin Finck 396c2c66affSColin Finck if (Info.dwCurrentState == SERVICE_RUNNING) 397c2c66affSColin Finck break; 398c2c66affSColin Finck 399c2c66affSColin Finck Sleep(1000); 400c2c66affSColin Finck 401c2c66affSColin Finck } while (Index++ < 20); 402c2c66affSColin Finck 403c2c66affSColin Finck CloseServiceHandle(hService); 404c2c66affSColin Finck CloseServiceHandle(hSCManager); 405c2c66affSColin Finck 406c2c66affSColin Finck /* If wdmaud is not running exit */ 407c2c66affSColin Finck if (Info.dwCurrentState != SERVICE_RUNNING) 408c2c66affSColin Finck { 409c2c66affSColin Finck WARN("wdmaud has not started!\n"); 410c2c66affSColin Finck return 0; 411c2c66affSColin Finck } 412c2c66affSColin Finck 413c2c66affSColin Finck /* Sound subsystem is running. Play logon sound. */ 414c2c66affSColin Finck TRACE("Playing logon sound: %ls\n", wszDest); 415c2c66affSColin Finck PlaySoundRoutine(wszDest, TRUE, SND_FILENAME); 416c2c66affSColin Finck return 0; 417c2c66affSColin Finck } 418c2c66affSColin Finck 419c2c66affSColin Finck static 420c2c66affSColin Finck VOID 421c2c66affSColin Finck PlayLogonSound( 422c2c66affSColin Finck IN OUT PWLSESSION Session) 423c2c66affSColin Finck { 424c2c66affSColin Finck HANDLE hThread; 425c2c66affSColin Finck 426c2c66affSColin Finck hThread = CreateThread(NULL, 0, PlayLogonSoundThread, (PVOID)Session->UserToken, 0, NULL); 427c2c66affSColin Finck if (hThread) 428c2c66affSColin Finck CloseHandle(hThread); 429c2c66affSColin Finck } 430c2c66affSColin Finck 431c2c66affSColin Finck static 4324cf87fdbSPierre Schweitzer VOID 4334cf87fdbSPierre Schweitzer RestoreAllConnections(PWLSESSION Session) 4344cf87fdbSPierre Schweitzer { 4354cf87fdbSPierre Schweitzer DWORD dRet; 4364cf87fdbSPierre Schweitzer HANDLE hEnum; 4374cf87fdbSPierre Schweitzer LPNETRESOURCE lpRes; 4384cf87fdbSPierre Schweitzer DWORD dSize = 0x1000; 4394cf87fdbSPierre Schweitzer DWORD dCount = -1; 4404cf87fdbSPierre Schweitzer LPNETRESOURCE lpCur; 4414cf87fdbSPierre Schweitzer BOOL UserProfile; 4424cf87fdbSPierre Schweitzer 4434cf87fdbSPierre Schweitzer UserProfile = (Session && Session->UserToken); 4444cf87fdbSPierre Schweitzer if (!UserProfile) 4454cf87fdbSPierre Schweitzer { 4464cf87fdbSPierre Schweitzer return; 4474cf87fdbSPierre Schweitzer } 4484cf87fdbSPierre Schweitzer 4494cf87fdbSPierre Schweitzer if (!ImpersonateLoggedOnUser(Session->UserToken)) 4504cf87fdbSPierre Schweitzer { 4514cf87fdbSPierre Schweitzer ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError()); 4524cf87fdbSPierre Schweitzer return; 4534cf87fdbSPierre Schweitzer } 4544cf87fdbSPierre Schweitzer 4554cf87fdbSPierre Schweitzer dRet = WNetOpenEnum(RESOURCE_REMEMBERED, RESOURCETYPE_DISK, 0, NULL, &hEnum); 4564cf87fdbSPierre Schweitzer if (dRet != WN_SUCCESS) 4574cf87fdbSPierre Schweitzer { 4584cf87fdbSPierre Schweitzer ERR("Failed to open enumeration: %lu\n", dRet); 4594cf87fdbSPierre Schweitzer goto quit; 4604cf87fdbSPierre Schweitzer } 4614cf87fdbSPierre Schweitzer 4624cf87fdbSPierre Schweitzer lpRes = HeapAlloc(GetProcessHeap(), 0, dSize); 4634cf87fdbSPierre Schweitzer if (!lpRes) 4644cf87fdbSPierre Schweitzer { 4654cf87fdbSPierre Schweitzer ERR("Failed to allocate memory\n"); 4664cf87fdbSPierre Schweitzer WNetCloseEnum(hEnum); 4674cf87fdbSPierre Schweitzer goto quit; 4684cf87fdbSPierre Schweitzer } 4694cf87fdbSPierre Schweitzer 4704cf87fdbSPierre Schweitzer do 4714cf87fdbSPierre Schweitzer { 4724cf87fdbSPierre Schweitzer dSize = 0x1000; 4734cf87fdbSPierre Schweitzer dCount = -1; 4744cf87fdbSPierre Schweitzer 4754cf87fdbSPierre Schweitzer memset(lpRes, 0, dSize); 4764cf87fdbSPierre Schweitzer dRet = WNetEnumResource(hEnum, &dCount, lpRes, &dSize); 4774cf87fdbSPierre Schweitzer if (dRet == WN_SUCCESS || dRet == WN_MORE_DATA) 4784cf87fdbSPierre Schweitzer { 4794cf87fdbSPierre Schweitzer lpCur = lpRes; 4804cf87fdbSPierre Schweitzer for (; dCount; dCount--) 4814cf87fdbSPierre Schweitzer { 4824cf87fdbSPierre Schweitzer WNetAddConnection(lpCur->lpRemoteName, NULL, lpCur->lpLocalName); 4834cf87fdbSPierre Schweitzer lpCur++; 4844cf87fdbSPierre Schweitzer } 4854cf87fdbSPierre Schweitzer } 4864cf87fdbSPierre Schweitzer } while (dRet != WN_NO_MORE_ENTRIES); 4874cf87fdbSPierre Schweitzer 4884cf87fdbSPierre Schweitzer HeapFree(GetProcessHeap(), 0, lpRes); 4894cf87fdbSPierre Schweitzer WNetCloseEnum(hEnum); 4904cf87fdbSPierre Schweitzer 4914cf87fdbSPierre Schweitzer quit: 4924cf87fdbSPierre Schweitzer RevertToSelf(); 4934cf87fdbSPierre Schweitzer } 4944cf87fdbSPierre Schweitzer 4954cf87fdbSPierre Schweitzer static 496c2c66affSColin Finck BOOL 497c2c66affSColin Finck HandleLogon( 498c2c66affSColin Finck IN OUT PWLSESSION Session) 499c2c66affSColin Finck { 500c2c66affSColin Finck PROFILEINFOW ProfileInfo; 501c2c66affSColin Finck BOOL ret = FALSE; 502c2c66affSColin Finck 503c2c66affSColin Finck /* Loading personal settings */ 504c2c66affSColin Finck DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOADINGYOURPERSONALSETTINGS); 505c2c66affSColin Finck ProfileInfo.hProfile = INVALID_HANDLE_VALUE; 506c2c66affSColin Finck if (0 == (Session->Options & WLX_LOGON_OPT_NO_PROFILE)) 507c2c66affSColin Finck { 508c2c66affSColin Finck if (Session->Profile == NULL 509c2c66affSColin Finck || (Session->Profile->dwType != WLX_PROFILE_TYPE_V1_0 510c2c66affSColin Finck && Session->Profile->dwType != WLX_PROFILE_TYPE_V2_0)) 511c2c66affSColin Finck { 512c2c66affSColin Finck ERR("WL: Wrong profile\n"); 513c2c66affSColin Finck goto cleanup; 514c2c66affSColin Finck } 515c2c66affSColin Finck 516c2c66affSColin Finck /* Load the user profile */ 517c2c66affSColin Finck ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW)); 518c2c66affSColin Finck ProfileInfo.dwSize = sizeof(PROFILEINFOW); 519c2c66affSColin Finck ProfileInfo.dwFlags = 0; 520c2c66affSColin Finck ProfileInfo.lpUserName = Session->MprNotifyInfo.pszUserName; 521c2c66affSColin Finck ProfileInfo.lpProfilePath = Session->Profile->pszProfile; 522c2c66affSColin Finck if (Session->Profile->dwType >= WLX_PROFILE_TYPE_V2_0) 523c2c66affSColin Finck { 524c2c66affSColin Finck ProfileInfo.lpDefaultPath = Session->Profile->pszNetworkDefaultUserProfile; 525c2c66affSColin Finck ProfileInfo.lpServerName = Session->Profile->pszServerName; 526c2c66affSColin Finck ProfileInfo.lpPolicyPath = Session->Profile->pszPolicy; 527c2c66affSColin Finck } 528c2c66affSColin Finck 529c2c66affSColin Finck if (!LoadUserProfileW(Session->UserToken, &ProfileInfo)) 530c2c66affSColin Finck { 531c2c66affSColin Finck ERR("WL: LoadUserProfileW() failed\n"); 532c2c66affSColin Finck goto cleanup; 533c2c66affSColin Finck } 534c2c66affSColin Finck } 535c2c66affSColin Finck 536c2c66affSColin Finck /* Create environment block for the user */ 537c2c66affSColin Finck if (!CreateUserEnvironment(Session)) 538c2c66affSColin Finck { 539c2c66affSColin Finck WARN("WL: SetUserEnvironment() failed\n"); 540c2c66affSColin Finck goto cleanup; 541c2c66affSColin Finck } 542c2c66affSColin Finck 543c2c66affSColin Finck CallNotificationDlls(Session, LogonHandler); 544c2c66affSColin Finck 545c2c66affSColin Finck DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGYOURPERSONALSETTINGS); 546c2c66affSColin Finck UpdatePerUserSystemParameters(0, TRUE); 547c2c66affSColin Finck 548c2c66affSColin Finck /* Set default user language */ 549c2c66affSColin Finck if (!SetDefaultLanguage(Session)) 550c2c66affSColin Finck { 551c2c66affSColin Finck WARN("WL: SetDefaultLanguage() failed\n"); 552c2c66affSColin Finck goto cleanup; 553c2c66affSColin Finck } 554c2c66affSColin Finck 555*f96c39f6SGeorge Bișoc /* Allow winsta and desktop access for this session */ 556*f96c39f6SGeorge Bișoc if (!AllowAccessOnSession(Session)) 557*f96c39f6SGeorge Bișoc { 558*f96c39f6SGeorge Bișoc WARN("WL: AllowAccessOnSession() failed to give winsta & desktop access for this session\n"); 559*f96c39f6SGeorge Bișoc goto cleanup; 560*f96c39f6SGeorge Bișoc } 56102eee253SHermès Bélusca-Maïto 5624cf87fdbSPierre Schweitzer /* Connect remote resources */ 5634cf87fdbSPierre Schweitzer RestoreAllConnections(Session); 5644cf87fdbSPierre Schweitzer 565c2c66affSColin Finck if (!StartUserShell(Session)) 566c2c66affSColin Finck { 567c2c66affSColin Finck //WCHAR StatusMsg[256]; 568c2c66affSColin Finck WARN("WL: WlxActivateUserShell() failed\n"); 569c2c66affSColin Finck //LoadStringW(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, sizeof(StatusMsg) / sizeof(StatusMsg[0])); 570c2c66affSColin Finck //MessageBoxW(0, StatusMsg, NULL, MB_ICONERROR); 571c2c66affSColin Finck goto cleanup; 572c2c66affSColin Finck } 573c2c66affSColin Finck 574c2c66affSColin Finck CallNotificationDlls(Session, StartShellHandler); 575c2c66affSColin Finck 576c2c66affSColin Finck if (!InitializeScreenSaver(Session)) 577c2c66affSColin Finck WARN("WL: Failed to initialize screen saver\n"); 578c2c66affSColin Finck 579c2c66affSColin Finck Session->hProfileInfo = ProfileInfo.hProfile; 580c2c66affSColin Finck 58140000a17SHermès Bélusca-Maïto /* Logon has succeeded. Play sound. */ 582c2c66affSColin Finck PlayLogonSound(Session); 583c2c66affSColin Finck 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 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 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 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 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 820c2c66affSColin Finck HandleLogoff( 821c2c66affSColin Finck IN OUT PWLSESSION Session, 822c2c66affSColin Finck IN UINT Flags) 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 } 837c2c66affSColin Finck LSData->Flags = Flags; 838c2c66affSColin Finck LSData->Session = Session; 839c2c66affSColin Finck 840c2c66affSColin Finck Status = CreateLogoffSecurityAttributes(&psa); 841c2c66affSColin Finck if (!NT_SUCCESS(Status)) 842c2c66affSColin Finck { 843c2c66affSColin Finck ERR("Failed to create a required security descriptor. Status 0x%08lx\n", Status); 844c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 845c2c66affSColin Finck return Status; 846c2c66affSColin Finck } 847c2c66affSColin Finck 848c2c66affSColin Finck /* Run logoff thread */ 849c2c66affSColin Finck hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL); 850c2c66affSColin Finck if (!hThread) 851c2c66affSColin Finck { 852c2c66affSColin Finck ERR("Unable to create logoff thread, error %lu\n", GetLastError()); 853c2c66affSColin Finck DestroyLogoffSecurityAttributes(psa); 854c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 855c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 856c2c66affSColin Finck } 857c2c66affSColin Finck WaitForSingleObject(hThread, INFINITE); 858c2c66affSColin Finck if (!GetExitCodeThread(hThread, &exitCode)) 859c2c66affSColin Finck { 860c2c66affSColin Finck ERR("Unable to get exit code of logoff thread (error %lu)\n", GetLastError()); 861c2c66affSColin Finck CloseHandle(hThread); 862c2c66affSColin Finck DestroyLogoffSecurityAttributes(psa); 863c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 864c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 865c2c66affSColin Finck } 866c2c66affSColin Finck CloseHandle(hThread); 867c2c66affSColin Finck if (exitCode == 0) 868c2c66affSColin Finck { 869c2c66affSColin Finck ERR("Logoff thread returned failure\n"); 870c2c66affSColin Finck DestroyLogoffSecurityAttributes(psa); 871c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 872c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 873c2c66affSColin Finck } 874c2c66affSColin Finck 875c2c66affSColin Finck SwitchDesktop(Session->WinlogonDesktop); 876c2c66affSColin Finck 87702eee253SHermès Bélusca-Maïto // TODO: Play logoff sound! 87802eee253SHermès Bélusca-Maïto 87902eee253SHermès Bélusca-Maïto SetWindowStationUser(Session->InteractiveWindowStation, 88002eee253SHermès Bélusca-Maïto &LuidNone, NULL, 0); 88102eee253SHermès Bélusca-Maïto 882c2c66affSColin Finck // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOGGINGOFF); 883c2c66affSColin Finck 884c2c66affSColin Finck // FIXME: Closing network connections! 885c2c66affSColin Finck // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_CLOSINGNETWORKCONNECTIONS); 886c2c66affSColin Finck 887c2c66affSColin Finck /* Kill remaining COM apps. Only at logoff! */ 888c2c66affSColin Finck hThread = CreateThread(psa, 0, KillComProcesses, (LPVOID)LSData, 0, NULL); 889c2c66affSColin Finck if (hThread) 890c2c66affSColin Finck { 891c2c66affSColin Finck WaitForSingleObject(hThread, INFINITE); 892c2c66affSColin Finck CloseHandle(hThread); 893c2c66affSColin Finck } 894c2c66affSColin Finck 895c2c66affSColin Finck /* We're done with the SECURITY_DESCRIPTOR */ 896c2c66affSColin Finck DestroyLogoffSecurityAttributes(psa); 897c2c66affSColin Finck psa = NULL; 898c2c66affSColin Finck 899c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 900c2c66affSColin Finck 901c2c66affSColin Finck DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_SAVEYOURSETTINGS); 902c2c66affSColin Finck 903c2c66affSColin Finck UnloadUserProfile(Session->UserToken, Session->hProfileInfo); 904c2c66affSColin Finck 905c2c66affSColin Finck CallNotificationDlls(Session, LogoffHandler); 906c2c66affSColin Finck 907c2c66affSColin Finck CloseHandle(Session->UserToken); 908c2c66affSColin Finck UpdatePerUserSystemParameters(0, FALSE); 909c2c66affSColin Finck Session->LogonState = STATE_LOGGED_OFF; 910c2c66affSColin Finck Session->UserToken = NULL; 911c2c66affSColin Finck 912c2c66affSColin Finck return STATUS_SUCCESS; 913c2c66affSColin Finck } 914c2c66affSColin Finck 915c2c66affSColin Finck static 916c2c66affSColin Finck INT_PTR 917c2c66affSColin Finck CALLBACK 918c2c66affSColin Finck ShutdownComputerWindowProc( 919c2c66affSColin Finck IN HWND hwndDlg, 920c2c66affSColin Finck IN UINT uMsg, 921c2c66affSColin Finck IN WPARAM wParam, 922c2c66affSColin Finck IN LPARAM lParam) 923c2c66affSColin Finck { 924c2c66affSColin Finck UNREFERENCED_PARAMETER(lParam); 925c2c66affSColin Finck 926c2c66affSColin Finck switch (uMsg) 927c2c66affSColin Finck { 928c2c66affSColin Finck case WM_COMMAND: 929c2c66affSColin Finck { 930c2c66affSColin Finck switch (LOWORD(wParam)) 931c2c66affSColin Finck { 932c2c66affSColin Finck case IDC_BTNSHTDOWNCOMPUTER: 933c2c66affSColin Finck EndDialog(hwndDlg, IDC_BTNSHTDOWNCOMPUTER); 934c2c66affSColin Finck return TRUE; 935c2c66affSColin Finck } 936c2c66affSColin Finck break; 937c2c66affSColin Finck } 938c2c66affSColin Finck case WM_INITDIALOG: 939c2c66affSColin Finck { 940c2c66affSColin Finck RemoveMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND); 941c2c66affSColin Finck SetFocus(GetDlgItem(hwndDlg, IDC_BTNSHTDOWNCOMPUTER)); 942c2c66affSColin Finck return TRUE; 943c2c66affSColin Finck } 944c2c66affSColin Finck } 945c2c66affSColin Finck return FALSE; 946c2c66affSColin Finck } 947c2c66affSColin Finck 948c2c66affSColin Finck static 949c2c66affSColin Finck VOID 950c2c66affSColin Finck UninitializeSAS( 951c2c66affSColin Finck IN OUT PWLSESSION Session) 952c2c66affSColin Finck { 953c2c66affSColin Finck if (Session->SASWindow) 954c2c66affSColin Finck { 955c2c66affSColin Finck DestroyWindow(Session->SASWindow); 956c2c66affSColin Finck Session->SASWindow = NULL; 957c2c66affSColin Finck } 958c2c66affSColin Finck if (Session->hEndOfScreenSaverThread) 959c2c66affSColin Finck SetEvent(Session->hEndOfScreenSaverThread); 960c2c66affSColin Finck UnregisterClassW(WINLOGON_SAS_CLASS, hAppInstance); 961c2c66affSColin Finck } 962c2c66affSColin Finck 963c2c66affSColin Finck NTSTATUS 964c2c66affSColin Finck HandleShutdown( 965c2c66affSColin Finck IN OUT PWLSESSION Session, 966c2c66affSColin Finck IN DWORD wlxAction) 967c2c66affSColin Finck { 968c2c66affSColin Finck PLOGOFF_SHUTDOWN_DATA LSData; 969c2c66affSColin Finck HANDLE hThread; 970c2c66affSColin Finck DWORD exitCode; 971c2c66affSColin Finck BOOLEAN Old; 972c2c66affSColin Finck 973c2c66affSColin Finck // SwitchDesktop(Session->WinlogonDesktop); 9745f033392SArnav Bhatt 9755f033392SArnav Bhatt /* If the system is rebooting, show the appropriate string */ 9765f033392SArnav Bhatt if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) 9775f033392SArnav Bhatt DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISRESTARTING); 9785f033392SArnav Bhatt else 979c2c66affSColin Finck DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISSHUTTINGDOWN); 980c2c66affSColin Finck 981c2c66affSColin Finck /* Prepare data for shutdown thread */ 982c2c66affSColin Finck LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA)); 983c2c66affSColin Finck if (!LSData) 984c2c66affSColin Finck { 985c2c66affSColin Finck ERR("Failed to allocate mem for thread data\n"); 986c2c66affSColin Finck return STATUS_NO_MEMORY; 987c2c66affSColin Finck } 988c2c66affSColin Finck if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_POWER_OFF) 989c2c66affSColin Finck LSData->Flags = EWX_POWEROFF; 990c2c66affSColin Finck else if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) 991c2c66affSColin Finck LSData->Flags = EWX_REBOOT; 992c2c66affSColin Finck else 993c2c66affSColin Finck LSData->Flags = EWX_SHUTDOWN; 994c2c66affSColin Finck LSData->Session = Session; 995c2c66affSColin Finck 996c2c66affSColin Finck // FIXME: We may need to specify this flag to really force application kill 997c2c66affSColin Finck // (we are shutting down ReactOS, not just logging off so no hangs, etc... 998c2c66affSColin Finck // should be allowed). 999c2c66affSColin Finck // LSData->Flags |= EWX_FORCE; 1000c2c66affSColin Finck 1001c2c66affSColin Finck /* Run shutdown thread */ 1002c2c66affSColin Finck hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL); 1003c2c66affSColin Finck if (!hThread) 1004c2c66affSColin Finck { 1005c2c66affSColin Finck ERR("Unable to create shutdown thread, error %lu\n", GetLastError()); 1006c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 1007c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 1008c2c66affSColin Finck } 1009c2c66affSColin Finck WaitForSingleObject(hThread, INFINITE); 1010c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LSData); 1011c2c66affSColin Finck if (!GetExitCodeThread(hThread, &exitCode)) 1012c2c66affSColin Finck { 1013c2c66affSColin Finck ERR("Unable to get exit code of shutdown thread (error %lu)\n", GetLastError()); 1014c2c66affSColin Finck CloseHandle(hThread); 1015c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 1016c2c66affSColin Finck } 1017c2c66affSColin Finck CloseHandle(hThread); 1018c2c66affSColin Finck if (exitCode == 0) 1019c2c66affSColin Finck { 1020c2c66affSColin Finck ERR("Shutdown thread returned failure\n"); 1021c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 1022c2c66affSColin Finck } 1023c2c66affSColin Finck 1024c2c66affSColin Finck CallNotificationDlls(Session, ShutdownHandler); 1025c2c66affSColin Finck 1026c2c66affSColin Finck /* Destroy SAS window */ 1027c2c66affSColin Finck UninitializeSAS(Session); 1028c2c66affSColin Finck 1029c2c66affSColin Finck /* Now we can shut down NT */ 1030c2c66affSColin Finck ERR("Shutting down NT...\n"); 1031c2c66affSColin Finck RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old); 1032c2c66affSColin Finck if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) 1033c2c66affSColin Finck { 1034c2c66affSColin Finck NtShutdownSystem(ShutdownReboot); 1035c2c66affSColin Finck } 1036c2c66affSColin Finck else 1037c2c66affSColin Finck { 1038c2c66affSColin Finck if (FALSE) 1039c2c66affSColin Finck { 1040c2c66affSColin Finck /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */ 1041c2c66affSColin Finck DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER), 1042c2c66affSColin Finck GetDesktopWindow(), ShutdownComputerWindowProc); 1043c2c66affSColin Finck } 1044c2c66affSColin Finck NtShutdownSystem(ShutdownNoReboot); 1045c2c66affSColin Finck } 1046c2c66affSColin Finck RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old); 1047c2c66affSColin Finck return STATUS_SUCCESS; 1048c2c66affSColin Finck } 1049c2c66affSColin Finck 1050c2c66affSColin Finck static 1051c2c66affSColin Finck VOID 1052c2c66affSColin Finck DoGenericAction( 1053c2c66affSColin Finck IN OUT PWLSESSION Session, 1054c2c66affSColin Finck IN DWORD wlxAction) 1055c2c66affSColin Finck { 1056c2c66affSColin Finck switch (wlxAction) 1057c2c66affSColin Finck { 1058c2c66affSColin Finck case WLX_SAS_ACTION_LOGON: /* 0x01 */ 1059c2c66affSColin Finck if (Session->LogonState == STATE_LOGGED_OFF_SAS) 1060c2c66affSColin Finck { 1061c2c66affSColin Finck if (!HandleLogon(Session)) 1062c2c66affSColin Finck { 1063c2c66affSColin Finck Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 1064c2c66affSColin Finck CallNotificationDlls(Session, LogonHandler); 1065c2c66affSColin Finck } 1066c2c66affSColin Finck } 1067c2c66affSColin Finck break; 1068c2c66affSColin Finck case WLX_SAS_ACTION_NONE: /* 0x02 */ 1069c2c66affSColin Finck if (Session->LogonState == STATE_LOGGED_OFF_SAS) 1070c2c66affSColin Finck { 1071c2c66affSColin Finck Session->LogonState = STATE_LOGGED_OFF; 1072c2c66affSColin Finck Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 1073c2c66affSColin Finck } 1074c2c66affSColin Finck else if (Session->LogonState == STATE_LOGGED_ON_SAS) 1075c2c66affSColin Finck { 1076c2c66affSColin Finck Session->LogonState = STATE_LOGGED_ON; 1077c2c66affSColin Finck } 1078c2c66affSColin Finck else if (Session->LogonState == STATE_LOCKED_SAS) 1079c2c66affSColin Finck { 1080c2c66affSColin Finck Session->LogonState = STATE_LOCKED; 1081c2c66affSColin Finck Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context); 1082c2c66affSColin Finck } 1083c2c66affSColin Finck break; 1084c2c66affSColin Finck case WLX_SAS_ACTION_LOCK_WKSTA: /* 0x03 */ 1085c2c66affSColin Finck if (Session->Gina.Functions.WlxIsLockOk(Session->Gina.Context)) 1086c2c66affSColin Finck { 1087c2c66affSColin Finck SwitchDesktop(Session->WinlogonDesktop); 1088c2c66affSColin Finck Session->LogonState = STATE_LOCKED; 1089c2c66affSColin Finck Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context); 1090c2c66affSColin Finck CallNotificationDlls(Session, LockHandler); 1091c2c66affSColin Finck } 1092c2c66affSColin Finck break; 1093c2c66affSColin Finck case WLX_SAS_ACTION_LOGOFF: /* 0x04 */ 1094c2c66affSColin Finck case WLX_SAS_ACTION_SHUTDOWN: /* 0x05 */ 1095c2c66affSColin Finck case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: /* 0x0a */ 1096c2c66affSColin Finck case WLX_SAS_ACTION_SHUTDOWN_REBOOT: /* 0x0b */ 1097c2c66affSColin Finck if (Session->LogonState != STATE_LOGGED_OFF) 1098c2c66affSColin Finck { 1099c2c66affSColin Finck if (!Session->Gina.Functions.WlxIsLogoffOk(Session->Gina.Context)) 1100c2c66affSColin Finck break; 1101c2c66affSColin Finck if (!NT_SUCCESS(HandleLogoff(Session, EWX_LOGOFF))) 1102c2c66affSColin Finck { 1103c2c66affSColin Finck RemoveStatusMessage(Session); 1104c2c66affSColin Finck break; 1105c2c66affSColin Finck } 1106c2c66affSColin Finck Session->Gina.Functions.WlxLogoff(Session->Gina.Context); 1107c2c66affSColin Finck } 1108c2c66affSColin Finck if (WLX_SHUTTINGDOWN(wlxAction)) 1109c2c66affSColin Finck { 1110c2c66affSColin Finck // FIXME: WlxShutdown should be done from inside HandleShutdown, 1111c2c66affSColin Finck // after having displayed "ReactOS is shutting down" message. 1112c2c66affSColin Finck Session->Gina.Functions.WlxShutdown(Session->Gina.Context, wlxAction); 1113c2c66affSColin Finck if (!NT_SUCCESS(HandleShutdown(Session, wlxAction))) 1114c2c66affSColin Finck { 1115c2c66affSColin Finck RemoveStatusMessage(Session); 1116c2c66affSColin Finck Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 1117c2c66affSColin Finck } 1118c2c66affSColin Finck } 1119c2c66affSColin Finck else 1120c2c66affSColin Finck { 1121c2c66affSColin Finck RemoveStatusMessage(Session); 1122c2c66affSColin Finck Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 1123c2c66affSColin Finck } 1124c2c66affSColin Finck break; 1125c2c66affSColin Finck case WLX_SAS_ACTION_TASKLIST: /* 0x07 */ 1126c2c66affSColin Finck SwitchDesktop(Session->ApplicationDesktop); 1127c2c66affSColin Finck Session->LogonState = STATE_LOGGED_ON; 1128c2c66affSColin Finck StartTaskManager(Session); 1129c2c66affSColin Finck break; 1130c2c66affSColin Finck case WLX_SAS_ACTION_UNLOCK_WKSTA: /* 0x08 */ 1131c2c66affSColin Finck SwitchDesktop(Session->ApplicationDesktop); 1132c2c66affSColin Finck Session->LogonState = STATE_LOGGED_ON; 1133c2c66affSColin Finck CallNotificationDlls(Session, UnlockHandler); 1134c2c66affSColin Finck break; 1135c2c66affSColin Finck default: 1136c2c66affSColin Finck WARN("Unknown SAS action 0x%lx\n", wlxAction); 1137c2c66affSColin Finck } 1138c2c66affSColin Finck } 1139c2c66affSColin Finck 1140c2c66affSColin Finck static 1141c2c66affSColin Finck VOID 1142c2c66affSColin Finck DispatchSAS( 1143c2c66affSColin Finck IN OUT PWLSESSION Session, 1144c2c66affSColin Finck IN DWORD dwSasType) 1145c2c66affSColin Finck { 1146c2c66affSColin Finck DWORD wlxAction = WLX_SAS_ACTION_NONE; 1147c2c66affSColin Finck PSID LogonSid = NULL; /* FIXME */ 1148c2c66affSColin Finck BOOL bSecure = TRUE; 1149c2c66affSColin Finck 1150c2c66affSColin Finck switch (dwSasType) 1151c2c66affSColin Finck { 1152c2c66affSColin Finck case WLX_SAS_TYPE_CTRL_ALT_DEL: 1153c2c66affSColin Finck switch (Session->LogonState) 1154c2c66affSColin Finck { 1155c2c66affSColin Finck case STATE_INIT: 1156c2c66affSColin Finck Session->LogonState = STATE_LOGGED_OFF; 1157c2c66affSColin Finck Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 1158c2c66affSColin Finck return; 1159c2c66affSColin Finck 1160c2c66affSColin Finck case STATE_LOGGED_OFF: 1161c2c66affSColin Finck Session->LogonState = STATE_LOGGED_OFF_SAS; 1162c2c66affSColin Finck 116302f3cb53SEric Kohl CloseAllDialogWindows(); 1164c2c66affSColin Finck 1165c2c66affSColin Finck Session->Options = 0; 1166c2c66affSColin Finck 1167c2c66affSColin Finck wlxAction = (DWORD)Session->Gina.Functions.WlxLoggedOutSAS( 1168c2c66affSColin Finck Session->Gina.Context, 1169c2c66affSColin Finck Session->SASAction, 1170c2c66affSColin Finck &Session->LogonId, 1171c2c66affSColin Finck LogonSid, 1172c2c66affSColin Finck &Session->Options, 1173c2c66affSColin Finck &Session->UserToken, 1174c2c66affSColin Finck &Session->MprNotifyInfo, 1175c2c66affSColin Finck (PVOID*)&Session->Profile); 1176c2c66affSColin Finck break; 1177c2c66affSColin Finck 1178c2c66affSColin Finck case STATE_LOGGED_OFF_SAS: 1179c2c66affSColin Finck /* Ignore SAS if we are already in an SAS state */ 1180c2c66affSColin Finck return; 1181c2c66affSColin Finck 1182c2c66affSColin Finck case STATE_LOGGED_ON: 1183c2c66affSColin Finck Session->LogonState = STATE_LOGGED_ON_SAS; 1184c2c66affSColin Finck wlxAction = (DWORD)Session->Gina.Functions.WlxLoggedOnSAS(Session->Gina.Context, dwSasType, NULL); 1185c2c66affSColin Finck break; 1186c2c66affSColin Finck 1187c2c66affSColin Finck case STATE_LOGGED_ON_SAS: 1188c2c66affSColin Finck /* Ignore SAS if we are already in an SAS state */ 1189c2c66affSColin Finck return; 1190c2c66affSColin Finck 1191c2c66affSColin Finck case STATE_LOCKED: 1192c2c66affSColin Finck Session->LogonState = STATE_LOCKED_SAS; 1193c2c66affSColin Finck 119402f3cb53SEric Kohl CloseAllDialogWindows(); 1195c2c66affSColin Finck 1196c2c66affSColin Finck wlxAction = (DWORD)Session->Gina.Functions.WlxWkstaLockedSAS(Session->Gina.Context, dwSasType); 1197c2c66affSColin Finck break; 1198c2c66affSColin Finck 1199c2c66affSColin Finck case STATE_LOCKED_SAS: 1200c2c66affSColin Finck /* Ignore SAS if we are already in an SAS state */ 1201c2c66affSColin Finck return; 1202c2c66affSColin Finck 1203c2c66affSColin Finck default: 1204c2c66affSColin Finck return; 1205c2c66affSColin Finck } 1206c2c66affSColin Finck break; 1207c2c66affSColin Finck 1208c2c66affSColin Finck case WLX_SAS_TYPE_TIMEOUT: 1209c2c66affSColin Finck return; 1210c2c66affSColin Finck 1211c2c66affSColin Finck case WLX_SAS_TYPE_SCRNSVR_TIMEOUT: 1212c2c66affSColin Finck if (!Session->Gina.Functions.WlxScreenSaverNotify(Session->Gina.Context, &bSecure)) 1213c2c66affSColin Finck { 1214c2c66affSColin Finck /* Skip start of screen saver */ 1215c2c66affSColin Finck SetEvent(Session->hEndOfScreenSaver); 1216c2c66affSColin Finck } 1217c2c66affSColin Finck else 1218c2c66affSColin Finck { 1219c2c66affSColin Finck StartScreenSaver(Session); 1220c2c66affSColin Finck if (bSecure) 1221c2c66affSColin Finck { 1222c2c66affSColin Finck wlxAction = WLX_SAS_ACTION_LOCK_WKSTA; 1223c2c66affSColin Finck // DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA); 1224c2c66affSColin Finck } 1225c2c66affSColin Finck } 1226c2c66affSColin Finck break; 1227c2c66affSColin Finck 1228c2c66affSColin Finck case WLX_SAS_TYPE_SCRNSVR_ACTIVITY: 1229c2c66affSColin Finck SetEvent(Session->hUserActivity); 1230c2c66affSColin Finck break; 1231c2c66affSColin Finck } 1232c2c66affSColin Finck 1233c2c66affSColin Finck DoGenericAction(Session, wlxAction); 1234c2c66affSColin Finck } 1235c2c66affSColin Finck 1236c2c66affSColin Finck static 1237c2c66affSColin Finck BOOL 1238c2c66affSColin Finck RegisterHotKeys( 1239c2c66affSColin Finck IN PWLSESSION Session, 1240c2c66affSColin Finck IN HWND hwndSAS) 1241c2c66affSColin Finck { 1242c2c66affSColin Finck /* Register Ctrl+Alt+Del Hotkey */ 1243c2c66affSColin Finck if (!RegisterHotKey(hwndSAS, HK_CTRL_ALT_DEL, MOD_CONTROL | MOD_ALT, VK_DELETE)) 1244c2c66affSColin Finck { 1245c2c66affSColin Finck ERR("WL: Unable to register Ctrl+Alt+Del hotkey!\n"); 1246c2c66affSColin Finck return FALSE; 1247c2c66affSColin Finck } 1248c2c66affSColin Finck 1249c2c66affSColin Finck /* Register Ctrl+Shift+Esc (optional) */ 1250c2c66affSColin Finck Session->TaskManHotkey = RegisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC, MOD_CONTROL | MOD_SHIFT, VK_ESCAPE); 1251c2c66affSColin Finck if (!Session->TaskManHotkey) 1252c2c66affSColin Finck WARN("WL: Warning: Unable to register Ctrl+Alt+Esc hotkey!\n"); 1253c2c66affSColin Finck return TRUE; 1254c2c66affSColin Finck } 1255c2c66affSColin Finck 1256c2c66affSColin Finck static 1257c2c66affSColin Finck BOOL 1258c2c66affSColin Finck UnregisterHotKeys( 1259c2c66affSColin Finck IN PWLSESSION Session, 1260c2c66affSColin Finck IN HWND hwndSAS) 1261c2c66affSColin Finck { 1262c2c66affSColin Finck /* Unregister hotkeys */ 1263c2c66affSColin Finck UnregisterHotKey(hwndSAS, HK_CTRL_ALT_DEL); 1264c2c66affSColin Finck 1265c2c66affSColin Finck if (Session->TaskManHotkey) 1266c2c66affSColin Finck UnregisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC); 1267c2c66affSColin Finck 1268c2c66affSColin Finck return TRUE; 1269c2c66affSColin Finck } 1270c2c66affSColin Finck 1271c2c66affSColin Finck BOOL 1272c2c66affSColin Finck WINAPI 1273c2c66affSColin Finck HandleMessageBeep(UINT uType) 1274c2c66affSColin Finck { 1275c2c66affSColin Finck LPWSTR EventName; 1276c2c66affSColin Finck 1277c2c66affSColin Finck switch(uType) 1278c2c66affSColin Finck { 1279c2c66affSColin Finck case 0xFFFFFFFF: 1280c2c66affSColin Finck EventName = NULL; 1281c2c66affSColin Finck break; 1282c2c66affSColin Finck case MB_OK: 1283c2c66affSColin Finck EventName = L"SystemDefault"; 1284c2c66affSColin Finck break; 1285c2c66affSColin Finck case MB_ICONASTERISK: 1286c2c66affSColin Finck EventName = L"SystemAsterisk"; 1287c2c66affSColin Finck break; 1288c2c66affSColin Finck case MB_ICONEXCLAMATION: 1289c2c66affSColin Finck EventName = L"SystemExclamation"; 1290c2c66affSColin Finck break; 1291c2c66affSColin Finck case MB_ICONHAND: 1292c2c66affSColin Finck EventName = L"SystemHand"; 1293c2c66affSColin Finck break; 1294c2c66affSColin Finck case MB_ICONQUESTION: 1295c2c66affSColin Finck EventName = L"SystemQuestion"; 1296c2c66affSColin Finck break; 1297c2c66affSColin Finck default: 1298c2c66affSColin Finck WARN("Unhandled type %d\n", uType); 1299c2c66affSColin Finck EventName = L"SystemDefault"; 1300c2c66affSColin Finck } 1301c2c66affSColin Finck 1302c2c66affSColin Finck return PlaySoundRoutine(EventName, FALSE, SND_ALIAS | SND_NOWAIT | SND_NOSTOP | SND_ASYNC); 1303c2c66affSColin Finck } 1304c2c66affSColin Finck 1305c2c66affSColin Finck static 1306c2c66affSColin Finck LRESULT 1307c2c66affSColin Finck CALLBACK 1308c2c66affSColin Finck SASWindowProc( 1309c2c66affSColin Finck IN HWND hwndDlg, 1310c2c66affSColin Finck IN UINT uMsg, 1311c2c66affSColin Finck IN WPARAM wParam, 1312c2c66affSColin Finck IN LPARAM lParam) 1313c2c66affSColin Finck { 1314c2c66affSColin Finck PWLSESSION Session = (PWLSESSION)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1315c2c66affSColin Finck 1316c2c66affSColin Finck switch (uMsg) 1317c2c66affSColin Finck { 1318c2c66affSColin Finck case WM_HOTKEY: 1319c2c66affSColin Finck { 1320c2c66affSColin Finck switch (lParam) 1321c2c66affSColin Finck { 1322c2c66affSColin Finck case MAKELONG(MOD_CONTROL | MOD_ALT, VK_DELETE): 1323c2c66affSColin Finck { 1324c2c66affSColin Finck TRACE("SAS: CONTROL+ALT+DELETE\n"); 1325c2c66affSColin Finck if (!Session->Gina.UseCtrlAltDelete) 1326c2c66affSColin Finck break; 1327c2c66affSColin Finck PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0); 1328c2c66affSColin Finck return TRUE; 1329c2c66affSColin Finck } 1330c2c66affSColin Finck case MAKELONG(MOD_CONTROL | MOD_SHIFT, VK_ESCAPE): 1331c2c66affSColin Finck { 1332c2c66affSColin Finck TRACE("SAS: CONTROL+SHIFT+ESCAPE\n"); 133346dcab7aSEric Kohl if (Session->LogonState == STATE_LOGGED_ON) 1334c2c66affSColin Finck DoGenericAction(Session, WLX_SAS_ACTION_TASKLIST); 1335c2c66affSColin Finck return TRUE; 1336c2c66affSColin Finck } 1337c2c66affSColin Finck } 1338c2c66affSColin Finck break; 1339c2c66affSColin Finck } 1340c2c66affSColin Finck case WM_CREATE: 1341c2c66affSColin Finck { 1342c2c66affSColin Finck /* Get the session pointer from the create data */ 1343c2c66affSColin Finck Session = (PWLSESSION)((LPCREATESTRUCT)lParam)->lpCreateParams; 1344c2c66affSColin Finck 1345c2c66affSColin Finck /* Save the Session pointer */ 1346c2c66affSColin Finck SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)Session); 1347c2c66affSColin Finck if (GetSetupType()) 1348c2c66affSColin Finck return TRUE; 1349c2c66affSColin Finck return RegisterHotKeys(Session, hwndDlg); 1350c2c66affSColin Finck } 1351c2c66affSColin Finck case WM_DESTROY: 1352c2c66affSColin Finck { 1353c2c66affSColin Finck if (!GetSetupType()) 1354c2c66affSColin Finck UnregisterHotKeys(Session, hwndDlg); 1355c2c66affSColin Finck return TRUE; 1356c2c66affSColin Finck } 1357c2c66affSColin Finck case WM_SETTINGCHANGE: 1358c2c66affSColin Finck { 1359c2c66affSColin Finck UINT uiAction = (UINT)wParam; 1360c2c66affSColin Finck if (uiAction == SPI_SETSCREENSAVETIMEOUT 1361c2c66affSColin Finck || uiAction == SPI_SETSCREENSAVEACTIVE) 1362c2c66affSColin Finck { 1363c2c66affSColin Finck SetEvent(Session->hScreenSaverParametersChanged); 1364c2c66affSColin Finck } 1365c2c66affSColin Finck return TRUE; 1366c2c66affSColin Finck } 1367c2c66affSColin Finck case WM_LOGONNOTIFY: 1368c2c66affSColin Finck { 1369c2c66affSColin Finck switch(wParam) 1370c2c66affSColin Finck { 1371c2c66affSColin Finck case LN_MESSAGE_BEEP: 1372c2c66affSColin Finck { 1373c2c66affSColin Finck return HandleMessageBeep(lParam); 1374c2c66affSColin Finck } 1375c2c66affSColin Finck case LN_SHELL_EXITED: 1376c2c66affSColin Finck { 1377c2c66affSColin Finck /* lParam is the exit code */ 13781f0fe386SEric Kohl if (lParam != 1 && 13791f0fe386SEric Kohl Session->LogonState != STATE_LOGGED_OFF && 13801f0fe386SEric Kohl Session->LogonState != STATE_LOGGED_OFF_SAS) 1381c2c66affSColin Finck { 1382c2c66affSColin Finck SetTimer(hwndDlg, 1, 1000, NULL); 1383c2c66affSColin Finck } 1384c2c66affSColin Finck break; 1385c2c66affSColin Finck } 1386c2c66affSColin Finck case LN_START_SCREENSAVE: 1387c2c66affSColin Finck { 1388c2c66affSColin Finck DispatchSAS(Session, WLX_SAS_TYPE_SCRNSVR_TIMEOUT); 1389c2c66affSColin Finck break; 1390c2c66affSColin Finck } 1391c2c66affSColin Finck case LN_LOCK_WORKSTATION: 1392c2c66affSColin Finck { 1393c2c66affSColin Finck DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA); 1394c2c66affSColin Finck break; 1395c2c66affSColin Finck } 1396c2c66affSColin Finck case LN_LOGOFF: 1397c2c66affSColin Finck { 1398c2c66affSColin Finck UINT Flags = (UINT)lParam; 1399c2c66affSColin Finck UINT Action = Flags & EWX_ACTION_MASK; 1400c2c66affSColin Finck DWORD wlxAction; 1401c2c66affSColin Finck 1402c2c66affSColin Finck TRACE("\tFlags : 0x%lx\n", lParam); 1403c2c66affSColin Finck 1404c2c66affSColin Finck /* 1405c2c66affSColin Finck * Our caller (USERSRV) should have added the shutdown flag 1406c2c66affSColin Finck * when setting also poweroff or reboot. 1407c2c66affSColin Finck */ 1408c2c66affSColin Finck if (Action & (EWX_POWEROFF | EWX_REBOOT)) 1409c2c66affSColin Finck { 1410c2c66affSColin Finck if ((Action & EWX_SHUTDOWN) == 0) 1411c2c66affSColin Finck { 1412c2c66affSColin Finck ERR("Missing EWX_SHUTDOWN flag for poweroff or reboot; action 0x%x\n", Action); 1413c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 1414c2c66affSColin Finck } 1415c2c66affSColin Finck 1416c2c66affSColin Finck /* Now we can locally remove it for performing checks */ 1417c2c66affSColin Finck Action &= ~EWX_SHUTDOWN; 1418c2c66affSColin Finck } 1419c2c66affSColin Finck 1420c2c66affSColin Finck /* Check parameters */ 1421c2c66affSColin Finck if (Action & EWX_FORCE) 1422c2c66affSColin Finck { 1423c2c66affSColin Finck // FIXME! 1424c2c66affSColin Finck ERR("FIXME: EWX_FORCE present for Winlogon, what to do?\n"); 1425c2c66affSColin Finck Action &= ~EWX_FORCE; 1426c2c66affSColin Finck } 1427c2c66affSColin Finck switch (Action) 1428c2c66affSColin Finck { 1429c2c66affSColin Finck case EWX_LOGOFF: 1430c2c66affSColin Finck wlxAction = WLX_SAS_ACTION_LOGOFF; 1431c2c66affSColin Finck break; 1432c2c66affSColin Finck case EWX_SHUTDOWN: 1433c2c66affSColin Finck wlxAction = WLX_SAS_ACTION_SHUTDOWN; 1434c2c66affSColin Finck break; 1435c2c66affSColin Finck case EWX_REBOOT: 1436c2c66affSColin Finck wlxAction = WLX_SAS_ACTION_SHUTDOWN_REBOOT; 1437c2c66affSColin Finck break; 1438c2c66affSColin Finck case EWX_POWEROFF: 1439c2c66affSColin Finck wlxAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF; 1440c2c66affSColin Finck break; 1441c2c66affSColin Finck 1442c2c66affSColin Finck default: 1443c2c66affSColin Finck { 1444c2c66affSColin Finck ERR("Invalid ExitWindows action 0x%x\n", Action); 1445c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 1446c2c66affSColin Finck } 1447c2c66affSColin Finck } 1448c2c66affSColin Finck 1449c2c66affSColin Finck TRACE("In LN_LOGOFF, exit_in_progress == %s\n", 1450c2c66affSColin Finck ExitReactOSInProgress ? "true" : "false"); 1451c2c66affSColin Finck 1452c2c66affSColin Finck /* 1453c2c66affSColin Finck * In case a parallel shutdown request is done (while we are 1454c2c66affSColin Finck * being to shut down) and it was not done by Winlogon itself, 1455c2c66affSColin Finck * then just stop here. 1456c2c66affSColin Finck */ 1457c2c66affSColin Finck #if 0 1458c2c66affSColin Finck // This code is commented at the moment (even if it's correct) because 1459c2c66affSColin Finck // our log-offs do not really work: the shell is restarted, no app is killed 1460c2c66affSColin Finck // etc... and as a result you just get explorer opening "My Documents". And 1461c2c66affSColin Finck // if you try now a shut down, it won't work because winlogon thinks it is 1462c2c66affSColin Finck // still in the middle of a shutdown. 1463c2c66affSColin Finck // Maybe we also need to reset ExitReactOSInProgress somewhere else?? 1464c2c66affSColin Finck if (ExitReactOSInProgress && (lParam & EWX_CALLER_WINLOGON) == 0) 1465c2c66affSColin Finck { 1466c2c66affSColin Finck break; 1467c2c66affSColin Finck } 1468c2c66affSColin Finck #endif 1469c2c66affSColin Finck /* Now do the shutdown action proper */ 1470c2c66affSColin Finck DoGenericAction(Session, wlxAction); 1471c2c66affSColin Finck return 1; 1472c2c66affSColin Finck } 1473c2c66affSColin Finck case LN_LOGOFF_CANCELED: 1474c2c66affSColin Finck { 1475c2c66affSColin Finck ERR("Logoff canceled!!, before: exit_in_progress == %s, after will be false\n", 1476c2c66affSColin Finck ExitReactOSInProgress ? "true" : "false"); 1477c2c66affSColin Finck 1478c2c66affSColin Finck ExitReactOSInProgress = FALSE; 1479c2c66affSColin Finck return 1; 1480c2c66affSColin Finck } 1481c2c66affSColin Finck default: 1482c2c66affSColin Finck { 1483c2c66affSColin Finck ERR("WM_LOGONNOTIFY case %d is unimplemented\n", wParam); 1484c2c66affSColin Finck } 1485c2c66affSColin Finck } 1486c2c66affSColin Finck return 0; 1487c2c66affSColin Finck } 1488c2c66affSColin Finck case WM_TIMER: 1489c2c66affSColin Finck { 1490c2c66affSColin Finck if (wParam == 1) 1491c2c66affSColin Finck { 1492c2c66affSColin Finck KillTimer(hwndDlg, 1); 1493c2c66affSColin Finck StartUserShell(Session); 1494c2c66affSColin Finck } 1495c2c66affSColin Finck break; 1496c2c66affSColin Finck } 1497c2c66affSColin Finck case WLX_WM_SAS: 1498c2c66affSColin Finck { 1499c2c66affSColin Finck DispatchSAS(Session, (DWORD)wParam); 1500c2c66affSColin Finck return TRUE; 1501c2c66affSColin Finck } 1502c2c66affSColin Finck } 1503c2c66affSColin Finck 1504c2c66affSColin Finck return DefWindowProc(hwndDlg, uMsg, wParam, lParam); 1505c2c66affSColin Finck } 1506c2c66affSColin Finck 1507c2c66affSColin Finck BOOL 1508c2c66affSColin Finck InitializeSAS( 1509c2c66affSColin Finck IN OUT PWLSESSION Session) 1510c2c66affSColin Finck { 1511c2c66affSColin Finck WNDCLASSEXW swc; 1512c2c66affSColin Finck BOOL ret = FALSE; 1513c2c66affSColin Finck 1514c2c66affSColin Finck if (!SwitchDesktop(Session->WinlogonDesktop)) 1515c2c66affSColin Finck { 1516c2c66affSColin Finck ERR("WL: Failed to switch to winlogon desktop\n"); 1517c2c66affSColin Finck goto cleanup; 1518c2c66affSColin Finck } 1519c2c66affSColin Finck 1520c2c66affSColin Finck /* Register SAS window class */ 1521c2c66affSColin Finck swc.cbSize = sizeof(WNDCLASSEXW); 1522c2c66affSColin Finck swc.style = CS_SAVEBITS; 1523c2c66affSColin Finck swc.lpfnWndProc = SASWindowProc; 1524c2c66affSColin Finck swc.cbClsExtra = 0; 1525c2c66affSColin Finck swc.cbWndExtra = 0; 1526c2c66affSColin Finck swc.hInstance = hAppInstance; 1527c2c66affSColin Finck swc.hIcon = NULL; 1528c2c66affSColin Finck swc.hCursor = NULL; 1529c2c66affSColin Finck swc.hbrBackground = NULL; 1530c2c66affSColin Finck swc.lpszMenuName = NULL; 1531c2c66affSColin Finck swc.lpszClassName = WINLOGON_SAS_CLASS; 1532c2c66affSColin Finck swc.hIconSm = NULL; 1533c2c66affSColin Finck if (RegisterClassExW(&swc) == 0) 1534c2c66affSColin Finck { 1535c2c66affSColin Finck ERR("WL: Failed to register SAS window class\n"); 1536c2c66affSColin Finck goto cleanup; 1537c2c66affSColin Finck } 1538c2c66affSColin Finck 1539c2c66affSColin Finck /* Create invisible SAS window */ 1540c2c66affSColin Finck Session->SASWindow = CreateWindowExW( 1541c2c66affSColin Finck 0, 1542c2c66affSColin Finck WINLOGON_SAS_CLASS, 1543c2c66affSColin Finck WINLOGON_SAS_TITLE, 1544c2c66affSColin Finck WS_POPUP, 1545c2c66affSColin Finck 0, 0, 0, 0, 0, 0, 1546c2c66affSColin Finck hAppInstance, Session); 1547c2c66affSColin Finck if (!Session->SASWindow) 1548c2c66affSColin Finck { 1549c2c66affSColin Finck ERR("WL: Failed to create SAS window\n"); 1550c2c66affSColin Finck goto cleanup; 1551c2c66affSColin Finck } 1552c2c66affSColin Finck 1553c2c66affSColin Finck /* Register SAS window to receive SAS notifications */ 1554c2c66affSColin Finck if (!SetLogonNotifyWindow(Session->SASWindow)) 1555c2c66affSColin Finck { 1556c2c66affSColin Finck ERR("WL: Failed to register SAS window\n"); 1557c2c66affSColin Finck goto cleanup; 1558c2c66affSColin Finck } 1559c2c66affSColin Finck 1560c2c66affSColin Finck if (!SetDefaultLanguage(NULL)) 1561c2c66affSColin Finck return FALSE; 1562c2c66affSColin Finck 1563c2c66affSColin Finck ret = TRUE; 1564c2c66affSColin Finck 1565c2c66affSColin Finck cleanup: 1566c2c66affSColin Finck if (!ret) 1567c2c66affSColin Finck UninitializeSAS(Session); 1568c2c66affSColin Finck return ret; 1569c2c66affSColin Finck } 1570