sas.c

来自「一个类似windows」· C语言 代码 · 共 291 行

C
291
字号
/*
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS kernel
 * FILE:            services/winlogon/sas.c
 * PURPOSE:         Secure Attention Sequence
 * PROGRAMMER:      Thomas Weidenmueller (w3seek@users.sourceforge.net)
 * UPDATE HISTORY:
 *                  Created 28/03/2004
 */

#include "winlogon.h"

#define NDEBUG
#include <debug.h>

#define WINLOGON_SAS_CLASS L"SAS window class"
#define WINLOGON_SAS_TITLE L"SAS"

#define HK_CTRL_ALT_DEL 0
#define HK_CTRL_SHIFT_ESC   1

#ifdef __USE_W32API
extern BOOL STDCALL SetLogonNotifyWindow(HWND Wnd, HWINSTA WinSta);
#endif

void
DispatchSAS(PWLSESSION Session, DWORD dwSasType)
{
  Session->SASAction = dwSasType;

}

void
UninitSAS(PWLSESSION Session)
{
  if(Session->SASWindow)
  {
    DestroyWindow(Session->SASWindow);
    Session->SASWindow = NULL;
  }
}

BOOL
SetupSAS(PWLSESSION Session, HWND hwndSAS)
{
  /* Register Ctrl+Alt+Del Hotkey */
  if(!RegisterHotKey(hwndSAS, HK_CTRL_ALT_DEL, MOD_CONTROL | MOD_ALT, VK_DELETE))
  {
    DPRINT1("WL-SAS: Unable to register Ctrl+Alt+Del hotkey!\n");
    return FALSE;
  }

  /* Register Ctrl+Shift+Esc */
  Session->TaskManHotkey = RegisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC, MOD_CONTROL | MOD_SHIFT, VK_ESCAPE);
  if(!Session->TaskManHotkey)
  {
    DPRINT1("WL-SAS: Warning: Unable to register Ctrl+Alt+Esc hotkey!\n");
  }
  return TRUE;
}

BOOL
DestroySAS(PWLSESSION Session, HWND hwndSAS)
{
  /* Unregister hotkeys */

  UnregisterHotKey(hwndSAS, HK_CTRL_ALT_DEL);

  if(Session->TaskManHotkey)
  {
    UnregisterHotKey(hwndSAS, HK_CTRL_SHIFT_ESC);
  }

  return TRUE;
}

#define EWX_ACTION_MASK 0xffffffeb
#define EWX_FLAGS_MASK  0x00000014

typedef struct tagLOGOFF_SHUTDOWN_DATA
{
  UINT Flags;
  PWLSESSION Session;
} LOGOFF_SHUTDOWN_DATA, *PLOGOFF_SHUTDOWN_DATA;

static DWORD WINAPI
LogoffShutdownThread(LPVOID Parameter)
{
  PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA) Parameter;

  if (! ImpersonateLoggedOnUser(LSData->Session->UserToken))
  {
    DPRINT1("ImpersonateLoggedOnUser failed with error %d\n", GetLastError());
    return 0;
  }
  if (! ExitWindowsEx(EWX_INTERNAL_KILL_USER_APPS | (LSData->Flags & EWX_FLAGS_MASK)
                      | (EWX_LOGOFF == (LSData->Flags & EWX_ACTION_MASK) ? EWX_INTERNAL_FLAG_LOGOFF : 0),
                      0))
  {
    DPRINT1("Unable to kill user apps, error %d\n", GetLastError());
    RevertToSelf();
    return 0;
  }
  RevertToSelf();

  HeapFree(GetProcessHeap(), 0, LSData);

  return 1;
}

