[WIN32CSR] Delete even the active screen buffer when all handles are closed. Fixes...
authorJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 06:04:15 +0000 (06:04 +0000)
committerJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 06:04:15 +0000 (06:04 +0000)
svn path=/trunk/; revision=47318

reactos/subsystems/win32/csrss/win32csr/conio.c
reactos/subsystems/win32/csrss/win32csr/conio.h
reactos/subsystems/win32/csrss/win32csr/handle.c

index 4b8e65c..92d6855 100644 (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;
index 14abebf..8c85368 100644 (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);
index a712fd3..e7b28b1 100644 (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);
         }
     }