コード例 #1
0
ファイル: sas.c プロジェクト: Moteesh/reactos
static
NTSTATUS
HandleLogoff(
    IN OUT PWLSESSION Session,
    IN UINT Flags)
{
    PLOGOFF_SHUTDOWN_DATA LSData;
    PSECURITY_ATTRIBUTES psa;
    HANDLE hThread;
    DWORD exitCode;
    NTSTATUS Status;

    /* Prepare data for logoff thread */
    LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
    if (!LSData)
    {
        ERR("Failed to allocate mem for thread data\n");
        return STATUS_NO_MEMORY;
    }
    LSData->Flags = Flags;
    LSData->Session = Session;

    Status = CreateLogoffSecurityAttributes(&psa);
    if (!NT_SUCCESS(Status))
    {
        ERR("Failed to create a required security descriptor. Status 0x%08lx\n", Status);
        HeapFree(GetProcessHeap(), 0, LSData);
        return Status;
    }

    /* Run logoff thread */
    hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
    if (!hThread)
    {
        ERR("Unable to create logoff thread, error %lu\n", GetLastError());
        DestroyLogoffSecurityAttributes(psa);
        HeapFree(GetProcessHeap(), 0, LSData);
        return STATUS_UNSUCCESSFUL;
    }
    WaitForSingleObject(hThread, INFINITE);
    if (!GetExitCodeThread(hThread, &exitCode))
    {
        ERR("Unable to get exit code of logoff thread (error %lu)\n", GetLastError());
        CloseHandle(hThread);
        DestroyLogoffSecurityAttributes(psa);
        HeapFree(GetProcessHeap(), 0, LSData);
        return STATUS_UNSUCCESSFUL;
    }
    CloseHandle(hThread);
    if (exitCode == 0)
    {
        ERR("Logoff thread returned failure\n");
        DestroyLogoffSecurityAttributes(psa);
        HeapFree(GetProcessHeap(), 0, LSData);
        return STATUS_UNSUCCESSFUL;
    }

    SwitchDesktop(Session->WinlogonDesktop);

    // TODO: Play logoff sound!

    SetWindowStationUser(Session->InteractiveWindowStation,
                         &LuidNone, NULL, 0);

    // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOGGINGOFF);

    // FIXME: Closing network connections!
    // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_CLOSINGNETWORKCONNECTIONS);

    /* Kill remaining COM apps. Only at logoff! */
    hThread = CreateThread(psa, 0, KillComProcesses, (LPVOID)LSData, 0, NULL);
    if (hThread)
    {
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
    }

    /* We're done with the SECURITY_DESCRIPTOR */
    DestroyLogoffSecurityAttributes(psa);
    psa = NULL;

    HeapFree(GetProcessHeap(), 0, LSData);

    DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_SAVEYOURSETTINGS);

    UnloadUserProfile(Session->UserToken, Session->hProfileInfo);

    CallNotificationDlls(Session, LogoffHandler);

    CloseHandle(Session->UserToken);
    UpdatePerUserSystemParameters(0, FALSE);
    Session->LogonState = STATE_LOGGED_OFF;
    Session->UserToken = NULL;

    return STATUS_SUCCESS;
}
コード例 #2
0
ファイル: sas.c プロジェクト: Moteesh/reactos
static
BOOL
HandleLogon(
    IN OUT PWLSESSION Session)
{
    PROFILEINFOW ProfileInfo;
    BOOL ret = FALSE;

    /* Loading personal settings */
    DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOADINGYOURPERSONALSETTINGS);
    ProfileInfo.hProfile = INVALID_HANDLE_VALUE;
    if (0 == (Session->Options & WLX_LOGON_OPT_NO_PROFILE))
    {
        if (Session->Profile == NULL
         || (Session->Profile->dwType != WLX_PROFILE_TYPE_V1_0
          && Session->Profile->dwType != WLX_PROFILE_TYPE_V2_0))
        {
            ERR("WL: Wrong profile\n");
            goto cleanup;
        }

        /* Load the user profile */
        ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
        ProfileInfo.dwSize = sizeof(PROFILEINFOW);
        ProfileInfo.dwFlags = 0;
        ProfileInfo.lpUserName = Session->MprNotifyInfo.pszUserName;
        ProfileInfo.lpProfilePath = Session->Profile->pszProfile;
        if (Session->Profile->dwType >= WLX_PROFILE_TYPE_V2_0)
        {
            ProfileInfo.lpDefaultPath = Session->Profile->pszNetworkDefaultUserProfile;
            ProfileInfo.lpServerName = Session->Profile->pszServerName;
            ProfileInfo.lpPolicyPath = Session->Profile->pszPolicy;
        }

        if (!LoadUserProfileW(Session->UserToken, &ProfileInfo))
        {
            ERR("WL: LoadUserProfileW() failed\n");
            goto cleanup;
        }
    }

    /* Create environment block for the user */
    if (!CreateUserEnvironment(Session))
    {
        WARN("WL: SetUserEnvironment() failed\n");
        goto cleanup;
    }

    CallNotificationDlls(Session, LogonHandler);

    DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGYOURPERSONALSETTINGS);
    UpdatePerUserSystemParameters(0, TRUE);

    /* Set default user language */
    if (!SetDefaultLanguage(Session))
    {
        WARN("WL: SetDefaultLanguage() failed\n");
        goto cleanup;
    }

    AllowWinstaAccess(Session);

    /* Connect remote resources */
    RestoreAllConnections(Session);

    if (!StartUserShell(Session))
    {
        //WCHAR StatusMsg[256];
        WARN("WL: WlxActivateUserShell() failed\n");
        //LoadStringW(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, sizeof(StatusMsg) / sizeof(StatusMsg[0]));
        //MessageBoxW(0, StatusMsg, NULL, MB_ICONERROR);
        goto cleanup;
    }

    CallNotificationDlls(Session, StartShellHandler);

    if (!InitializeScreenSaver(Session))
        WARN("WL: Failed to initialize screen saver\n");

    Session->hProfileInfo = ProfileInfo.hProfile;

    /* Logon has succeeded. Play sound. */
    PlayLogonSound(Session);

    ret = TRUE;

