⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guiconsole.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: guiconsole.c 28058 2007-07-31 21:41:15Z greatlrd $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            subsys/csrss/win32csr/guiconsole.c
 * PURPOSE:         Implementation of gui-mode consoles
 */

/* INCLUDES ******************************************************************/

#include "w32csr.h"

#define NDEBUG
#include <debug.h>

/* Not defined in any header file */
extern VOID STDCALL PrivateCsrssManualGuiCheck(LONG Check);

/* GLOBALS *******************************************************************/

typedef struct GUI_CONSOLE_DATA_TAG
{
  HFONT Font;
  unsigned CharWidth;
  unsigned CharHeight;
  PWCHAR LineBuffer;
  BOOL CursorBlinkOn;
  BOOL ForceCursorOff;
  CRITICAL_SECTION Lock;
  RECT Selection;
  POINT SelectionStart;
  BOOL MouseDown;
  HMODULE ConsoleLibrary;
  HANDLE hGuiInitEvent;
  HWND hVScrollBar;
  HWND hHScrollBar;
  WCHAR FontName[LF_FACESIZE];
  DWORD FontSize;
  DWORD FontWeight;
  DWORD HistoryNoDup;
  DWORD FullScreen;
  DWORD QuickEdit;
  DWORD InsertMode;
  DWORD NumberOfHistoryBuffers;
  DWORD HistoryBufferSize;
  DWORD WindowPosition;
  DWORD ScreenBufferSize;
  DWORD UseRasterFonts;
  COLORREF ScreenText;
  COLORREF ScreenBackground;
  COLORREF PopupBackground;
  COLORREF PopupText;
  COLORREF Colors[16];
  WCHAR szProcessName[MAX_PATH];
} GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;

#ifndef WM_APP
#define WM_APP 0x8000
#endif
#define PM_CREATE_CONSOLE  (WM_APP + 1)
#define PM_DESTROY_CONSOLE (WM_APP + 2)

#define CURSOR_BLINK_TIME 500
#define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)

static BOOL ConsInitialized = FALSE;
static HWND NotifyWnd;

typedef struct _GUICONSOLE_MENUITEM
{
    UINT uID;
    const struct _GUICONSOLE_MENUITEM *SubMenu;
    WORD wCmdID;
} GUICONSOLE_MENUITEM, *PGUICONSOLE_MENUITEM;

static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems[] =
{
    { IDS_MARK, NULL, ID_SYSTEM_EDIT_MARK },
    { IDS_COPY, NULL, ID_SYSTEM_EDIT_COPY },
    { IDS_PASTE, NULL, ID_SYSTEM_EDIT_PASTE },
    { IDS_SELECTALL, NULL, ID_SYSTEM_EDIT_SELECTALL },
    { IDS_SCROLL, NULL, ID_SYSTEM_EDIT_SCROLL },
    { IDS_FIND, NULL, ID_SYSTEM_EDIT_FIND },

    { 0, NULL, 0 } /* End of list */
};

static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems[] =
{
    { (UINT)-1, NULL, 0 }, /* Separator */
    { IDS_EDIT, GuiConsoleEditMenuItems, 0 },
    { IDS_DEFAULTS, NULL, ID_SYSTEM_DEFAULTS },
    { IDS_PROPERTIES, NULL, ID_SYSTEM_PROPERTIES },

    { 0, NULL, 0 } /* End of list */
};

static const COLORREF s_Colors[] =
{
    RGB(0, 0, 0),
    RGB(0, 0, 128),
    RGB(0, 128, 0),
    RGB(0, 128, 128),
    RGB(128, 0, 0),
    RGB(128, 0, 128),
    RGB(128, 128, 0),
    RGB(192, 192, 192),
    RGB(128, 128, 128),
    RGB(0, 0, 255),
    RGB(0, 255, 0),
    RGB(0, 255, 255),
    RGB(255, 0, 0),
    RGB(255, 0, 255),
    RGB(255, 255, 0),
    RGB(255, 255, 255)
};

