Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensas.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Winlogon 00004 * FILE: base/system/winlogon/sas.c 00005 * PURPOSE: Secure Attention Sequence 00006 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net) 00007 * Hervé Poussineau (hpoussin@reactos.org) 00008 * UPDATE HISTORY: 00009 * Created 28/03/2004 00010 */ 00011 00012 /* INCLUDES *****************************************************************/ 00013 00014 #include "winlogon.h" 00015 00016 #include <wine/debug.h> 00017 00018 WINE_DEFAULT_DEBUG_CHANNEL(winlogon); 00019 00020 /* GLOBALS ******************************************************************/ 00021 00022 #define WINLOGON_SAS_CLASS L"SAS Window class" 00023 #define WINLOGON_SAS_TITLE L"SAS window" 00024 00025 #define HK_CTRL_ALT_DEL 0 00026 #define HK_CTRL_SHIFT_ESC 1 00027 00028 static BOOL inScrn = FALSE; 00029 00030 /* FUNCTIONS ****************************************************************/ 00031 00032 static BOOL 00033 StartTaskManager( 00034 IN OUT PWLSESSION Session) 00035 { 00036 LPVOID lpEnvironment; 00037 BOOL ret; 00038 00039 if (!Session->Gina.Functions.WlxStartApplication) 00040 return FALSE; 00041 00042 if (!CreateEnvironmentBlock( 00043 &lpEnvironment, 00044 Session->UserToken, 00045 TRUE)) 00046 { 00047 return FALSE; 00048 } 00049 00050 ret = Session->Gina.Functions.WlxStartApplication( 00051 Session->Gina.Context, 00052 L"Default", 00053 lpEnvironment, 00054 L"taskmgr.exe"); 00055 00056 DestroyEnvironmentBlock(lpEnvironment); 00057 return ret; 00058 } 00059 00060 static BOOL 00061 StartUserShell( 00062 IN OUT PWLSESSION Session) 00063 { 00064 LPVOID lpEnvironment = NULL; 00065 BOOLEAN Old; 00066 BOOL ret; 00067 00068 /* Create environment block for the user */ 00069 if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE)) 00070 { 00071 WARN("WL: CreateEnvironmentBlock() failed\n"); 00072 return FALSE; 00073 } 00074 00075 /* Get privilege */ 00076 /* FIXME: who should do it? winlogon or gina? */ 00077 /* FIXME: reverting to lower privileges after creating user shell? */ 00078 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old); 00079 00080 ret = Session->Gina.Functions.WlxActivateUserShell( 00081 Session->Gina.Context, 00082 L"Default", 00083 NULL, /* FIXME */ 00084 lpEnvironment); 00085 00086 DestroyEnvironmentBlock(lpEnvironment); 00087 return ret; 00088 } 00089 00090 00091 BOOL 00092 SetDefaultLanguage( 00093 IN BOOL UserProfile) 00094 { 00095 HKEY BaseKey; 00096 LPCWSTR SubKey; 00097 LPCWSTR ValueName; 00098 LONG rc; 00099 HKEY hKey = NULL; 00100 DWORD dwType, dwSize; 00101 LPWSTR Value = NULL; 00102 UNICODE_STRING ValueString; 00103 NTSTATUS Status; 00104 LCID Lcid; 00105 BOOL ret = FALSE; 00106 00107 if (UserProfile) 00108 { 00109 BaseKey = HKEY_CURRENT_USER; 00110 SubKey = L"Control Panel\\International"; 00111 ValueName = L"Locale"; 00112 } 00113 else 00114 { 00115 BaseKey = HKEY_LOCAL_MACHINE; 00116 SubKey = L"System\\CurrentControlSet\\Control\\Nls\\Language"; 00117 ValueName = L"Default"; 00118 } 00119 00120 rc = RegOpenKeyExW( 00121 BaseKey, 00122 SubKey, 00123 0, 00124 KEY_READ, 00125 &hKey); 00126 if (rc != ERROR_SUCCESS) 00127 { 00128 TRACE("RegOpenKeyEx() failed with error %lu\n", rc); 00129 goto cleanup; 00130 } 00131 rc = RegQueryValueExW( 00132 hKey, 00133 ValueName, 00134 NULL, 00135 &dwType, 00136 NULL, 00137 &dwSize); 00138 if (rc != ERROR_SUCCESS) 00139 { 00140 TRACE("RegQueryValueEx() failed with error %lu\n", rc); 00141 goto cleanup; 00142 } 00143 else if (dwType != REG_SZ) 00144 { 00145 TRACE("Wrong type for %S\\%S registry entry (got 0x%lx, expected 0x%x)\n", 00146 SubKey, ValueName, dwType, REG_SZ); 00147 goto cleanup; 00148 } 00149 00150 Value = HeapAlloc(GetProcessHeap(), 0, dwSize); 00151 if (!Value) 00152 { 00153 TRACE("HeapAlloc() failed\n"); 00154 goto cleanup; 00155 } 00156 rc = RegQueryValueExW( 00157 hKey, 00158 ValueName, 00159 NULL, 00160 NULL, 00161 (LPBYTE)Value, 00162 &dwSize); 00163 if (rc != ERROR_SUCCESS) 00164 { 00165 TRACE("RegQueryValueEx() failed with error %lu\n", rc); 00166 goto cleanup; 00167 } 00168 00169 /* Convert Value to a Lcid */ 00170 ValueString.Length = ValueString.MaximumLength = (USHORT)dwSize; 00171 ValueString.Buffer = Value; 00172 Status = RtlUnicodeStringToInteger(&ValueString, 16, (PULONG)&Lcid); 00173 if (!NT_SUCCESS(Status)) 00174 { 00175 TRACE("RtlUnicodeStringToInteger() failed with status 0x%08lx\n", Status); 00176 goto cleanup; 00177 } 00178 00179 TRACE("%s language is 0x%08lx\n", 00180 UserProfile ? "User" : "System", Lcid); 00181 Status = NtSetDefaultLocale(UserProfile, Lcid); 00182 if (!NT_SUCCESS(Status)) 00183 { 00184 TRACE("NtSetDefaultLocale() failed with status 0x%08lx\n", Status); 00185 goto cleanup; 00186 } 00187 00188 ret = TRUE; 00189 00190 cleanup: 00191 if (hKey) 00192 RegCloseKey(hKey); 00193 if (Value) 00194 HeapFree(GetProcessHeap(), 0, Value); 00195 return ret; 00196 } 00197 00198 BOOL 00199 PlaySoundRoutine( 00200 IN LPCWSTR FileName, 00201 IN UINT bLogon, 00202 IN UINT Flags) 00203 { 00204 typedef BOOL (WINAPI *PLAYSOUNDW)(LPCWSTR,HMODULE,DWORD); 00205 typedef UINT (WINAPI *WAVEOUTGETNUMDEVS)(VOID); 00206 PLAYSOUNDW Play; 00207 WAVEOUTGETNUMDEVS waveOutGetNumDevs; 00208 UINT NumDevs; 00209 HMODULE hLibrary; 00210 BOOL Ret = FALSE; 00211 00212 hLibrary = LoadLibraryW(L"winmm.dll"); 00213 if (hLibrary) 00214 { 00215 waveOutGetNumDevs = (WAVEOUTGETNUMDEVS)GetProcAddress(hLibrary, "waveOutGetNumDevs"); 00216 if (waveOutGetNumDevs) 00217 { 00218 NumDevs = waveOutGetNumDevs(); 00219 if (!NumDevs) 00220 { 00221 if (!bLogon) 00222 { 00223 Beep(500, 500); 00224 } 00225 FreeLibrary(hLibrary); 00226 return FALSE; 00227 } 00228 } 00229 00230 Play = (PLAYSOUNDW)GetProcAddress(hLibrary, "PlaySoundW"); 00231 if (Play) 00232 { 00233 Ret = Play(FileName, NULL, Flags); 00234 } 00235 FreeLibrary(hLibrary); 00236 } 00237 00238 return Ret; 00239 } 00240 00241 DWORD 00242 WINAPI 00243 PlayLogonSoundThread( 00244 IN LPVOID lpParameter) 00245 { 00246 BYTE TokenUserBuffer[256]; 00247 PTOKEN_USER pTokenUser = (TOKEN_USER*)TokenUserBuffer; 00248 ULONG Length; 00249 HKEY hKey; 00250 WCHAR wszBuffer[MAX_PATH] = {0}; 00251 WCHAR wszDest[MAX_PATH]; 00252 DWORD dwSize = sizeof(wszBuffer), dwType; 00253 SERVICE_STATUS_PROCESS Info; 00254 UNICODE_STRING SidString; 00255 NTSTATUS Status; 00256 ULONG Index = 0; 00257 SC_HANDLE hSCManager, hService; 00258 00259 /* Get SID of current user */ 00260 Status = NtQueryInformationToken((HANDLE)lpParameter, 00261 TokenUser, 00262 TokenUserBuffer, 00263 sizeof(TokenUserBuffer), 00264 &Length); 00265 if (!NT_SUCCESS(Status)) 00266 { 00267 ERR("NtQueryInformationToken failed: %x!\n", Status); 00268 return 0; 00269 } 00270 00271 /* Convert SID to string */ 00272 RtlInitEmptyUnicodeString(&SidString, wszBuffer, sizeof(wszBuffer)); 00273 Status = RtlConvertSidToUnicodeString(&SidString, pTokenUser->User.Sid, FALSE); 00274 if (!NT_SUCCESS(Status)) 00275 { 00276 ERR("RtlConvertSidToUnicodeString failed: %x!\n", Status); 00277 return 0; 00278 } 00279 00280 /* Build path to logon sound registry key. 00281 Note: We can't use HKCU here, because Winlogon is owned by SYSTEM user */ 00282 if (FAILED(StringCbCopyW(wszBuffer + SidString.Length/sizeof(WCHAR), 00283 sizeof(wszBuffer) - SidString.Length, 00284 L"\\AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current"))) 00285 { 00286 /* SID is too long. Should not happen. */ 00287 ERR("StringCbCopyW failed!\n"); 00288 return 0; 00289 } 00290 00291 /* Open registry key and query sound path */ 00292 if (RegOpenKeyExW(HKEY_USERS, wszBuffer, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 00293 { 00294 ERR("RegOpenKeyExW(%ls) failed!\n", wszBuffer); 00295 return 0; 00296 } 00297 00298 if (RegQueryValueExW(hKey, NULL, NULL, &dwType, 00299 (LPBYTE)wszBuffer, &dwSize) != ERROR_SUCCESS || 00300 (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) 00301 { 00302 ERR("RegQueryValueExW failed!\n"); 00303 RegCloseKey(hKey); 00304 return 0; 00305 } 00306 00307 RegCloseKey(hKey); 00308 00309 if (!wszBuffer[0]) 00310 { 00311 /* No sound has been set */ 00312 ERR("No sound has been set\n"); 00313 return 0; 00314 } 00315 00316 /* Expand environment variables */ 00317 if (!ExpandEnvironmentStringsW(wszBuffer, wszDest, MAX_PATH)) 00318 { 00319 ERR("ExpandEnvironmentStringsW failed!\n"); 00320 return 0; 00321 } 00322 00323 /* Open service manager */ 00324 hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 00325 if (!hSCManager) 00326 { 00327 ERR("OpenSCManager failed (%x)\n", GetLastError()); 00328 return 0; 00329 } 00330 00331 /* Open wdmaud service */ 00332 hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ); 00333 if (!hService) 00334 { 00335 /* Sound is not installed */ 00336 TRACE("Failed to open wdmaud service (%x)\n", GetLastError()); 00337 CloseServiceHandle(hSCManager); 00338 return 0; 00339 } 00340 00341 /* Wait for wdmaud start */ 00342 do 00343 { 00344 if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize)) 00345 { 00346 TRACE("QueryServiceStatusEx failed (%x)\n", GetLastError()); 00347 break; 00348 } 00349 00350 if (Info.dwCurrentState == SERVICE_RUNNING) 00351 break; 00352 00353 Sleep(1000); 00354 00355 } while (Index++ < 20); 00356 00357 CloseServiceHandle(hService); 00358 CloseServiceHandle(hSCManager); 00359 00360 /* If wdmaud is not running exit */ 00361 if (Info.dwCurrentState != SERVICE_RUNNING) 00362 { 00363 WARN("wdmaud has not started!\n"); 00364 return 0; 00365 } 00366 00367 /* Sound subsystem is running. Play logon sound. */ 00368 TRACE("Playing logon sound: %ls\n", wszDest); 00369 PlaySoundRoutine(wszDest, TRUE, SND_FILENAME); 00370 return 0; 00371 } 00372 00373 static VOID 00374 PlayLogonSound( 00375 IN OUT PWLSESSION Session) 00376 { 00377 HANDLE hThread; 00378 00379 hThread = CreateThread(NULL, 0, PlayLogonSoundThread, (PVOID)Session->UserToken, 0, NULL); 00380 if (hThread) 00381 CloseHandle(hThread); 00382 } 00383 00384 static BOOL 00385 HandleLogon( 00386 IN OUT PWLSESSION Session) 00387 { 00388 PROFILEINFOW ProfileInfo; 00389 BOOL ret = FALSE; 00390 00391 /* Loading personal settings */ 00392 DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOADINGYOURPERSONALSETTINGS); 00393 ProfileInfo.hProfile = INVALID_HANDLE_VALUE; 00394 if (0 == (Session->Options & WLX_LOGON_OPT_NO_PROFILE)) 00395 { 00396 if (Session->Profile == NULL 00397 || (Session->Profile->dwType != WLX_PROFILE_TYPE_V1_0 00398 && Session->Profile->dwType != WLX_PROFILE_TYPE_V2_0)) 00399 { 00400 ERR("WL: Wrong profile\n"); 00401 goto cleanup; 00402 } 00403 00404 /* Load the user profile */ 00405 ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW)); 00406 ProfileInfo.dwSize = sizeof(PROFILEINFOW); 00407 ProfileInfo.dwFlags = 0; 00408 ProfileInfo.lpUserName = Session->MprNotifyInfo.pszUserName; 00409 ProfileInfo.lpProfilePath = Session->Profile->pszProfile; 00410 if (Session->Profile->dwType >= WLX_PROFILE_TYPE_V2_0) 00411 { 00412 ProfileInfo.lpDefaultPath = Session->Profile->pszNetworkDefaultUserProfile; 00413 ProfileInfo.lpServerName = Session->Profile->pszServerName; 00414 ProfileInfo.lpPolicyPath = Session->Profile->pszPolicy; 00415 } 00416 00417 if (!LoadUserProfileW(Session->UserToken, &ProfileInfo)) 00418 { 00419 ERR("WL: LoadUserProfileW() failed\n"); 00420 goto cleanup; 00421 } 00422 } 00423 00424 /* Create environment block for the user */ 00425 if (!CreateUserEnvironment(Session)) 00426 { 00427 WARN("WL: SetUserEnvironment() failed\n"); 00428 goto cleanup; 00429 } 00430 00431 DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGYOURPERSONALSETTINGS); 00432 UpdatePerUserSystemParameters(0, TRUE); 00433 00434 /* Set default language */ 00435 if (!SetDefaultLanguage(TRUE)) 00436 { 00437 WARN("WL: SetDefaultLanguage() failed\n"); 00438 goto cleanup; 00439 } 00440 00441 if (!StartUserShell(Session)) 00442 { 00443 //WCHAR StatusMsg[256]; 00444 WARN("WL: WlxActivateUserShell() failed\n"); 00445 //LoadStringW(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, sizeof(StatusMsg)); 00446 //MessageBoxW(0, StatusMsg, NULL, MB_ICONERROR); 00447 goto cleanup; 00448 } 00449 00450 if (!InitializeScreenSaver(Session)) 00451 WARN("WL: Failed to initialize screen saver\n"); 00452 00453 Session->hProfileInfo = ProfileInfo.hProfile; 00454 00455 /* Logon has successed. Play sound. */ 00456 PlayLogonSound(Session); 00457 00458 ret = TRUE; 00459 00460 cleanup: 00461 if (Session->Profile) 00462 { 00463 HeapFree(GetProcessHeap(), 0, Session->Profile->pszProfile); 00464 HeapFree(GetProcessHeap(), 0, Session->Profile); 00465 } 00466 Session->Profile = NULL; 00467 if (!ret 00468 && ProfileInfo.hProfile != INVALID_HANDLE_VALUE) 00469 { 00470 UnloadUserProfile(WLSession->UserToken, ProfileInfo.hProfile); 00471 } 00472 RemoveStatusMessage(Session); 00473 if (!ret) 00474 { 00475 CloseHandle(Session->UserToken); 00476 Session->UserToken = NULL; 00477 } 00478 return ret; 00479 } 00480 00481 #define EWX_ACTION_MASK 0xffffffeb 00482 #define EWX_FLAGS_MASK 0x00000014 00483 00484 typedef struct tagLOGOFF_SHUTDOWN_DATA 00485 { 00486 UINT Flags; 00487 PWLSESSION Session; 00488 } LOGOFF_SHUTDOWN_DATA, *PLOGOFF_SHUTDOWN_DATA; 00489 00490 static DWORD WINAPI 00491 LogoffShutdownThread(LPVOID Parameter) 00492 { 00493 PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA)Parameter; 00494 00495 if (LSData->Session->UserToken != NULL && !ImpersonateLoggedOnUser(LSData->Session->UserToken)) 00496 { 00497 ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError()); 00498 return 0; 00499 } 00500 00501 /* Close processes of the interactive user */ 00502 if (!ExitWindowsEx( 00503 EWX_INTERNAL_KILL_USER_APPS | (LSData->Flags & EWX_FLAGS_MASK) | 00504 (EWX_LOGOFF == (LSData->Flags & EWX_ACTION_MASK) ? EWX_INTERNAL_FLAG_LOGOFF : 0), 00505 0)) 00506 { 00507 ERR("Unable to kill user apps, error %lu\n", GetLastError()); 00508 RevertToSelf(); 00509 return 0; 00510 } 00511 00512 /* FIXME: Call ExitWindowsEx() to terminate COM processes */ 00513 00514 if (LSData->Session->UserToken) 00515 RevertToSelf(); 00516 00517 return 1; 00518 } 00519 00520 00521 static NTSTATUS 00522 CreateLogoffSecurityAttributes( 00523 OUT PSECURITY_ATTRIBUTES* ppsa) 00524 { 00525 /* The following code is not working yet and messy */ 00526 /* Still, it gives some ideas about data types and functions involved and */ 00527 /* required to set up a SECURITY_DESCRIPTOR for a SECURITY_ATTRIBUTES */ 00528 /* instance for a thread, to allow that thread to ImpersonateLoggedOnUser(). */ 00529 /* Specifically THREAD_SET_THREAD_TOKEN is required. */ 00530 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 00531 PSECURITY_ATTRIBUTES psa = 0; 00532 BYTE* pMem; 00533 PACL pACL; 00534 EXPLICIT_ACCESS Access; 00535 PSID pEveryoneSID = NULL; 00536 static SID_IDENTIFIER_AUTHORITY WorldAuthority = { SECURITY_WORLD_SID_AUTHORITY }; 00537 00538 *ppsa = NULL; 00539 00540 // Let's first try to enumerate what kind of data we need for this to ever work: 00541 // 1. The Winlogon SID, to be able to give it THREAD_SET_THREAD_TOKEN. 00542 // 2. The users SID (the user trying to logoff, or rather shut down the system). 00543 // 3. At least two EXPLICIT_ACCESS instances: 00544 // 3.1 One for Winlogon itself, giving it the rights 00545 // required to THREAD_SET_THREAD_TOKEN (as it's needed to successfully call 00546 // ImpersonateLoggedOnUser). 00547 // 3.2 One for the user, to allow *that* thread to perform its work. 00548 // 4. An ACL to hold the these EXPLICIT_ACCESS ACE's. 00549 // 5. A SECURITY_DESCRIPTOR to hold the ACL, and finally. 00550 // 6. A SECURITY_ATTRIBUTES instance to pull all of this required stuff 00551 // together, to hand it to CreateThread. 00552 // 00553 // However, it seems struct LOGOFF_SHUTDOWN_DATA doesn't contain 00554 // these required SID's, why they'd have to be added. 00555 // The Winlogon's own SID should probably only be created once, 00556 // while the user's SID obviously must be created for each new user. 00557 // Might as well store it when the user logs on? 00558 00559 if(!AllocateAndInitializeSid(&WorldAuthority, 00560 1, 00561 SECURITY_WORLD_RID, 00562 0, 0, 0, 0, 0, 0, 0, 00563 &pEveryoneSID)) 00564 { 00565 ERR("Failed to initialize security descriptor for logoff thread!\n"); 00566 return STATUS_UNSUCCESSFUL; 00567 } 00568 00569 /* set up the required security attributes to be able to shut down */ 00570 /* To save space and time, allocate a single block of memory holding */ 00571 /* both SECURITY_ATTRIBUTES and SECURITY_DESCRIPTOR */ 00572 pMem = HeapAlloc(GetProcessHeap(), 00573 0, 00574 sizeof(SECURITY_ATTRIBUTES) + 00575 SECURITY_DESCRIPTOR_MIN_LENGTH + 00576 sizeof(ACL)); 00577 if (!pMem) 00578 { 00579 ERR("Failed to allocate memory for logoff security descriptor!\n"); 00580 return STATUS_NO_MEMORY; 00581 } 00582 00583 /* Note that the security descriptor needs to be in _absolute_ format, */ 00584 /* meaning its members must be pointers to other structures, rather */ 00585 /* than the relative format using offsets */ 00586 psa = (PSECURITY_ATTRIBUTES)pMem; 00587 SecurityDescriptor = (PSECURITY_DESCRIPTOR)(pMem + sizeof(SECURITY_ATTRIBUTES)); 00588 pACL = (PACL)(((PBYTE)SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH); 00589 00590 // Initialize an EXPLICIT_ACCESS structure for an ACE. 00591 // The ACE will allow this thread to log off (and shut down the system, currently). 00592 ZeroMemory(&Access, sizeof(Access)); 00593 Access.grfAccessPermissions = THREAD_SET_THREAD_TOKEN; 00594 Access.grfAccessMode = SET_ACCESS; // GRANT_ACCESS? 00595 Access.grfInheritance = NO_INHERITANCE; 00596 Access.Trustee.TrusteeForm = TRUSTEE_IS_SID; 00597 Access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 00598 Access.Trustee.ptstrName = pEveryoneSID; 00599 00600 if (SetEntriesInAcl(1, &Access, NULL, &pACL) != ERROR_SUCCESS) 00601 { 00602 ERR("Failed to set Access Rights for logoff thread. Logging out will most likely fail.\n"); 00603 00604 HeapFree(GetProcessHeap(), 0, pMem); 00605 return STATUS_UNSUCCESSFUL; 00606 } 00607 00608 if (!InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) 00609 { 00610 ERR("Failed to initialize security descriptor for logoff thread!\n"); 00611 HeapFree(GetProcessHeap(), 0, pMem); 00612 return STATUS_UNSUCCESSFUL; 00613 } 00614 00615 if (!SetSecurityDescriptorDacl(SecurityDescriptor, 00616 TRUE, // bDaclPresent flag 00617 pACL, 00618 FALSE)) // not a default DACL 00619 { 00620 ERR("SetSecurityDescriptorDacl Error %lu\n", GetLastError()); 00621 HeapFree(GetProcessHeap(), 0, pMem); 00622 return STATUS_UNSUCCESSFUL; 00623 } 00624 00625 psa->nLength = sizeof(SECURITY_ATTRIBUTES); 00626 psa->lpSecurityDescriptor = SecurityDescriptor; 00627 psa->bInheritHandle = FALSE; 00628 00629 *ppsa = psa; 00630 00631 return STATUS_SUCCESS; 00632 } 00633 00634 static VOID 00635 DestroyLogoffSecurityAttributes( 00636 IN PSECURITY_ATTRIBUTES psa) 00637 { 00638 if (psa) 00639 { 00640 HeapFree(GetProcessHeap(), 0, psa); 00641 } 00642 } 00643 00644 00645 static NTSTATUS 00646 HandleLogoff( 00647 IN OUT PWLSESSION Session, 00648 IN UINT Flags) 00649 { 00650 PLOGOFF_SHUTDOWN_DATA LSData; 00651 PSECURITY_ATTRIBUTES psa; 00652 HANDLE hThread; 00653 DWORD exitCode; 00654 NTSTATUS Status; 00655 00656 DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_SAVEYOURSETTINGS); 00657 00658 /* Prepare data for logoff thread */ 00659 LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA)); 00660 if (!LSData) 00661 { 00662 ERR("Failed to allocate mem for thread data\n"); 00663 return STATUS_NO_MEMORY; 00664 } 00665 LSData->Flags = Flags; 00666 LSData->Session = Session; 00667 00668 Status = CreateLogoffSecurityAttributes(&psa); 00669 if (!NT_SUCCESS(Status)) 00670 { 00671 ERR("Failed to create a required security descriptor. Status 0x%08lx\n", Status); 00672 HeapFree(GetProcessHeap(), 0, LSData); 00673 return Status; 00674 } 00675 00676 /* Run logoff thread */ 00677 hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL); 00678 00679 /* we're done with the SECURITY_DESCRIPTOR */ 00680 DestroyLogoffSecurityAttributes(psa); 00681 psa = NULL; 00682 00683 if (!hThread) 00684 { 00685 ERR("Unable to create logoff thread, error %lu\n", GetLastError()); 00686 HeapFree(GetProcessHeap(), 0, LSData); 00687 return STATUS_UNSUCCESSFUL; 00688 } 00689 WaitForSingleObject(hThread, INFINITE); 00690 HeapFree(GetProcessHeap(), 0, LSData); 00691 if (!GetExitCodeThread(hThread, &exitCode)) 00692 { 00693 ERR("Unable to get exit code of logoff thread (error %lu)\n", GetLastError()); 00694 CloseHandle(hThread); 00695 return STATUS_UNSUCCESSFUL; 00696 } 00697 CloseHandle(hThread); 00698 if (exitCode == 0) 00699 { 00700 ERR("Logoff thread returned failure\n"); 00701 return STATUS_UNSUCCESSFUL; 00702 } 00703 00704 UnloadUserProfile(Session->UserToken, Session->hProfileInfo); 00705 CloseHandle(Session->UserToken); 00706 UpdatePerUserSystemParameters(0, FALSE); 00707 Session->LogonStatus = WKSTA_IS_LOGGED_OFF; 00708 Session->UserToken = NULL; 00709 return STATUS_SUCCESS; 00710 } 00711 00712 static INT_PTR CALLBACK 00713 ShutdownComputerWindowProc( 00714 IN HWND hwndDlg, 00715 IN UINT uMsg, 00716 IN WPARAM wParam, 00717 IN LPARAM lParam) 00718 { 00719 UNREFERENCED_PARAMETER(lParam); 00720 00721 switch (uMsg) 00722 { 00723 case WM_COMMAND: 00724 { 00725 switch (LOWORD(wParam)) 00726 { 00727 case IDC_BTNSHTDOWNCOMPUTER: 00728 EndDialog(hwndDlg, IDC_BTNSHTDOWNCOMPUTER); 00729 return TRUE; 00730 } 00731 break; 00732 } 00733 case WM_INITDIALOG: 00734 { 00735 RemoveMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND); 00736 SetFocus(GetDlgItem(hwndDlg, IDC_BTNSHTDOWNCOMPUTER)); 00737 return TRUE; 00738 } 00739 } 00740 return FALSE; 00741 } 00742 00743 static VOID 00744 UninitializeSAS( 00745 IN OUT PWLSESSION Session) 00746 { 00747 if (Session->SASWindow) 00748 { 00749 DestroyWindow(Session->SASWindow); 00750 Session->SASWindow = NULL; 00751 } 00752 if (Session->hEndOfScreenSaverThread) 00753 SetEvent(Session->hEndOfScreenSaverThread); 00754 UnregisterClassW(WINLOGON_SAS_CLASS, hAppInstance); 00755 } 00756 00757 NTSTATUS 00758 HandleShutdown( 00759 IN OUT PWLSESSION Session, 00760 IN DWORD wlxAction) 00761 { 00762 PLOGOFF_SHUTDOWN_DATA LSData; 00763 HANDLE hThread; 00764 DWORD exitCode; 00765 00766 DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISSHUTTINGDOWN); 00767 00768 /* Prepare data for shutdown thread */ 00769 LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA)); 00770 if (!LSData) 00771 { 00772 ERR("Failed to allocate mem for thread data\n"); 00773 return STATUS_NO_MEMORY; 00774 } 00775 if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_POWER_OFF) 00776 LSData->Flags = EWX_POWEROFF; 00777 else if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) 00778 LSData->Flags = EWX_REBOOT; 00779 else 00780 LSData->Flags = EWX_SHUTDOWN; 00781 LSData->Session = Session; 00782 00783 /* Run shutdown thread */ 00784 hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL); 00785 if (!hThread) 00786 { 00787 ERR("Unable to create shutdown thread, error %lu\n", GetLastError()); 00788 HeapFree(GetProcessHeap(), 0, LSData); 00789 return STATUS_UNSUCCESSFUL; 00790 } 00791 WaitForSingleObject(hThread, INFINITE); 00792 HeapFree(GetProcessHeap(), 0, LSData); 00793 if (!GetExitCodeThread(hThread, &exitCode)) 00794 { 00795 ERR("Unable to get exit code of shutdown thread (error %lu)\n", GetLastError()); 00796 CloseHandle(hThread); 00797 return STATUS_UNSUCCESSFUL; 00798 } 00799 CloseHandle(hThread); 00800 if (exitCode == 0) 00801 { 00802 ERR("Shutdown thread returned failure\n"); 00803 return STATUS_UNSUCCESSFUL; 00804 } 00805 00806 /* Destroy SAS window */ 00807 UninitializeSAS(Session); 00808 00809 FIXME("FIXME: Call SMSS API #1\n"); 00810 if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) 00811 NtShutdownSystem(ShutdownReboot); 00812 else 00813 { 00814 if (FALSE) 00815 { 00816 /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */ 00817 DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER), GetDesktopWindow(), ShutdownComputerWindowProc); 00818 } 00819 NtShutdownSystem(ShutdownNoReboot); 00820 } 00821 return STATUS_SUCCESS; 00822 } 00823 00824 static VOID 00825 DoGenericAction( 00826 IN OUT PWLSESSION Session, 00827 IN DWORD wlxAction) 00828 { 00829 switch (wlxAction) 00830 { 00831 case WLX_SAS_ACTION_LOGON: /* 0x01 */ 00832 if (HandleLogon(Session)) 00833 { 00834 SwitchDesktop(Session->ApplicationDesktop); 00835 Session->LogonStatus = WKSTA_IS_LOGGED_ON; 00836 } 00837 else 00838 Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 00839 break; 00840 case WLX_SAS_ACTION_NONE: /* 0x02 */ 00841 break; 00842 case WLX_SAS_ACTION_LOCK_WKSTA: /* 0x03 */ 00843 if (Session->Gina.Functions.WlxIsLockOk(Session->Gina.Context)) 00844 { 00845 SwitchDesktop(WLSession->WinlogonDesktop); 00846 Session->LogonStatus = WKSTA_IS_LOCKED; 00847 Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context); 00848 } 00849 break; 00850 case WLX_SAS_ACTION_LOGOFF: /* 0x04 */ 00851 case WLX_SAS_ACTION_SHUTDOWN: /* 0x05 */ 00852 case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: /* 0x0a */ 00853 case WLX_SAS_ACTION_SHUTDOWN_REBOOT: /* 0x0b */ 00854 if (Session->LogonStatus != WKSTA_IS_LOGGED_OFF) 00855 { 00856 if (!Session->Gina.Functions.WlxIsLogoffOk(Session->Gina.Context)) 00857 break; 00858 SwitchDesktop(WLSession->WinlogonDesktop); 00859 Session->Gina.Functions.WlxLogoff(Session->Gina.Context); 00860 if (!NT_SUCCESS(HandleLogoff(Session, EWX_LOGOFF))) 00861 { 00862 RemoveStatusMessage(Session); 00863 break; 00864 } 00865 } 00866 if (WLX_SHUTTINGDOWN(wlxAction)) 00867 { 00868 Session->Gina.Functions.WlxShutdown(Session->Gina.Context, wlxAction); 00869 if (!NT_SUCCESS(HandleShutdown(Session, wlxAction))) 00870 { 00871 RemoveStatusMessage(Session); 00872 Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 00873 } 00874 } 00875 else 00876 { 00877 RemoveStatusMessage(Session); 00878 Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 00879 } 00880 break; 00881 case WLX_SAS_ACTION_TASKLIST: /* 0x07 */ 00882 SwitchDesktop(WLSession->ApplicationDesktop); 00883 StartTaskManager(Session); 00884 break; 00885 case WLX_SAS_ACTION_UNLOCK_WKSTA: /* 0x08 */ 00886 SwitchDesktop(WLSession->ApplicationDesktop); 00887 Session->LogonStatus = WKSTA_IS_LOGGED_ON; 00888 break; 00889 default: 00890 WARN("Unknown SAS action 0x%lx\n", wlxAction); 00891 } 00892 } 00893 00894 static VOID 00895 DispatchSAS( 00896 IN OUT PWLSESSION Session, 00897 IN DWORD dwSasType) 00898 { 00899 DWORD wlxAction = WLX_SAS_ACTION_NONE; 00900 00901 if (Session->LogonStatus == WKSTA_IS_LOGGED_ON) 00902 wlxAction = (DWORD)Session->Gina.Functions.WlxLoggedOnSAS(Session->Gina.Context, dwSasType, NULL); 00903 else if (Session->LogonStatus == WKSTA_IS_LOCKED) 00904 wlxAction = (DWORD)Session->Gina.Functions.WlxWkstaLockedSAS(Session->Gina.Context, dwSasType); 00905 else 00906 { 00907 /* Display a new dialog (if necessary) */ 00908 switch (dwSasType) 00909 { 00910 case WLX_SAS_TYPE_TIMEOUT: /* 0x00 */ 00911 { 00912 Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context); 00913 break; 00914 } 00915 default: 00916 { 00917 PSID LogonSid = NULL; /* FIXME */ 00918 00919 Session->Options = 0; 00920 00921 wlxAction = (DWORD)Session->Gina.Functions.WlxLoggedOutSAS( 00922 Session->Gina.Context, 00923 Session->SASAction, 00924 &Session->LogonId, 00925 LogonSid, 00926 &Session->Options, 00927 &Session->UserToken, 00928 &Session->MprNotifyInfo, 00929 (PVOID*)&Session->Profile); 00930 break; 00931 } 00932 } 00933 } 00934 00935 if (dwSasType == WLX_SAS_TYPE_SCRNSVR_TIMEOUT) 00936 { 00937 BOOL bSecure = TRUE; 00938 if (!Session->Gina.Functions.WlxScreenSaverNotify(Session->Gina.Context, &bSecure)) 00939 { 00940 /* Skip start of screen saver */ 00941 SetEvent(Session->hEndOfScreenSaver); 00942 } 00943 else 00944 { 00945 if (bSecure) 00946 DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA); 00947 StartScreenSaver(Session); 00948 } 00949 } 00950 else if (dwSasType == WLX_SAS_TYPE_SCRNSVR_ACTIVITY) 00951 SetEvent(Session->hUserActivity); 00952 00953 DoGenericAction(Session, wlxAction); 00954 } 00955 00956 static BOOL 00957 RegisterHotKeys( 00958 IN PWLSESSION Session, 00959 IN HWND hwndSAS) 00960 { 00961 /* Register Ctrl+Alt+Del Hotkey */ 00962 if (!RegisterHotKey(hwndSAS, HK_CTRL_ALT_DEL, MOD_CONTROL | MOD_ALT, VK_DELETE)) 00963 { 00964 ERR("WL: Unable to register Ctrl+Alt+Del hotkey!\n"); 00965 return FALSE; 00966 } 00967 00968 /* Register Ctrl+Shift+Esc (optional) */ 00969 Session->TaskManHotkey = RegisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC, MOD_CONTROL | MOD_SHIFT, VK_ESCAPE); 00970 if (!Session->TaskManHotkey) 00971 WARN("WL: Warning: Unable to register Ctrl+Alt+Esc hotkey!\n"); 00972 return TRUE; 00973 } 00974 00975 static BOOL 00976 UnregisterHotKeys( 00977 IN PWLSESSION Session, 00978 IN HWND hwndSAS) 00979 { 00980 /* Unregister hotkeys */ 00981 UnregisterHotKey(hwndSAS, HK_CTRL_ALT_DEL); 00982 00983 if (Session->TaskManHotkey) 00984 UnregisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC); 00985 00986 return TRUE; 00987 } 00988 00989 static NTSTATUS 00990 CheckForShutdownPrivilege( 00991 IN DWORD RequestingProcessId) 00992 { 00993 HANDLE Process; 00994 HANDLE Token; 00995 BOOL CheckResult; 00996 PPRIVILEGE_SET PrivSet; 00997 00998 TRACE("CheckForShutdownPrivilege()\n"); 00999 01000 Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, RequestingProcessId); 01001 if (!Process) 01002 { 01003 WARN("OpenProcess() failed with error %lu\n", GetLastError()); 01004 return STATUS_INVALID_HANDLE; 01005 } 01006 if (!OpenProcessToken(Process, TOKEN_QUERY, &Token)) 01007 { 01008 WARN("OpenProcessToken() failed with error %lu\n", GetLastError()); 01009 CloseHandle(Process); 01010 return STATUS_INVALID_HANDLE; 01011 } 01012 CloseHandle(Process); 01013 PrivSet = HeapAlloc(GetProcessHeap(), 0, sizeof(PRIVILEGE_SET) + sizeof(LUID_AND_ATTRIBUTES)); 01014 if (!PrivSet) 01015 { 01016 ERR("Failed to allocate mem for privilege set\n"); 01017 CloseHandle(Token); 01018 return STATUS_NO_MEMORY; 01019 } 01020 PrivSet->PrivilegeCount = 1; 01021 PrivSet->Control = PRIVILEGE_SET_ALL_NECESSARY; 01022 if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &PrivSet->Privilege[0].Luid)) 01023 { 01024 WARN("LookupPrivilegeValue() failed with error %lu\n", GetLastError()); 01025 HeapFree(GetProcessHeap(), 0, PrivSet); 01026 CloseHandle(Token); 01027 return STATUS_UNSUCCESSFUL; 01028 } 01029 if (!PrivilegeCheck(Token, PrivSet, &CheckResult)) 01030 { 01031 WARN("PrivilegeCheck() failed with error %lu\n", GetLastError()); 01032 HeapFree(GetProcessHeap(), 0, PrivSet); 01033 CloseHandle(Token); 01034 return STATUS_ACCESS_DENIED; 01035 } 01036 HeapFree(GetProcessHeap(), 0, PrivSet); 01037 CloseHandle(Token); 01038 01039 if (!CheckResult) 01040 { 01041 WARN("SE_SHUTDOWN privilege not enabled\n"); 01042 return STATUS_ACCESS_DENIED; 01043 } 01044 return STATUS_SUCCESS; 01045 } 01046 01047 BOOL 01048 WINAPI 01049 HandleMessageBeep(UINT uType) 01050 { 01051 LPWSTR EventName; 01052 01053 switch(uType) 01054 { 01055 case 0xFFFFFFFF: 01056 EventName = NULL; 01057 break; 01058 case MB_OK: 01059 EventName = L"SystemDefault"; 01060 break; 01061 case MB_ICONASTERISK: 01062 EventName = L"SystemAsterisk"; 01063 break; 01064 case MB_ICONEXCLAMATION: 01065 EventName = L"SystemExclamation"; 01066 break; 01067 case MB_ICONHAND: 01068 EventName = L"SystemHand"; 01069 break; 01070 case MB_ICONQUESTION: 01071 EventName = L"SystemQuestion"; 01072 break; 01073 default: 01074 WARN("Unhandled type %d\n", uType); 01075 EventName = L"SystemDefault"; 01076 } 01077 01078 return PlaySoundRoutine(EventName, FALSE, SND_ALIAS | SND_NOWAIT | SND_NOSTOP | SND_ASYNC); 01079 } 01080 01081 static LRESULT CALLBACK 01082 SASWindowProc( 01083 IN HWND hwndDlg, 01084 IN UINT uMsg, 01085 IN WPARAM wParam, 01086 IN LPARAM lParam) 01087 { 01088 PWLSESSION Session = (PWLSESSION)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 01089 01090 switch (uMsg) 01091 { 01092 case WM_HOTKEY: 01093 { 01094 switch (lParam) 01095 { 01096 case MAKELONG(MOD_CONTROL | MOD_ALT, VK_DELETE): 01097 { 01098 TRACE("SAS: CONTROL+ALT+DELETE\n"); 01099 if (!Session->Gina.UseCtrlAltDelete) 01100 break; 01101 PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0); 01102 return TRUE; 01103 } 01104 case MAKELONG(MOD_CONTROL | MOD_SHIFT, VK_ESCAPE): 01105 { 01106 TRACE("SAS: CONTROL+SHIFT+ESCAPE\n"); 01107 DoGenericAction(Session, WLX_SAS_ACTION_TASKLIST); 01108 return TRUE; 01109 } 01110 } 01111 break; 01112 } 01113 case WM_CREATE: 01114 { 01115 /* Get the session pointer from the create data */ 01116 Session = (PWLSESSION)((LPCREATESTRUCT)lParam)->lpCreateParams; 01117 01118 /* Save the Session pointer */ 01119 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)Session); 01120 if (GetSetupType()) 01121 return TRUE; 01122 return RegisterHotKeys(Session, hwndDlg); 01123 } 01124 case WM_DESTROY: 01125 { 01126 if (!GetSetupType()) 01127 UnregisterHotKeys(Session, hwndDlg); 01128 return TRUE; 01129 } 01130 case WM_SETTINGCHANGE: 01131 { 01132 UINT uiAction = (UINT)wParam; 01133 if (uiAction == SPI_SETSCREENSAVETIMEOUT 01134 || uiAction == SPI_SETSCREENSAVEACTIVE) 01135 { 01136 SetEvent(Session->hScreenSaverParametersChanged); 01137 } 01138 return TRUE; 01139 } 01140 case WM_LOGONNOTIFY: 01141 { 01142 switch(wParam) 01143 { 01144 case LN_MESSAGE_BEEP: 01145 { 01146 return HandleMessageBeep(lParam); 01147 } 01148 case LN_SHELL_EXITED: 01149 { 01150 /* lParam is the exit code */ 01151 if(lParam != 1) 01152 { 01153 SetTimer(hwndDlg, 1, 1000, NULL); 01154 } 01155 break; 01156 } 01157 case LN_START_SCREENSAVE: 01158 { 01159 BOOL bSecure = FALSE; 01160 01161 if (inScrn) 01162 break; 01163 01164 inScrn = TRUE; 01165 01166 // lParam 1 == Secure 01167 if (lParam) 01168 { 01169 if (Session->Gina.Functions.WlxScreenSaverNotify(Session->Gina.Context, &bSecure)) 01170 { 01171 if (bSecure) DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA); 01172 } 01173 } 01174 01175 StartScreenSaver(Session); 01176 inScrn = FALSE; 01177 break; 01178 } 01179 default: 01180 { 01181 ERR("WM_LOGONNOTIFY case %d is unimplemented\n", wParam); 01182 } 01183 } 01184 return 0; 01185 } 01186 case WM_TIMER: 01187 { 01188 if (wParam == 1) 01189 { 01190 KillTimer(hwndDlg, 1); 01191 StartUserShell(Session); 01192 } 01193 break; 01194 } 01195 case WLX_WM_SAS: 01196 { 01197 DispatchSAS(Session, (DWORD)wParam); 01198 return TRUE; 01199 } 01200 case PM_WINLOGON_EXITWINDOWS: 01201 { 01202 UINT Flags = (UINT)lParam; 01203 UINT Action = Flags & EWX_ACTION_MASK; 01204 DWORD wlxAction; 01205 01206 /* Check parameters */ 01207 switch (Action) 01208 { 01209 case EWX_LOGOFF: wlxAction = WLX_SAS_ACTION_LOGOFF; break; 01210 case EWX_SHUTDOWN: wlxAction = WLX_SAS_ACTION_SHUTDOWN; break; 01211 case EWX_REBOOT: wlxAction = WLX_SAS_ACTION_SHUTDOWN_REBOOT; break; 01212 case EWX_POWEROFF: wlxAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF; break; 01213 default: 01214 { 01215 ERR("Invalid ExitWindows action 0x%x\n", Action); 01216 return STATUS_INVALID_PARAMETER; 01217 } 01218 } 01219 01220 if (WLX_SHUTTINGDOWN(wlxAction)) 01221 { 01222 NTSTATUS Status = CheckForShutdownPrivilege((DWORD)wParam); 01223 if (!NT_SUCCESS(Status)) 01224 return Status; 01225 } 01226 DoGenericAction(Session, wlxAction); 01227 return 1; 01228 } 01229 } 01230 01231 return DefWindowProc(hwndDlg, uMsg, wParam, lParam); 01232 } 01233 01234 BOOL 01235 InitializeSAS( 01236 IN OUT PWLSESSION Session) 01237 { 01238 WNDCLASSEXW swc; 01239 BOOL ret = FALSE; 01240 01241 if (!SwitchDesktop(Session->WinlogonDesktop)) 01242 { 01243 ERR("WL: Failed to switch to winlogon desktop\n"); 01244 goto cleanup; 01245 } 01246 01247 /* Register SAS window class */ 01248 swc.cbSize = sizeof(WNDCLASSEXW); 01249 swc.style = CS_SAVEBITS; 01250 swc.lpfnWndProc = SASWindowProc; 01251 swc.cbClsExtra = 0; 01252 swc.cbWndExtra = 0; 01253 swc.hInstance = hAppInstance; 01254 swc.hIcon = NULL; 01255 swc.hCursor = NULL; 01256 swc.hbrBackground = NULL; 01257 swc.lpszMenuName = NULL; 01258 swc.lpszClassName = WINLOGON_SAS_CLASS; 01259 swc.hIconSm = NULL; 01260 if (RegisterClassExW(&swc) == 0) 01261 { 01262 ERR("WL: Failed to register SAS window class\n"); 01263 goto cleanup; 01264 } 01265 01266 /* Create invisible SAS window */ 01267 Session->SASWindow = CreateWindowExW( 01268 0, 01269 WINLOGON_SAS_CLASS, 01270 WINLOGON_SAS_TITLE, 01271 WS_POPUP, 01272 0, 0, 0, 0, 0, 0, 01273 hAppInstance, Session); 01274 if (!Session->SASWindow) 01275 { 01276 ERR("WL: Failed to create SAS window\n"); 01277 goto cleanup; 01278 } 01279 01280 /* Register SAS window to receive SAS notifications */ 01281 if (!SetLogonNotifyWindow(Session->SASWindow, Session->InteractiveWindowStation)) 01282 { 01283 ERR("WL: Failed to register SAS window\n"); 01284 goto cleanup; 01285 } 01286 01287 if (!SetDefaultLanguage(FALSE)) 01288 return FALSE; 01289 01290 ret = TRUE; 01291 01292 cleanup: 01293 if (!ret) 01294 UninitializeSAS(Session); 01295 return ret; 01296 } Generated on Sat May 26 2012 04:17:45 for ReactOS by
1.7.6.1
|