cleanup:
    if (Session->Profile)
    {
        HeapFree(GetProcessHeap(), 0, Session->Profile->pszProfile);
        HeapFree(GetProcessHeap(), 0, Session->Profile);
    }
    Session->Profile = NULL;
    if (!ret && ProfileInfo.hProfile != INVALID_HANDLE_VALUE)
    {
        UnloadUserProfile(Session->UserToken, ProfileInfo.hProfile);
    }
    RemoveStatusMessage(Session);
    if (!ret)
    {
        SetWindowStationUser(Session->InteractiveWindowStation,
                             &LuidNone, NULL, 0);
        CloseHandle(Session->UserToken);
        Session->UserToken = NULL;
    }

    if (ret)
    {
        SwitchDesktop(Session->ApplicationDesktop);
        Session->LogonState = STATE_LOGGED_ON;
    }

    return ret;
}
コード例 #3
0
ファイル: sas.c プロジェクト: Moteesh/reactos
static
VOID
DoGenericAction(
    IN OUT PWLSESSION Session,
    IN DWORD wlxAction)
{
    switch (wlxAction)
    {
        case WLX_SAS_ACTION_LOGON: /* 0x01 */
            if (Session->LogonState == STATE_LOGGED_OFF_SAS)
            {
                if (!HandleLogon(Session))
                {
                    Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
                    CallNotificationDlls(Session, LogonHandler);
                }
            }
            break;
        case WLX_SAS_ACTION_NONE: /* 0x02 */
            if (Session->LogonState == STATE_LOGGED_OFF_SAS)
            {
                Session->LogonState = STATE_LOGGED_OFF;
                Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
            }
            else if (Session->LogonState == STATE_LOGGED_ON_SAS)
            {
                Session->LogonState = STATE_LOGGED_ON;
            }
            else if (Session->LogonState == STATE_LOCKED_SAS)
            {
                Session->LogonState = STATE_LOCKED;
                Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context);
            }
            break;
        case WLX_SAS_ACTION_LOCK_WKSTA: /* 0x03 */
            if (Session->Gina.Functions.WlxIsLockOk(Session->Gina.Context))
            {
                SwitchDesktop(Session->WinlogonDesktop);
                Session->LogonState = STATE_LOCKED;
                Session->Gina.Functions.WlxDisplayLockedNotice(Session->Gina.Context);
                CallNotificationDlls(Session, LockHandler);
            }
            break;
        case WLX_SAS_ACTION_LOGOFF: /* 0x04 */
        case WLX_SAS_ACTION_SHUTDOWN: /* 0x05 */
        case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: /* 0x0a */
        case WLX_SAS_ACTION_SHUTDOWN_REBOOT: /* 0x0b */
            if (Session->LogonState != STATE_LOGGED_OFF)
            {
                if (!Session->Gina.Functions.WlxIsLogoffOk(Session->Gina.Context))
                    break;
                if (!NT_SUCCESS(HandleLogoff(Session, EWX_LOGOFF)))
                {
                    RemoveStatusMessage(Session);
                    break;
                }
                Session->Gina.Functions.WlxLogoff(Session->Gina.Context);
            }
            if (WLX_SHUTTINGDOWN(wlxAction))
            {
                // FIXME: WlxShutdown should be done from inside HandleShutdown,
                // after having displayed "ReactOS is shutting down" message.
                Session->Gina.Functions.WlxShutdown(Session->Gina.Context, wlxAction);
                if (!NT_SUCCESS(HandleShutdown(Session, wlxAction)))
                {
                    RemoveStatusMessage(Session);
                    Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
                }
            }
            else
            {
                RemoveStatusMessage(Session);
                Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
            }
            break;
        case WLX_SAS_ACTION_TASKLIST: /* 0x07 */
            SwitchDesktop(Session->ApplicationDesktop);
            Session->LogonState = STATE_LOGGED_ON;
            StartTaskManager(Session);
            break;
        case WLX_SAS_ACTION_UNLOCK_WKSTA: /* 0x08 */
            SwitchDesktop(Session->ApplicationDesktop);
            Session->LogonState = STATE_LOGGED_ON;
            CallNotificationDlls(Session, UnlockHandler);
            break;
        default:
            WARN("Unknown SAS action 0x%lx\n", wlxAction);
    }
}
コード例 #4
0
ファイル: sas.c プロジェクト: Moteesh/reactos
NTSTATUS
HandleShutdown(
    IN OUT PWLSESSION Session,
    IN DWORD wlxAction)
{
    PLOGOFF_SHUTDOWN_DATA LSData;
    HANDLE hThread;
    DWORD exitCode;
    BOOLEAN Old;

    // SwitchDesktop(Session->WinlogonDesktop);
    DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISSHUTTINGDOWN);

    /* Prepare data for shutdown thread */
    LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
    if (!LSData)
    {
        ERR("Failed to allocate mem for thread data\n");
        return STATUS_NO_MEMORY;
    }
    if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_POWER_OFF)
        LSData->Flags = EWX_POWEROFF;
    else if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT)
        LSData->Flags = EWX_REBOOT;
    else
        LSData->Flags = EWX_SHUTDOWN;
    LSData->Session = Session;

    // FIXME: We may need to specify this flag to really force application kill
    // (we are shutting down ReactOS, not just logging off so no hangs, etc...
    // should be allowed).
    // LSData->Flags |= EWX_FORCE;

    /* Run shutdown thread */
    hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
    if (!hThread)
    {
        ERR("Unable to create shutdown thread, error %lu\n", GetLastError());
        HeapFree(GetProcessHeap(), 0, LSData);
        return STATUS_UNSUCCESSFUL;
    }
    WaitForSingleObject(hThread, INFINITE);
    HeapFree(GetProcessHeap(), 0, LSData);
    if (!GetExitCodeThread(hThread, &exitCode))
    {
        ERR("Unable to get exit code of shutdown thread (error %lu)\n", GetLastError());
        CloseHandle(hThread);
        return STATUS_UNSUCCESSFUL;
    }
    CloseHandle(hThread);
    if (exitCode == 0)
    {
        ERR("Shutdown thread returned failure\n");
        return STATUS_UNSUCCESSFUL;
    }

    CallNotificationDlls(Session, ShutdownHandler);

    /* Destroy SAS window */
    UninitializeSAS(Session);

    /* Now we can shut down NT */
    ERR("Shutting down NT...\n");
    RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
    if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT)
    {
        NtShutdownSystem(ShutdownReboot);
    }
    else
    {
        if (FALSE)
        {
            /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */
            DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER),
                      GetDesktopWindow(), ShutdownComputerWindowProc);
        }
        NtShutdownSystem(ShutdownNoReboot);
    }
    RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
    return STATUS_SUCCESS;
}
コード例 #5
0
ファイル: screensaver.c プロジェクト: GYGit/reactos
VOID
StartScreenSaver(
    IN PWLSESSION Session)
{
    HKEY hKey = NULL, hCurrentUser = NULL;
    WCHAR szApplicationName[MAX_PATH];
    WCHAR szCommandLine[MAX_PATH + 3];
    DWORD bufferSize = sizeof(szApplicationName) - sizeof(WCHAR);
    DWORD dwType;
    STARTUPINFOW StartupInfo;
    PROCESS_INFORMATION ProcessInformation;
    HANDLE HandleArray[2];
    LONG rc;
    DWORD Status;
    BOOL ret = FALSE;

    if (!ImpersonateLoggedOnUser(Session->UserToken))
    {
        ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
        goto cleanup;
    }

    rc = RegOpenCurrentUser(KEY_READ,
                            &hCurrentUser);
    if (rc != ERROR_SUCCESS)
    {
        ERR("WL: RegOpenCurrentUser error %lu\n", rc);
        goto cleanup;
    }

    rc = RegOpenKeyExW(hCurrentUser,
                       L"Control Panel\\Desktop",
                       0,
                       KEY_QUERY_VALUE,
                       &hKey);
    if (rc != ERROR_SUCCESS)
    {
        ERR("WL: RegOpenKeyEx error %lu\n", rc);
        goto cleanup;
    }

    rc = RegQueryValueExW(hKey,
                          L"SCRNSAVE.EXE",
                          0,
                          &dwType,
                          (LPBYTE)szApplicationName,
                          &bufferSize);
    if (rc != ERROR_SUCCESS || dwType != REG_SZ)
    {
        if (rc != ERROR_FILE_NOT_FOUND)
            ERR("WL: RegQueryValueEx error %lu\n", rc);
        goto cleanup;
    }

    if (bufferSize == 0)
    {
        ERR("WL: Buffer size is NULL!\n");
        goto cleanup;
    }

    szApplicationName[bufferSize / sizeof(WCHAR)] = 0; /* Terminate the string */

    if (wcslen(szApplicationName) == 0)
    {
        ERR("WL: Application Name length is zero!\n");
        goto cleanup;
    }

    wsprintfW(szCommandLine, L"%s /s", szApplicationName);
    TRACE("WL: Executing %S\n", szCommandLine);

    ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW));
    ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    StartupInfo.cb = sizeof(STARTUPINFOW);
    StartupInfo.dwFlags = STARTF_SCRNSAVER;

    /* FIXME: run the screen saver on the screen saver desktop */
    ret = CreateProcessW(szApplicationName,
                         szCommandLine,
                         NULL,
                         NULL,
                         FALSE,
                         0,
                         NULL,
                         NULL,
                         &StartupInfo,
                         &ProcessInformation);
    if (!ret)
    {
        ERR("WL: Unable to start %S, error %lu\n", szApplicationName, GetLastError());
        goto cleanup;
    }

    CloseHandle(ProcessInformation.hThread);

    SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0);

    CallNotificationDlls(Session, StartScreenSaverHandler);

    /* Wait the end of the process or some other activity */
    ResetEvent(Session->hUserActivity);
    HandleArray[0] = ProcessInformation.hProcess;
    HandleArray[1] = Session->hUserActivity;
    Status = WaitForMultipleObjects(2, HandleArray, FALSE, INFINITE);
    if (Status == WAIT_OBJECT_0 + 1)
    {
        /* Kill the screen saver */
        TerminateProcess(ProcessInformation.hProcess, 0);
    }

    SetEvent(Session->hEndOfScreenSaver);

    CloseHandle(ProcessInformation.hProcess);

    CallNotificationDlls(Session, StopScreenSaverHandler);

