mirror of
https://github.com/reactos/reactos.git
synced 2024-10-09 10:48:55 +00:00
463 lines
16 KiB
C
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 */
|