reactos/win32ss/user/consrv/guisettings.c
Hermès Bélusca-Maïto 53eba1ba5f [CONSOLE.DLL-CONSRV]
- Further separate properties of the GUI terminal front-end and those independent of the UI.
- Fix some console initialization steps.

svn path=/branches/ros-csrss/; revision=58605
2013-03-24 17:08:10 +00:00

463 lines
16 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/guisettings.c
* PURPOSE: GUI terminal emulator settings management
* PROGRAMMERS: Hermes Belusca - Maito
*/
/* INCLUDES *******************************************************************/
#include "consrv.h"
#include "conio.h"
#include "settings.h"
#include "guiconsole.h"
#include "guisettings.h"
#define NDEBUG
#include <debug.h>
VOID GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData);
/* FUNCTIONS ******************************************************************/
BOOL
GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
IN LPCWSTR ConsoleTitle,
IN DWORD ProcessId)
{
/*****************************************************
* Adapted from ConSrvReadUserSettings in settings.c *
*****************************************************/
BOOL RetVal = FALSE;
HKEY hKey;
DWORD dwNumSubKeys = 0;
DWORD dwIndex;
DWORD dwType;
WCHAR szValueName[MAX_PATH];
DWORD dwValueName;
WCHAR szValue[LF_FACESIZE] = L"\0";
DWORD Value;
DWORD dwValue;
if (!ConSrvOpenUserSettings(ProcessId,
ConsoleTitle,
&hKey, KEY_READ,
FALSE))
{
DPRINT("ConSrvOpenUserSettings failed\n");
return FALSE;
}
if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
&dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
RegCloseKey(hKey);
return FALSE;
}
DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys);
for (dwIndex = 0; dwIndex < dwNumSubKeys; dwIndex++)
{
dwValue = sizeof(Value);
dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)&Value, &dwValue) != ERROR_SUCCESS)
{
if (dwType == REG_SZ)
{
/*
* Retry in case of string value
*/
dwValue = sizeof(szValue);
dwValueName = MAX_PATH; // sizeof(szValueName)/sizeof(szValueName[0])
if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
break;
}
else
{
break;
}
}
if (!wcscmp(szValueName, L"FaceName"))
{
wcsncpy(TermInfo->FaceName, szValue, LF_FACESIZE);
RetVal = TRUE;
}
else if (!wcscmp(szValueName, L"FontFamily"))
{
TermInfo->FontFamily = Value;
RetVal = TRUE;
}
else if (!wcscmp(szValueName, L"FontSize"))
{
TermInfo->FontSize = Value;
RetVal = TRUE;
}
else if (!wcscmp(szValueName, L"FontWeight"))
{
TermInfo->FontWeight = Value;
RetVal = TRUE;
}
else if (!wcscmp(szValueName, L"WindowPosition"))
{
TermInfo->AutoPosition = FALSE;
TermInfo->WindowOrigin.x = LOWORD(Value);
TermInfo->WindowOrigin.y = HIWORD(Value);
RetVal = TRUE;
}
}
RegCloseKey(hKey);
return RetVal;
}
BOOL
GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
IN LPCWSTR ConsoleTitle,
IN DWORD ProcessId)
{
/******************************************************
* Adapted from ConSrvWriteUserSettings in settings.c *
******************************************************/
BOOL GlobalSettings = (ConsoleTitle[0] == L'\0');
HKEY hKey;
DWORD Storage = 0;
#define SetConsoleSetting(SettingName, SettingType, SettingSize, Setting, DefaultValue) \
do { \
if (GlobalSettings || (!GlobalSettings && (*(Setting) != (DefaultValue)))) \
{ \
RegSetValueExW(hKey, (SettingName), 0, (SettingType), (PBYTE)(Setting), (SettingSize)); \
} \
else \
{ \
RegDeleteValue(hKey, (SettingName)); \
} \
} while (0)
if (!ConSrvOpenUserSettings(ProcessId,
ConsoleTitle,
&hKey, KEY_WRITE,
TRUE))
{
return FALSE;
}
SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0');
SetConsoleSetting(L"FontFamily", REG_DWORD, sizeof(DWORD), &TermInfo->FontFamily, FF_DONTCARE);
SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &TermInfo->FontSize, 0);
SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE);
if (TermInfo->AutoPosition == FALSE)
{
Storage = MAKELONG(TermInfo->WindowOrigin.x, TermInfo->WindowOrigin.y);
RegSetValueExW(hKey, L"WindowPosition", 0, REG_DWORD, (PBYTE)&Storage, sizeof(DWORD));
}
else
{
RegDeleteValue(hKey, L"WindowPosition");
}
RegCloseKey(hKey);
return TRUE;
}
VOID
GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
IN DWORD ProcessId)
{
/*******************************************************
* Adapted from ConSrvGetDefaultSettings in settings.c *
*******************************************************/
if (TermInfo == NULL) return;
/*
* 1. Load the default values
*/
// wcsncpy(TermInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
// TermInfo->FontSize = MAKELONG(12, 8); // 0x0008000C; // font is 8x12
// TermInfo->FontSize = MAKELONG(16, 16); // font is 16x16
// TermInfo->FontWeight = FW_NORMAL;
wcsncpy(TermInfo->FaceName, L"Fixedsys", LF_FACESIZE); // HACK: !!
// TermInfo->FaceName[0] = L'\0';
TermInfo->FontFamily = FF_DONTCARE;
TermInfo->FontSize = 0;
TermInfo->FontWeight = FW_DONTCARE;
TermInfo->UseRasterFonts = TRUE;
TermInfo->ShowWindow = SW_SHOWNORMAL;
TermInfo->AutoPosition = TRUE;
TermInfo->WindowOrigin = (POINT){0, 0};
/*
* 2. Overwrite them with the ones stored in HKCU\Console.
* If the HKCU\Console key doesn't exist, create it
* and store the default values inside.
*/
if (!GuiConsoleReadUserSettings(TermInfo, L"", ProcessId))
{
GuiConsoleWriteUserSettings(TermInfo, L"", ProcessId);
}
}
VOID
GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
BOOL Defaults)
{
NTSTATUS Status;
PCONSOLE Console = GuiData->Console;
PCONSOLE_PROCESS_DATA ProcessData;
HANDLE hSection = NULL, hClientSection = NULL;
LARGE_INTEGER SectionSize;
ULONG ViewSize = 0;
SIZE_T Length = 0;
PCONSOLE_PROPS pSharedInfo = NULL;
PGUI_CONSOLE_INFO GuiInfo = NULL;
DPRINT("GuiConsoleShowConsoleProperties entered\n");
/*
* Create a memory section to share with the applet, and map it.
*/
/* Holds data for console.dll + console info + terminal-specific info */
SectionSize.QuadPart = sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO);
Status = NtCreateSection(&hSection,
SECTION_ALL_ACCESS,
NULL,
&SectionSize,
PAGE_READWRITE,
SEC_COMMIT,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status);
return;
}
Status = NtMapViewOfSection(hSection,
NtCurrentProcess(),
(PVOID*)&pSharedInfo,
0,
0,
NULL,
&ViewSize,
ViewUnmap,
0,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
NtClose(hSection);
return;
}
/*
* Setup the shared console properties structure.
*/
/* Header */
pSharedInfo->hConsoleWindow = GuiData->hWindow;
pSharedInfo->ShowDefaultParams = Defaults;
/* Console information */
pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize;
pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup;
pSharedInfo->ci.FullScreen = Console->FullScreen;
pSharedInfo->ci.QuickEdit = Console->QuickEdit;
pSharedInfo->ci.InsertMode = Console->InsertMode;
pSharedInfo->ci.InputBufferSize = 0;
pSharedInfo->ci.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
pSharedInfo->ci.ConsoleSize = Console->ConsoleSize;
pSharedInfo->ci.CursorBlinkOn;
pSharedInfo->ci.ForceCursorOff;
pSharedInfo->ci.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
pSharedInfo->ci.ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
pSharedInfo->ci.PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
pSharedInfo->ci.CodePage;
/* GUI Information */
pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1);
wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
GuiInfo->FontSize = (DWORD)GuiData->GuiInfo.FontSize;
GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts;
/// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition;
GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
/* Offsetize */
pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo);
/* Palette */
memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors));
/* Title of the console, original one corresponding to the one set by the console leader */
Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1,
Console->OriginalTitle.Length / sizeof(WCHAR));
wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
pSharedInfo->ci.ConsoleTitle[Length] = L'\0';
/* Unmap the view */
NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo);
/* Get the console leader process, our client */
ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink,
CONSOLE_PROCESS_DATA,
ConsoleLink);
/* Duplicate the section handle for the client */
Status = NtDuplicateObject(NtCurrentProcess(),
hSection,
ProcessData->Process->ProcessHandle,
&hClientSection,
0, 0, DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status))
{
DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status);
NtClose(hSection);
return;
}
/* Start the properties dialog */
if (ProcessData->PropDispatcher)
{
HANDLE Thread;
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
ProcessData->PropDispatcher,
(PVOID)hClientSection, 0, NULL);
if (NULL == Thread)
{
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
return;
}
DPRINT1("We succeeded at creating ProcessData->PropDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
/// WaitForSingleObject(Thread, INFINITE);
CloseHandle(Thread);
}
/* We have finished, close the section handle */
NtClose(hSection);
return;
}
NTSTATUS
GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
HANDLE hClientSection,
BOOL SaveSettings)
{
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE Console = GuiData->Console;
PCONSOLE_PROCESS_DATA ProcessData;
HANDLE hSection = NULL;
ULONG ViewSize = 0;
PCONSOLE_PROPS pConInfo = NULL;
PCONSOLE_INFO ConInfo = NULL;
PTERMINAL_INFO TermInfo = NULL;
PGUI_CONSOLE_INFO GuiInfo = NULL;
/// LOCK /// EnterCriticalSection(&Console->Lock);
/* Get the console leader process, our client */
ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink,
CONSOLE_PROCESS_DATA,
ConsoleLink);
/* Duplicate the section handle for ourselves */
Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
hClientSection,
NtCurrentProcess(),
&hSection,
0, 0, DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status))
{
DPRINT1("Error when mapping client handle, Status = %lu\n", Status);
return Status;
}
/* Get a view of the shared section */
Status = NtMapViewOfSection(hSection,
NtCurrentProcess(),
(PVOID*)&pConInfo,
0,
0,
NULL,
&ViewSize,
ViewUnmap,
0,
PAGE_READONLY);
if (!NT_SUCCESS(Status))
{
DPRINT1("Error when mapping view of file, Status = %lu\n", Status);
NtClose(hSection);
return Status;
}
/* Check that the section is well-sized */
if ( (ViewSize < sizeof(CONSOLE_PROPS)) ||
(pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) ||
(ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) )
{
DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n");
Status = STATUS_INVALID_VIEW_SIZE;
goto Quit;
}
// TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
/* Set the console informations */
ConInfo = &pConInfo->ci;
ConSrvApplyUserSettings(Console, ConInfo);
/* Set the terminal informations - De-offsetization of the pointer */
TermInfo = &pConInfo->TerminalInfo;
GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo);
// memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
/* Move the window to the user's values */
GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition;
GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin;
GuiConsoleMoveWindow(GuiData);
InvalidateRect(GuiData->hWindow, NULL, TRUE);
/*
* Save settings if needed
*/
// FIXME: Do it in the console properties applet ??
if (SaveSettings)
{
DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
ConSrvWriteUserSettings(ConInfo, ProcessId);
GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId);
}
Status = STATUS_SUCCESS;
/// LOCK /// LeaveCriticalSection(&Console->Lock);
Quit:
/* Finally, close the section and return */
NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
NtClose(hSection);
return Status;
}
/* EOF */