* PROGRAMMERS: Gé van Geldorp
* Jeffrey Morlan
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
/* INCLUDES *******************************************************************/
#include <consrv.h>
-
-#include <alias.h>
#include <coninput.h>
+#include "../../concfg/font.h"
#define NDEBUG
#include <debug.h>
-// FIXME: Add this prototype to winternl.h / rtlfuncs.h / ...
-NTSTATUS NTAPI RtlGetLastNtStatus(VOID);
-
-
/* GLOBALS ********************************************************************/
-static ULONG ConsoleListSize;
-static PCONSOLE* ConsoleList; /* The list of all the allocated consoles */
+static ULONG CurrentConsoleID = 0;
+
+/* Linked list of consoles */
+static LIST_ENTRY ConDrvConsoleList;
static RTL_RESOURCE ListLock;
#define ConDrvLockConsoleListExclusive() \
#define ConDrvUnlockConsoleList() \
RtlReleaseResource(&ListLock)
-// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
-static 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
-static VOID
-ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
-{
- if (UnicodeString->Buffer)
- {
- ConsoleFreeHeap(UnicodeString->Buffer);
- RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
- }
-}
-
static NTSTATUS
-InsertConsole(OUT PHANDLE Handle,
- IN PCONSOLE Console)
+ConDrvInsertConsole(IN PCONSOLE Console)
{
-#define CONSOLE_HANDLES_INCREMENT 2 * 3
-
- NTSTATUS Status = STATUS_SUCCESS;
- ULONG i = 0;
- PCONSOLE* Block;
-
- ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) ||
- (ConsoleList != NULL && ConsoleListSize != 0) );
+ ASSERT(Console);
/* All went right, so add the console to the list */
ConDrvLockConsoleListExclusive();
- DPRINT1("Insert in the list\n");
-
- if (ConsoleList)
- {
- for (i = 0; i < ConsoleListSize; i++)
- {
- if (ConsoleList[i] == NULL) break;
- }
- }
-
- if (i >= ConsoleListSize)
- {
- DPRINT1("Creation of a new handles table\n");
- /* Allocate a new handles table */
- Block = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
- (ConsoleListSize +
- CONSOLE_HANDLES_INCREMENT) * sizeof(PCONSOLE));
- if (Block == NULL)
- {
- Status = STATUS_UNSUCCESSFUL;
- goto Quit;
- }
-
- /* If we previously had a handles table, free it and use the new one */
- if (ConsoleList)
- {
- /* Copy the handles from the old table to the new one */
- RtlCopyMemory(Block,
- ConsoleList,
- ConsoleListSize * sizeof(PCONSOLE));
- ConsoleFreeHeap(ConsoleList);
- }
- ConsoleList = Block;
- ConsoleListSize += CONSOLE_HANDLES_INCREMENT;
- }
-
- ConsoleList[i] = Console;
- *Handle = ULongToHandle((i << 2) | 0x3);
-
-Quit:
- /* Unlock the console list and return status */
- ConDrvUnlockConsoleList();
- return Status;
-}
-
-/* Unused */
-#if 0
-static NTSTATUS
-RemoveConsoleByHandle(IN HANDLE Handle)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- PCONSOLE Console;
-
- BOOLEAN ValidHandle = ((HandleToULong(Handle) & 0x3) == 0x3);
- ULONG Index = HandleToULong(Handle) >> 2;
-
- if (!ValidHandle) return STATUS_INVALID_HANDLE;
-
- ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) ||
- (ConsoleList != NULL && ConsoleListSize != 0) );
-
- /* Remove the console from the list */
- ConDrvLockConsoleListExclusive();
- if (Index >= ConsoleListSize ||
- (Console = ConsoleList[Index]) == NULL)
- {
- Status = STATUS_INVALID_HANDLE;
- goto Quit;
- }
+ DPRINT("Insert in the list\n");
+ InsertTailList(&ConDrvConsoleList, &Console->ListEntry);
- ConsoleList[Index] = NULL;
+ // FIXME: Move this code to the caller function!!
+ /* Get a new console ID */
+ _InterlockedExchange((PLONG)&Console->ConsoleID, CurrentConsoleID);
+ _InterlockedIncrement((PLONG)&CurrentConsoleID);
-Quit:
- /* Unlock the console list and return status */
+ /* Unlock the console list and return success */
ConDrvUnlockConsoleList();
- return Status;
+ return STATUS_SUCCESS;
}
-#endif
static NTSTATUS
-RemoveConsoleByPointer(IN PCONSOLE Console)
+RemoveConsole(IN PCONSOLE Console)
{
- ULONG i = 0;
-
+ // ASSERT(Console);
if (!Console) return STATUS_INVALID_PARAMETER;
- ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) ||
- (ConsoleList != NULL && ConsoleListSize != 0) );
-
/* Remove the console from the list */
ConDrvLockConsoleListExclusive();
- if (ConsoleList)
- {
- for (i = 0; i < ConsoleListSize; i++)
- {
- if (ConsoleList[i] == Console) ConsoleList[i] = NULL;
- }
- }
+ RemoveEntryList(&Console->ListEntry);
- /* Unlock the console list */
+ /* Unlock the console list and return success */
ConDrvUnlockConsoleList();
-
return STATUS_SUCCESS;
}
-/* For resetting the frontend - defined in dummyfrontend.c */
-VOID ResetFrontEnd(IN PCONSOLE Console);
-
-
/* PRIVATE FUNCTIONS **********************************************************/
-static NTSTATUS
-ConDrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent,
- 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(CtrlEvent), 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;
-}
-
-NTSTATUS
-ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent,
- IN PCONSOLE_PROCESS_DATA ProcessData)
+VOID NTAPI
+ConDrvPause(PCONSOLE Console)
{
- return ConDrvConsoleCtrlEventTimeout(CtrlEvent, ProcessData, 0);
-}
+ /* In case we already have a pause event, just exit... */
+ if (Console->UnpauseEvent) return;
-VOID FASTCALL
-ConioPause(PCONSOLE Console, UINT Flags)
-{
- Console->PauseFlags |= Flags;
- if (!Console->UnpauseEvent)
- Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ /* ... otherwise create it */
+ NtCreateEvent(&Console->UnpauseEvent, EVENT_ALL_ACCESS,
+ NULL, NotificationEvent, FALSE);
}
-VOID FASTCALL
-ConioUnpause(PCONSOLE Console, UINT Flags)
+VOID NTAPI
+ConDrvUnpause(PCONSOLE Console)
{
- Console->PauseFlags &= ~Flags;
+ /* In case we already freed the event, just exit... */
+ if (!Console->UnpauseEvent) return;
- // 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,
- TRUE,
- NULL,
- NULL);
- if (!IsListEmpty(&Console->WriteWaitQueue))
- {
- CsrDereferenceWait(&Console->WriteWaitQueue);
- }
- }
+ /* ... otherwise set and free it */
+ NtSetEvent(Console->UnpauseEvent, NULL);
+ NtClose(Console->UnpauseEvent);
+ Console->UnpauseEvent = NULL;
}
return TRUE;
}
-BOOLEAN NTAPI
-ConDrvValidateConsole(OUT PCONSOLE* Console,
- IN HANDLE ConsoleHandle,
- IN CONSOLE_STATE ExpectedState,
- IN BOOLEAN LockConsole)
-{
- BOOLEAN RetVal = FALSE;
- PCONSOLE ValidatedConsole;
-
- BOOLEAN ValidHandle = ((HandleToULong(ConsoleHandle) & 0x3) == 0x3);
- ULONG Index = HandleToULong(ConsoleHandle) >> 2;
-
- if (!ValidHandle) return FALSE;
-
- if (!Console) return FALSE;
- *Console = NULL;
-
- /*
- * Forbid creation or deletion of consoles when
- * checking for the existence of a console.
- */
- ConDrvLockConsoleListShared();
-
- if (Index >= ConsoleListSize ||
- (ValidatedConsole = ConsoleList[Index]) == NULL)
- {
- /* Unlock the console list */
- ConDrvUnlockConsoleList();
-
- return FALSE;
- }
-
- ValidatedConsole = ConsoleList[Index];
-
- /* Unlock the console list and return */
- ConDrvUnlockConsoleList();
-
- RetVal = ConDrvValidateConsoleUnsafe(ValidatedConsole,
- ExpectedState,
- LockConsole);
- if (RetVal) *Console = ValidatedConsole;
-
- return RetVal;
-}
-
-NTSTATUS NTAPI
-ConDrvGetConsole(OUT PCONSOLE* Console,
- IN HANDLE ConsoleHandle,
- IN BOOLEAN LockConsole)
-{
- NTSTATUS Status = STATUS_INVALID_HANDLE;
- PCONSOLE GrabConsole;
-
- if (Console == NULL) return STATUS_INVALID_PARAMETER;
- *Console = NULL;
-
- if (ConDrvValidateConsole(&GrabConsole,
- ConsoleHandle,
- CONSOLE_RUNNING,
- LockConsole))
- {
- InterlockedIncrement(&GrabConsole->ReferenceCount);
- *Console = GrabConsole;
- 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 *******************************************/
DPRINT("CONSRV: ConDrvInitConsoleSupport()\n");
/* Initialize the console list and its lock */
- ConsoleListSize = 0;
- ConsoleList = NULL;
+ InitializeListHead(&ConDrvConsoleList);
RtlInitializeResource(&ListLock);
-
- /* Should call LoadKeyboardLayout */
}
+/* For resetting the terminal - defined in dummyterm.c */
+VOID ResetTerminal(IN PCONSOLE Console);
+
NTSTATUS NTAPI
-ConDrvInitConsole(OUT PHANDLE NewConsoleHandle,
- OUT PCONSOLE* NewConsole,
- IN PCONSOLE_INFO ConsoleInfo,
- IN ULONG ConsoleLeaderProcessId)
+ConDrvInitConsole(OUT PCONSOLE* NewConsole,
+ IN PCONSOLE_INFO ConsoleInfo)
{
NTSTATUS Status;
- SECURITY_ATTRIBUTES SecurityAttributes;
// CONSOLE_INFO CapturedConsoleInfo;
TEXTMODE_BUFFER_INFO ScreenBufferInfo;
- HANDLE ConsoleHandle;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER NewBuffer;
- // WCHAR DefaultTitle[128];
- if (NewConsoleHandle == NULL || NewConsole == NULL || ConsoleInfo == NULL)
+ if (NewConsole == NULL || ConsoleInfo == NULL)
return STATUS_INVALID_PARAMETER;
- *NewConsoleHandle = NULL;
*NewConsole = NULL;
/*
- * Allocate a console structure
+ * Allocate a new console
*/
- Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE));
+ Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*Console));
if (NULL == Console)
{
DPRINT1("Not enough memory for console creation.\n");
}
/*
- * 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
+ * Set and fix the screen buffer size if needed.
+ * The rule is: ScreenBufferSize >= ConsoleSize
*/
+ if (ConsoleInfo->ScreenBufferSize.X == 0) ConsoleInfo->ScreenBufferSize.X = 1;
+ if (ConsoleInfo->ScreenBufferSize.Y == 0) ConsoleInfo->ScreenBufferSize.Y = 1;
if (ConsoleInfo->ScreenBufferSize.X < ConsoleInfo->ConsoleSize.X)
ConsoleInfo->ScreenBufferSize.X = ConsoleInfo->ConsoleSize.X;
if (ConsoleInfo->ScreenBufferSize.Y < ConsoleInfo->ConsoleSize.Y)
Console->State = CONSOLE_INITIALIZING;
Console->ReferenceCount = 0;
InitializeCriticalSection(&Console->Lock);
- InitializeListHead(&Console->ProcessList);
- Console->NotifiedLastCloseProcess = NULL;
- Console->NotifyLastClose = FALSE;
- /* Initialize the frontend interface */
- ResetFrontEnd(Console);
+ /* Initialize the terminal interface */
+ ResetTerminal(Console);
- 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);
+ Console->FixedSize = FALSE; // Value by default; is reseted by the terminals if needed.
- SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- SecurityAttributes.lpSecurityDescriptor = NULL;
- SecurityAttributes.bInheritHandle = TRUE;
- Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
- if (NULL == Console->InputBuffer.ActiveEvent)
+ /* Initialize the input buffer */
+ Status = ConDrvInitInputBuffer(Console, 0 /* ConsoleInfo->InputBufferSize */);
+ if (!NT_SUCCESS(Status))
{
+ DPRINT1("ConDrvInitInputBuffer: failed, Status = 0x%08lx\n", Status);
DeleteCriticalSection(&Console->Lock);
ConsoleFreeHeap(Console);
- return STATUS_UNSUCCESSFUL;
+ return Status;
}
- 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 = FALSE;
- Console->LineInsertToggle = Console->InsertMode;
- // LineWakeupMask
-
/* Set-up the code page */
- Console->CodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
+ if (IsValidCodePage(ConsoleInfo->CodePage))
+ Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
+
+ Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
/* Initialize a new text-mode screen buffer with default settings */
ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
+ ScreenBufferInfo.ViewSize = ConsoleInfo->ConsoleSize;
ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
ScreenBufferInfo.PopupAttrib = ConsoleInfo->PopupAttrib;
- ScreenBufferInfo.IsCursorVisible = TRUE;
ScreenBufferInfo.CursorSize = ConsoleInfo->CursorSize;
+ ScreenBufferInfo.IsCursorVisible = TRUE;
InitializeListHead(&Console->BufferList);
Status = ConDrvCreateScreenBuffer(&NewBuffer,
Console,
+ NULL,
CONSOLE_TEXTMODE_BUFFER,
&ScreenBufferInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("ConDrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
- CloseHandle(Console->InputBuffer.ActiveEvent);
+ ConDrvDeinitInputBuffer(Console);
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 */
- Status = InsertConsole(&ConsoleHandle, Console);
+ Status = ConDrvInsertConsole(Console);
if (!NT_SUCCESS(Status))
{
/* Fail */
DPRINT("Change state\n");
Console->State = CONSOLE_RUNNING;
- /* Unlock the console */
- // LeaveCriticalSection(&Console->Lock);
-
/* Return the newly created console to the caller and a success code too */
- *NewConsoleHandle = ConsoleHandle;
- *NewConsole = Console;
+ *NewConsole = Console;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
-ConDrvRegisterFrontEnd(IN PCONSOLE Console,
- IN PFRONTEND FrontEnd)
+ConDrvAttachTerminal(IN PCONSOLE Console,
+ IN PTERMINAL Terminal)
{
NTSTATUS Status;
- if (Console == NULL || FrontEnd == NULL)
+ if (Console == NULL || Terminal == 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.
+ * Attach the terminal to the console. Use now the TermIFace of the console,
+ * and not the user-defined temporary Terminal pointer.
*/
- Console->TermIFace = *FrontEnd;
+ Console->TermIFace = *Terminal;
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);
+ /* Initialize the terminal AFTER having attached it to the console */
+ DPRINT("Finish initialization of terminal\n");
+ Status = Console->TermIFace.Vtbl->InitTerminal(&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
- ResetFrontEnd(Console);
+ DPRINT1("Terminal initialization failed, Status = 0x%08lx\n", Status);
+ /* We failed, detach the terminal from the console */
+ Terminal->Console = NULL; // For the caller
+ ResetTerminal(Console);
return Status;
}
/* Copy buffer contents to screen */
- // FrontEnd.Draw();
- // ConioDrawConsole(Console);
- DPRINT("Console drawn\n");
+ // Terminal.Draw();
- DPRINT("Terminal FrontEnd initialization done\n");
+ DPRINT("Terminal initialization done\n");
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
-ConDrvDeregisterFrontEnd(IN PCONSOLE Console)
+ConDrvDetachTerminal(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*/);
+ /* Deinitialize the terminal BEFORE detaching it from the console */
+ Console->TermIFace.Vtbl->DeinitTerminal(&Console->TermIFace/*, Console*/);
/*
- * Detach the frontend from the console:
- * reinitialize the frontend interface.
+ * Detach the terminal from the console:
+ * reinitialize the terminal interface.
*/
- ResetFrontEnd(Console);
+ ResetTerminal(Console);
- DPRINT("Terminal FrontEnd unregistered\n");
+ DPRINT("Terminal unregistered\n");
return STATUS_SUCCESS;
}
/*
* 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
+ * ConDrvValidateConsoleUnsafe 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");
+ /* Deregister the terminal */
+ DPRINT("Deregister terminal\n");
+ ConDrvDetachTerminal(Console);
+ DPRINT("Terminal deregistered\n");
/***
* Check that the console is in terminating state before continuing
Console->ReferenceCount = 0;
/* Remove the console from the list */
- RemoveConsoleByPointer(Console);
-
- /* Discard all entries in the input event queue */
- PurgeInputBuffer(Console);
-
- if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
-
- IntDeleteAllAliases(Console);
- HistoryDeleteBuffers(Console);
+ RemoveConsole(Console);
- ConioDeleteScreenBuffer(Console->ActiveBuffer);
+ /* Delete the last screen buffer */
+ ConDrvDeleteScreenBuffer(Console->ActiveBuffer);
Console->ActiveBuffer = NULL;
if (!IsListEmpty(&Console->BufferList))
{
- DPRINT1("BUG: screen buffer list not empty\n");
- ASSERT(FALSE);
+ /***ConDrvUnlockConsoleList();***/
+ ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE);
}
- /**/ CloseHandle(Console->InputBuffer.ActiveEvent); /**/
- if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
+ /* Deinitialize the input buffer */
+ ConDrvDeinitInputBuffer(Console);
- ConsoleFreeUnicodeString(&Console->OriginalTitle);
- ConsoleFreeUnicodeString(&Console->Title);
+ if (Console->UnpauseEvent) NtClose(Console->UnpauseEvent);
DPRINT("ConDrvDeleteConsole - Unlocking\n");
LeaveCriticalSection(&Console->Lock);
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)
{
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 )
{
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 )
+ /* Only the presence of valid mode flags is allowed */
+ if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES)
{
Status = STATUS_INVALID_PARAMETER;
- goto Quit;
}
- */
-
- /*
- * 3. Now we can continue.
- */
- if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
+ else
{
- Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
- Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
+ InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
}
- 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);
-
+ /* Only the presence of valid mode flags is allowed */
if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
{
Status = STATUS_INVALID_PARAMETER;
Status = STATUS_INVALID_HANDLE;
}
-Quit:
return Status;
}
-NTSTATUS NTAPI
-ConDrvGetConsoleTitle(IN PCONSOLE Console,
- IN BOOLEAN Unicode,
- IN OUT PVOID TitleBuffer,
- IN OUT PULONG BufLength)
-{
- ULONG Length;
-
- if (Console == NULL || TitleBuffer == NULL || BufLength == NULL)
- return STATUS_INVALID_PARAMETER;
-
- /* Copy title of the console to the user title buffer */
- if (Unicode)
- {
- if (*BufLength >= sizeof(WCHAR))
- {
- Length = min(*BufLength - sizeof(WCHAR), Console->Title.Length);
- RtlCopyMemory(TitleBuffer, Console->Title.Buffer, Length);
- ((PWCHAR)TitleBuffer)[Length / sizeof(WCHAR)] = L'\0';
- *BufLength = Length;
- }
- else
- {
- *BufLength = Console->Title.Length;
- }
- }
- else
- {
- if (*BufLength >= sizeof(CHAR))
- {
- Length = min(*BufLength - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR));
- Length = WideCharToMultiByte(Console->CodePage, 0,
- Console->Title.Buffer, Length,
- TitleBuffer, Length,
- NULL, NULL);
- ((PCHAR)TitleBuffer)[Length] = '\0';
- *BufLength = Length;
- }
- else
- {
- *BufLength = Console->Title.Length / sizeof(WCHAR);
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS NTAPI
-ConDrvSetConsoleTitle(IN PCONSOLE Console,
- IN BOOLEAN Unicode,
- IN PVOID TitleBuffer,
- IN ULONG BufLength)
-{
- PWCHAR Buffer;
- ULONG Length;
-
- if (Console == NULL || TitleBuffer == NULL)
- return STATUS_INVALID_PARAMETER;
-
- if (Unicode)
- {
- /* Length is in bytes */
- Length = BufLength;
- }
- else
- {
- /* Use the console input CP for the conversion */
- Length = MultiByteToWideChar(Console->CodePage, 0,
- TitleBuffer, BufLength,
- NULL, 0);
- /* The returned Length was in number of wchars, convert it in bytes */
- Length *= sizeof(WCHAR);
- }
-
- /* Allocate a new buffer to hold the new title (NULL-terminated) */
- Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Length + 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 = Length;
- Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
-
- if (Unicode)
- {
- RtlCopyMemory(Console->Title.Buffer, TitleBuffer, Console->Title.Length);
- }
- else
- {
- MultiByteToWideChar(Console->CodePage, 0,
- TitleBuffer, BufLength,
- Console->Title.Buffer,
- Console->Title.Length / sizeof(WCHAR));
- }
-
- /* NULL-terminate */
- Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
-
- // TermChangeTitle(Console);
- return STATUS_SUCCESS;
-}
-
NTSTATUS NTAPI
ConDrvGetConsoleCP(IN PCONSOLE Console,
OUT PUINT CodePage,
if (Console == NULL || CodePage == NULL)
return STATUS_INVALID_PARAMETER;
- *CodePage = (OutputCP ? Console->OutputCodePage : Console->CodePage);
+ *CodePage = (OutputCP ? Console->OutputCodePage : Console->InputCodePage);
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
if (OutputCP)
+ {
Console->OutputCodePage = CodePage;
+ Console->IsCJK = IsCJKCodePage(CodePage);
+ }
else
- Console->CodePage = CodePage;
-
- return STATUS_SUCCESS;
-}
-
-PCONSOLE_PROCESS_DATA NTAPI
-ConDrvGetConsoleLeaderProcess(IN PCONSOLE Console)
-{
- if (Console == NULL) return NULL;
-
- return CONTAINING_RECORD(Console->ProcessList.Blink,
- CONSOLE_PROCESS_DATA,
- ConsoleLink);
-}
-
-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);
- }
+ Console->InputCodePage = CodePage;
}
return STATUS_SUCCESS;
}
-// ConDrvGenerateConsoleCtrlEvent
-NTSTATUS NTAPI
-ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console,
- IN ULONG ProcessGroupId,
- IN ULONG CtrlEvent)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- PLIST_ENTRY current_entry;
- PCONSOLE_PROCESS_DATA current;
-
- /* If the console is already being destroyed, just return */
- if (!ConDrvValidateConsoleState(Console, CONSOLE_RUNNING))
- 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(CtrlEvent, current);
- }
- }
-
- return Status;
-}
-
/* EOF */