/* FUNCTIONS *****************************************************************/

static VOID FASTCALL
GuiConsoleAppendMenuItems(HMENU hMenu,
                          const GUICONSOLE_MENUITEM *Items)
{
    UINT i;
    WCHAR szMenuString[255];
    HMENU hSubMenu;

    for (i = 0; Items[i].uID != 0; i++)
    {
        if (Items[i].uID != (UINT)-1)
        {
            if (LoadStringW(Win32CsrDllHandle,
                            Items[i].uID,
                            szMenuString,
                            sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
            {
                if (Items[i].SubMenu != NULL)
                {
                    hSubMenu = CreatePopupMenu();
                    if (hSubMenu != NULL)
                    {
                        GuiConsoleAppendMenuItems(hSubMenu,
                                                  Items[i].SubMenu);

                        if (!AppendMenuW(hMenu,
                                         MF_STRING | MF_POPUP,
                                         (UINT_PTR)hSubMenu,
                                         szMenuString))
                        {
                            DestroyMenu(hSubMenu);
                        }
                    }
                }
                else
                {
                    AppendMenuW(hMenu,
                                MF_STRING,
                                Items[i].wCmdID,
                                szMenuString);
                }
            }
        }
        else
        {
            AppendMenuW(hMenu,
                        MF_SEPARATOR,
                        0,
                        NULL);
        }
    }
}

static VOID FASTCALL
GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console)
{
    HMENU hMenu;

    hMenu = GetSystemMenu(Console->hWindow,
                          FALSE);
    if (hMenu != NULL)
    {
        GuiConsoleAppendMenuItems(hMenu,
                                  GuiConsoleMainMenuItems);
    }
}

static VOID FASTCALL
GuiConsoleGetDataPointers(HWND hWnd, PCSRSS_CONSOLE *Console, PGUI_CONSOLE_DATA *GuiData)
{
  *Console = (PCSRSS_CONSOLE) GetWindowLongPtrW(hWnd, GWL_USERDATA);
  *GuiData = (NULL == *Console ? NULL : (*Console)->PrivateData);
}

static BOOL FASTCALL
GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId, PHANDLE hProcHandle, PHKEY hResult, REGSAM samDesired)
{
  HANDLE hProcessToken = NULL;
  HANDLE hProcess;
  
  BYTE Buffer[256];
  DWORD Length = 0;
  UNICODE_STRING SidName;
  LONG res;
  PTOKEN_USER TokUser;
  
  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | READ_CONTROL, FALSE, ProcessId);
  if (!hProcess)
    {
      DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
      return FALSE;
    }

  if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
    {
      DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
      CloseHandle(hProcess);
      return FALSE;
    }

  if (!GetTokenInformation(hProcessToken, TokenUser, (PVOID)Buffer, sizeof(Buffer), &Length))
    {
      DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
      CloseHandle(hProcess);
      CloseHandle(hProcessToken);
      return FALSE;
    }
  
  TokUser = ((PTOKEN_USER)Buffer)->User.Sid;
  if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName, TokUser, TRUE)))
    {
      DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
      return FALSE;
    }
  
  res = RegOpenKeyExW(HKEY_USERS, SidName.Buffer, 0, samDesired, hResult);
  RtlFreeUnicodeString(&SidName);

  CloseHandle(hProcessToken);
  if (hProcHandle)
    *hProcHandle = hProcess;
  else
    CloseHandle(hProcess);

  if (res != ERROR_SUCCESS)
    return FALSE;
  else
    return TRUE;
}

