diff options
Diffstat (limited to 'private/windows/gina/winlogon/sas.c')
-rw-r--r-- | private/windows/gina/winlogon/sas.c | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/private/windows/gina/winlogon/sas.c b/private/windows/gina/winlogon/sas.c new file mode 100644 index 000000000..f28bdd805 --- /dev/null +++ b/private/windows/gina/winlogon/sas.c @@ -0,0 +1,524 @@ +/****************************** Module Header ******************************\ +* Module Name: sas.c +* +* Copyright (c) 1991, Microsoft Corporation +* +* Support routines to implement processing of the secure attention sequence +* +* Users must always press the SAS key sequence before entering a password. +* This module catches the key press and forwards a SAS message to the +* correct winlogon window. +* +* History: +* 12-05-91 Davidc Created. +\***************************************************************************/ + +#include "precomp.h" +#pragma hdrstop + +// Internal Prototypes +LONG SASWndProc( + HWND hwnd, + UINT message, + DWORD wParam, + LONG lParam); + +BOOL SASCreate( + HWND hwnd); + +BOOL SASDestroy( + HWND hwnd); + + +// Global used to hold the window handle of the SAS window. +static HWND hwndSAS = NULL; +// LATER this hwndSAS will have to go in instance data when we have multiple threads + +// Global for SAS window class name +static PWCHAR szSASClass = TEXT("SAS window class"); + + +#if DBG +#define DEFAULT_QUICK_REBOOT 1 +#else +#define DEFAULT_QUICK_REBOOT 0 +#endif + +#define SHELL_RESTART_TIMER_ID 100 + +/***************************************************************************\ +* SASInit +* +* Initialises this module. +* +* Creates a window to receive the SAS and registers the +* key sequence as a hot key. +* +* Returns TRUE on success, FALSE on failure. +* +* 12-05-91 Davidc Created. +\***************************************************************************/ + +BOOL SASInit( + PGLOBALS pGlobals) +{ + WNDCLASS wc; + + if (hwndSAS != NULL) { + DebugLog((DEB_ERROR, "SAS module already initialized !!")); + return(FALSE); + } + + // + // Register the notification window class + // + + wc.style = CS_SAVEBITS; + wc.lpfnWndProc = (WNDPROC)SASWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = pGlobals->hInstance; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = szSASClass; + + if (!RegisterClass(&wc)) + return FALSE; + + hwndSAS = CreateWindowEx(0L, szSASClass, TEXT("SAS window"), + WS_OVERLAPPEDWINDOW, + 0, 0, 0, 0, + NULL, NULL, pGlobals->hInstance, NULL); + + if (hwndSAS == NULL) + return FALSE; + + // + // Store our globals pointer in the window user data + // + + SetWindowLong(hwndSAS, GWL_USERDATA, (LONG)pGlobals); + + // + // Register this window with windows so we get notified for + // screen-saver startup and user log-off + // + if (!SetLogonNotifyWindow(pGlobals->WindowStation.hwinsta, hwndSAS)) { + DebugLog((DEB_ERROR, "Failed to set logon notify window")); + return(FALSE); + } + + return(TRUE); +} + + +/***************************************************************************\ +* SASTerminate +* +* Terminates this module. +* +* Unregisters the SAS and destroys the SAS windows +* +* 12-05-91 Davidc Created. +\***************************************************************************/ + +VOID SASTerminate(VOID) +{ + DestroyWindow(hwndSAS); + + // Reset our globals + hwndSAS = NULL; +} + + +/***************************************************************************\ +* SASWndProc +* +* Window procedure for the SAS window. +* +* This window registers the SAS hotkey sequence, and forwards any hotkey +* messages to the current winlogon window. It does this using a +* timeout module function. i.e. every window should register a timeout +* even if it's 0 if they want to get SAS messages. +* +* History: +* 12-09-91 Davidc Created. +\***************************************************************************/ + +LONG SASWndProc( + HWND hwnd, + UINT message, + DWORD wParam, + LONG lParam) +{ + PGLOBALS pGlobals = (PGLOBALS)GetWindowLong(hwnd, GWL_USERDATA); + + switch (message) + { + + case WM_CREATE: + if (!SASCreate(hwnd)) + { + return(TRUE); // Fail creation + } + return(FALSE); // Continue creating window + + case WM_DESTROY: + DebugLog(( DEB_TRACE, "SAS Window Shutting down?\n")); +#if DBG + DebugBreak(); +#endif + SASDestroy(hwnd); + return(0); + + case WM_HOTKEY: + if (wParam == 1) + { + QuickReboot(pGlobals, TRUE); + return(0); + } + +#if DBG + if (wParam == 2) + { + switch (pGlobals->WindowStation.ActiveDesktop) + { + case Desktop_Winlogon: + SetActiveDesktop(&pGlobals->WindowStation, Desktop_Application); + break; + case Desktop_Application: + SetActiveDesktop(&pGlobals->WindowStation, Desktop_Winlogon); + break; + } + return(0); + } + if (wParam == 3) + { + DebugBreak(); + return(0); + } +#endif + + if (wParam == 4) + { + PGINASESSION pGina = pGlobals->pGina; + WCHAR szTaskMgr[] = L"taskmgr.exe"; + + DebugLog((DEB_TRACE, "Starting taskmgr.exe.\n")); + + if (pGlobals->UserLoggedOn ) { + pGina->pWlxStartApplication(pGina->pGinaContext, + APPLICATION_DESKTOP_PATH, + pGlobals->UserProcessData.pEnvironment, + szTaskMgr); + } + return(0); + } + + CADNotify(pGlobals, WLX_SAS_TYPE_CTRL_ALT_DEL); + return(0); + + case WM_LOGONNOTIFY: // A private notification from Windows + + DebugLog((DEB_TRACE_SAS, "LOGONNOTIFY message %d\n", wParam )); + + switch (wParam) + { + + + case LOGON_LOGOFF: + +#if DBG + DebugLog((DEB_TRACE_SAS, "\tWINLOGON : %s\n", (lParam & EWX_WINLOGON_CALLER) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tSYSTEM : %s\n", (lParam & EWX_SYSTEM_CALLER) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tSHUTDOWN : %s\n", (lParam & EWX_SHUTDOWN) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tREBOOT : %s\n", (lParam & EWX_REBOOT) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tPOWEROFF : %s\n", (lParam & EWX_POWEROFF) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tFORCE : %s\n", (lParam & EWX_FORCE) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tOLD_SYSTEM : %s\n", (lParam & EWX_WINLOGON_OLD_SYSTEM) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tOLD_SHUTDOWN : %s\n", (lParam & EWX_WINLOGON_OLD_SHUTDOWN) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tOLD_REBOOT : %s\n", (lParam & EWX_WINLOGON_OLD_REBOOT) ? "True" : "False")); + DebugLog((DEB_TRACE_SAS, "\tOLD_POWEROFF : %s\n", (lParam & EWX_WINLOGON_OLD_POWEROFF) ? "True" : "False")); +#endif + + // + // If there is an exit windows in progress, reject this + // message if it is not our own call coming back. This + // prevents people from calling ExitWindowsEx repeatedly + // + + if ( ExitWindowsInProgress && + ( !( lParam & EWX_WINLOGON_CALLER ) ) ) + { + break; + + } + pGlobals->LogoffFlags = lParam; + CADNotify(pGlobals, WLX_SAS_TYPE_USER_LOGOFF); + break; + + case LOGON_INPUT_TIMEOUT: + // + // Notify the current window + // + // ForwardMessage(pGlobals, WM_SCREEN_SAVER_TIMEOUT, 0, 0); + CADNotify(pGlobals, WLX_SAS_TYPE_SCRNSVR_TIMEOUT); + break; + + case LOGON_RESTARTSHELL: + // + // Restart the shell after X seconds + // + // We don't restart the shell for the following conditions: + // + // 1) No one is logged on + // 2) We are in the process of logging off + // (logoffflags will be non-zero) + // 3) The shell exiting gracefully + // (Exit status is in lParam. 1 = graceful) + // 4) A new user has logged on after the request + // to restart the shell. + // (in the case of autoadminlogon, the new + // user could be logged on before the restart + // request comes through). + // + + if (!pGlobals->UserLoggedOn || + pGlobals->LogoffFlags || + (lParam == 1) || + (pGlobals->TickCount > (DWORD)GetMessageTime())) { + + break; + } + + SetTimer (hwnd, SHELL_RESTART_TIMER_ID, 2000, NULL); + break; + } + + return(0); + + case WM_TIMER: + { + PGINASESSION pGina; + LONG lResult; + HKEY hKey; + BOOL bRestart = TRUE; + DWORD dwType, dwSize; + + + // + // Restart the shell + // + + if (wParam != SHELL_RESTART_TIMER_ID) { + break; + } + + KillTimer (hwnd, SHELL_RESTART_TIMER_ID); + + + // + // Check if we should restart the shell + // + + lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, + WINLOGON_KEY, + 0, + KEY_READ, + &hKey); + + if (lResult == ERROR_SUCCESS) { + + dwSize = sizeof(bRestart); + RegQueryValueEx (hKey, + TEXT("AutoRestartShell"), + NULL, + &dwType, + (LPBYTE) &bRestart, + &dwSize); + + RegCloseKey (hKey); + } + + + if (bRestart) { + PWCH pchData; + PWSTR pszTok; + + DebugLog((DEB_TRACE, "Restarting user's shell.\n")); + + + pGina = pGlobals->pGina; + + pchData = AllocAndGetPrivateProfileString(APPLICATION_NAME, + SHELL_KEY, + TEXT("explorer.exe"), + NULL); + + if (!pchData) { + break; + } + + pszTok = wcstok(pchData, TEXT(",")); + while (pszTok) + { + if (*pszTok == TEXT(' ')) + { + while (*pszTok++ == TEXT(' ')) + ; + } + + + if (pGina->pWlxStartApplication(pGina->pGinaContext, + APPLICATION_DESKTOP_PATH, + pGlobals->UserProcessData.pEnvironment, + pszTok)) { + + ReportWinlogonEvent(pGlobals, + EVENTLOG_INFORMATION_TYPE, + EVENT_SHELL_RESTARTED, + 0, + NULL, + 1, + pszTok); + } + + pszTok = wcstok(NULL, TEXT(",")); + } + + Free(pchData); + } + + } + break; + + default: + return DefWindowProc(hwnd, message, wParam, lParam); + + } + + return 0L; +} + +BOOL bRegisteredQuickReboot; +BOOL bRegisteredDesktopSwitching; +BOOL bRegisteredWinlogonBreakpoint; +BOOL bRegisteredTaskmgr; + + +/***************************************************************************\ +* SASCreate +* +* Does any processing required for WM_CREATE message. +* +* Returns TRUE on success, FALSE on failure +* +* History: +* 12-09-91 Davidc Created. +\***************************************************************************/ + +BOOL SASCreate( + HWND hwnd) +{ + // Register the SAS unless we are told not to. + + + if (GetProfileInt( APPNAME_WINLOGON, VARNAME_AUTOLOGON, 0 ) != 2) { + if (!RegisterHotKey(hwnd, 0, MOD_CONTROL | MOD_ALT, VK_DELETE)) { + DebugLog((DEB_ERROR, "failed to register SAS")); + return(FALSE); // Fail creation + } + } + + + // + // (Ctrl+Alt+Shift+Del) hotkey to reboot into DOS directly + // + + if (GetProfileInt( APPNAME_WINLOGON, VARNAME_ENABLEQUICKREBOOT, DEFAULT_QUICK_REBOOT) != 0) { + if (!RegisterHotKey(hwnd, 1, MOD_CONTROL | MOD_ALT | MOD_SHIFT, VK_DELETE)) { + DebugLog((DEB_ERROR, "failed to register quick reboot SAS")); + bRegisteredQuickReboot = FALSE; + } else { + bRegisteredQuickReboot = TRUE; + } + } + +#if DBG + // + // (Ctrl+Alt+Tab) will switch between desktops + // + if (GetProfileInt( APPNAME_WINLOGON, VARNAME_ENABLEDESKTOPSWITCHING, 0 ) != 0) { + if (!RegisterHotKey(hwnd, 2, MOD_CONTROL | MOD_ALT, VK_TAB)) { + DebugLog((DEB_ERROR, "failed to register desktop switch SAS")); + bRegisteredDesktopSwitching = FALSE; + } else { + bRegisteredDesktopSwitching = TRUE; + } + } + + + if (WinlogonInfoLevel & DEB_COOL_SWITCH) { + if (!RegisterHotKey(hwnd, 3, MOD_CONTROL | MOD_ALT | MOD_SHIFT, VK_TAB)) { + DebugLog((DEB_ERROR, "failed to register breakpoint SAS")); + bRegisteredWinlogonBreakpoint = FALSE; + } else { + bRegisteredWinlogonBreakpoint = TRUE; + } + } +#endif + + // + // (Ctrl+Shift+Esc) will start taskmgr + // + + if (!RegisterHotKey(hwnd, 4, MOD_CONTROL | MOD_SHIFT, VK_ESCAPE)) { + DebugLog((DEB_ERROR, "failed to register taskmgr hotkey")); + bRegisteredTaskmgr = FALSE; + } else { + bRegisteredTaskmgr = TRUE; + } + + return(TRUE); +} + + +/***************************************************************************\ +* SASDestroy +* +* Does any processing required for WM_DESTROY message. +* +* Returns TRUE on success, FALSE on failure +* +* History: +* 12-09-91 Davidc Created. +\***************************************************************************/ + +BOOL SASDestroy( + HWND hwnd) +{ + // Unregister the SAS + UnregisterHotKey(hwnd, 0); + + if (bRegisteredQuickReboot) { + UnregisterHotKey(hwnd, 1); + } + if (bRegisteredDesktopSwitching) { + UnregisterHotKey(hwnd, 2); + } + +#if DBG + if (bRegisteredWinlogonBreakpoint) { + UnregisterHotKey(hwnd, 3); + } +#endif + + if (bRegisteredTaskmgr) { + UnregisterHotKey(hwnd, 4); + } + + + return(TRUE); +} |