[WIN32CSR] Delete even the active screen buffer when all handles are closed. Fixes a winetest.

svn path=/trunk/; revision=47318
This commit is contained in:
Jeffrey Morlan 2010-05-23 06:04:15 +00:00
parent 3c777cde9c
commit 85b0f2bc12
3 changed files with 34 additions and 13 deletions

View file

@ -137,6 +137,7 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
Buffer->CurrentX = 0;
Buffer->CurrentY = 0;
InsertHeadList(&Console->BufferList, &Buffer->ListEntry);
return STATUS_SUCCESS;
}
@ -162,6 +163,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
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();
@ -893,11 +895,24 @@ CSR_API(CsrWriteConsole)
}
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
@ -929,9 +944,11 @@ ConioDeleteConsole(Object_t *Object)
}
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);
@ -1998,7 +2015,7 @@ CSR_API(CsrSetScreenBuffer)
/* 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;

View file

@ -46,6 +46,7 @@ typedef struct tagCSRSS_SCREEN_BUFFER
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;
@ -76,6 +77,7 @@ typedef struct tagCSRSS_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 */
@ -103,7 +105,7 @@ typedef struct ConsoleInput_t
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);

View file

@ -49,11 +49,13 @@ Win32CsrCloseHandleEntry(
&& 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);
}
}