Start to separate better the CSR console server layer from the pure set of console functions (which will constitute a future console driver called... condrv :) ), and rework the terminal frontends interface.
Now load the frontends by order :
- the tui if we're in console mode
- the gui, otherwise.
(It's a temporary solution)
More modifications to come !
svn path=/trunk/; revision=59297
alias.c
coninput.c
conoutput.c
- graphics.c
text.c
console.c
+ frontendctl.c
handle.c
init.c
lineinput.c
settings.c
+ condrv/console.c
+ condrv/graphics.c
+ frontends/input.c
frontends/gui/guiterm.c
frontends/gui/guisettings.c
frontends/gui/graphics.c
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/condrv/console.c
+ * PURPOSE: Console Management Functions
+ * PROGRAMMERS: Gé van Geldorp
+ * Jeffrey Morlan
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "handle.h"
+#include "procinit.h"
+#include "alias.h"
+#include "coninput.h"
+#include "conoutput.h"
+#include "lineinput.h"
+#include "include/settings.h"
+
+#include "include/console.h"
+#include "console.h"
+#include "resource.h"
+
+#define NDEBUG
+#include <debug.h>
+
+// FIXME: Add this prototype to winternl.h / rtlfuncs.h / ...
+NTSTATUS NTAPI RtlGetLastNtStatus(VOID);
+
+
+/* GLOBALS ********************************************************************/
+
+static LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */
+static RTL_RESOURCE ListLock;
+
+#define ConDrvLockConsoleListExclusive() \
+ RtlAcquireResourceExclusive(&ListLock, TRUE)
+
+#define ConDrvLockConsoleListShared() \
+ RtlAcquireResourceShared(&ListLock, TRUE)
+
+#define ConDrvUnlockConsoleList() \
+ RtlReleaseResource(&ListLock)
+
+// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
+BOOLEAN
+ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest,
+ IN PCWSTR Source)
+{
+ SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
+ if (Size > MAXUSHORT) return FALSE;
+
+ UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
+ if (UniDest->Buffer == NULL) return FALSE;
+
+ RtlCopyMemory(UniDest->Buffer, Source, Size);
+ UniDest->MaximumLength = (USHORT)Size;
+ UniDest->Length = (USHORT)Size - sizeof(WCHAR);
+
+ return TRUE;
+}
+
+// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
+VOID
+ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
+{
+ if (UnicodeString->Buffer)
+ {
+ ConsoleFreeHeap(UnicodeString->Buffer);
+ RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
+ }
+}
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static NTSTATUS
+ConDrvConsoleCtrlEventTimeout(IN ULONG Event,
+ IN PCONSOLE_PROCESS_DATA ProcessData,
+ IN ULONG Timeout)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DPRINT("ConDrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
+
+ if (ProcessData->CtrlDispatcher)
+ {
+ _SEH2_TRY
+ {
+ HANDLE Thread = NULL;
+
+ _SEH2_TRY
+ {
+ Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
+ ProcessData->CtrlDispatcher,
+ UlongToPtr(Event), 0, NULL);
+ if (NULL == Thread)
+ {
+ Status = RtlGetLastNtStatus();
+ DPRINT1("Failed thread creation, Status = 0x%08lx\n", Status);
+ }
+ else
+ {
+ DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
+ WaitForSingleObject(Thread, Timeout);
+ }
+ }
+ _SEH2_FINALLY
+ {
+ CloseHandle(Thread);
+ }
+ _SEH2_END;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ DPRINT1("ConDrvConsoleCtrlEventTimeout - Caught an exception, Status = 0x%08lx\n", Status);
+ }
+ _SEH2_END;
+ }
+
+ return Status;
+}
+
+static NTSTATUS
+ConDrvConsoleCtrlEvent(IN ULONG Event,
+ IN PCONSOLE_PROCESS_DATA ProcessData)
+{
+ return ConDrvConsoleCtrlEventTimeout(Event, ProcessData, 0);
+}
+
+VOID FASTCALL
+ConioPause(PCONSOLE Console, UINT Flags)
+{
+ Console->PauseFlags |= Flags;
+ if (!Console->UnpauseEvent)
+ Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+}
+
+VOID FASTCALL
+ConioUnpause(PCONSOLE Console, UINT Flags)
+{
+ Console->PauseFlags &= ~Flags;
+
+ // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
+ if (Console->PauseFlags == 0 && Console->UnpauseEvent)
+ {
+ SetEvent(Console->UnpauseEvent);
+ CloseHandle(Console->UnpauseEvent);
+ Console->UnpauseEvent = NULL;
+
+ CsrNotifyWait(&Console->WriteWaitQueue,
+ WaitAll,
+ NULL,
+ NULL);
+ if (!IsListEmpty(&Console->WriteWaitQueue))
+ {
+ CsrDereferenceWait(&Console->WriteWaitQueue);
+ }
+ }
+}
+
+
+/*
+ * Console accessibility check helpers
+ */
+
+BOOLEAN NTAPI
+ConDrvValidateConsolePointer(IN PCONSOLE Console)
+{
+ PLIST_ENTRY ConsoleEntry;
+ PCONSOLE CurrentConsole = NULL;
+
+ if (!Console) return FALSE;
+
+ /* The console list must be locked */
+ // ASSERT(Console_list_locked);
+
+ ConsoleEntry = ConsoleList.Flink;
+ while (ConsoleEntry != &ConsoleList)
+ {
+ CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry);
+ ConsoleEntry = ConsoleEntry->Flink;
+ if (CurrentConsole == Console) return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleState(IN PCONSOLE Console,
+ IN CONSOLE_STATE ExpectedState)
+{
+ // if (!Console) return FALSE;
+
+ /* The console must be locked */
+ // ASSERT(Console_locked);
+
+ return (Console->State == ExpectedState);
+}
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleUnsafe(IN PCONSOLE Console,
+ IN CONSOLE_STATE ExpectedState,
+ IN BOOLEAN LockConsole)
+{
+ if (!Console) return FALSE;
+
+ /*
+ * Lock the console to forbid possible console's state changes
+ * (which must be done when the console is already locked).
+ * If we don't want to lock it, it's because the lock is already
+ * held. So there must be no problems.
+ */
+ if (LockConsole) EnterCriticalSection(&Console->Lock);
+
+ // ASSERT(Console_locked);
+
+ /* Check whether the console's state is what we expect */
+ if (!ConDrvValidateConsoleState(Console, ExpectedState))
+ {
+ if (LockConsole) LeaveCriticalSection(&Console->Lock);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN NTAPI
+ConDrvValidateConsole(IN PCONSOLE Console,
+ IN CONSOLE_STATE ExpectedState,
+ IN BOOLEAN LockConsole)
+{
+ BOOLEAN RetVal = FALSE;
+
+ if (!Console) return FALSE;
+
+ /*
+ * Forbid creation or deletion of consoles when
+ * checking for the existence of a console.
+ */
+ ConDrvLockConsoleListShared();
+
+ if (ConDrvValidateConsolePointer(Console))
+ {
+ RetVal = ConDrvValidateConsoleUnsafe(Console,
+ ExpectedState,
+ LockConsole);
+ }
+
+ /* Unlock the console list and return */
+ ConDrvUnlockConsoleList();
+ return RetVal;
+}
+
+NTSTATUS NTAPI
+ConDrvGrabConsole(IN PCONSOLE Console,
+ IN BOOLEAN LockConsole)
+{
+ NTSTATUS Status = STATUS_INVALID_HANDLE;
+
+ if (ConDrvValidateConsole(Console, CONSOLE_RUNNING, LockConsole))
+ {
+ InterlockedIncrement(&Console->ReferenceCount);
+ Status = STATUS_SUCCESS;
+ }
+
+ return Status;
+}
+
+VOID NTAPI
+ConDrvReleaseConsole(IN PCONSOLE Console,
+ IN BOOLEAN WasConsoleLocked)
+{
+ LONG RefCount = 0;
+
+ if (!Console) return;
+ // if (Console->ReferenceCount == 0) return; // This shouldn't happen
+ ASSERT(Console->ReferenceCount > 0);
+
+ /* The console must be locked */
+ // ASSERT(Console_locked);
+
+ /*
+ * Decrement the reference count. Save the new value too,
+ * because Console->ReferenceCount might be modified after
+ * the console gets unlocked but before we check whether we
+ * can destroy it.
+ */
+ RefCount = _InterlockedDecrement(&Console->ReferenceCount);
+
+ /* Unlock the console if needed */
+ if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock);
+
+ /* Delete the console if needed */
+ if (RefCount <= 0) ConDrvDeleteConsole(Console);
+}
+
+
+/* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
+
+VOID NTAPI
+ConDrvInitConsoleSupport(VOID)
+{
+ DPRINT("CONSRV: ConDrvInitConsoleSupport()\n");
+
+ /* Initialize the console list and its lock */
+ InitializeListHead(&ConsoleList);
+ RtlInitializeResource(&ListLock);
+
+ /* Should call LoadKeyboardLayout */
+}
+
+
+NTSTATUS NTAPI
+ConDrvInitConsole(OUT PCONSOLE* NewConsole,
+ IN PCONSOLE_INFO ConsoleInfo,
+ IN ULONG ConsoleLeaderProcessId)
+{
+ NTSTATUS Status;
+ SECURITY_ATTRIBUTES SecurityAttributes;
+ // CONSOLE_INFO CapturedConsoleInfo;
+ TEXTMODE_BUFFER_INFO ScreenBufferInfo;
+ PCONSOLE Console;
+ PCONSOLE_SCREEN_BUFFER NewBuffer;
+ // WCHAR DefaultTitle[128];
+
+ if (NewConsole == NULL || ConsoleInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ *NewConsole = NULL;
+
+ /*
+ * Allocate a console structure
+ */
+ Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE));
+ if (NULL == Console)
+ {
+ DPRINT1("Not enough memory for console creation.\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ /*
+ * Load the console settings
+ */
+
+ /* 1. Load the default settings */
+ // ConSrvGetDefaultSettings(ConsoleInfo, ProcessId);
+
+ // /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
+ // Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
+ // sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1);
+ // wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
+ // ConsoleInfo.ConsoleTitle[Length] = L'\0';
+
+ /*
+ * 4. Load the remaining console settings via the registry.
+ */
+#if 0
+ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ {
+ /*
+ * Either we weren't created by an app launched via a shell-link,
+ * or we failed to load shell-link console properties.
+ * Therefore, load the console infos for the application from the registry.
+ */
+ ConSrvReadUserSettings(ConsoleInfo, ProcessId);
+
+ /*
+ * Now, update them with the properties the user might gave to us
+ * via the STARTUPINFO structure before calling CreateProcess
+ * (and which was transmitted via the ConsoleStartInfo structure).
+ * We therefore overwrite the values read in the registry.
+ */
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
+ {
+ ConsoleInfo->ScreenAttrib = (USHORT)ConsoleStartInfo->FillAttribute;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
+ {
+ ConsoleInfo->ScreenBufferSize = ConsoleStartInfo->ScreenBufferSize;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
+ {
+ // ConsoleInfo->ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
+ ConsoleInfo->ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
+ ConsoleInfo->ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
+ }
+ }
+#endif
+
+ /*
+ * Fix the screen buffer size if needed. The rule is:
+ * ScreenBufferSize >= ConsoleSize
+ */
+ if (ConsoleInfo->ScreenBufferSize.X < ConsoleInfo->ConsoleSize.X)
+ ConsoleInfo->ScreenBufferSize.X = ConsoleInfo->ConsoleSize.X;
+ if (ConsoleInfo->ScreenBufferSize.Y < ConsoleInfo->ConsoleSize.Y)
+ ConsoleInfo->ScreenBufferSize.Y = ConsoleInfo->ConsoleSize.Y;
+
+ /*
+ * Initialize the console
+ */
+ Console->State = CONSOLE_INITIALIZING;
+ Console->ReferenceCount = 0;
+ InitializeCriticalSection(&Console->Lock);
+ InitializeListHead(&Console->ProcessList);
+ RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
+
+ memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(ConsoleInfo->Colors));
+ Console->ConsoleSize = ConsoleInfo->ConsoleSize;
+ Console->FixedSize = FALSE; // Value by default; is reseted by the front-ends if needed.
+
+ /*
+ * Initialize the input buffer
+ */
+ ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console);
+
+ SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ SecurityAttributes.lpSecurityDescriptor = NULL;
+ SecurityAttributes.bInheritHandle = TRUE;
+ Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
+ if (NULL == Console->InputBuffer.ActiveEvent)
+ {
+ DeleteCriticalSection(&Console->Lock);
+ ConsoleFreeHeap(Console);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Console->InputBuffer.InputBufferSize = 0; // FIXME!
+ InitializeListHead(&Console->InputBuffer.InputEvents);
+ InitializeListHead(&Console->InputBuffer.ReadWaitQueue);
+ Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
+ ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
+
+ Console->QuickEdit = ConsoleInfo->QuickEdit;
+ Console->InsertMode = ConsoleInfo->InsertMode;
+ Console->LineBuffer = NULL;
+ Console->LineMaxSize = Console->LineSize = Console->LinePos = 0;
+ Console->LineComplete = Console->LineUpPressed = Console->LineInsertToggle = FALSE;
+ // LineWakeupMask
+
+ // FIXME: This is terminal-specific !! VV
+ RtlZeroMemory(&Console->Selection, sizeof(CONSOLE_SELECTION_INFO));
+ Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
+ // dwSelectionCursor
+
+ /* Set-up the code page */
+ Console->CodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
+
+ /* Initialize a new text-mode screen buffer with default settings */
+ ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
+ ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
+ ScreenBufferInfo.PopupAttrib = ConsoleInfo->PopupAttrib;
+ ScreenBufferInfo.IsCursorVisible = TRUE;
+ ScreenBufferInfo.CursorSize = ConsoleInfo->CursorSize;
+
+ InitializeListHead(&Console->BufferList);
+ Status = ConSrvCreateScreenBuffer(&NewBuffer,
+ Console,
+ CONSOLE_TEXTMODE_BUFFER,
+ &ScreenBufferInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ConSrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
+ CloseHandle(Console->InputBuffer.ActiveEvent);
+ DeleteCriticalSection(&Console->Lock);
+ ConsoleFreeHeap(Console);
+ return Status;
+ }
+ /* Make the new screen buffer active */
+ Console->ActiveBuffer = NewBuffer;
+ InitializeListHead(&Console->WriteWaitQueue);
+ Console->PauseFlags = 0;
+ Console->UnpauseEvent = NULL;
+
+ /*
+ * Initialize the alias and history buffers
+ */
+ Console->Aliases = NULL;
+ InitializeListHead(&Console->HistoryBuffers);
+ Console->HistoryBufferSize = ConsoleInfo->HistoryBufferSize;
+ Console->NumberOfHistoryBuffers = ConsoleInfo->NumberOfHistoryBuffers;
+ Console->HistoryNoDup = ConsoleInfo->HistoryNoDup;
+
+ /* Initialize the console title */
+ ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo->ConsoleTitle);
+ // if (ConsoleInfo.ConsoleTitle[0] == L'\0')
+ // {
+ // if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
+ // {
+ // ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
+ // }
+ // else
+ // {
+ // ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
+ // }
+ // }
+ // else
+ // {
+ ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo->ConsoleTitle);
+ // }
+
+ /* Lock the console until its initialization is finished */
+ // EnterCriticalSection(&Console->Lock);
+
+ DPRINT("Console initialized\n");
+
+ /* All went right, so add the console to the list */
+ ConDrvLockConsoleListExclusive();
+ DPRINT("Insert in the list\n");
+ InsertTailList(&ConsoleList, &Console->Entry);
+
+ /* The initialization is finished */
+ DPRINT("Change state\n");
+ Console->State = CONSOLE_RUNNING;
+
+ /* Unlock the console */
+ // LeaveCriticalSection(&Console->Lock);
+
+ /* Unlock the console list */
+ ConDrvUnlockConsoleList();
+
+ /* Return the newly created console to the caller and a success code too */
+ *NewConsole = Console;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvRegisterFrontEnd(IN PCONSOLE Console,
+ IN PFRONTEND FrontEnd)
+{
+ NTSTATUS Status;
+
+ if (Console == NULL || FrontEnd == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* FIXME: Lock the console before ?? */
+
+ /*
+ * Attach the frontend to the console. Use now the TermIFace of the console,
+ * and not the user-defined temporary FrontEnd pointer.
+ */
+ Console->TermIFace = *FrontEnd;
+ Console->TermIFace.Console = Console;
+
+ /* Initialize the frontend AFTER having attached it to the console */
+ DPRINT("Finish initialization of frontend\n");
+ Status = Console->TermIFace.Vtbl->InitFrontEnd(&Console->TermIFace, Console);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("FrontEnd initialization failed, Status = 0x%08lx\n", Status);
+
+ /* We failed, detach the frontend from the console */
+ FrontEnd->Console = NULL; // For the caller
+ RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
+
+ return Status;
+ }
+
+ /* Copy buffer contents to screen */
+ // FrontEnd.Draw();
+ // ConioDrawConsole(Console);
+ DPRINT("Console drawn\n");
+
+ DPRINT("Terminal FrontEnd initialization done\n");
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvDeregisterFrontEnd(IN PCONSOLE Console)
+{
+ if (Console == NULL) return STATUS_INVALID_PARAMETER;
+
+ /* FIXME: Lock the console before ?? */
+
+ /* Deinitialize the frontend BEFORE detaching it from the console */
+ Console->TermIFace.Vtbl->DeinitFrontEnd(&Console->TermIFace/*, Console*/);
+
+ /* Detach the frontend from the console */
+ RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
+
+ DPRINT("Terminal FrontEnd unregistered\n");
+ return STATUS_SUCCESS;
+}
+
+VOID NTAPI
+ConDrvDeleteConsole(IN PCONSOLE Console)
+{
+ DPRINT("ConDrvDeleteConsole(0x%p)\n", Console);
+
+ /*
+ * Forbid validation of any console by other threads
+ * during the deletion of this console.
+ */
+ ConDrvLockConsoleListExclusive();
+
+ /* Check the existence of the console, and if it's ok, continue */
+ if (!ConDrvValidateConsolePointer(Console))
+ {
+ /* Unlock the console list and return */
+ ConDrvUnlockConsoleList();
+ return;
+ }
+
+ /*
+ * If the console is already being destroyed
+ * (thus not running), just return.
+ */
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ {
+ /* Unlock the console list and return */
+ ConDrvUnlockConsoleList();
+ return;
+ }
+
+ /*
+ * We are about to be destroyed. Signal it to other people
+ * so that they can terminate what they are doing, and that
+ * they cannot longer validate the console.
+ */
+ Console->State = CONSOLE_TERMINATING;
+
+ /*
+ * Allow other threads to finish their job: basically, unlock
+ * all other calls to EnterCriticalSection(&Console->Lock); by
+ * ConDrvValidateConsole(Unsafe) functions so that they just see
+ * that we are not in CONSOLE_RUNNING state anymore, or unlock
+ * other concurrent calls to ConDrvDeleteConsole so that they
+ * can see that we are in fact already deleting the console.
+ */
+ LeaveCriticalSection(&Console->Lock);
+ ConDrvUnlockConsoleList();
+
+ /* FIXME: Send a terminate message to all the processes owning this console */
+
+ /* Cleanup the UI-oriented part */
+ DPRINT("Deregister console\n");
+ ConDrvDeregisterFrontEnd(Console);
+ DPRINT("Console deregistered\n");
+
+ /***
+ * Check that the console is in terminating state before continuing
+ * (the cleanup code must not change the state of the console...
+ * ...unless to cancel console deletion ?).
+ ***/
+
+ ConDrvLockConsoleListExclusive();
+
+ /* Re-check the existence of the console, and if it's ok, continue */
+ if (!ConDrvValidateConsolePointer(Console))
+ {
+ /* Unlock the console list and return */
+ ConDrvUnlockConsoleList();
+ return;
+ }
+
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE))
+ {
+ ConDrvUnlockConsoleList();
+ return;
+ }
+
+ /* We are now in destruction */
+ Console->State = CONSOLE_IN_DESTRUCTION;
+
+ /* Remove the console from the list */
+ RemoveEntryList(&Console->Entry);
+
+ /* We really delete the console. Reset the count to be sure. */
+ Console->ReferenceCount = 0;
+
+ /* Discard all entries in the input event queue */
+ PurgeInputBuffer(Console);
+
+ if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
+
+ IntDeleteAllAliases(Console);
+ HistoryDeleteBuffers(Console);
+
+ ConioDeleteScreenBuffer(Console->ActiveBuffer);
+ if (!IsListEmpty(&Console->BufferList))
+ {
+ DPRINT1("BUG: screen buffer list not empty\n");
+ ASSERT(FALSE);
+ }
+
+ /**/ CloseHandle(Console->InputBuffer.ActiveEvent); /**/
+ if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
+
+ ConsoleFreeUnicodeString(&Console->OriginalTitle);
+ ConsoleFreeUnicodeString(&Console->Title);
+
+ DPRINT("ConDrvDeleteConsole - Unlocking\n");
+ LeaveCriticalSection(&Console->Lock);
+ DPRINT("ConDrvDeleteConsole - Destroying lock\n");
+ DeleteCriticalSection(&Console->Lock);
+ DPRINT("ConDrvDeleteConsole - Lock destroyed ; freeing console\n");
+
+ ConsoleFreeHeap(Console);
+ DPRINT("ConDrvDeleteConsole - Console destroyed\n");
+
+ /* Unlock the console list and return */
+ ConDrvUnlockConsoleList();
+}
+
+
+/* PUBLIC SERVER APIS *********************************************************/
+
+NTSTATUS NTAPI
+ConDrvGetConsoleMode(IN PCONSOLE Console,
+ IN PCONSOLE_IO_OBJECT Object,
+ OUT PULONG ConsoleMode)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (Console == NULL || Object == NULL || ConsoleMode == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Validity check */
+ ASSERT(Console == Object->Console);
+
+ /*** FIXME: */ *ConsoleMode = 0; /***/
+
+ if (INPUT_BUFFER == Object->Type)
+ {
+ PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
+
+ *ConsoleMode = InputBuffer->Mode;
+
+ if (Console->QuickEdit || Console->InsertMode)
+ {
+ // Windows does this, even if it's not documented on MSDN
+ *ConsoleMode |= ENABLE_EXTENDED_FLAGS;
+
+ if (Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
+ if (Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE;
+ }
+ }
+ else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
+ {
+ PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
+ *ConsoleMode = Buffer->Mode;
+ }
+ else
+ {
+ Status = STATUS_INVALID_HANDLE;
+ }
+
+ return Status;
+}
+
+NTSTATUS NTAPI
+ConDrvSetConsoleMode(IN PCONSOLE Console,
+ IN PCONSOLE_IO_OBJECT Object,
+ IN ULONG ConsoleMode)
+{
+#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
+#define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
+ ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
+ ENABLE_MOUSE_INPUT )
+#define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (Console == NULL || Object == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Validity check */
+ ASSERT(Console == Object->Console);
+
+ if (INPUT_BUFFER == Object->Type)
+ {
+ PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
+
+ DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode);
+
+ /*
+ * 1. Only the presence of valid mode flags is allowed.
+ */
+ if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
+ }
+
+ /*
+ * 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS,
+ * then consider the flags invalid.
+ *
+ if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) &&
+ (ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 )
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
+ }
+ */
+
+ /*
+ * 3. Now we can continue.
+ */
+ if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
+ {
+ Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
+ Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
+ }
+ InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
+ }
+ else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
+ {
+ PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
+
+ DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode);
+
+ if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
+ }
+ }
+ else
+ {
+ Status = STATUS_INVALID_HANDLE;
+ }
+
+Quit:
+ return Status;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleTitle(IN PCONSOLE Console,
+ IN OUT PWCHAR Title,
+ IN OUT PULONG BufLength)
+{
+ ULONG Length;
+
+ if (Console == NULL || Title == NULL || BufLength == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Copy title of the console to the user title buffer */
+ if (*BufLength >= sizeof(WCHAR))
+ {
+ Length = min(*BufLength - sizeof(WCHAR), Console->Title.Length);
+ RtlCopyMemory(Title, Console->Title.Buffer, Length);
+ Title[Length / sizeof(WCHAR)] = L'\0';
+ }
+
+ *BufLength = Console->Title.Length;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvSetConsoleTitle(IN PCONSOLE Console,
+ IN PWCHAR Title,
+ IN ULONG BufLength)
+{
+ PWCHAR Buffer;
+
+ if (Console == NULL || Title == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* Allocate a new buffer to hold the new title (NULL-terminated) */
+ Buffer = ConsoleAllocHeap(0, BufLength + sizeof(WCHAR));
+ if (!Buffer) return STATUS_NO_MEMORY;
+
+ /* Free the old title */
+ ConsoleFreeUnicodeString(&Console->Title);
+
+ /* Copy title to console */
+ Console->Title.Buffer = Buffer;
+ Console->Title.Length = BufLength;
+ Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
+ RtlCopyMemory(Console->Title.Buffer, Title, Console->Title.Length);
+ Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
+
+ // ConioChangeTitle(Console);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleCP(IN PCONSOLE Console,
+ OUT PUINT CodePage,
+ IN BOOLEAN InputCP)
+{
+ if (Console == NULL || CodePage == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ *CodePage = (InputCP ? Console->CodePage : Console->OutputCodePage);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvSetConsoleCP(IN PCONSOLE Console,
+ IN UINT CodePage,
+ IN BOOLEAN InputCP)
+{
+ if (Console == NULL || !IsValidCodePage(CodePage))
+ return STATUS_INVALID_PARAMETER;
+
+ if (InputCP)
+ Console->CodePage = CodePage;
+ else
+ Console->OutputCodePage = CodePage;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+ConDrvGetConsoleProcessList(IN PCONSOLE Console,
+ IN OUT PULONG ProcessIdsList,
+ IN ULONG MaxIdListItems,
+ OUT PULONG ProcessIdsTotal)
+{
+ PCONSOLE_PROCESS_DATA current;
+ PLIST_ENTRY current_entry;
+
+ if (Console == NULL || ProcessIdsList == NULL || ProcessIdsTotal == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ *ProcessIdsTotal = 0;
+
+ for (current_entry = Console->ProcessList.Flink;
+ current_entry != &Console->ProcessList;
+ current_entry = current_entry->Flink)
+ {
+ current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+ if (++(*ProcessIdsTotal) <= MaxIdListItems)
+ {
+ *ProcessIdsList++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+// ConDrvGenerateConsoleCtrlEvent
+NTSTATUS NTAPI
+ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
+ IN ULONG ProcessGroupId,
+ IN ULONG Event)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PLIST_ENTRY current_entry;
+ PCONSOLE_PROCESS_DATA current;
+
+ /* If the console is already being destroyed, just return */
+ if (!ConDrvValidateConsole(Console, CONSOLE_RUNNING, FALSE))
+ return STATUS_UNSUCCESSFUL;
+
+ /*
+ * Loop through the process list, from the most recent process
+ * (the active one) to the oldest one (the first created, i.e.
+ * the console leader process), and for each, send an event
+ * (new processes are inserted at the head of the console process list).
+ */
+ current_entry = Console->ProcessList.Flink;
+ while (current_entry != &Console->ProcessList)
+ {
+ current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+ current_entry = current_entry->Flink;
+
+ /*
+ * Only processes belonging to the same process group are signaled.
+ * If the process group ID is zero, then all the processes are signaled.
+ */
+ if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId)
+ {
+ Status = ConDrvConsoleCtrlEvent(Event, current);
+ }
+ }
+
+ return Status;
+}
+
+/* EOF */
CloseHandle(Console->InputBuffer.ActiveEvent);
}
-static DWORD FASTCALL
-ConioGetShiftState(PBYTE KeyState, LPARAM lParam)
+VOID NTAPI
+ConDrvProcessKey(IN PCONSOLE Console,
+ IN BOOLEAN Down,
+ IN UINT VirtualKeyCode,
+ IN UINT VirtualScanCode,
+ IN WCHAR UnicodeChar,
+ IN ULONG ShiftState,
+ IN BYTE KeyStateCtrl)
{
- DWORD ssOut = 0;
-
- if (KeyState[VK_CAPITAL] & 0x01)
- ssOut |= CAPSLOCK_ON;
-
- if (KeyState[VK_NUMLOCK] & 0x01)
- ssOut |= NUMLOCK_ON;
-
- if (KeyState[VK_SCROLL] & 0x01)
- ssOut |= SCROLLLOCK_ON;
-
- if (KeyState[VK_SHIFT] & 0x80)
- ssOut |= SHIFT_PRESSED;
-
- if (KeyState[VK_LCONTROL] & 0x80)
- ssOut |= LEFT_CTRL_PRESSED;
- if (KeyState[VK_RCONTROL] & 0x80)
- ssOut |= RIGHT_CTRL_PRESSED;
-
- if (KeyState[VK_LMENU] & 0x80)
- ssOut |= LEFT_ALT_PRESSED;
- if (KeyState[VK_RMENU] & 0x80)
- ssOut |= RIGHT_ALT_PRESSED;
-
- /* See WM_CHAR MSDN documentation for instance */
- if (lParam & 0x01000000)
- ssOut |= ENHANCED_KEY;
-
- return ssOut;
-}
-
-VOID WINAPI
-ConioProcessKey(PCONSOLE Console, MSG* msg)
-{
- static BYTE KeyState[256] = { 0 };
- /* MSDN mentions that you should use the last virtual key code received
- * when putting a virtual key identity to a WM_CHAR message since multiple
- * or translated keys may be involved. */
- static UINT LastVirtualKey = 0;
- DWORD ShiftState;
- WCHAR UnicodeChar;
- UINT VirtualKeyCode;
- UINT VirtualScanCode;
- BOOL Down = FALSE;
INPUT_RECORD er;
- BOOLEAN Fake; // synthesized, not a real event
- BOOLEAN NotChar; // message should not be used to return a character
-
- if (NULL == Console)
- {
- DPRINT1("No Active Console!\n");
- return;
- }
-
- VirtualScanCode = HIWORD(msg->lParam) & 0xFF;
- Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
- msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
-
- GetKeyboardState(KeyState);
- ShiftState = ConioGetShiftState(KeyState, msg->lParam);
-
- if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
- {
- VirtualKeyCode = LastVirtualKey;
- UnicodeChar = msg->wParam;
- }
- else
- {
- WCHAR Chars[2];
- INT RetChars = 0;
-
- VirtualKeyCode = msg->wParam;
- RetChars = ToUnicodeEx(VirtualKeyCode,
- VirtualScanCode,
- KeyState,
- Chars,
- 2,
- 0,
- NULL);
- UnicodeChar = (1 == RetChars ? Chars[0] : 0);
- }
-
- er.EventType = KEY_EVENT;
- er.Event.KeyEvent.bKeyDown = Down;
- er.Event.KeyEvent.wRepeatCount = 1;
- er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
- er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
- er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
- er.Event.KeyEvent.dwControlKeyState = ShiftState;
-
- if (ConioProcessKeyCallback(Console,
- msg,
- KeyState[VK_MENU],
- ShiftState,
- VirtualKeyCode,
- Down))
- {
- return;
- }
-
- Fake = UnicodeChar &&
- (msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
- msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
- NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
- if (NotChar) LastVirtualKey = msg->wParam;
-
- DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
- Down ? "down" : "up ",
- (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
- "char" : "key ",
- Fake ? "fake" : "real",
- NotChar ? "notc" : "char",
- VirtualScanCode,
- VirtualKeyCode,
- (UnicodeChar >= L' ') ? UnicodeChar : L'.',
- ShiftState);
-
- if (Fake) return;
/* process Ctrl-C and Ctrl-Break */
- if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
- er.Event.KeyEvent.bKeyDown &&
- ((er.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
- (er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
- (er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80))
+ if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT &&
+ Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') &&
+ (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) )
{
DPRINT1("Console_Api Ctrl-C\n");
- ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT);
+ ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT);
if (Console->LineBuffer && !Console->LineComplete)
{
return;
}
- if (0 != (er.Event.KeyEvent.dwControlKeyState
- & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
- && (VK_UP == er.Event.KeyEvent.wVirtualKeyCode
- || VK_DOWN == er.Event.KeyEvent.wVirtualKeyCode))
+ if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 &&
+ (VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) )
{
- if (er.Event.KeyEvent.bKeyDown)
+ if (!Down) return;
+
+ /* scroll up or down */
+ if (VK_UP == VirtualKeyCode)
{
- /* scroll up or down */
- if (VK_UP == er.Event.KeyEvent.wVirtualKeyCode)
+ /* only scroll up if there is room to scroll up into */
+ if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1)
{
- /* only scroll up if there is room to scroll up into */
- if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1)
- {
- Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
- Console->ActiveBuffer->ScreenBufferSize.Y - 1) %
- Console->ActiveBuffer->ScreenBufferSize.Y;
- Console->ActiveBuffer->CursorPosition.Y++;
- }
+ Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
+ Console->ActiveBuffer->ScreenBufferSize.Y - 1) %
+ Console->ActiveBuffer->ScreenBufferSize.Y;
+ Console->ActiveBuffer->CursorPosition.Y++;
}
- else
+ }
+ else
+ {
+ /* only scroll down if there is room to scroll down into */
+ if (Console->ActiveBuffer->CursorPosition.Y != 0)
{
- /* only scroll down if there is room to scroll down into */
- if (Console->ActiveBuffer->CursorPosition.Y != 0)
- {
- Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
- Console->ActiveBuffer->ScreenBufferSize.Y;
- Console->ActiveBuffer->CursorPosition.Y--;
- }
+ Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
+ Console->ActiveBuffer->ScreenBufferSize.Y;
+ Console->ActiveBuffer->CursorPosition.Y--;
}
- ConioDrawConsole(Console);
}
+
+ ConioDrawConsole(Console);
return;
}
+
+ er.EventType = KEY_EVENT;
+ er.Event.KeyEvent.bKeyDown = Down;
+ er.Event.KeyEvent.wRepeatCount = 1;
+ er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
+ er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
+ er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
+ er.Event.KeyEvent.dwControlKeyState = ShiftState;
+
ConioProcessInputEvent(Console, &er);
}
VOID FASTCALL PurgeInputBuffer(PCONSOLE Console);
+VOID NTAPI
+ConDrvProcessKey(IN PCONSOLE Console,
+ IN BOOLEAN Down,
+ IN UINT VirtualKeyCode,
+ IN UINT VirtualScanCode,
+ IN WCHAR UnicodeChar,
+ IN ULONG ShiftState,
+ IN BYTE KeyStateCtrl);
+
/* EOF */
/* Macros used to call functions in the FRONTEND_VTBL virtual table */
-#define ConioCleanupConsole(Console) \
- (Console)->TermIFace.Vtbl->CleanupConsole(Console)
#define ConioDrawRegion(Console, Region) \
- (Console)->TermIFace.Vtbl->DrawRegion((Console), (Region))
+ (Console)->TermIFace.Vtbl->DrawRegion(&(Console)->TermIFace, (Region))
#define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \
- (Console)->TermIFace.Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \
+ (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Block), (CurStartX), (CurStartY), \
(ScrolledLines), (Buffer), (Length))
#define ConioSetCursorInfo(Console, Buff) \
- (Console)->TermIFace.Vtbl->SetCursorInfo((Console), (Buff))
+ (Console)->TermIFace.Vtbl->SetCursorInfo(&(Console)->TermIFace, (Buff))
#define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \
- (Console)->TermIFace.Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY))
+ (Console)->TermIFace.Vtbl->SetScreenInfo(&(Console)->TermIFace, (Buff), (OldCursorX), (OldCursorY))
#define ConioResizeTerminal(Console) \
- (Console)->TermIFace.Vtbl->ResizeTerminal(Console)
+ (Console)->TermIFace.Vtbl->ResizeTerminal(&(Console)->TermIFace)
#define ConioProcessKeyCallback(Console, Msg, KeyStateMenu, ShiftState, VirtualKeyCode, Down) \
- (Console)->TermIFace.Vtbl->ProcessKeyCallback((Console), (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down))
+ (Console)->TermIFace.Vtbl->ProcessKeyCallback(&(Console)->TermIFace, (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down))
#define ConioRefreshInternalInfo(Console) \
- (Console)->TermIFace.Vtbl->RefreshInternalInfo(Console)
+ (Console)->TermIFace.Vtbl->RefreshInternalInfo(&(Console)->TermIFace)
#define ConioChangeTitle(Console) \
- (Console)->TermIFace.Vtbl->ChangeTitle(Console)
+ (Console)->TermIFace.Vtbl->ChangeTitle(&(Console)->TermIFace)
#define ConioChangeIcon(Console, hWindowIcon) \
- (Console)->TermIFace.Vtbl->ChangeIcon((Console), (hWindowIcon))
+ (Console)->TermIFace.Vtbl->ChangeIcon(&(Console)->TermIFace, (hWindowIcon))
#define ConioGetConsoleWindowHandle(Console) \
- (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(Console)
+ (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(&(Console)->TermIFace)
#define ConioGetLargestConsoleWindowSize(Console, pSize) \
- (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize((Console), (pSize))
+ (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize))
#define ConioGetDisplayMode(Console) \
- (Console)->TermIFace.Vtbl->GetDisplayMode(Console)
+ (Console)->TermIFace.Vtbl->GetDisplayMode(&(Console)->TermIFace)
#define ConioSetDisplayMode(Console, NewMode) \
- (Console)->TermIFace.Vtbl->SetDisplayMode((Console), (NewMode))
+ (Console)->TermIFace.Vtbl->SetDisplayMode(&(Console)->TermIFace, (NewMode))
#define ConioShowMouseCursor(Console, Show) \
- (Console)->TermIFace.Vtbl->ShowMouseCursor((Console), (Show))
+ (Console)->TermIFace.Vtbl->ShowMouseCursor(&(Console)->TermIFace, (Show))
#define ConioSetMouseCursor(Console, hCursor) \
- (Console)->TermIFace.Vtbl->SetMouseCursor((Console), (hCursor))
+ (Console)->TermIFace.Vtbl->SetMouseCursor(&(Console)->TermIFace, (hCursor))
#define ConioMenuControl(Console, CmdIdLow, CmdIdHigh) \
- (Console)->TermIFace.Vtbl->MenuControl((Console), (CmdIdLow), (CmdIdHigh))
+ (Console)->TermIFace.Vtbl->MenuControl(&(Console)->TermIFace, (CmdIdLow), (CmdIdHigh))
#define ConioSetMenuClose(Console, Enable) \
- (Console)->TermIFace.Vtbl->SetMenuClose((Console), (Enable))
+ (Console)->TermIFace.Vtbl->SetMenuClose(&(Console)->TermIFace, (Enable))
/* EOF */
// ConioDrawConsole(Console);
}
+PCONSOLE_SCREEN_BUFFER
+ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
+{
+ return (Console ? Console->ActiveBuffer : NULL);
+}
/* PUBLIC SERVER APIS *********************************************************/
VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
VOID FASTCALL ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
+PCONSOLE_SCREEN_BUFFER
+ConDrvGetActiveScreenBuffer(IN PCONSOLE Console);
+
/* EOF */
/* INCLUDES *******************************************************************/
-#define COBJMACROS
-#define NONAMELESSUNION
-
#include "consrv.h"
#include "include/conio.h"
#include "conio.h"
#include "include/settings.h"
#include "frontends/gui/guiterm.h"
+#ifdef TUITERM_COMPILE
#include "frontends/tui/tuiterm.h"
+#endif
#include "include/console.h"
#include "console.h"
#include "resource.h"
-#include <shlwapi.h>
-#include <shlobj.h>
-
#define NDEBUG
#include <debug.h>
-/* GLOBALS ********************************************************************/
-
-static LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */
-static RTL_RESOURCE ListLock;
-
-#define ConSrvLockConsoleListExclusive() \
- RtlAcquireResourceExclusive(&ListLock, TRUE)
-
-#define ConSrvLockConsoleListShared() \
- RtlAcquireResourceShared(&ListLock, TRUE)
-
-#define ConSrvUnlockConsoleList() \
- RtlReleaseResource(&ListLock)
-// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
-BOOLEAN
-ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest,
- IN PCWSTR Source)
-{
- SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
- if (Size > MAXUSHORT) return FALSE;
-
- UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
- if (UniDest->Buffer == NULL) return FALSE;
-
- RtlCopyMemory(UniDest->Buffer, Source, Size);
- UniDest->MaximumLength = (USHORT)Size;
- UniDest->Length = (USHORT)Size - sizeof(WCHAR);
-
- return TRUE;
-}
-
-// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
-VOID
-ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
-{
- if (UnicodeString->Buffer)
- {
- ConsoleFreeHeap(UnicodeString->Buffer);
- RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
- }
-}
-
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-static BOOL
-DtbgIsDesktopVisible(VOID)
-{
- return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
-}
+/* GLOBALS ********************************************************************/
-static ULONG
-ConSrvConsoleCtrlEventTimeout(DWORD Event,
- PCONSOLE_PROCESS_DATA ProcessData,
- DWORD Timeout)
-{
- ULONG Status = ERROR_SUCCESS;
+/***************/
+#ifdef TUITERM_COMPILE
+NTSTATUS NTAPI
+TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+ IN OUT PCONSOLE_INFO ConsoleInfo,
+ IN OUT PVOID ExtraConsoleInfo,
+ IN ULONG ProcessId);
+NTSTATUS NTAPI
+TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
+#endif
- DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
+NTSTATUS NTAPI
+GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+ IN OUT PCONSOLE_INFO ConsoleInfo,
+ IN OUT PVOID ExtraConsoleInfo,
+ IN ULONG ProcessId);
+NTSTATUS NTAPI
+GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
+/***************/
+
+typedef
+NTSTATUS NTAPI
+(*FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
+ IN OUT PCONSOLE_INFO ConsoleInfo,
+ IN OUT PVOID ExtraConsoleInfo,
+ IN ULONG ProcessId);
+
+typedef
+NTSTATUS NTAPI
+(*FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
- if (ProcessData->CtrlDispatcher)
- {
- _SEH2_TRY
- {
- HANDLE Thread = NULL;
-
- _SEH2_TRY
- {
- Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
- ProcessData->CtrlDispatcher,
- UlongToPtr(Event), 0, NULL);
- if (NULL == Thread)
- {
- Status = GetLastError();
- DPRINT1("Failed thread creation (Error: 0x%x)\n", Status);
- }
- else
- {
- DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
- WaitForSingleObject(Thread, Timeout);
- }
- }
- _SEH2_FINALLY
- {
- CloseHandle(Thread);
- }
- _SEH2_END;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = RtlNtStatusToDosError(_SEH2_GetExceptionCode());
- DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = %08X\n", Status);
- }
- _SEH2_END;
- }
-
- return Status;
-}
+/*
+ * If we are not in GUI-mode, start the text-mode terminal emulator.
+ * If we fail, try to start the GUI-mode terminal emulator.
+ *
+ * Try to open the GUI-mode terminal emulator. Two cases are possible:
+ * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
+ * failed and we start GUI-mode terminal emulator.
+ * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
+ * succeeded BUT we failed at starting text-mode terminal emulator.
+ * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
+ * terminal emulator (Win32k will automatically switch to graphical mode,
+ * therefore no additional code is needed).
+ */
-static ULONG
-ConSrvConsoleCtrlEvent(DWORD Event,
- PCONSOLE_PROCESS_DATA ProcessData)
+/*
+ * NOTE: Each entry of the table should be retrieved when loading a front-end
+ * (examples of the CSR servers which register some data for CSRSS).
+ */
+struct
{
- return ConSrvConsoleCtrlEventTimeout(Event, ProcessData, 0);
-}
-
-ULONG FASTCALL
-ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
- ULONG ProcessGroupId,
- DWORD Event)
+ CHAR FrontEndName[80];
+ FRONTEND_LOAD FrontEndLoad;
+ FRONTEND_UNLOAD FrontEndUnload;
+} FrontEndLoadingMethods[] =
{
- ULONG Status = ERROR_SUCCESS;
- PLIST_ENTRY current_entry;
- PCONSOLE_PROCESS_DATA current;
-
- /* If the console is already being destroyed, just return */
- if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, FALSE))
- return STATUS_UNSUCCESSFUL;
+#ifdef TUITERM_COMPILE
+ {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd},
+#endif
+ {"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd},
- /*
- * Loop through the process list, from the most recent process
- * (the active one) to the oldest one (the first created, i.e.
- * the console leader process), and for each, send an event
- * (new processes are inserted at the head of the console process list).
- */
- current_entry = Console->ProcessList.Flink;
- while (current_entry != &Console->ProcessList)
- {
- current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
- current_entry = current_entry->Flink;
+// {"Not found", 0, NULL}
+};
- /*
- * Only processes belonging to the same process group are signaled.
- * If the process group ID is zero, then all the processes are signaled.
- */
- if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId)
- {
- Status = ConSrvConsoleCtrlEvent(Event, current);
- }
- }
- return Status;
-}
+/* PRIVATE FUNCTIONS **********************************************************/
+#if 0000
VOID FASTCALL
ConioPause(PCONSOLE Console, UINT Flags)
{
}
}
}
+#endif
-BOOL FASTCALL
-ConSrvValidateConsolePointer(PCONSOLE Console)
-{
- PLIST_ENTRY ConsoleEntry;
- PCONSOLE CurrentConsole = NULL;
-
- if (!Console) return FALSE;
-
- /* The console list must be locked */
- // ASSERT(Console_list_locked);
-
- ConsoleEntry = ConsoleList.Flink;
- while (ConsoleEntry != &ConsoleList)
- {
- CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry);
- ConsoleEntry = ConsoleEntry->Flink;
- if (CurrentConsole == Console) return TRUE;
- }
-
- return FALSE;
-}
-
-BOOL FASTCALL
-ConSrvValidateConsoleState(PCONSOLE Console,
- CONSOLE_STATE ExpectedState)
-{
- // if (!Console) return FALSE;
-
- /* The console must be locked */
- // ASSERT(Console_locked);
-
- return (Console->State == ExpectedState);
-}
-
-BOOL FASTCALL
-ConSrvValidateConsoleUnsafe(PCONSOLE Console,
- CONSOLE_STATE ExpectedState,
- BOOL LockConsole)
-{
- if (!Console) return FALSE;
-
- /*
- * Lock the console to forbid possible console's state changes
- * (which must be done when the console is already locked).
- * If we don't want to lock it, it's because the lock is already
- * held. So there must be no problems.
- */
- if (LockConsole) EnterCriticalSection(&Console->Lock);
-
- // ASSERT(Console_locked);
-
- /* Check whether the console's state is what we expect */
- if (!ConSrvValidateConsoleState(Console, ExpectedState))
- {
- if (LockConsole) LeaveCriticalSection(&Console->Lock);
- return FALSE;
- }
-
- return TRUE;
-}
-
-BOOL FASTCALL
-ConSrvValidateConsole(PCONSOLE Console,
- CONSOLE_STATE ExpectedState,
- BOOL LockConsole)
-{
- BOOL RetVal = FALSE;
-
- if (!Console) return FALSE;
-
- /*
- * Forbid creation or deletion of consoles when
- * checking for the existence of a console.
- */
- ConSrvLockConsoleListShared();
-
- if (ConSrvValidateConsolePointer(Console))
- {
- RetVal = ConSrvValidateConsoleUnsafe(Console,
- ExpectedState,
- LockConsole);
- }
-
- /* Unlock the console list and return */
- ConSrvUnlockConsoleList();
- return RetVal;
-}
-NTSTATUS
-FASTCALL
+NTSTATUS FASTCALL
ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
PCONSOLE* Console,
BOOL LockConsole)
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE ProcessConsole;
+ ASSERT(Console);
+ *Console = NULL;
+
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
ProcessConsole = ProcessData->Console;
- if (ConSrvValidateConsole(ProcessConsole, CONSOLE_RUNNING, LockConsole))
- {
- InterlockedIncrement(&ProcessConsole->ReferenceCount);
- *Console = ProcessConsole;
- }
- else
- {
- *Console = NULL;
- Status = STATUS_INVALID_HANDLE;
- }
+ Status = ConDrvGrabConsole(ProcessConsole, LockConsole);
+ if (NT_SUCCESS(Status)) *Console = ProcessConsole;
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
ConSrvReleaseConsole(PCONSOLE Console,
BOOL WasConsoleLocked)
{
- LONG RefCount = 0;
-
- if (!Console) return;
- // if (Console->ReferenceCount == 0) return; // This shouldn't happen
- ASSERT(Console->ReferenceCount > 0);
-
- /* The console must be locked */
- // ASSERT(Console_locked);
-
- /*
- * Decrement the reference count. Save the new value too,
- * because Console->ReferenceCount might be modified after
- * the console gets unlocked but before we check whether we
- * can destroy it.
- */
- RefCount = _InterlockedDecrement(&Console->ReferenceCount);
-
- /* Unlock the console if needed */
- if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock);
-
- /* Delete the console if needed */
- if (RefCount <= 0) ConSrvDeleteConsole(Console);
-}
-
-VOID WINAPI
-ConSrvInitConsoleSupport(VOID)
-{
- DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
-
- /* Initialize the console list and its lock */
- InitializeListHead(&ConsoleList);
- RtlInitializeResource(&ListLock);
-
- /* Should call LoadKeyboardLayout */
+ /* Just call the driver*/
+ ConDrvReleaseConsole(Console, WasConsoleLocked);
}
-static BOOL
-LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN OUT PCONSOLE_INFO ConsoleInfo,
- OUT LPWSTR IconPath,
- IN SIZE_T IconPathLength,
- OUT PINT piIcon)
-{
-#define PATH_SEPARATOR L'\\'
-
- BOOL RetVal = FALSE;
- HRESULT hRes = S_OK;
- LPWSTR LinkName = NULL;
- SIZE_T Length = 0;
-
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
- return FALSE;
-
- if (IconPath == NULL || piIcon == NULL)
- return FALSE;
-
- IconPath[0] = L'\0';
- *piIcon = 0;
-
- /* 1- Find the last path separator if any */
- LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
- if (LinkName == NULL)
- {
- LinkName = ConsoleStartInfo->ConsoleTitle;
- }
- else
- {
- /* Skip the path separator */
- ++LinkName;
- }
-
- /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
- Length = wcslen(LinkName);
- if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
- return FALSE;
-
- /* 3- It may be a link. Try to retrieve some properties */
- hRes = CoInitialize(NULL);
- if (SUCCEEDED(hRes))
- {
- /* Get a pointer to the IShellLink interface */
- IShellLinkW* pshl = NULL;
- hRes = CoCreateInstance(&CLSID_ShellLink,
- NULL,
- CLSCTX_INPROC_SERVER,
- &IID_IShellLinkW,
- (LPVOID*)&pshl);
- if (SUCCEEDED(hRes))
- {
- /* Get a pointer to the IPersistFile interface */
- IPersistFile* ppf = NULL;
- hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
- if (SUCCEEDED(hRes))
- {
- /* Load the shortcut */
- hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
- if (SUCCEEDED(hRes))
- {
- /*
- * Finally we can get the properties !
- * Update the old ones if needed.
- */
- INT ShowCmd = 0;
- // WORD HotKey = 0;
-
- /* Reset the name of the console with the name of the shortcut */
- Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
- sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
- wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
- ConsoleInfo->ConsoleTitle[Length] = L'\0';
-
- /* Get the window showing command */
- hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
- if (SUCCEEDED(hRes)) ConsoleStartInfo->ShowWindow = (WORD)ShowCmd;
-
- /* Get the hotkey */
- // hRes = pshl->GetHotkey(&ShowCmd);
- // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
-
- /* Get the icon location, if any */
- hRes = IShellLinkW_GetIconLocation(pshl, IconPath, IconPathLength, piIcon);
- if (!SUCCEEDED(hRes))
- {
- IconPath[0] = L'\0';
- }
-
- // FIXME: Since we still don't load console properties from the shortcut,
- // return false. When this will be done, we will return true instead.
- RetVal = FALSE;
- }
- IPersistFile_Release(ppf);
- }
- IShellLinkW_Release(pshl);
- }
- }
- CoUninitialize();
-
- return RetVal;
-}
NTSTATUS WINAPI
ConSrvInitConsole(OUT PCONSOLE* NewConsole,
IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN PCSR_PROCESS ConsoleLeaderProcess)
+ IN ULONG ConsoleLeaderProcessId)
{
NTSTATUS Status;
- SECURITY_ATTRIBUTES SecurityAttributes;
- SIZE_T Length = 0;
- DWORD ProcessId = HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
- CONSOLE_INFO ConsoleInfo;
- TEXTMODE_BUFFER_INFO ScreenBufferInfo;
PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER NewBuffer;
- BOOL GuiMode;
- WCHAR DefaultTitle[128];
- WCHAR IconPath[MAX_PATH + 1] = L"";
- INT iIcon = 0;
+ CONSOLE_INFO ConsoleInfo;
+ SIZE_T Length = 0;
+ ULONG i = 0;
+ FRONTEND FrontEnd;
- if (NewConsole == NULL) return STATUS_INVALID_PARAMETER;
- *NewConsole = NULL;
+ if (NewConsole == NULL || ConsoleStartInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
- /*
- * Allocate a console structure
- */
- Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE));
- if (NULL == Console)
- {
- DPRINT1("Not enough memory for console creation.\n");
- return STATUS_NO_MEMORY;
- }
+ *NewConsole = NULL;
/*
* Load the console settings
*/
/* 1. Load the default settings */
- ConSrvGetDefaultSettings(&ConsoleInfo, ProcessId);
+ ConSrvGetDefaultSettings(&ConsoleInfo, ConsoleLeaderProcessId);
/* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
ConsoleInfo.ConsoleTitle[Length] = L'\0';
+
/*
- * 3. Check whether the process creating the console was launched
- * via a shell-link. ConsoleInfo.ConsoleTitle may be updated by
- * the name of the shortcut.
+ * Choose an adequate terminal front-end to load, and load it
*/
- if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
- {
- if (!LoadShellLinkConsoleInfo(ConsoleStartInfo,
- &ConsoleInfo,
- IconPath,
- MAX_PATH,
- &iIcon))
+ Status = STATUS_SUCCESS;
+ for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i)
+ {
+ DPRINT("CONSRV: Trying to load %s terminal emulator...\n", FrontEndLoadingMethods[i].FrontEndName);
+ Status = FrontEndLoadingMethods[i].FrontEndLoad(&FrontEnd,
+ &ConsoleInfo,
+ ConsoleStartInfo,
+ ConsoleLeaderProcessId);
+ if (NT_SUCCESS(Status))
{
- ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
+ DPRINT("CONSRV: %s terminal emulator loaded successfully\n", FrontEndLoadingMethods[i].FrontEndName);
+ break;
}
+ else
+ {
+ DPRINT1("CONSRV: Loading %s terminal emulator failed, Status = 0x%08lx , continuing...\n", FrontEndLoadingMethods[i].FrontEndName, Status);
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
+ return Status;
}
+ DPRINT("CONSRV: Frontend initialized\n");
+
+
+/******************************************************************************/
/*
* 4. Load the remaining console settings via the registry.
*/
* or we failed to load shell-link console properties.
* Therefore, load the console infos for the application from the registry.
*/
- ConSrvReadUserSettings(&ConsoleInfo, ProcessId);
+ ConSrvReadUserSettings(&ConsoleInfo, ConsoleLeaderProcessId);
/*
* Now, update them with the properties the user might gave to us
}
if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
{
- // ConsoleInfo->ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
+ // ConsoleInfo.ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
ConsoleInfo.ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
ConsoleInfo.ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
}
}
- /*
- * Fix the screen buffer size if needed. The rule is:
- * ScreenBufferSize >= ConsoleSize
- */
- if (ConsoleInfo.ScreenBufferSize.X < ConsoleInfo.ConsoleSize.X)
- ConsoleInfo.ScreenBufferSize.X = ConsoleInfo.ConsoleSize.X;
- if (ConsoleInfo.ScreenBufferSize.Y < ConsoleInfo.ConsoleSize.Y)
- ConsoleInfo.ScreenBufferSize.Y = ConsoleInfo.ConsoleSize.Y;
-
- /*
- * Initialize the console
- */
- Console->State = CONSOLE_INITIALIZING;
- Console->ReferenceCount = 0;
- InitializeCriticalSection(&Console->Lock);
- InitializeListHead(&Console->ProcessList);
- RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace));
-
- memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
- Console->ConsoleSize = ConsoleInfo.ConsoleSize;
- Console->FixedSize = FALSE; // Value by default; is reseted by the front-ends if needed.
-
- /*
- * Initialize the input buffer
- */
- ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console);
-
- SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- SecurityAttributes.lpSecurityDescriptor = NULL;
- SecurityAttributes.bInheritHandle = TRUE;
- Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
- if (NULL == Console->InputBuffer.ActiveEvent)
- {
- DeleteCriticalSection(&Console->Lock);
- ConsoleFreeHeap(Console);
- return STATUS_UNSUCCESSFUL;
- }
+ /* Set-up the code page */
+ ConsoleInfo.CodePage = GetOEMCP();
+/******************************************************************************/
- Console->InputBuffer.InputBufferSize = 0; // FIXME!
- InitializeListHead(&Console->InputBuffer.InputEvents);
- InitializeListHead(&Console->InputBuffer.ReadWaitQueue);
- Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
- ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
-
- Console->QuickEdit = ConsoleInfo.QuickEdit;
- Console->InsertMode = ConsoleInfo.InsertMode;
- Console->LineBuffer = NULL;
- Console->LineMaxSize = Console->LineSize = Console->LinePos = 0;
- Console->LineComplete = Console->LineUpPressed = Console->LineInsertToggle = FALSE;
- // LineWakeupMask
- RtlZeroMemory(&Console->Selection, sizeof(CONSOLE_SELECTION_INFO));
- Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
- // dwSelectionCursor
-
- Console->CodePage = GetOEMCP();
- Console->OutputCodePage = GetOEMCP();
-
- /* Initialize a new text-mode screen buffer with default settings */
- ScreenBufferInfo.ScreenBufferSize = ConsoleInfo.ScreenBufferSize;
- ScreenBufferInfo.ScreenAttrib = ConsoleInfo.ScreenAttrib;
- ScreenBufferInfo.PopupAttrib = ConsoleInfo.PopupAttrib;
- ScreenBufferInfo.IsCursorVisible = TRUE;
- ScreenBufferInfo.CursorSize = ConsoleInfo.CursorSize;
-
- InitializeListHead(&Console->BufferList);
- Status = ConSrvCreateScreenBuffer(&NewBuffer,
- Console,
- CONSOLE_TEXTMODE_BUFFER,
- &ScreenBufferInfo);
+ Status = ConDrvInitConsole(&Console, &ConsoleInfo, ConsoleLeaderProcessId);
if (!NT_SUCCESS(Status))
{
- DPRINT1("ConSrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
- CloseHandle(Console->InputBuffer.ActiveEvent);
- DeleteCriticalSection(&Console->Lock);
- ConsoleFreeHeap(Console);
+ DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status);
+ FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
return Status;
}
- /* Make the new screen buffer active */
- Console->ActiveBuffer = NewBuffer;
- InitializeListHead(&Console->WriteWaitQueue);
- Console->PauseFlags = 0;
- Console->UnpauseEvent = NULL;
-
- /*
- * Initialize the alias and history buffers
- */
- Console->Aliases = NULL;
- InitializeListHead(&Console->HistoryBuffers);
- Console->HistoryBufferSize = ConsoleInfo.HistoryBufferSize;
- Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers;
- Console->HistoryNoDup = ConsoleInfo.HistoryNoDup;
-
- /* Initialize the console title */
- ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo.ConsoleTitle);
- if (ConsoleInfo.ConsoleTitle[0] == L'\0')
- {
- if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
- {
- ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
- }
- else
- {
- ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
- }
- }
- else
- {
- ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle);
- }
-
- /* Lock the console until its initialization is finished */
- // EnterCriticalSection(&Console->Lock);
-
- /*
- * If we are not in GUI-mode, start the text-mode terminal emulator.
- * If we fail, try to start the GUI-mode terminal emulator.
- */
- GuiMode = DtbgIsDesktopVisible();
- if (!GuiMode)
- {
- DPRINT("CONSRV: Opening text-mode terminal emulator\n");
- Status = TuiInitConsole(Console,
- ConsoleStartInfo,
- &ConsoleInfo,
- ProcessId);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to open text-mode terminal emulator, switching to gui-mode, Status = 0x%08lx\n", Status);
- GuiMode = TRUE;
- }
- }
+ ASSERT(Console);
+ DPRINT("Console initialized\n");
- /*
- * Try to open the GUI-mode terminal emulator. Two cases are possible:
- * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
- * failed and we start GUI-mode terminal emulator.
- * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
- * succeeded BUT we failed at starting text-mode terminal emulator.
- * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
- * terminal emulator (Win32k will automatically switch to graphical mode,
- * therefore no additional code is needed).
- */
- if (GuiMode)
+ Status = ConDrvRegisterFrontEnd(Console, &FrontEnd);
+ if (!NT_SUCCESS(Status))
{
- DPRINT("CONSRV: Opening GUI-mode terminal emulator\n");
- Status = GuiInitConsole(Console,
- ConsoleStartInfo,
- &ConsoleInfo,
- ProcessId,
- IconPath,
- iIcon);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
- ConsoleFreeUnicodeString(&Console->OriginalTitle);
- ConsoleFreeUnicodeString(&Console->Title);
- ConioDeleteScreenBuffer(NewBuffer);
- CloseHandle(Console->InputBuffer.ActiveEvent);
- // LeaveCriticalSection(&Console->Lock);
- DeleteCriticalSection(&Console->Lock);
- ConsoleFreeHeap(Console);
- return Status;
- }
+ DPRINT1("Failed to register frontend to the given console, Status = 0x%08lx\n", Status);
+ ConDrvDeleteConsole(Console);
+ FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd);
+ return Status;
}
-
- DPRINT("Terminal initialized\n");
-
- /* All went right, so add the console to the list */
- ConSrvLockConsoleListExclusive();
- DPRINT("Insert in the list\n");
- InsertTailList(&ConsoleList, &Console->Entry);
-
- /* The initialization is finished */
- DPRINT("Change state\n");
- Console->State = CONSOLE_RUNNING;
-
- /* Unlock the console */
- // LeaveCriticalSection(&Console->Lock);
-
- /* Unlock the console list */
- ConSrvUnlockConsoleList();
-
- /* Copy buffer contents to screen */
- ConioDrawConsole(Console);
- DPRINT("Console drawn\n");
+ DPRINT("FrontEnd registered\n");
/* Return the newly created console to the caller and a success code too */
*NewConsole = Console;
{
DPRINT("ConSrvDeleteConsole\n");
- /*
- * Forbid validation of any console by other threads
- * during the deletion of this console.
- */
- ConSrvLockConsoleListExclusive();
-
- /* Check the existence of the console, and if it's ok, continue */
- if (!ConSrvValidateConsolePointer(Console))
- {
- /* Unlock the console list and return */
- ConSrvUnlockConsoleList();
- return;
- }
-
- /*
- * If the console is already being destroyed
- * (thus not running), just return.
- */
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
- {
- /* Unlock the console list and return */
- ConSrvUnlockConsoleList();
- return;
- }
-
- /*
- * We are about to be destroyed. Signal it to other people
- * so that they can terminate what they are doing, and that
- * they cannot longer validate the console.
- */
- Console->State = CONSOLE_TERMINATING;
-
- /*
- * Allow other threads to finish their job: basically, unlock
- * all other calls to EnterCriticalSection(&Console->Lock); by
- * ConSrvValidateConsole(Unsafe) functions so that they just see
- * that we are not in CONSOLE_RUNNING state anymore, or unlock
- * other concurrent calls to ConSrvDeleteConsole so that they
- * can see that we are in fact already deleting the console.
- */
- LeaveCriticalSection(&Console->Lock);
- ConSrvUnlockConsoleList();
-
- /* FIXME: Send a terminate message to all the processes owning this console */
-
- /* Cleanup the UI-oriented part */
- ConioCleanupConsole(Console);
-
- /***
- * Check that the console is in terminating state before continuing
- * (the cleanup code must not change the state of the console...
- * ...unless to cancel console deletion ?).
- ***/
-
- ConSrvLockConsoleListExclusive();
-
- /* Re-check the existence of the console, and if it's ok, continue */
- if (!ConSrvValidateConsolePointer(Console))
- {
- /* Unlock the console list and return */
- ConSrvUnlockConsoleList();
- return;
- }
-
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE))
- {
- ConSrvUnlockConsoleList();
- return;
- }
-
- /* We are in destruction */
- Console->State = CONSOLE_IN_DESTRUCTION;
-
- /* Remove the console from the list */
- RemoveEntryList(&Console->Entry);
-
- /* Reset the count to be sure */
- Console->ReferenceCount = 0;
-
- /* Discard all entries in the input event queue */
- PurgeInputBuffer(Console);
-
- if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
-
- IntDeleteAllAliases(Console);
- HistoryDeleteBuffers(Console);
-
- ConioDeleteScreenBuffer(Console->ActiveBuffer);
- if (!IsListEmpty(&Console->BufferList))
- {
- DPRINT1("BUG: screen buffer list not empty\n");
- }
-
- // CloseHandle(Console->InputBuffer.ActiveEvent);
- if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
-
- ConsoleFreeUnicodeString(&Console->OriginalTitle);
- ConsoleFreeUnicodeString(&Console->Title);
-
- DPRINT("ConSrvDeleteConsole - Unlocking\n");
- LeaveCriticalSection(&Console->Lock);
- DPRINT("ConSrvDeleteConsole - Destroying lock\n");
- DeleteCriticalSection(&Console->Lock);
- DPRINT("ConSrvDeleteConsole - Lock destroyed ; freeing console\n");
-
- ConsoleFreeHeap(Console);
- DPRINT("ConSrvDeleteConsole - Console freed\n");
-
- /* Unlock the console list and return */
- ConSrvUnlockConsoleList();
+ /* Just call the driver. ConSrvDeregisterFrontEnd is called on-demand. */
+ ConDrvDeleteConsole(Console);
}
return STATUS_SUCCESS;
}
+NTSTATUS NTAPI
+ConDrvGetConsoleMode(IN PCONSOLE Console,
+ IN PCONSOLE_IO_OBJECT Object,
+ OUT PULONG ConsoleMode);
CSR_API(SrvGetConsoleMode)
{
NTSTATUS Status;
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
- PCONSOLE_IO_OBJECT Object = NULL;
+ PCONSOLE_IO_OBJECT Object;
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ConsoleModeRequest->ConsoleHandle,
&Object, NULL, GENERIC_READ, TRUE, 0);
if (!NT_SUCCESS(Status)) return Status;
- Status = STATUS_SUCCESS;
-
- if (INPUT_BUFFER == Object->Type)
- {
- PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
- PCONSOLE Console = InputBuffer->Header.Console;
- DWORD ConsoleMode = InputBuffer->Mode;
-
- if (Console->QuickEdit || Console->InsertMode)
- {
- // Windows does this, even if it's not documented on MSDN
- ConsoleMode |= ENABLE_EXTENDED_FLAGS;
-
- if (Console->QuickEdit ) ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
- if (Console->InsertMode) ConsoleMode |= ENABLE_INSERT_MODE;
- }
-
- ConsoleModeRequest->ConsoleMode = ConsoleMode;
- }
- else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
- {
- PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
- ConsoleModeRequest->ConsoleMode = Buffer->Mode;
- }
- else
- {
- Status = STATUS_INVALID_HANDLE;
- }
+ Status = ConDrvGetConsoleMode(Object->Console, Object,
+ &ConsoleModeRequest->ConsoleMode);
ConSrvReleaseObject(Object, TRUE);
return Status;
}
+NTSTATUS NTAPI
+ConDrvSetConsoleMode(IN PCONSOLE Console,
+ IN PCONSOLE_IO_OBJECT Object,
+ IN ULONG ConsoleMode);
CSR_API(SrvSetConsoleMode)
{
-#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
-#define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
- ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
- ENABLE_MOUSE_INPUT )
-#define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
-
NTSTATUS Status;
PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
- DWORD ConsoleMode = ConsoleModeRequest->ConsoleMode;
- PCONSOLE_IO_OBJECT Object = NULL;
+ PCONSOLE_IO_OBJECT Object;
Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ConsoleModeRequest->ConsoleHandle,
&Object, NULL, GENERIC_WRITE, TRUE, 0);
if (!NT_SUCCESS(Status)) return Status;
- Status = STATUS_SUCCESS;
+ Status = ConDrvSetConsoleMode(Object->Console, Object,
+ ConsoleModeRequest->ConsoleMode);
- if (INPUT_BUFFER == Object->Type)
- {
- PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
- PCONSOLE Console = InputBuffer->Header.Console;
-
- DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode);
-
- /*
- * 1. Only the presence of valid mode flags is allowed.
- */
- if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES))
- {
- Status = STATUS_INVALID_PARAMETER;
- goto Quit;
- }
-
- /*
- * 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS,
- * then consider the flags invalid.
- *
- if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) &&
- (ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 )
- {
- Status = STATUS_INVALID_PARAMETER;
- goto Quit;
- }
- */
-
- /*
- * 3. Now we can continue.
- */
- if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
- {
- Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
- Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
- }
- InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
- }
- else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
- {
- PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
-
- DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode);
-
- if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
- {
- Status = STATUS_INVALID_PARAMETER;
- }
- else
- {
- Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
- }
- }
- else
- {
- Status = STATUS_INVALID_HANDLE;
- }
-
-Quit:
ConSrvReleaseObject(Object, TRUE);
return Status;
}
+NTSTATUS NTAPI
+ConDrvGetConsoleTitle(IN PCONSOLE Console,
+ IN OUT PWCHAR Title,
+ IN OUT PULONG BufLength);
CSR_API(SrvGetConsoleTitle)
{
NTSTATUS Status;
PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
- // PCSR_PROCESS Process = CsrGetClientThread()->Process;
PCONSOLE Console;
- DWORD Length;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&TitleRequest->Title,
return Status;
}
- /* Copy title of the console to the user title buffer */
- if (TitleRequest->Length >= sizeof(WCHAR))
- {
- Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
- memcpy(TitleRequest->Title, Console->Title.Buffer, Length);
- TitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
- }
-
- TitleRequest->Length = Console->Title.Length;
+ Status = ConDrvGetConsoleTitle(Console,
+ TitleRequest->Title,
+ &TitleRequest->Length);
ConSrvReleaseConsole(Console, TRUE);
- return STATUS_SUCCESS;
+ return Status;
}
+NTSTATUS NTAPI
+ConDrvSetConsoleTitle(IN PCONSOLE Console,
+ IN PWCHAR Title,
+ IN ULONG BufLength);
CSR_API(SrvSetConsoleTitle)
{
NTSTATUS Status;
PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
- // PCSR_PROCESS Process = CsrGetClientThread()->Process;
PCONSOLE Console;
- PWCHAR Buffer;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&TitleRequest->Title,
return Status;
}
- /* Allocate a new buffer to hold the new title (NULL-terminated) */
- Buffer = ConsoleAllocHeap(0, TitleRequest->Length + sizeof(WCHAR));
- if (Buffer)
- {
- /* Free the old title */
- ConsoleFreeUnicodeString(&Console->Title);
-
- /* Copy title to console */
- Console->Title.Buffer = Buffer;
- Console->Title.Length = TitleRequest->Length;
- Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
- RtlCopyMemory(Console->Title.Buffer,
- TitleRequest->Title,
- Console->Title.Length);
- Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
-
- ConioChangeTitle(Console);
- Status = STATUS_SUCCESS;
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
+ Status = ConDrvSetConsoleTitle(Console,
+ TitleRequest->Title,
+ TitleRequest->Length);
- ConSrvReleaseConsole(Console, TRUE);
- return Status;
-}
-
-/**********************************************************************
- * HardwareStateProperty
- *
- * DESCRIPTION
- * Set/Get the value of the HardwareState and switch
- * between direct video buffer ouput and GDI windowed
- * output.
- * ARGUMENTS
- * Client hands us a CONSOLE_GETSETHWSTATE object.
- * We use the same object to Request.
- * NOTE
- * ConsoleHwState has the correct size to be compatible
- * with NT's, but values are not.
- */
-#if 0
-static NTSTATUS FASTCALL
-SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
-{
- DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
-
- if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
- ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
- {
- if (Console->HardwareState != ConsoleHwState)
- {
- /* TODO: implement switching from full screen to windowed mode */
- /* TODO: or back; now simply store the hardware state */
- Console->HardwareState = ConsoleHwState;
- }
-
- return STATUS_SUCCESS;
- }
-
- return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
-}
-#endif
-
-CSR_API(SrvGetConsoleHardwareState)
-{
-#if 0
- NTSTATUS Status;
- PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
- PCONSOLE_SCREEN_BUFFER Buff;
- PCONSOLE Console;
-
- Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- HardwareStateRequest->OutputHandle,
- &Buff,
- GENERIC_READ,
- TRUE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
- return Status;
- }
-
- Console = Buff->Header.Console;
- HardwareStateRequest->State = Console->HardwareState;
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return Status;
-#else
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-#endif
-}
-
-CSR_API(SrvSetConsoleHardwareState)
-{
-#if 0
- NTSTATUS Status;
- PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
- PCONSOLE_SCREEN_BUFFER Buff;
- PCONSOLE Console;
-
- Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- HardwareStateRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
- return Status;
- }
-
- DPRINT("Setting console hardware state.\n");
- Console = Buff->Header.Console;
- Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return Status;
-#else
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-#endif
-}
-
-CSR_API(SrvGetConsoleDisplayMode)
-{
- NTSTATUS Status;
- PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
- PCONSOLE Console;
-
- Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- &Console, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- GetDisplayModeRequest->DisplayMode = ConioGetDisplayMode(Console);
-
- ConSrvReleaseConsole(Console, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleDisplayMode)
-{
- NTSTATUS Status;
- PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- SetDisplayModeRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- if (ConioSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
- {
- SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
- Status = STATUS_SUCCESS;
- }
- else
- {
- Status = STATUS_INVALID_PARAMETER;
- }
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return Status;
-}
-
-CSR_API(SrvGetLargestConsoleWindowSize)
-{
- NTSTATUS Status;
- PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
- PCONSOLE_SCREEN_BUFFER Buff;
- PCONSOLE Console;
-
- Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- GetLargestWindowSizeRequest->OutputHandle,
- &Buff,
- GENERIC_READ,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
- ConioGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvShowConsoleCursor)
-{
- NTSTATUS Status;
- PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- ShowCursorRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- ShowCursorRequest->RefCount = ConioShowMouseCursor(Console, ShowCursorRequest->Show);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleCursor)
-{
- NTSTATUS Status;
- BOOL Success;
- PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
-
- // FIXME: Tests show that this function is used only for graphics screen buffers
- // and otherwise it returns false + set last error to invalid handle.
- // NOTE: I find that behaviour is ridiculous but ok, let's accept that at the moment...
- Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- SetCursorRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- Success = ConioSetMouseCursor(Console, SetCursorRequest->hCursor);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
-}
-
-CSR_API(SrvConsoleMenuControl)
-{
- NTSTATUS Status;
- PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
- PCONSOLE Console;
- PCONSOLE_SCREEN_BUFFER Buff;
-
- Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- MenuControlRequest->OutputHandle,
- &Buff,
- GENERIC_WRITE,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Console = Buff->Header.Console;
-
- MenuControlRequest->hMenu = ConioMenuControl(Console,
- MenuControlRequest->dwCmdIdLow,
- MenuControlRequest->dwCmdIdHigh);
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleMenuClose)
-{
- NTSTATUS Status;
- BOOL Success;
- PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
- PCONSOLE Console;
-
- Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- &Console, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Success = ConioSetMenuClose(Console, SetMenuCloseRequest->Enable);
-
- ConSrvReleaseConsole(Console, TRUE);
- return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
-}
-
-CSR_API(SrvSetConsoleWindowInfo)
-{
- NTSTATUS Status;
- PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
- PCONSOLE_SCREEN_BUFFER Buff;
- SMALL_RECT WindowRect = SetWindowInfoRequest->WindowRect;
-
- DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
- SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
- WindowRect.Left, WindowRect.Top, WindowRect.Right, WindowRect.Bottom);
-
- Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- SetWindowInfoRequest->OutputHandle,
- &Buff,
- GENERIC_READ,
- TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- if (SetWindowInfoRequest->Absolute == FALSE)
- {
- /* Relative positions given. Transform them to absolute ones */
- WindowRect.Left += Buff->ViewOrigin.X;
- WindowRect.Top += Buff->ViewOrigin.Y;
- WindowRect.Right += Buff->ViewOrigin.X + Buff->ViewSize.X - 1;
- WindowRect.Bottom += Buff->ViewOrigin.Y + Buff->ViewSize.Y - 1;
- }
-
- /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
- if ( (WindowRect.Left < 0) || (WindowRect.Top < 0) ||
- (WindowRect.Right >= Buff->ScreenBufferSize.X) ||
- (WindowRect.Bottom >= Buff->ScreenBufferSize.Y) ||
- (WindowRect.Right <= WindowRect.Left) ||
- (WindowRect.Bottom <= WindowRect.Top) )
- {
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_INVALID_PARAMETER;
- }
-
- Buff->ViewOrigin.X = WindowRect.Left;
- Buff->ViewOrigin.Y = WindowRect.Top;
-
- Buff->ViewSize.X = WindowRect.Right - WindowRect.Left + 1;
- Buff->ViewSize.Y = WindowRect.Bottom - WindowRect.Top + 1;
-
- ConSrvReleaseScreenBuffer(Buff, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvGetConsoleWindow)
-{
- NTSTATUS Status;
- PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
- PCONSOLE Console;
-
- Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- GetWindowRequest->WindowHandle = ConioGetConsoleWindowHandle(Console);
-
- ConSrvReleaseConsole(Console, TRUE);
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvSetConsoleIcon)
-{
- NTSTATUS Status;
- PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
- PCONSOLE Console;
-
- Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
-
- Status = (ConioChangeIcon(Console, SetIconRequest->WindowIcon)
- ? STATUS_SUCCESS
- : STATUS_UNSUCCESSFUL);
+ if (NT_SUCCESS(Status)) ConioChangeTitle(Console);
ConSrvReleaseConsole(Console, TRUE);
return Status;
}
+NTSTATUS NTAPI
+ConDrvGetConsoleCP(IN PCONSOLE Console,
+ OUT PUINT CodePage,
+ IN BOOLEAN InputCP);
CSR_API(SrvGetConsoleCP)
{
NTSTATUS Status;
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- ConsoleCPRequest->CodePage = (ConsoleCPRequest->InputCP ? Console->CodePage
- : Console->OutputCodePage);
+ Status = ConDrvGetConsoleCP(Console,
+ &ConsoleCPRequest->CodePage,
+ ConsoleCPRequest->InputCP);
+
ConSrvReleaseConsole(Console, TRUE);
- return STATUS_SUCCESS;
+ return Status;
}
+NTSTATUS NTAPI
+ConDrvSetConsoleCP(IN PCONSOLE Console,
+ IN UINT CodePage,
+ IN BOOLEAN InputCP);
CSR_API(SrvSetConsoleCP)
{
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
PCONSOLE Console;
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- if (IsValidCodePage(ConsoleCPRequest->CodePage))
- {
- if (ConsoleCPRequest->InputCP)
- Console->CodePage = ConsoleCPRequest->CodePage;
- else
- Console->OutputCodePage = ConsoleCPRequest->CodePage;
-
- ConSrvReleaseConsole(Console, TRUE);
- return STATUS_SUCCESS;
- }
+ Status = ConDrvSetConsoleCP(Console,
+ ConsoleCPRequest->CodePage,
+ ConsoleCPRequest->InputCP);
ConSrvReleaseConsole(Console, TRUE);
- return STATUS_INVALID_PARAMETER;
+ return Status;
}
+NTSTATUS NTAPI
+ConDrvGetConsoleProcessList(IN PCONSOLE Console,
+ IN OUT PULONG ProcessIdsList,
+ IN ULONG MaxIdListItems,
+ OUT PULONG ProcessIdsTotal);
CSR_API(SrvGetConsoleProcessList)
{
NTSTATUS Status;
PCONSOLE_GETPROCESSLIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
- PDWORD Buffer;
- // PCSR_PROCESS Process = CsrGetClientThread()->Process;
PCONSOLE Console;
- PCONSOLE_PROCESS_DATA current;
- PLIST_ENTRY current_entry;
- ULONG nItems = 0;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&GetProcessListRequest->pProcessIds,
return STATUS_INVALID_PARAMETER;
}
- Buffer = GetProcessListRequest->pProcessIds;
-
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- for (current_entry = Console->ProcessList.Flink;
- current_entry != &Console->ProcessList;
- current_entry = current_entry->Flink)
- {
- current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
- if (++nItems <= GetProcessListRequest->nMaxIds)
- {
- *Buffer++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
- }
- }
+ Status = ConDrvGetConsoleProcessList(Console,
+ GetProcessListRequest->pProcessIds,
+ GetProcessListRequest->nMaxIds,
+ &GetProcessListRequest->nProcessIdsTotal);
ConSrvReleaseConsole(Console, TRUE);
-
- GetProcessListRequest->nProcessIdsTotal = nItems;
- return STATUS_SUCCESS;
+ return Status;
}
CSR_API(SrvGenerateConsoleCtrlEvent)
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- Status = ConSrvConsoleProcessCtrlEvent(Console,
+ Status = ConDrvConsoleProcessCtrlEvent(Console,
GenerateCtrlEventRequest->ProcessGroup,
GenerateCtrlEventRequest->Event);
return Status;
}
-CSR_API(SrvGetConsoleSelectionInfo)
-{
- NTSTATUS Status;
- PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
- PCONSOLE Console;
-
- Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
- if (NT_SUCCESS(Status))
- {
- memset(&GetSelectionInfoRequest->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
- if (Console->Selection.dwFlags != 0)
- GetSelectionInfoRequest->Info = Console->Selection;
- ConSrvReleaseConsole(Console, TRUE);
- }
-
- return Status;
-}
-
/* EOF */
#pragma once
-VOID WINAPI ConSrvInitConsoleSupport(VOID);
+VOID NTAPI
+ConDrvInitConsoleSupport(VOID);
-NTSTATUS WINAPI ConSrvInitConsole(OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
- IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN PCSR_PROCESS ConsoleLeaderProcess);
+NTSTATUS WINAPI
+ConSrvInitConsole(OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
+ IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+ IN ULONG ConsoleLeaderProcessId);
VOID WINAPI ConSrvDeleteConsole(struct _CONSOLE* /* PCONSOLE */ Console);
+
NTSTATUS FASTCALL ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
struct _CONSOLE** /* PCONSOLE* */ Console,
BOOL LockConsole);
VOID FASTCALL ConSrvReleaseConsole(struct _CONSOLE* /* PCONSOLE */ Console,
BOOL WasConsoleLocked);
+/******************************************************************************/
+
+NTSTATUS NTAPI
+ConDrvGrabConsole(IN struct _CONSOLE* /* PCONSOLE */ Console,
+ IN BOOLEAN LockConsole);
+VOID NTAPI
+ConDrvReleaseConsole(IN struct _CONSOLE* /* PCONSOLE */ Console,
+ IN BOOLEAN WasConsoleLocked);
+
+typedef struct _FRONTEND FRONTEND, *PFRONTEND;
+typedef struct _CONSOLE_INFO CONSOLE_INFO, *PCONSOLE_INFO;
+
+NTSTATUS NTAPI
+ConDrvInitConsole(OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole,
+ // IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+ IN PCONSOLE_INFO ConsoleInfo,
+ IN ULONG ConsoleLeaderProcessId);
+NTSTATUS NTAPI
+ConDrvRegisterFrontEnd(IN struct _CONSOLE* /* PCONSOLE */ Console,
+ IN PFRONTEND FrontEnd);
+NTSTATUS NTAPI
+ConDrvDeregisterFrontEnd(IN struct _CONSOLE* /* PCONSOLE */ Console);
+VOID NTAPI
+ConDrvDeleteConsole(IN struct _CONSOLE* /* PCONSOLE */ Console);
+
/* EOF */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/frontendctl.c
+ * PURPOSE: Terminal Front-Ends Control
+ * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "conoutput.h"
+#include "console.h"
+#include "handle.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+
+/* PUBLIC SERVER APIS *********************************************************/
+
+/**********************************************************************
+ * HardwareStateProperty
+ *
+ * DESCRIPTION
+ * Set/Get the value of the HardwareState and switch
+ * between direct video buffer ouput and GDI windowed
+ * output.
+ * ARGUMENTS
+ * Client hands us a CONSOLE_GETSETHWSTATE object.
+ * We use the same object to Request.
+ * NOTE
+ * ConsoleHwState has the correct size to be compatible
+ * with NT's, but values are not.
+ */
+#if 0
+static NTSTATUS FASTCALL
+SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
+{
+ DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
+
+ if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
+ ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
+ {
+ if (Console->HardwareState != ConsoleHwState)
+ {
+ /* TODO: implement switching from full screen to windowed mode */
+ /* TODO: or back; now simply store the hardware state */
+ Console->HardwareState = ConsoleHwState;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
+}
+#endif
+
+CSR_API(SrvGetConsoleHardwareState)
+{
+#if 0
+ NTSTATUS Status;
+ PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+ PCONSOLE Console;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ HardwareStateRequest->OutputHandle,
+ &Buff,
+ GENERIC_READ,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
+ return Status;
+ }
+
+ Console = Buff->Header.Console;
+ HardwareStateRequest->State = Console->HardwareState;
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return Status;
+#else
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
+CSR_API(SrvSetConsoleHardwareState)
+{
+#if 0
+ NTSTATUS Status;
+ PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+ PCONSOLE Console;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ HardwareStateRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
+ return Status;
+ }
+
+ DPRINT("Setting console hardware state.\n");
+ Console = Buff->Header.Console;
+ Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return Status;
+#else
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
+CSR_API(SrvGetConsoleDisplayMode)
+{
+ NTSTATUS Status;
+ PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
+ PCONSOLE Console;
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ GetDisplayModeRequest->DisplayMode = ConioGetDisplayMode(Console);
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleDisplayMode)
+{
+ NTSTATUS Status;
+ PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
+ PCONSOLE Console;
+ PCONSOLE_SCREEN_BUFFER Buff;
+
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ SetDisplayModeRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ if (ConioSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode))
+ {
+ SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return Status;
+}
+
+CSR_API(SrvGetLargestConsoleWindowSize)
+{
+ NTSTATUS Status;
+ PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+ PCONSOLE Console;
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ GetLargestWindowSizeRequest->OutputHandle,
+ &Buff,
+ GENERIC_READ,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+ ConioGetLargestConsoleWindowSize(Console, &GetLargestWindowSizeRequest->Size);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvShowConsoleCursor)
+{
+ NTSTATUS Status;
+ PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
+ PCONSOLE Console;
+ PCONSOLE_SCREEN_BUFFER Buff;
+
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ ShowCursorRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ ShowCursorRequest->RefCount = ConioShowMouseCursor(Console, ShowCursorRequest->Show);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleCursor)
+{
+ NTSTATUS Status;
+ BOOL Success;
+ PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
+ PCONSOLE Console;
+ PCONSOLE_SCREEN_BUFFER Buff;
+
+ // FIXME: Tests show that this function is used only for graphics screen buffers
+ // and otherwise it returns false + set last error to invalid handle.
+ // NOTE: I find that behaviour is ridiculous but ok, let's accept that at the moment...
+ Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ SetCursorRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ Success = ConioSetMouseCursor(Console, SetCursorRequest->hCursor);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+}
+
+CSR_API(SrvConsoleMenuControl)
+{
+ NTSTATUS Status;
+ PCONSOLE_MENUCONTROL MenuControlRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.MenuControlRequest;
+ PCONSOLE Console;
+ PCONSOLE_SCREEN_BUFFER Buff;
+
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ MenuControlRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Console = Buff->Header.Console;
+
+ MenuControlRequest->hMenu = ConioMenuControl(Console,
+ MenuControlRequest->dwCmdIdLow,
+ MenuControlRequest->dwCmdIdHigh);
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleMenuClose)
+{
+ NTSTATUS Status;
+ BOOL Success;
+ PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetMenuCloseRequest;
+ PCONSOLE Console;
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Success = ConioSetMenuClose(Console, SetMenuCloseRequest->Enable);
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+}
+
+CSR_API(SrvSetConsoleWindowInfo)
+{
+ NTSTATUS Status;
+ PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+ SMALL_RECT WindowRect = SetWindowInfoRequest->WindowRect;
+
+ DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
+ SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
+ WindowRect.Left, WindowRect.Top, WindowRect.Right, WindowRect.Bottom);
+
+ Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ SetWindowInfoRequest->OutputHandle,
+ &Buff,
+ GENERIC_READ,
+ TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ if (SetWindowInfoRequest->Absolute == FALSE)
+ {
+ /* Relative positions given. Transform them to absolute ones */
+ WindowRect.Left += Buff->ViewOrigin.X;
+ WindowRect.Top += Buff->ViewOrigin.Y;
+ WindowRect.Right += Buff->ViewOrigin.X + Buff->ViewSize.X - 1;
+ WindowRect.Bottom += Buff->ViewOrigin.Y + Buff->ViewSize.Y - 1;
+ }
+
+ /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
+ if ( (WindowRect.Left < 0) || (WindowRect.Top < 0) ||
+ (WindowRect.Right >= Buff->ScreenBufferSize.X) ||
+ (WindowRect.Bottom >= Buff->ScreenBufferSize.Y) ||
+ (WindowRect.Right <= WindowRect.Left) ||
+ (WindowRect.Bottom <= WindowRect.Top) )
+ {
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Buff->ViewOrigin.X = WindowRect.Left;
+ Buff->ViewOrigin.Y = WindowRect.Top;
+
+ Buff->ViewSize.X = WindowRect.Right - WindowRect.Left + 1;
+ Buff->ViewSize.Y = WindowRect.Bottom - WindowRect.Top + 1;
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvGetConsoleWindow)
+{
+ NTSTATUS Status;
+ PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
+ PCONSOLE Console;
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ GetWindowRequest->WindowHandle = ConioGetConsoleWindowHandle(Console);
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return STATUS_SUCCESS;
+}
+
+CSR_API(SrvSetConsoleIcon)
+{
+ NTSTATUS Status;
+ PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
+ PCONSOLE Console;
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Status = (ConioChangeIcon(Console, SetIconRequest->WindowIcon)
+ ? STATUS_SUCCESS
+ : STATUS_UNSUCCESSFUL);
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return Status;
+}
+
+CSR_API(SrvGetConsoleSelectionInfo)
+{
+ NTSTATUS Status;
+ PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
+ PCONSOLE Console;
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ memset(&GetSelectionInfoRequest->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
+ if (Console->Selection.dwFlags != 0)
+ GetSelectionInfoRequest->Info = Console->Selection;
+ ConSrvReleaseConsole(Console, TRUE);
+ }
+
+ return Status;
+}
+
+/* EOF */
/* INCLUDES *******************************************************************/
+#define COBJMACROS
+#define NONAMELESSUNION
+
#include "consrv.h"
#include "include/conio.h"
#include "include/console.h"
#include "include/settings.h"
+#include "conoutput.h"
#include "guiterm.h"
#include "guisettings.h"
#include "resource.h"
#include <windowsx.h>
+#include <shlwapi.h>
+#include <shlobj.h>
+
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
+typedef struct _GUI_INIT_INFO
+{
+ PCONSOLE_INFO ConsoleInfo;
+ PCONSOLE_START_INFO ConsoleStartInfo;
+ ULONG ProcessId;
+} GUI_INIT_INFO, *PGUI_INIT_INFO;
+
/**************************************************************\
\** Define the Console Leader Process for the console window **/
#define GWLP_CONSOLEWND_ALLOC (2 * sizeof(LONG_PTR))
static VOID
GuiConsoleUpdateSelection(PCONSOLE Console, PCOORD coord);
static VOID WINAPI
-GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region);
+GuiDrawRegion(IN OUT PFRONTEND This, SMALL_RECT* Region);
static VOID
GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData);
PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER ActiveBuffer;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
Ret = FALSE;
goto Quit;
}
- ActiveBuffer = Console->ActiveBuffer;
+ ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
/*
* In case the selected menu item belongs to the user-reserved menu id range,
GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData)
{
PCONSOLE Console = GuiData->Console;
- PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+ PCONSOLE_SCREEN_BUFFER Buff = ConDrvGetActiveScreenBuffer(Console);
SCROLLINFO sInfo;
DWORD Width, Height;
PCONSOLE Console = GuiData->Console;
// DEVMODE dmScreenSettings;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
/* Switch to full-screen or to windowed mode */
GuiData->GuiInfo.FullScreen = !GuiData->GuiInfo.FullScreen;
SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
{
PCONSOLE Console = GuiData->Console;
- PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+ PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
UINT WidthUnit, HeightUnit;
if (GetType(Buffer) == TEXTMODE_BUFFER)
HDC hDC;
PAINTSTRUCT ps;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
Success = FALSE;
goto Quit;
}
- ActiveBuffer = Console->ActiveBuffer;
+ ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
hDC = BeginPaint(GuiData->hWindow, &ps);
if (hDC != NULL &&
PCONSOLE Console = GuiData->Console;
PCONSOLE_SCREEN_BUFFER ActiveBuffer;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
- ActiveBuffer = Console->ActiveBuffer;
+ ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
if (Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS)
{
}
static VOID
-GuiInvalidateCell(PCONSOLE Console, SHORT x, SHORT y)
+GuiInvalidateCell(IN OUT PFRONTEND This, SHORT x, SHORT y)
{
SMALL_RECT CellRect = { x, y, x, y };
- GuiDrawRegion(Console, &CellRect);
+ GuiDrawRegion(This, &CellRect);
}
static VOID
SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
- Buff = Console->ActiveBuffer;
+ Buff = ConDrvGetActiveScreenBuffer(Console);
if (GetType(Buff) == TEXTMODE_BUFFER)
{
- GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+ GuiInvalidateCell(&Console->TermIFace, Buff->CursorPosition.X, Buff->CursorPosition.Y);
Buff->CursorBlinkOn = !Buff->CursorBlinkOn;
if ((GuiData->OldCursor.x != Buff->CursorPosition.X) || (GuiData->OldCursor.y != Buff->CursorPosition.Y))
LeaveCriticalSection(&Console->Lock);
}
-static VOID
+static BOOL
GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData)
{
PCONSOLE Console = GuiData->Console;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ return TRUE;
+
+ // TODO: Prompt for termination ? (Warn the user about possible apps running in this console)
/*
* FIXME: Windows will wait up to 5 seconds for the thread to exit.
* We shouldn't wait here, though, since the console lock is entered.
* A copy of the thread list probably needs to be made.
*/
- ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
+ ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
LeaveCriticalSection(&Console->Lock);
+ return FALSE;
}
static LRESULT
GuiConsoleHandleNcDestroy(HWND hWnd)
{
- // PGUI_CONSOLE_DATA GuiData;
-
KillTimer(hWnd, CONGUI_UPDATE_TIMER);
GetSystemMenu(hWnd, TRUE);
/* Free the GuiData registration */
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (DWORD_PTR)NULL);
- // GuiData->hWindow = NULL;
- // return 0;
return DefWindowProcW(hWnd, WM_NCDESTROY, 0, 0);
}
PointToCoord(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
{
PCONSOLE Console = GuiData->Console;
- PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+ PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
COORD Coord;
UINT WidthUnit, HeightUnit;
goto Quit;
}
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
Err = TRUE;
goto Quit;
if (OpenClipboard(GuiData->hWindow) == TRUE)
{
PCONSOLE Console = GuiData->Console;
- PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+ PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
if (GetType(Buffer) == TEXTMODE_BUFFER)
{
if (OpenClipboard(GuiData->hWindow) == TRUE)
{
PCONSOLE Console = GuiData->Console;
- PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
+ PCONSOLE_SCREEN_BUFFER Buffer = ConDrvGetActiveScreenBuffer(Console);
if (GetType(Buffer) == TEXTMODE_BUFFER)
{
DWORD windx, windy;
UINT WidthUnit, HeightUnit;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
- ActiveBuffer = Console->ActiveBuffer;
+ ActiveBuffer = ConDrvGetActiveScreenBuffer(Console);
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
{
{
PCONSOLE Console = GuiData->Console;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
if ((GuiData->WindowSizeLock == FALSE) &&
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
{
- PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+ PCONSOLE_SCREEN_BUFFER Buff = ConDrvGetActiveScreenBuffer(Console);
DWORD windx, windy, charx, chary;
UINT WidthUnit, HeightUnit;
int old_pos, Maximum;
PSHORT pShowXY;
- if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
+ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
- Buff = Console->ActiveBuffer;
+ Buff = ConDrvGetActiveScreenBuffer(Console);
if (uMsg == WM_HSCROLL)
{
* If there is no data, just go away.
*/
GuiData = GuiGetGuiData(hWnd);
- if (GuiData == NULL) return 0;
+ if (GuiData == NULL) return DefWindowProcW(hWnd, msg, wParam, lParam);
/*
* Just retrieve a pointer to the console in case somebody needs it.
}
case WM_CLOSE:
- GuiConsoleHandleClose(GuiData);
+ if (GuiConsoleHandleClose(GuiData)) goto Default;
break;
case WM_PAINT:
IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
}
- if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
GuiSendMenuEvent(Console, WM_INITMENU);
LeaveCriticalSection(&Console->Lock);
{
if (HIWORD(wParam) == 0xFFFF) // Allow all the menu flags
{
- if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
GuiSendMenuEvent(Console, WM_MENUSELECT);
LeaveCriticalSection(&Console->Lock);
case WM_SETFOCUS:
case WM_KILLFOCUS:
{
- if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
INPUT_RECORD er;
er.EventType = FOCUS_EVENT;
case PM_APPLY_CONSOLE_INFO:
{
- if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
{
GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
LeaveCriticalSection(&Console->Lock);
******************************************************************************/
static VOID WINAPI
-GuiCleanupConsole(PCONSOLE Console)
+GuiDeinitFrontEnd(IN OUT PFRONTEND This);
+
+NTSTATUS NTAPI
+GuiInitFrontEnd(IN OUT PFRONTEND This,
+ IN PCONSOLE Console)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_INIT_INFO GuiInitInfo;
+ PCONSOLE_INFO ConsoleInfo;
+ PCONSOLE_START_INFO ConsoleStartInfo;
+
+ PGUI_CONSOLE_DATA GuiData;
+ GUI_CONSOLE_INFO TermInfo;
+
+ SIZE_T Length = 0;
+ LPWSTR IconPath = NULL;
+ INT IconIndex = 0;
+
+ if (This == NULL || Console == NULL || This->OldData == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ ASSERT(This->Console == Console);
+
+ GuiInitInfo = This->OldData;
+
+ if (GuiInitInfo->ConsoleInfo == NULL || GuiInitInfo->ConsoleStartInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ ConsoleInfo = GuiInitInfo->ConsoleInfo;
+ ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
+
+ IconPath = ConsoleStartInfo->IconPath;
+ IconIndex = ConsoleStartInfo->IconIndex;
+
+
+ /* Terminal data allocation */
+ GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
+ if (!GuiData)
+ {
+ DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ /* HACK */ Console->TermIFace.Data = (PVOID)GuiData; /* HACK */
+ GuiData->Console = Console;
+ GuiData->hWindow = NULL;
+
+ /* The console can be resized */
+ Console->FixedSize = FALSE;
+
+ InitializeCriticalSection(&GuiData->Lock);
+
+
+ /*
+ * Load terminal settings
+ */
+
+ /* 1. Load the default settings */
+ GuiConsoleGetDefaultSettings(&TermInfo, GuiInitInfo->ProcessId);
+
+ /* 3. Load the remaining console settings via the registry. */
+ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ {
+ /* Load the terminal infos from the registry. */
+ GuiConsoleReadUserSettings(&TermInfo,
+ ConsoleInfo->ConsoleTitle,
+ GuiInitInfo->ProcessId);
+
+ /*
+ * Now, update them with the properties the user might gave to us
+ * via the STARTUPINFO structure before calling CreateProcess
+ * (and which was transmitted via the ConsoleStartInfo structure).
+ * We therefore overwrite the values read in the registry.
+ */
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
+ {
+ TermInfo.ShowWindow = ConsoleStartInfo->ShowWindow;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
+ {
+ TermInfo.AutoPosition = FALSE;
+ TermInfo.WindowOrigin = ConsoleStartInfo->ConsoleWindowOrigin;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+ {
+ TermInfo.FullScreen = TRUE;
+ }
+ }
+
+
+ /*
+ * Set up GUI data
+ */
+
+ Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
+ wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE);
+ GuiData->GuiInfo.FaceName[Length] = L'\0';
+ GuiData->GuiInfo.FontFamily = TermInfo.FontFamily;
+ GuiData->GuiInfo.FontSize = TermInfo.FontSize;
+ GuiData->GuiInfo.FontWeight = TermInfo.FontWeight;
+ GuiData->GuiInfo.UseRasterFonts = TermInfo.UseRasterFonts;
+ GuiData->GuiInfo.FullScreen = TermInfo.FullScreen;
+ GuiData->GuiInfo.ShowWindow = TermInfo.ShowWindow;
+ GuiData->GuiInfo.AutoPosition = TermInfo.AutoPosition;
+ GuiData->GuiInfo.WindowOrigin = TermInfo.WindowOrigin;
+
+ /* Initialize the icon handles to their default values */
+ GuiData->hIcon = ghDefaultIcon;
+ GuiData->hIconSm = ghDefaultIconSm;
+
+ /* Get the associated icon, if any */
+ if (IconPath == NULL || IconPath[0] == L'\0')
+ {
+ IconPath = ConsoleStartInfo->AppPath;
+ IconIndex = 0;
+ }
+ DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
+ if (IconPath && IconPath[0] != L'\0')
+ {
+ HICON hIcon = NULL, hIconSm = NULL;
+ PrivateExtractIconExW(IconPath,
+ IconIndex,
+ &hIcon,
+ &hIconSm,
+ 1);
+ DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
+ if (hIcon != NULL)
+ {
+ DPRINT("Effectively set the icons\n");
+ GuiData->hIcon = hIcon;
+ GuiData->hIconSm = hIconSm;
+ }
+ }
+
+ /* Mouse is shown by default with its default cursor shape */
+ GuiData->hCursor = ghDefaultCursor;
+ GuiData->MouseCursorRefCount = 0;
+
+ /* A priori don't ignore mouse signals */
+ GuiData->IgnoreNextMouseSignal = FALSE;
+
+ /* Close button and the corresponding system menu item are enabled by default */
+ GuiData->IsCloseButtonEnabled = TRUE;
+
+ /* There is no user-reserved menu id range by default */
+ GuiData->cmdIdLow = GuiData->cmdIdHigh = 0;
+
+ /*
+ * We need to wait until the GUI has been fully initialized
+ * to retrieve custom settings i.e. WindowSize etc...
+ * Ideally we could use SendNotifyMessage for this but its not
+ * yet implemented.
+ */
+ GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+ DPRINT("GUI - Checkpoint\n");
+
+ /* Create the terminal window */
+ PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
+
+ /* Wait until initialization has finished */
+ WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
+ DPRINT("OK we created the console window\n");
+ CloseHandle(GuiData->hGuiInitEvent);
+ GuiData->hGuiInitEvent = NULL;
+
+ /* Check whether we really succeeded in initializing the terminal window */
+ if (GuiData->hWindow == NULL)
+ {
+ DPRINT("GuiInitConsole - We failed at creating a new terminal window\n");
+ GuiDeinitFrontEnd(This);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Finally, finish to initialize the frontend structure */
+ This->Data = GuiData;
+ if (This->OldData) ConsoleFreeHeap(This->OldData);
+ This->OldData = NULL;
+
+ return STATUS_SUCCESS;
+}
+
+static VOID WINAPI
+GuiDeinitFrontEnd(IN OUT PFRONTEND This)
+{
+ PGUI_CONSOLE_DATA GuiData = This->Data;
SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
DestroyIcon(GuiData->hIconSm);
}
- Console->TermIFace.Data = NULL;
+ This->Data = NULL;
DeleteCriticalSection(&GuiData->Lock);
ConsoleFreeHeap(GuiData);
- DPRINT("Quit GuiCleanupConsole\n");
+ DPRINT("Quit GuiDeinitFrontEnd\n");
}
static VOID WINAPI
-GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
+GuiDrawRegion(IN OUT PFRONTEND This,
+ SMALL_RECT* Region)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
RECT RegionRect;
SmallRectToRect(GuiData, &RegionRect, Region);
}
static VOID WINAPI
-GuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
- UINT ScrolledLines, PWCHAR Buffer, UINT Length)
+GuiWriteStream(IN OUT PFRONTEND This,
+ SMALL_RECT* Region,
+ SHORT CursorStartX,
+ SHORT CursorStartY,
+ UINT ScrolledLines,
+ PWCHAR Buffer,
+ UINT Length)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
- PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
+ PCONSOLE_SCREEN_BUFFER Buff;
SHORT CursorEndX, CursorEndY;
RECT ScrollRect;
if (NULL == GuiData || NULL == GuiData->hWindow) return;
+
+ Buff = ConDrvGetActiveScreenBuffer(GuiData->Console);
if (GetType(Buff) != TEXTMODE_BUFFER) return;
if (0 != ScrolledLines)
SW_INVALIDATE);
}
- GuiDrawRegion(Console, Region);
+ GuiDrawRegion(This, Region);
if (CursorStartX < Region->Left || Region->Right < CursorStartX
|| CursorStartY < Region->Top || Region->Bottom < CursorStartY)
{
- GuiInvalidateCell(Console, CursorStartX, CursorStartY);
+ GuiInvalidateCell(This, CursorStartX, CursorStartY);
}
CursorEndX = Buff->CursorPosition.X;
|| CursorEndY < Region->Top || Region->Bottom < CursorEndY)
&& (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
{
- GuiInvalidateCell(Console, CursorEndX, CursorEndY);
+ GuiInvalidateCell(This, CursorEndX, CursorEndY);
}
// Set up the update timer (very short interval) - this is a "hack" for getting the OS to
}
static BOOL WINAPI
-GuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
+GuiSetCursorInfo(IN OUT PFRONTEND This,
+ PCONSOLE_SCREEN_BUFFER Buff)
{
- if (Console->ActiveBuffer == Buff)
+ PGUI_CONSOLE_DATA GuiData = This->Data;
+
+ if (ConDrvGetActiveScreenBuffer(GuiData->Console) == Buff)
{
- GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+ GuiInvalidateCell(This, Buff->CursorPosition.X, Buff->CursorPosition.Y);
}
return TRUE;
}
static BOOL WINAPI
-GuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, SHORT OldCursorX, SHORT OldCursorY)
+GuiSetScreenInfo(IN OUT PFRONTEND This,
+ PCONSOLE_SCREEN_BUFFER Buff,
+ SHORT OldCursorX,
+ SHORT OldCursorY)
{
- if (Console->ActiveBuffer == Buff)
+ PGUI_CONSOLE_DATA GuiData = This->Data;
+
+ if (ConDrvGetActiveScreenBuffer(GuiData->Console) == Buff)
{
/* Redraw char at old position (remove cursor) */
- GuiInvalidateCell(Console, OldCursorX, OldCursorY);
+ GuiInvalidateCell(This, OldCursorX, OldCursorY);
/* Redraw char at new position (show cursor) */
- GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
+ GuiInvalidateCell(This, Buff->CursorPosition.X, Buff->CursorPosition.Y);
}
return TRUE;
}
static VOID WINAPI
-GuiResizeTerminal(PCONSOLE Console)
+GuiResizeTerminal(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
/* Resize the window to the user's values */
// GuiData->WindowSizeLock = TRUE;
}
static BOOL WINAPI
-GuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down)
+GuiProcessKeyCallback(IN OUT PFRONTEND This,
+ MSG* msg,
+ BYTE KeyStateMenu,
+ DWORD ShiftState,
+ UINT VirtualKeyCode,
+ BOOL Down)
{
if ((ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) || KeyStateMenu & 0x80) &&
(VirtualKeyCode == VK_ESCAPE || VirtualKeyCode == VK_TAB || VirtualKeyCode == VK_SPACE))
}
static BOOL WINAPI
-GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor);
+GuiSetMouseCursor(IN OUT PFRONTEND This,
+ HCURSOR hCursor);
static VOID WINAPI
-GuiRefreshInternalInfo(PCONSOLE Console)
+GuiRefreshInternalInfo(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
/* Update the console leader information held by the window */
SetConsoleWndConsoleLeaderCID(GuiData);
/* Mouse is shown by default with its default cursor shape */
GuiData->MouseCursorRefCount = 0; // Reinitialize the reference counter
- GuiSetMouseCursor(Console, NULL);
+ GuiSetMouseCursor(This, NULL);
}
static VOID WINAPI
-GuiChangeTitle(PCONSOLE Console)
+GuiChangeTitle(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
// PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
- SetWindowText(GuiData->hWindow, Console->Title.Buffer);
+ SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
}
static BOOL WINAPI
-GuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
+GuiChangeIcon(IN OUT PFRONTEND This,
+ HICON hWindowIcon)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
HICON hIcon, hIconSm;
if (hWindowIcon == NULL)
}
static HWND WINAPI
-GuiGetConsoleWindowHandle(PCONSOLE Console)
+GuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
return GuiData->hWindow;
}
static VOID WINAPI
-GuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
+GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
+ PCOORD pSize)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer;
RECT WorkArea;
LONG width, height;
UINT WidthUnit, HeightUnit;
return;
}
- if (Console->ActiveBuffer)
+ ActiveBuffer = ConDrvGetActiveScreenBuffer(GuiData->Console);
+ if (ActiveBuffer)
{
- if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
+ if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
{
WidthUnit = GuiData->CharWidth ;
HeightUnit = GuiData->CharHeight;
}
- else /* if (GetType(Console->ActiveBuffer) == GRAPHICS_BUFFER) */
+ else /* if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) */
{
WidthUnit = 1;
HeightUnit = 1;
}
static ULONG WINAPI
-GuiGetDisplayMode(PCONSOLE Console)
+GuiGetDisplayMode(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
ULONG DisplayMode = 0;
if (GuiData->GuiInfo.FullScreen)
}
static BOOL WINAPI
-GuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
+GuiSetDisplayMode(IN OUT PFRONTEND This,
+ ULONG NewMode)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
return FALSE;
}
static INT WINAPI
-GuiShowMouseCursor(PCONSOLE Console, BOOL Show)
+GuiShowMouseCursor(IN OUT PFRONTEND This,
+ BOOL Show)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
/* Set the reference count */
if (Show) ++GuiData->MouseCursorRefCount;
}
static BOOL WINAPI
-GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
+GuiSetMouseCursor(IN OUT PFRONTEND This,
+ HCURSOR hCursor)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
/*
* Set the cursor's handle. If the given handle is NULL,
}
static HMENU WINAPI
-GuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
+GuiMenuControl(IN OUT PFRONTEND This,
+ UINT cmdIdLow,
+ UINT cmdIdHigh)
{
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
GuiData->cmdIdLow = cmdIdLow ;
GuiData->cmdIdHigh = cmdIdHigh;
}
static BOOL WINAPI
-GuiSetMenuClose(PCONSOLE Console, BOOL Enable)
+GuiSetMenuClose(IN OUT PFRONTEND This,
+ BOOL Enable)
{
/*
* NOTE: See http://www.mail-archive.com/harbour@harbour-project.org/msg27509.html
* for more information.
*/
- PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
+ PGUI_CONSOLE_DATA GuiData = This->Data;
HMENU hSysMenu = GetSystemMenu(GuiData->hWindow, FALSE);
if (hSysMenu == NULL) return FALSE;
static FRONTEND_VTBL GuiVtbl =
{
- GuiCleanupConsole,
+ GuiInitFrontEnd,
+ GuiDeinitFrontEnd,
GuiDrawRegion,
GuiWriteStream,
GuiSetCursorInfo,
GuiSetMenuClose,
};
-NTSTATUS FASTCALL
-GuiInitConsole(PCONSOLE Console,
- /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
- PCONSOLE_INFO ConsoleInfo,
- DWORD ProcessId,
- LPCWSTR IconPath,
- INT IconIndex)
+
+static BOOL
+LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+ IN OUT PCONSOLE_INFO ConsoleInfo)
{
- PGUI_CONSOLE_DATA GuiData;
- GUI_CONSOLE_INFO TermInfo;
- SIZE_T Length = 0;
+#define PATH_SEPARATOR L'\\'
- if (Console == NULL || ConsoleInfo == NULL)
- return STATUS_INVALID_PARAMETER;
+ BOOL RetVal = FALSE;
+ HRESULT hRes = S_OK;
+ LPWSTR LinkName = NULL;
+ SIZE_T Length = 0;
- /* Initialize the GUI terminal emulator */
- if (!GuiInit()) return STATUS_UNSUCCESSFUL;
+ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ return FALSE;
- /* Initialize the console */
- Console->TermIFace.Vtbl = &GuiVtbl;
+ ConsoleStartInfo->IconPath[0] = L'\0';
+ ConsoleStartInfo->IconIndex = 0;
- GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
- if (!GuiData)
+ /* 1- Find the last path separator if any */
+ LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
+ if (LinkName == NULL)
{
- DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
- return STATUS_UNSUCCESSFUL;
+ LinkName = ConsoleStartInfo->ConsoleTitle;
}
- Console->TermIFace.Data = (PVOID)GuiData;
- GuiData->Console = Console;
- GuiData->hWindow = NULL;
-
- /* The console can be resized */
- Console->FixedSize = FALSE;
-
- InitializeCriticalSection(&GuiData->Lock);
-
-
- /*
- * Load the terminal settings
- */
-
- /***********************************************
- * Adapted from ConSrvInitConsole in console.c *
- ***********************************************/
-
- /* 1. Load the default settings */
- GuiConsoleGetDefaultSettings(&TermInfo, ProcessId);
-
- /* 2. Load the remaining console settings via the registry. */
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ else
{
- /* Load the terminal infos from the registry. */
- GuiConsoleReadUserSettings(&TermInfo, ConsoleInfo->ConsoleTitle, ProcessId);
+ /* Skip the path separator */
+ ++LinkName;
+ }
- /*
- * Now, update them with the properties the user might gave to us
- * via the STARTUPINFO structure before calling CreateProcess
- * (and which was transmitted via the ConsoleStartInfo structure).
- * We therefore overwrite the values read in the registry.
- */
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
- {
- TermInfo.ShowWindow = ConsoleStartInfo->ShowWindow;
- }
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
- {
- TermInfo.AutoPosition = FALSE;
- TermInfo.WindowOrigin = ConsoleStartInfo->ConsoleWindowOrigin;
- }
- if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+ /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
+ Length = wcslen(LinkName);
+ if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
+ return FALSE;
+
+ /* 3- It may be a link. Try to retrieve some properties */
+ hRes = CoInitialize(NULL);
+ if (SUCCEEDED(hRes))
+ {
+ /* Get a pointer to the IShellLink interface */
+ IShellLinkW* pshl = NULL;
+ hRes = CoCreateInstance(&CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ &IID_IShellLinkW,
+ (LPVOID*)&pshl);
+ if (SUCCEEDED(hRes))
{
- TermInfo.FullScreen = TRUE;
+ /* Get a pointer to the IPersistFile interface */
+ IPersistFile* ppf = NULL;
+ hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
+ if (SUCCEEDED(hRes))
+ {
+ /* Load the shortcut */
+ hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
+ if (SUCCEEDED(hRes))
+ {
+ /*
+ * Finally we can get the properties !
+ * Update the old ones if needed.
+ */
+ INT ShowCmd = 0;
+ // WORD HotKey = 0;
+
+ /* Reset the name of the console with the name of the shortcut */
+ Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
+ sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
+ wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
+ ConsoleInfo->ConsoleTitle[Length] = L'\0';
+
+ /* Get the window showing command */
+ hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
+ if (SUCCEEDED(hRes)) ConsoleStartInfo->ShowWindow = (WORD)ShowCmd;
+
+ /* Get the hotkey */
+ // hRes = pshl->GetHotkey(&ShowCmd);
+ // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
+
+ /* Get the icon location, if any */
+
+ hRes = IShellLinkW_GetIconLocation(pshl,
+ ConsoleStartInfo->IconPath,
+ sizeof(ConsoleStartInfo->IconPath)/sizeof(ConsoleStartInfo->IconPath[0]) - 1, // == MAX_PATH
+ &ConsoleStartInfo->IconIndex);
+ if (!SUCCEEDED(hRes))
+ {
+ ConsoleStartInfo->IconPath[0] = L'\0';
+ ConsoleStartInfo->IconIndex = 0;
+ }
+
+ // FIXME: Since we still don't load console properties from the shortcut,
+ // return false. When this will be done, we will return true instead.
+ RetVal = FALSE;
+ }
+ IPersistFile_Release(ppf);
+ }
+ IShellLinkW_Release(pshl);
}
}
+ CoUninitialize();
+ return RetVal;
+}
- /*
- * Set up the GUI data
- */
+NTSTATUS NTAPI
+GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+ IN OUT PCONSOLE_INFO ConsoleInfo,
+ IN OUT PVOID ExtraConsoleInfo,
+ IN ULONG ProcessId)
+{
+ PCONSOLE_START_INFO ConsoleStartInfo = ExtraConsoleInfo;
+ PGUI_INIT_INFO GuiInitInfo;
- Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
- wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE);
- GuiData->GuiInfo.FaceName[Length] = L'\0';
- GuiData->GuiInfo.FontFamily = TermInfo.FontFamily;
- GuiData->GuiInfo.FontSize = TermInfo.FontSize;
- GuiData->GuiInfo.FontWeight = TermInfo.FontWeight;
- GuiData->GuiInfo.UseRasterFonts = TermInfo.UseRasterFonts;
- GuiData->GuiInfo.FullScreen = TermInfo.FullScreen;
- GuiData->GuiInfo.ShowWindow = TermInfo.ShowWindow;
- GuiData->GuiInfo.AutoPosition = TermInfo.AutoPosition;
- GuiData->GuiInfo.WindowOrigin = TermInfo.WindowOrigin;
+ if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
- /* Initialize the icon handles to their default values */
- GuiData->hIcon = ghDefaultIcon;
- GuiData->hIconSm = ghDefaultIconSm;
+ /* Initialize GUI terminal emulator common functionalities */
+ if (!GuiInit()) return STATUS_UNSUCCESSFUL;
- /* Get the associated icon, if any */
- if (IconPath == NULL || *IconPath == L'\0')
- {
- IconPath = ConsoleStartInfo->AppPath;
- IconIndex = 0;
- }
- DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
- if (IconPath)
+ /*
+ * Load per-application terminal settings.
+ *
+ * Check whether the process creating the console was launched via
+ * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
+ * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
+ */
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
{
- HICON hIcon = NULL, hIconSm = NULL;
- PrivateExtractIconExW(IconPath,
- IconIndex,
- &hIcon,
- &hIconSm,
- 1);
- DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
- if (hIcon != NULL)
+ if (!LoadShellLinkConsoleInfo(ConsoleStartInfo, ConsoleInfo))
{
- DPRINT("Effectively set the icons\n");
- GuiData->hIcon = hIcon;
- GuiData->hIconSm = hIconSm;
+ ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
}
}
- /* Mouse is shown by default with its default cursor shape */
- GuiData->hCursor = ghDefaultCursor;
- GuiData->MouseCursorRefCount = 0;
-
- /* A priori don't ignore mouse signals */
- GuiData->IgnoreNextMouseSignal = FALSE;
-
- /* Close button and the corresponding system menu item are enabled by default */
- GuiData->IsCloseButtonEnabled = TRUE;
-
- /* There is no user-reserved menu id range by default */
- GuiData->cmdIdLow = GuiData->cmdIdHigh = 0;
-
/*
- * We need to wait until the GUI has been fully initialized
- * to retrieve custom settings i.e. WindowSize etc...
- * Ideally we could use SendNotifyMessage for this but its not
- * yet implemented.
+ * Initialize a private initialization info structure for later use.
+ * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
*/
- GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+ GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_INIT_INFO));
+ if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
- /* Create the terminal window */
- PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
+ // HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
+ GuiInitInfo->ConsoleInfo = ConsoleInfo;
+ GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo;
+ GuiInitInfo->ProcessId = ProcessId;
- /* Wait until initialization has finished */
- WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
- DPRINT("OK we created the console window\n");
- CloseHandle(GuiData->hGuiInitEvent);
- GuiData->hGuiInitEvent = NULL;
+ /* Finally, initialize the frontend structure */
+ FrontEnd->Vtbl = &GuiVtbl;
+ FrontEnd->Data = NULL;
+ FrontEnd->OldData = GuiInitInfo;
- /* Check whether we really succeeded in initializing the terminal window */
- if (GuiData->hWindow == NULL)
- {
- DPRINT("GuiInitConsole - We failed at creating a new terminal window\n");
- // ConioCleanupConsole(Console);
- GuiCleanupConsole(Console);
- return STATUS_UNSUCCESSFUL;
- }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
+{
+ if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
+
+ if (FrontEnd->Data) GuiDeinitFrontEnd(FrontEnd);
+ if (FrontEnd->OldData) ConsoleFreeHeap(FrontEnd->OldData);
return STATUS_SUCCESS;
}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/consrv/frontends/input.c
+ * PURPOSE: Common Front-Ends Input functions
+ * PROGRAMMERS: Jeffrey Morlan
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "coninput.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static DWORD FASTCALL
+ConioGetShiftState(PBYTE KeyState, LPARAM lParam)
+{
+ DWORD ssOut = 0;
+
+ if (KeyState[VK_CAPITAL] & 0x01)
+ ssOut |= CAPSLOCK_ON;
+
+ if (KeyState[VK_NUMLOCK] & 0x01)
+ ssOut |= NUMLOCK_ON;
+
+ if (KeyState[VK_SCROLL] & 0x01)
+ ssOut |= SCROLLLOCK_ON;
+
+ if (KeyState[VK_SHIFT] & 0x80)
+ ssOut |= SHIFT_PRESSED;
+
+ if (KeyState[VK_LCONTROL] & 0x80)
+ ssOut |= LEFT_CTRL_PRESSED;
+ if (KeyState[VK_RCONTROL] & 0x80)
+ ssOut |= RIGHT_CTRL_PRESSED;
+
+ if (KeyState[VK_LMENU] & 0x80)
+ ssOut |= LEFT_ALT_PRESSED;
+ if (KeyState[VK_RMENU] & 0x80)
+ ssOut |= RIGHT_ALT_PRESSED;
+
+ /* See WM_CHAR MSDN documentation for instance */
+ if (lParam & 0x01000000)
+ ssOut |= ENHANCED_KEY;
+
+ return ssOut;
+}
+
+VOID WINAPI
+ConioProcessKey(PCONSOLE Console, MSG* msg)
+{
+ static BYTE KeyState[256] = { 0 };
+ /* MSDN mentions that you should use the last virtual key code received
+ * when putting a virtual key identity to a WM_CHAR message since multiple
+ * or translated keys may be involved. */
+ static UINT LastVirtualKey = 0;
+ DWORD ShiftState;
+ WCHAR UnicodeChar;
+ UINT VirtualKeyCode;
+ UINT VirtualScanCode;
+ BOOL Down = FALSE;
+ BOOLEAN Fake; // synthesized, not a real event
+ BOOLEAN NotChar; // message should not be used to return a character
+
+ if (NULL == Console)
+ {
+ DPRINT1("No Active Console!\n");
+ return;
+ }
+
+ VirtualScanCode = HIWORD(msg->lParam) & 0xFF;
+ Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
+ msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
+
+ GetKeyboardState(KeyState);
+ ShiftState = ConioGetShiftState(KeyState, msg->lParam);
+
+ if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
+ {
+ VirtualKeyCode = LastVirtualKey;
+ UnicodeChar = msg->wParam;
+ }
+ else
+ {
+ WCHAR Chars[2];
+ INT RetChars = 0;
+
+ VirtualKeyCode = msg->wParam;
+ RetChars = ToUnicodeEx(VirtualKeyCode,
+ VirtualScanCode,
+ KeyState,
+ Chars,
+ 2,
+ 0,
+ NULL);
+ UnicodeChar = (1 == RetChars ? Chars[0] : 0);
+ }
+
+ if (ConioProcessKeyCallback(Console,
+ msg,
+ KeyState[VK_MENU],
+ ShiftState,
+ VirtualKeyCode,
+ Down))
+ {
+ return;
+ }
+
+ Fake = UnicodeChar &&
+ (msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
+ msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
+ NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
+ if (NotChar) LastVirtualKey = msg->wParam;
+
+ DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
+ Down ? "down" : "up ",
+ (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
+ "char" : "key ",
+ Fake ? "fake" : "real",
+ NotChar ? "notc" : "char",
+ VirtualScanCode,
+ VirtualKeyCode,
+ (UnicodeChar >= L' ') ? UnicodeChar : L'.',
+ ShiftState);
+
+ if (Fake) return;
+
+ /* Send the key press to the console driver */
+ ConDrvProcessKey(Console,
+ Down,
+ VirtualKeyCode,
+ VirtualScanCode,
+ UnicodeChar,
+ ShiftState,
+ KeyState[VK_CONTROL]);
+}
+
+/* EOF */
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
+#ifdef TUITERM_COMPILE
+
#include "consrv.h"
#include "include/conio.h"
#include "include/console.h"
case WM_KEYUP:
case WM_SYSKEYUP:
{
- if (ConSrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
{
MSG Message;
Message.hwnd = hWnd;
case WM_ACTIVATE:
{
- if (ConSrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE))
{
if (LOWORD(wParam) != WA_INACTIVE)
{
******************************************************************************/
static VOID WINAPI
-TuiCleanupConsole(PCONSOLE Console)
+TuiDeinitFrontEnd(IN OUT PFRONTEND This /*,
+ IN PCONSOLE Console */);
+
+NTSTATUS NTAPI
+TuiInitFrontEnd(IN OUT PFRONTEND This,
+ IN PCONSOLE Console)
{
- PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data;
+ PTUI_CONSOLE_DATA TuiData;
+ HANDLE ThreadHandle;
+
+ if (This == NULL || Console == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ // if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
+ // return STATUS_INVALID_PARAMETER;
+
+ // /* Initialize the console */
+ // Console->TermIFace.Vtbl = &TuiVtbl;
+
+ TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
+ if (!TuiData)
+ {
+ DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ // Console->TermIFace.Data = (PVOID)TuiData;
+ TuiData->Console = Console;
+ TuiData->hWindow = NULL;
+
+ InitializeCriticalSection(&TuiData->Lock);
+
+ /*
+ * HACK: Resize the console since we don't support for now changing
+ * the console size when we display it with the hardware.
+ */
+ // Console->ConsoleSize = PhysicalConsoleSize;
+ // ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
+
+ // /* The console cannot be resized anymore */
+ // Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
+ // // ConioResizeTerminal(Console);
+
+ /*
+ * Contrary to what we do in the GUI front-end, here we create
+ * an input thread for each console. It will dispatch all the
+ * input messages to the proper console (on the GUI it is done
+ * via the default GUI dispatch thread).
+ */
+ ThreadHandle = CreateThread(NULL,
+ 0,
+ TuiConsoleThread,
+ (PVOID)TuiData,
+ 0,
+ NULL);
+ if (NULL == ThreadHandle)
+ {
+ DPRINT1("CONSRV: Unable to create console thread\n");
+ // TuiDeinitFrontEnd(Console);
+ TuiDeinitFrontEnd(This);
+ return STATUS_UNSUCCESSFUL;
+ }
+ CloseHandle(ThreadHandle);
+
+ /*
+ * Insert the newly created console in the list of virtual consoles
+ * and activate it (give it the focus).
+ */
+ EnterCriticalSection(&ActiveVirtConsLock);
+ InsertTailList(&VirtConsList, &TuiData->Entry);
+ ActiveConsole = TuiData;
+ LeaveCriticalSection(&ActiveVirtConsLock);
+
+ /* Finally, initialize the frontend structure */
+ This->Data = TuiData;
+ This->OldData = NULL;
+
+ return STATUS_SUCCESS;
+}
+
+static VOID WINAPI
+TuiDeinitFrontEnd(IN OUT PFRONTEND This)
+{
+ // PCONSOLE Console = This->Console;
+ PTUI_CONSOLE_DATA TuiData = This->Data; // Console->TermIFace.Data;
/* Close the notification window */
DestroyWindow(TuiData->hWindow);
/* Switch to the next console */
if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console);
- Console->TermIFace.Data = NULL;
+ // Console->TermIFace.Data = NULL;
+ This->Data = NULL;
DeleteCriticalSection(&TuiData->Lock);
ConsoleFreeHeap(TuiData);
}
static VOID WINAPI
-TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region)
+TuiDrawRegion(IN OUT PFRONTEND This,
+ SMALL_RECT* Region)
{
DWORD BytesReturned;
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
}
static VOID WINAPI
-TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY,
- UINT ScrolledLines, PWCHAR Buffer, UINT Length)
+TuiWriteStream(IN OUT PFRONTEND This,
+ SMALL_RECT* Region,
+ SHORT CursorStartX,
+ SHORT CursorStartY,
+ UINT ScrolledLines,
+ PWCHAR Buffer,
+ UINT Length)
{
PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer;
PCHAR NewBuffer;
}
static BOOL WINAPI
-TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff)
+TuiSetCursorInfo(IN OUT PFRONTEND This,
+ PCONSOLE_SCREEN_BUFFER Buff)
{
CONSOLE_CURSOR_INFO Info;
DWORD BytesReturned;
}
static BOOL WINAPI
-TuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, SHORT OldCursorX, SHORT OldCursorY)
+TuiSetScreenInfo(IN OUT PFRONTEND This,
+ PCONSOLE_SCREEN_BUFFER Buff,
+ SHORT OldCursorX,
+ SHORT OldCursorY)
{
CONSOLE_SCREEN_BUFFER_INFO Info;
DWORD BytesReturned;
}
static VOID WINAPI
-TuiResizeTerminal(PCONSOLE Console)
+TuiResizeTerminal(IN OUT PFRONTEND This)
{
}
static BOOL WINAPI
-TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down)
+TuiProcessKeyCallback(IN OUT PFRONTEND This,
+ MSG* msg,
+ BYTE KeyStateMenu,
+ DWORD ShiftState,
+ UINT VirtualKeyCode,
+ BOOL Down)
{
if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) &&
VK_TAB == VirtualKeyCode)
}
static VOID WINAPI
-TuiRefreshInternalInfo(PCONSOLE Console)
+TuiRefreshInternalInfo(IN OUT PFRONTEND This)
{
}
static VOID WINAPI
-TuiChangeTitle(PCONSOLE Console)
+TuiChangeTitle(IN OUT PFRONTEND This)
{
}
static BOOL WINAPI
-TuiChangeIcon(PCONSOLE Console, HICON hWindowIcon)
+TuiChangeIcon(IN OUT PFRONTEND This,
+ HICON hWindowIcon)
{
return TRUE;
}
static HWND WINAPI
-TuiGetConsoleWindowHandle(PCONSOLE Console)
+TuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
{
- PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data;
+ PTUI_CONSOLE_DATA TuiData = This->Data;
return TuiData->hWindow;
}
static VOID WINAPI
-TuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize)
+TuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
+ PCOORD pSize)
{
if (!pSize) return;
*pSize = PhysicalConsoleSize;
}
static ULONG WINAPI
-TuiGetDisplayMode(PCONSOLE Console)
+TuiGetDisplayMode(IN OUT PFRONTEND This)
{
return CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN;
}
static BOOL WINAPI
-TuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
+TuiSetDisplayMode(IN OUT PFRONTEND This,
+ ULONG NewMode)
{
// if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
// return FALSE;
}
static INT WINAPI
-TuiShowMouseCursor(PCONSOLE Console, BOOL Show)
+TuiShowMouseCursor(IN OUT PFRONTEND This,
+ BOOL Show)
{
return 0;
}
static BOOL WINAPI
-TuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
+TuiSetMouseCursor(IN OUT PFRONTEND This,
+ HCURSOR hCursor)
{
return TRUE;
}
static HMENU WINAPI
-TuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
+TuiMenuControl(IN OUT PFRONTEND This,
+ UINT cmdIdLow,
+ UINT cmdIdHigh)
{
return NULL;
}
static BOOL WINAPI
-TuiSetMenuClose(PCONSOLE Console, BOOL Enable)
+TuiSetMenuClose(IN OUT PFRONTEND This,
+ BOOL Enable)
{
return TRUE;
}
static FRONTEND_VTBL TuiVtbl =
{
- TuiCleanupConsole,
+ TuiInitFrontEnd,
+ TuiDeinitFrontEnd,
TuiDrawRegion,
TuiWriteStream,
TuiSetCursorInfo,
TuiSetMenuClose,
};
-NTSTATUS FASTCALL
-TuiInitConsole(PCONSOLE Console,
- /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
- PCONSOLE_INFO ConsoleInfo,
- DWORD ProcessId)
+// static BOOL
+// DtbgIsDesktopVisible(VOID)
+// {
+ // return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
+// }
+static BOOLEAN
+IsConsoleMode(VOID)
{
- PTUI_CONSOLE_DATA TuiData;
- HANDLE ThreadHandle;
+ return (BOOLEAN)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE);
+}
- if (Console == NULL || ConsoleInfo == NULL)
+NTSTATUS NTAPI
+TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+ IN OUT PCONSOLE_INFO ConsoleInfo,
+ IN OUT PVOID ExtraConsoleInfo,
+ IN ULONG ProcessId)
+{
+ if (FrontEnd == NULL || ConsoleInfo == NULL)
return STATUS_INVALID_PARAMETER;
- if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER)
- return STATUS_INVALID_PARAMETER;
+ /* We must be in console mode already */
+ if (!IsConsoleMode()) return STATUS_UNSUCCESSFUL;
/* Initialize the TUI terminal emulator */
- if (!TuiInit(Console->CodePage)) return STATUS_UNSUCCESSFUL;
-
- /* Initialize the console */
- Console->TermIFace.Vtbl = &TuiVtbl;
-
- TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA));
- if (!TuiData)
- {
- DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n");
- return STATUS_UNSUCCESSFUL;
- }
- Console->TermIFace.Data = (PVOID)TuiData;
- TuiData->Console = Console;
- TuiData->hWindow = NULL;
-
- InitializeCriticalSection(&TuiData->Lock);
-
- /*
- * HACK: Resize the console since we don't support for now changing
- * the console size when we display it with the hardware.
- */
- Console->ConsoleSize = PhysicalConsoleSize;
- ConioResizeBuffer(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), PhysicalConsoleSize);
+ if (!TuiInit(ConsoleInfo->CodePage)) return STATUS_UNSUCCESSFUL;
- /* The console cannot be resized anymore */
- Console->FixedSize = TRUE; // MUST be placed AFTER the call to ConioResizeBuffer !!
- // ConioResizeTerminal(Console);
+ /* Finally, initialize the frontend structure */
+ FrontEnd->Vtbl = &TuiVtbl;
+ FrontEnd->Data = NULL;
+ FrontEnd->OldData = NULL;
- /*
- * Contrary to what we do in the GUI front-end, here we create
- * an input thread for each console. It will dispatch all the
- * input messages to the proper console (on the GUI it is done
- * via the default GUI dispatch thread).
- */
- ThreadHandle = CreateThread(NULL,
- 0,
- TuiConsoleThread,
- (PVOID)TuiData,
- 0,
- NULL);
- if (NULL == ThreadHandle)
- {
- DPRINT1("CONSRV: Unable to create console thread\n");
- TuiCleanupConsole(Console);
- return STATUS_UNSUCCESSFUL;
- }
- CloseHandle(ThreadHandle);
+ return STATUS_SUCCESS;
+}
- /*
- * Insert the newly created console in the list of virtual consoles
- * and activate it (give it the focus).
- */
- EnterCriticalSection(&ActiveVirtConsLock);
- InsertTailList(&VirtConsList, &TuiData->Entry);
- ActiveConsole = TuiData;
- LeaveCriticalSection(&ActiveVirtConsLock);
+NTSTATUS NTAPI
+TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
+{
+ if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
+ if (FrontEnd->Data) TuiDeinitFrontEnd(FrontEnd);
return STATUS_SUCCESS;
}
+#endif
+
/* EOF */
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- if (ConSrvValidateConsole(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
+ if (ConDrvValidateConsole(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
{
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
ConSrvFreeHandlesTable(ProcessData);
/* Initialize a new Console owned by this process */
- Status = ConSrvInitConsole(&ProcessData->Console, ConsoleStartInfo, ProcessData->Process);
+ Status = ConSrvInitConsole(&ProcessData->Console,
+ ConsoleStartInfo,
+ HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
if (!NT_SUCCESS(Status))
{
DPRINT1("Console initialization failed\n");
NTSTATUS Status = STATUS_SUCCESS;
/* Validate and lock the console */
- if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
+ if (!ConDrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
{
// FIXME: Find another status code
return STATUS_UNSUCCESSFUL;
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
/* Validate and lock the console */
- if (ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
{
DPRINT("ConSrvRemoveConsole - Locking OK\n");
COORD OldScreenBufferSize; /* Old size of this screen buffer */
COORD OldViewSize; /* Old associated view size */
- COORD ViewOrigin; /* Beginning offset for the actual display area */
+ COORD ViewOrigin; /* Beginning offset for the actual display area */
/***** Put that VV in TEXTMODE_SCREEN_BUFFER ?? *****/
USHORT VirtualY; /* Top row of buffer being displayed, reported to callers */
USHORT Mode; /* Input buffer modes */
} CONSOLE_INPUT_BUFFER, *PCONSOLE_INPUT_BUFFER;
+
+typedef struct _FRONTEND FRONTEND, *PFRONTEND;
+/* HACK: */ typedef struct _CONSOLE_INFO *PCONSOLE_INFO;
typedef struct _FRONTEND_VTBL
{
/*
* Internal interface (functions called by the console server only)
*/
- // BOOL (WINAPI *Init)();
- VOID (WINAPI *CleanupConsole)(struct _CONSOLE* Console);
+ NTSTATUS (WINAPI *InitFrontEnd)(IN OUT PFRONTEND This,
+ IN struct _CONSOLE* Console);
+ VOID (WINAPI *DeinitFrontEnd)(IN OUT PFRONTEND This);
+
/* Interface used for both text-mode and graphics screen buffers */
- VOID (WINAPI *DrawRegion)(struct _CONSOLE* Console,
+ VOID (WINAPI *DrawRegion)(IN OUT PFRONTEND This,
SMALL_RECT* Region);
/* Interface used only for text-mode screen buffers */
- VOID (WINAPI *WriteStream)(struct _CONSOLE* Console,
+ VOID (WINAPI *WriteStream)(IN OUT PFRONTEND This,
SMALL_RECT* Block,
SHORT CursorStartX,
SHORT CursorStartY,
UINT ScrolledLines,
PWCHAR Buffer,
UINT Length);
- BOOL (WINAPI *SetCursorInfo)(struct _CONSOLE* Console,
+ BOOL (WINAPI *SetCursorInfo)(IN OUT PFRONTEND This,
PCONSOLE_SCREEN_BUFFER ScreenBuffer);
- BOOL (WINAPI *SetScreenInfo)(struct _CONSOLE* Console,
+ BOOL (WINAPI *SetScreenInfo)(IN OUT PFRONTEND This,
PCONSOLE_SCREEN_BUFFER ScreenBuffer,
SHORT OldCursorX,
SHORT OldCursorY);
- VOID (WINAPI *ResizeTerminal)(struct _CONSOLE* Console);
- BOOL (WINAPI *ProcessKeyCallback)(struct _CONSOLE* Console,
+ VOID (WINAPI *ResizeTerminal)(IN OUT PFRONTEND This);
+ BOOL (WINAPI *ProcessKeyCallback)(IN OUT PFRONTEND This,
MSG* msg,
BYTE KeyStateMenu,
DWORD ShiftState,
UINT VirtualKeyCode,
BOOL Down);
- VOID (WINAPI *RefreshInternalInfo)(struct _CONSOLE* Console);
+ VOID (WINAPI *RefreshInternalInfo)(IN OUT PFRONTEND This);
/*
* External interface (functions corresponding to the Console API)
*/
- VOID (WINAPI *ChangeTitle)(struct _CONSOLE* Console);
- BOOL (WINAPI *ChangeIcon)(struct _CONSOLE* Console,
+ VOID (WINAPI *ChangeTitle)(IN OUT PFRONTEND This);
+ BOOL (WINAPI *ChangeIcon)(IN OUT PFRONTEND This,
HICON hWindowIcon);
- HWND (WINAPI *GetConsoleWindowHandle)(struct _CONSOLE* Console);
- VOID (WINAPI *GetLargestConsoleWindowSize)(struct _CONSOLE* Console,
+ HWND (WINAPI *GetConsoleWindowHandle)(IN OUT PFRONTEND This);
+ VOID (WINAPI *GetLargestConsoleWindowSize)(IN OUT PFRONTEND This,
PCOORD pSize);
- ULONG (WINAPI *GetDisplayMode)(struct _CONSOLE* Console);
- BOOL (WINAPI *SetDisplayMode)(struct _CONSOLE* Console,
+ ULONG (WINAPI *GetDisplayMode)(IN OUT PFRONTEND This);
+ BOOL (WINAPI *SetDisplayMode)(IN OUT PFRONTEND This,
ULONG NewMode);
- INT (WINAPI *ShowMouseCursor)(struct _CONSOLE* Console,
+ INT (WINAPI *ShowMouseCursor)(IN OUT PFRONTEND This,
BOOL Show);
- BOOL (WINAPI *SetMouseCursor)(struct _CONSOLE* Console,
+ BOOL (WINAPI *SetMouseCursor)(IN OUT PFRONTEND This,
HCURSOR hCursor);
- HMENU (WINAPI *MenuControl)(struct _CONSOLE* Console,
+ HMENU (WINAPI *MenuControl)(IN OUT PFRONTEND This,
UINT cmdIdLow,
UINT cmdIdHigh);
- BOOL (WINAPI *SetMenuClose)(struct _CONSOLE* Console,
+ BOOL (WINAPI *SetMenuClose)(IN OUT PFRONTEND This,
BOOL Enable);
#if 0 // Possible future front-end interface
- BOOL (WINAPI *GetFrontEndProperty)(struct _CONSOLE* Console,
+ BOOL (WINAPI *GetFrontEndProperty)(IN OUT PFRONTEND This,
ULONG Flag,
PVOID Info,
ULONG Size);
- BOOL (WINAPI *SetFrontEndProperty)(struct _CONSOLE* Console,
+ BOOL (WINAPI *SetFrontEndProperty)(IN OUT PFRONTEND This,
ULONG Flag,
PVOID Info /*,
ULONG Size */);
#endif
} FRONTEND_VTBL, *PFRONTEND_VTBL;
-typedef struct _FRONTEND_IFACE
+struct _FRONTEND
{
- PFRONTEND_VTBL Vtbl; /* Virtual table */
- PVOID Data; /* Private data */
- PVOID OldData; /* Reserved */
-} FRONTEND_IFACE, *PFRONTEND_IFACE;
+ PFRONTEND_VTBL Vtbl; /* Virtual table */
+ struct _CONSOLE* Console; /* Console to which the frontend is attached to */
+ PVOID Data; /* Private data */
+ PVOID OldData; /* Reserved */
+};
/*
* WARNING: Change the state of the console ONLY when the console is locked !
LIST_ENTRY Entry; /* Entry in the list of consoles */
LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */
- FRONTEND_IFACE TermIFace; /* Frontend-specific interface */
+ FRONTEND TermIFace; /* Frontend-specific interface */
/**************************** Input buffer and data ***************************/
CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */
/* console.c */
VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags);
VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags);
-ULONG FASTCALL ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
- ULONG ProcessGroupId,
- DWORD Event);
+
+NTSTATUS NTAPI
+ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
+ IN ULONG ProcessGroupId,
+ IN ULONG Event);
/* coninput.c */
VOID WINAPI ConioProcessKey(PCONSOLE Console, MSG* msg);
#pragma once
-BOOL FASTCALL ConSrvValidateConsolePointer(PCONSOLE Console);
-BOOL FASTCALL ConSrvValidateConsoleState(PCONSOLE Console,
- CONSOLE_STATE ExpectedState);
-BOOL FASTCALL ConSrvValidateConsoleUnsafe(PCONSOLE Console,
- CONSOLE_STATE ExpectedState,
- BOOL LockConsole);
-BOOL FASTCALL ConSrvValidateConsole(PCONSOLE Console,
- CONSOLE_STATE ExpectedState,
- BOOL LockConsole);
+BOOLEAN NTAPI
+ConDrvValidateConsolePointer(IN PCONSOLE Console);
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleState(IN PCONSOLE Console,
+ IN CONSOLE_STATE ExpectedState);
+
+BOOLEAN NTAPI
+ConDrvValidateConsoleUnsafe(IN PCONSOLE Console,
+ IN CONSOLE_STATE ExpectedState,
+ IN BOOLEAN LockConsole);
+
+BOOLEAN NTAPI
+ConDrvValidateConsole(IN PCONSOLE Console,
+ IN CONSOLE_STATE ExpectedState,
+ IN BOOLEAN LockConsole);
/* EOF */
PCONSOLE_PROCESS_DATA SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
/* Validate and lock the parent's console */
- if (ConSrvValidateConsole(SourceProcessData->Console, CONSOLE_RUNNING, TRUE))
+ if (ConDrvValidateConsole(SourceProcessData->Console, CONSOLE_RUNNING, TRUE))
{
/* Inherit the parent's handles table */
Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
if (!ConSrvHeap) return STATUS_NO_MEMORY;
*/
- ConSrvInitConsoleSupport();
+ ConDrvInitConsoleSupport();
/* Setup the DLL Object */
LoadedServerDll->ApiBase = CONSRV_FIRST_API_NUMBER;