From: Jeffrey Morlan Date: Sun, 23 May 2010 06:04:15 +0000 (+0000) Subject: [WIN32CSR] Delete even the active screen buffer when all handles are closed. Fixes... X-Git-Tag: backups/header-work@57446~11^2~278 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=85b0f2bc12f3255417494e11721a35435fce0cae [WIN32CSR] Delete even the active screen buffer when all handles are closed. Fixes a winetest. svn path=/trunk/; revision=47318 --- diff --git a/reactos/subsystems/win32/csrss/win32csr/conio.c b/reactos/subsystems/win32/csrss/win32csr/conio.c index 4b8e65c8cd4..92d68554a53 100644 --- a/reactos/subsystems/win32/csrss/win32csr/conio.c +++ b/reactos/subsystems/win32/csrss/win32csr/conio.c @@ -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; diff --git a/reactos/subsystems/win32/csrss/win32csr/conio.h b/reactos/subsystems/win32/csrss/win32csr/conio.h index 14abebf8478..8c853689b30 100644 --- a/reactos/subsystems/win32/csrss/win32csr/conio.h +++ b/reactos/subsystems/win32/csrss/win32csr/conio.h @@ -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); diff --git a/reactos/subsystems/win32/csrss/win32csr/handle.c b/reactos/subsystems/win32/csrss/win32csr/handle.c index a712fd356b2..e7b28b1977b 100644 --- a/reactos/subsystems/win32/csrss/win32csr/handle.c +++ b/reactos/subsystems/win32/csrss/win32csr/handle.c @@ -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); } }