📄 guiconsole.c
字号:
/* $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 + -