summaryrefslogtreecommitdiffstats
path: root/private/windows/gina/winlogon/sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/windows/gina/winlogon/sas.c')
-rw-r--r--private/windows/gina/winlogon/sas.c524
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);
+}