static LRESULT
HandleExitWindows(PWLSESSION Session, DWORD RequestingProcessId, UINT Flags)
{
  UINT Action;
  HANDLE Process;
  HANDLE Token;
  HANDLE Thread;
  BOOL CheckResult;
  PPRIVILEGE_SET PrivSet;
  PLOGOFF_SHUTDOWN_DATA LSData;

  /* Check parameters */
  Action = Flags & EWX_ACTION_MASK;
  if (EWX_LOGOFF != Action && EWX_SHUTDOWN != Action && EWX_REBOOT != Action
      && EWX_POWEROFF != Action)
  {
    DPRINT1("Invalid ExitWindows action 0x%x\n", Action);
    return STATUS_INVALID_PARAMETER;
  }

  /* Check privilege */
  if (EWX_LOGOFF != Action)
  {
    Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, RequestingProcessId);
    if (NULL == Process)
    {
      DPRINT1("OpenProcess failed with error %d\n", GetLastError());
      return STATUS_INVALID_HANDLE;
    }
    if (! OpenProcessToken(Process, TOKEN_QUERY, &Token))
    {
      DPRINT1("OpenProcessToken failed with error %d\n", GetLastError());
      CloseHandle(Process);
      return STATUS_INVALID_HANDLE;
    }
    CloseHandle(Process);
    PrivSet = HeapAlloc(GetProcessHeap(), 0, sizeof(PRIVILEGE_SET) + sizeof(LUID_AND_ATTRIBUTES));
    if (NULL == PrivSet)
    {
      DPRINT1("Failed to allocate mem for privilege set\n");
      CloseHandle(Token);
      return STATUS_NO_MEMORY;
    }
    PrivSet->PrivilegeCount = 1;
    PrivSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
    if (! LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &PrivSet->Privilege[0].Luid))
    {
      DPRINT1("LookupPrivilegeValue failed with error %d\n", GetLastError());
      HeapFree(GetProcessHeap(), 0, PrivSet);
      CloseHandle(Token);
      return STATUS_UNSUCCESSFUL;
    }
    if (! PrivilegeCheck(Token, PrivSet, &CheckResult))
    {
      DPRINT1("PrivilegeCheck failed with error %d\n", GetLastError());
      HeapFree(GetProcessHeap(), 0, PrivSet);
      CloseHandle(Token);
      return STATUS_ACCESS_DENIED;
    }
    HeapFree(GetProcessHeap(), 0, PrivSet);
    CloseHandle(Token);
    if (! CheckResult)
    {
      DPRINT1("SE_SHUTDOWN privilege not enabled\n");
      return STATUS_ACCESS_DENIED;
    }
  }

  LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
  if (NULL == LSData)
  {
    DPRINT1("Failed to allocate mem for thread data\n");
    return STATUS_NO_MEMORY;
  }
  LSData->Flags = Flags;
  LSData->Session = Session;
  Thread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID) LSData, 0, NULL);
  if (NULL == Thread)
  {
    DPRINT1("Unable to create shutdown thread, error %d\n", GetLastError());
    HeapFree(GetProcessHeap(), 0, LSData);
    return STATUS_UNSUCCESSFUL;
  }
  CloseHandle(Thread);

  return 1;
}

LRESULT CALLBACK
SASProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  PWLSESSION Session = (PWLSESSION)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  if(!Session)
  {
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
  }
  switch(uMsg)
  {
    case WM_HOTKEY:
    {
      switch(wParam)
      {
        case HK_CTRL_ALT_DEL:
          DPRINT1("SAS: CTR+ALT+DEL\n");
          break;
        case HK_CTRL_SHIFT_ESC:
          DPRINT1("SAS: CTR+SHIFT+ESC\n");
          break;
      }
      return 0;
    }
    case WM_CREATE:
    {
      /* Get the session pointer from the create data */
      Session = (PWLSESSION)((LPCREATESTRUCT)lParam)->lpCreateParams;

      /* Save the Session pointer */
      SetWindowLongPtr(Session->SASWindow, GWLP_USERDATA, (DWORD_PTR)Session);

      if(!SetupSAS(Session, hwnd))
      {
        /* Fail! */
        return 1;
      }
      return 0;
    }
    case PM_WINLOGON_EXITWINDOWS:
    {
      return HandleExitWindows(Session, (DWORD) wParam, (UINT) lParam);
    }
    case WM_DESTROY:
    {
      DestroySAS(Session, hwnd);
      return 0;
    }
  }
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

BOOL
InitializeSAS(PWLSESSION Session)
{
  WNDCLASSEX swc;

  /* register SAS window class.
     WARNING! MAKE SURE WE ARE IN THE WINLOGON DESKTOP! */
  swc.cbSize = sizeof(WNDCLASSEXW);
  swc.style = CS_SAVEBITS;
  swc.lpfnWndProc = SASProc;
  swc.cbClsExtra = 0;
  swc.cbWndExtra = 0;
  swc.hInstance = hAppInstance;
  swc.hIcon = NULL;
  swc.hCursor = NULL;
  swc.hbrBackground = NULL;
  swc.lpszMenuName = NULL;
  swc.lpszClassName = WINLOGON_SAS_CLASS;
  swc.hIconSm = NULL;
  RegisterClassEx(&swc);

  /* create invisible SAS window */
  Session->SASWindow = CreateWindowEx(0, WINLOGON_SAS_CLASS, WINLOGON_SAS_TITLE, WS_POPUP,
                                      0, 0, 0, 0, 0, 0, hAppInstance, Session);
  if(!Session->SASWindow)
  {
    DPRINT1("WL: Failed to create SAS window\n");
    return FALSE;
  }

  /* Register SAS window to receive SAS notifications */
  if(!SetLogonNotifyWindow(Session->SASWindow, Session->InteractiveWindowStation))
  {
    UninitSAS(Session);
    DPRINT1("WL: Failed to register SAS window\n");
    return FALSE;
  }

  return TRUE;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?