Buffer->CurrentX = 0;
Buffer->CurrentY = 0;
+ InsertHeadList(&Console->BufferList, &Buffer->ListEntry);
return STATUS_SUCCESS;
}
Console->Header.Console = Console;
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
Console->EarlyReturn = FALSE;
+ InitializeListHead(&Console->BufferList);
Console->ActiveBuffer = NULL;
InitializeListHead(&Console->InputEvents);
Console->CodePage = GetOEMCP();
}
VOID WINAPI
-ConioDeleteScreenBuffer(Object_t *Object)
+ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer)
{
- PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
- HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
- HeapFree(Win32CsrApiHeap, 0, Buffer);
+ PCSRSS_CONSOLE Console = Buffer->Header.Console;
+
+ RemoveEntryList(&Buffer->ListEntry);
+ if (Buffer == Console->ActiveBuffer)
+ {
+ /* Deleted active buffer; switch to most recently created */
+ Console->ActiveBuffer = NULL;
+ if (!IsListEmpty(&Console->BufferList))
+ {
+ Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CSRSS_SCREEN_BUFFER, ListEntry);
+ ConioDrawConsole(Console);
+ }
+ }
+
+ HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
+ HeapFree(Win32CsrApiHeap, 0, Buffer);
}
VOID FASTCALL
}
ConioCleanupConsole(Console);
- ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
-
- Console->ActiveBuffer = NULL;
+ ConioDeleteScreenBuffer(Console->ActiveBuffer);
+ if (!IsListEmpty(&Console->BufferList))
+ {
+ DPRINT1("BUG: screen buffer list not empty\n");
+ }
CloseHandle(Console->ActiveEvent);
DeleteCriticalSection(&Console->Lock);
/* If old buffer has no handles, it's now unreferenced */
if (Console->ActiveBuffer->Header.HandleCount == 0)
{
- ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
+ ConioDeleteScreenBuffer(Console->ActiveBuffer);
}
/* tie console to new buffer */
Console->ActiveBuffer = Buff;
USHORT VirtualY; /* top row of buffer being displayed, reported to callers */
CONSOLE_CURSOR_INFO CursorInfo;
USHORT Mode;
+ LIST_ENTRY ListEntry; /* entry in console's list of buffers */
} CSRSS_SCREEN_BUFFER, *PCSRSS_SCREEN_BUFFER;
typedef struct tagCSRSS_CONSOLE *PCSRSS_CONSOLE;
LIST_ENTRY InputEvents; /* List head for input event queue */
WORD WaitingChars;
WORD WaitingLines; /* number of chars and lines in input queue */
+ LIST_ENTRY BufferList; /* List of all screen buffers for this console */
PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
WORD Mode; /* Console mode flags */
WORD EchoCount; /* count of chars to echo, in line buffered mode */
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console);
VOID WINAPI ConioDeleteConsole(Object_t *Object);
-VOID WINAPI ConioDeleteScreenBuffer(Object_t *Buffer);
+VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer);
VOID WINAPI CsrInitConsoleSupport(VOID);
void WINAPI ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode);
PBYTE FASTCALL ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buf, ULONG X, ULONG Y);
&& Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
{
PCSRSS_CONSOLE Console = Object->Console;
+ PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
EnterCriticalSection(&Console->Lock);
- /* TODO: Should delete even the active buffer, but we're not yet ready
- * to deal with the case where this results in no buffers left. */
- if (Object != &Console->ActiveBuffer->Header)
- ConioDeleteScreenBuffer(Object);
+ /* ...unless it's the only buffer left. Windows allows deletion
+ * even of the last buffer, but having to deal with a lack of
+ * any active buffer might be error-prone. */
+ if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
+ ConioDeleteScreenBuffer(Buffer);
LeaveCriticalSection(&Console->Lock);
}
}