cleanup:
    RevertToSelf();
    if (hKey)
        RegCloseKey(hKey);

    if (hCurrentUser)
        RegCloseKey(hCurrentUser);

    if (!ret)
    {
        PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_ACTIVITY, 0);
#ifndef USE_GETLASTINPUTINFO
        InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());
#endif
    }
}
コード例 #6
-2
ファイル: winlogon.c プロジェクト: ariscop/reactos
int
WINAPI
WinMain(
    IN HINSTANCE hInstance,
    IN HINSTANCE hPrevInstance,
    IN LPSTR lpCmdLine,
    IN int nShowCmd)
{
#if 0
    LSA_STRING ProcessName, PackageName;
    HANDLE LsaHandle;
    LSA_OPERATIONAL_MODE Mode;
    BOOLEAN Old;
    ULONG AuthenticationPackage;
    NTSTATUS Status;
#endif
    ULONG HardErrorResponse;
    MSG Msg;

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    UNREFERENCED_PARAMETER(nShowCmd);

    hAppInstance = hInstance;

    /* Make us critical */
    RtlSetProcessIsCritical(TRUE, NULL, FALSE);
    RtlSetThreadIsCritical(TRUE, NULL, FALSE);

    if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE))
    {
        ERR("WL: Could not register logon process\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION));
    if (!WLSession)
    {
        ERR("WL: Could not allocate memory for winlogon instance\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    ZeroMemory(WLSession, sizeof(WLSESSION));
    WLSession->DialogTimeout = 120; /* 2 minutes */

    /* Initialize the dialog tracking list */
    InitDialogListHead();

    if (!CreateWindowStationAndDesktops(WLSession))
    {
        ERR("WL: Could not create window station and desktops\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    LockWorkstation(WLSession);

    /* Load default keyboard layouts */
    if (!InitKeyboardLayouts())
    {
        ERR("WL: Could not preload keyboard layouts\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    if (!StartRpcServer())
    {
        ERR("WL: Could not start the RPC server\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    if (!StartServicesManager())
    {
        ERR("WL: Could not start services.exe\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    if (!StartLsass())
    {
        ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    /* Wait for the LSA server */
    WaitForLsass();

    /* Init Notifications */
    InitNotifications();

    /* Load and initialize gina */
    if (!GinaInit(WLSession))
    {
        ERR("WL: Failed to initialize Gina\n");
        // FIXME: Retrieve the real name of the GINA DLL we were trying to load.
        // It is known only inside the GinaInit function...
        DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"msgina.dll");
        HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT);
        ExitProcess(1);
    }

    DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP);

#if 0
    /* Connect to NetLogon service (lsass.exe) */
    /* Real winlogon uses "Winlogon" */
    RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon");
    Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
    if (Status == STATUS_PORT_CONNECTION_REFUSED)
    {
        /* Add the 'SeTcbPrivilege' privilege and try again */
        Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old);
        if (!NT_SUCCESS(Status))
        {
            ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status));
            return 1;
        }

        Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
    }

    if (!NT_SUCCESS(Status))
    {
        ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status));
        return 1;
    }

    RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W);
    Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage);
    if (!NT_SUCCESS(Status))
    {
        ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status));
        LsaDeregisterLogonProcess(LsaHandle);
        return 1;
    }
#endif

    CallNotificationDlls(WLSession, StartupHandler);

    /* Create a hidden window to get SAS notifications */
    if (!InitializeSAS(WLSession))
    {
        ERR("WL: Failed to initialize SAS\n");
        ExitProcess(2);
    }

    // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
    // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);

    /* Display logged out screen */
    WLSession->LogonState = STATE_INIT;
    RemoveStatusMessage(WLSession);

    /* Check for pending setup */
    if (GetSetupType() != 0)
    {
        /* Run setup and reboot when done */
        TRACE("WL: Setup mode detected\n");
        RunSetup();
    }
    else
    {
        PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0);
    }

    (void)LoadLibraryW(L"sfc_os.dll");

    /* Tell kernel that CurrentControlSet is good (needed
     * to support Last good known configuration boot) */
    NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1);

    /* Message loop for the SAS window */
    while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessageW(&Msg);
    }

    CleanupNotifications();

    /* We never go there */

    return 0;
}