ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sas.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.