static BOOL FASTCALL
GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData, DWORD ProcessId, PHKEY hSubKey, REGSAM samDesired, BOOL bCreate)
{
  WCHAR szProcessName[MAX_PATH];
  WCHAR szBuffer[MAX_PATH];
  UINT fLength, wLength;
  DWORD dwBitmask, dwLength;
  WCHAR CurDrive[] = { 'A',':', 0 };
  HANDLE hProcess;
  HKEY hKey;
  WCHAR * ptr;

  /*
   * console properties are stored under
   * HKCU\Console\*
   * 
   * There are 3 ways to store console properties
   * 
   *  1. use console title as subkey name
   *    i.e. cmd.exe
   *
   *  2. use application name as subkey name
   *
   *  3. use unexpanded path to console application.
   *     i.e. %SystemRoot%_system32_cmd.exe
   */
  
  DPRINT("GuiConsoleOpenUserSettings entered\n");

  if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId, &hProcess, &hKey, samDesired))
    {
      DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n"); 
      return FALSE;
    }

  /* FIXME we do not getting the process name so no menu will be loading, why ?*/
  fLength = GetProcessImageFileNameW(hProcess, szProcessName, sizeof(GuiData->szProcessName) / sizeof(WCHAR));
  CloseHandle(hProcess);

  //DPRINT1("szProcessName3 : %S\n",szProcessName);

  if (!fLength)
    {
      DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess);
      return FALSE;
    }
  /*
   * try the process name as path
   */
    
  ptr = wcsrchr(szProcessName, L'\\');
  wcscpy(GuiData->szProcessName, ptr);

  swprintf(szBuffer, L"Console%s",ptr);
  DPRINT("#1 Path : %S\n", szBuffer);

  if (bCreate)
    {
      if (RegCreateKeyW(hKey, szBuffer, hSubKey) == ERROR_SUCCESS)
        {
          RegCloseKey(hKey);
          return TRUE;
        }
      RegCloseKey(hKey);
      return FALSE;
  }

  if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
    {
      RegCloseKey(hKey);
      return TRUE;
    }

  /*
   * try the "Shortcut to processname" as path
   * FIXME: detect wheter the process was started as a shortcut
   */

  swprintf(szBuffer, L"Console\\Shortcut to %S", ptr);
  DPRINT("#2 Path : %S\n", szBuffer);
  if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
    {
      swprintf(GuiData->szProcessName, L"Shortcut to %S", ptr);
      RegCloseKey(hKey);
      return TRUE;
    }

  /*
   * if the path contains \\Device\\HarddiskVolume1\... remove it
   */

  if (szProcessName[0] == L'\\')
    {
      dwBitmask = GetLogicalDrives();
      while(dwBitmask)
        {
          if (dwBitmask & 0x1)
            {
              dwLength = QueryDosDeviceW(CurDrive, szBuffer, MAX_PATH);
              if (dwLength)
                {
                  if (!memcmp(szBuffer, szProcessName, (dwLength-2)*sizeof(WCHAR)))
                    {
                      wcscpy(szProcessName, CurDrive);
                      RtlMoveMemory(&szProcessName[2], &szProcessName[dwLength-1], fLength - dwLength -1);
                      break;
                    }
                }
            }
          dwBitmask = (dwBitmask >> 1);
          CurDrive[0]++;
        }
    }

  /*
   * last attempt: check whether the file is under %SystemRoot%
   * and use path like Console\%SystemRoot%_dir_dir2_file.exe
   */

  wLength = GetWindowsDirectoryW(szBuffer, MAX_PATH);
  if (wLength)
    {
      if (!wcsncmp(szProcessName, szBuffer, wLength))
        {
          /* replace slashes by underscores */
          while((ptr = wcschr(szProcessName, L'\\')))
            ptr[0] = L'_';
          
          swprintf(szBuffer, L"Console\\\%SystemRoot\%%S", &szProcessName[wLength]);
          DPRINT("#3 Path : %S\n", szBuffer);
          if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
            {
              swprintf(GuiData->szProcessName, L"\%SystemRoot\%%S", &szProcessName[wLength]);
              RegCloseKey(hKey);
              return TRUE;
            }
        }
    }
  RegCloseKey(hKey);
  return FALSE;
}

static VOID
GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData)
{
    HKEY hKey;
    PCSRSS_PROCESS_DATA ProcessData;

    if (Console->ProcessList.Flink == &Console->ProcessList)
      {
        DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
        return;
      }
    ProcessData = CONTAINING_RECORD(Console->ProcessList.Flink, CSRSS_PROCESS_DATA, ProcessEntry);
    if (!GuiConsoleOpenUserSettings(GuiData, PtrToUlong(ProcessData->ProcessId), &hKey, KEY_READ | KEY_WRITE, TRUE))
      {
        return;
      }

  if (Console->ActiveBuffer->CursorInfo.dwSize <= 1)
    {
      RegDeleteKeyW(hKey, L"CursorSize");
    }
  else
    {
      RegSetValueExW(hKey, L"CursorSize", 0, REG_DWORD, (const BYTE *)&Console->ActiveBuffer->CursorInfo.dwSize, sizeof(DWORD));
    }

  if (GuiData->NumberOfHistoryBuffers == 5)
    {
      RegDeleteKeyW(hKey, L"NumberOfHistoryBuffers");
    }
  else
    {
      RegSetValueExW(hKey, L"NumberOfHistoryBuffers", 0, REG_DWORD, (const BYTE *)&GuiData->NumberOfHistoryBuffers, sizeof(DWORD));
    }

  if (GuiData->HistoryBufferSize == 50)
    {
      RegDeleteKeyW(hKey, L"HistoryBufferSize");
    }
  else
    {
      RegSetValueExW(hKey, L"HistoryBufferSize", 0, REG_DWORD, (const BYTE *)&GuiData->HistoryBufferSize, sizeof(DWORD));
    }

  if (GuiData->FullScreen == FALSE)
    {
      RegDeleteKeyW(hKey, L"FullScreen");
    }
  else
    {
      RegSetValueExW(hKey, L"FullScreen", 0, REG_DWORD, (const BYTE *)&GuiData->FullScreen, sizeof(DWORD));
    }

  if ( GuiData->QuickEdit == FALSE)
    {
      RegDeleteKeyW(hKey, L"QuickEdit");
    }
    else
    {
      RegSetValueExW(hKey, L"QuickEdit", 0, REG_DWORD, (const BYTE *)&GuiData->QuickEdit, sizeof(DWORD));
    }

  if (GuiData->InsertMode == TRUE)
    {
      RegDeleteKeyW(hKey, L"InsertMode");
    }
  else
    {
      RegSetValueExW(hKey, L"InsertMode", 0, REG_DWORD, (const BYTE *)&GuiData->InsertMode, sizeof(DWORD));
    }

  if (GuiData->HistoryNoDup == FALSE)
    {
      RegDeleteKeyW(hKey, L"HistoryNoDup");
    }
  else
    {
      RegSetValueExW(hKey, L"HistoryNoDup", 0, REG_DWORD, (const BYTE *)&GuiData->HistoryNoDup, sizeof(DWORD));
    }

  if (GuiData->ScreenText == RGB(192, 192, 192))
    {
      /*
       * MS uses console attributes instead of real color
       */
       RegDeleteKeyW(hKey, L"ScreenText");
    }
  else
    {
       RegSetValueExW(hKey, L"ScreenText", 0, REG_DWORD, (const BYTE *)&GuiData->ScreenText, sizeof(COLORREF));
    }

  if (GuiData->ScreenBackground == RGB(0, 0, 0))
    {
       RegDeleteKeyW(hKey, L"ScreenBackground");
    }
  else
    {
       RegSetValueExW(hKey, L"ScreenBackground", 0, REG_DWORD, (const BYTE *)&GuiData->ScreenBackground, sizeof(COLORREF));
    }

  RegCloseKey(hKey);
}

static void FASTCALL
GuiConsoleReadUserSettings(HKEY hKey, PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PCSRSS_SCREEN_BUFFER Buffer)
{
  DWORD dwNumSubKeys = 0;
  DWORD dwIndex;
  DWORD dwValueName;
  DWORD dwValue;
  DWORD dwType;
  WCHAR szValueName[MAX_PATH];
  WCHAR szValue[MAX_PATH];
  DWORD Value;

  if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
    {
       DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");

⌨️ 快捷键说明

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