- add hActiveBuffer member to struct to ensure that modifying the screenbuffer is secured

- fix a bugs in the screen buffer resize code
- resizing now "works" (unfortunately a few drawing bugs show up)

svn path=/trunk/; revision=28794
This commit is contained in:
Johannes Anderwald 2007-09-03 01:58:43 +00:00
parent 81f092736f
commit 9b81b3ab92
4 changed files with 91 additions and 22 deletions

View file

@ -70,6 +70,7 @@ typedef struct tagCSRSS_CONSOLE
WORD WaitingChars;
WORD WaitingLines; /* number of chars and lines in input queue */
PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
HANDLE hActiveBuffer;
WORD Mode; /* Console mode flags */
WORD EchoCount; /* count of chars to echo, in line buffered mode */
UNICODE_STRING Title; /* Title of console */

View file

@ -153,6 +153,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
Console->EarlyReturn = FALSE;
Console->ActiveBuffer = NULL;
Console->hActiveBuffer = INVALID_HANDLE_VALUE;
InitializeListHead(&Console->InputEvents);
Console->CodePage = GetOEMCP();
Console->OutputCodePage = GetOEMCP();
@ -174,13 +175,6 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
/* allocate console screen buffer */
NewBuffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
/* init screen buffer with defaults */
NewBuffer->CursorInfo.bVisible = TRUE;
NewBuffer->CursorInfo.dwSize = 5;
/* make console active, and insert into console list */
Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
/* add a reference count because the buffer is tied to the console */
InterlockedIncrement(&Console->ActiveBuffer->Header.ReferenceCount);
if (NULL == NewBuffer)
{
RtlFreeUnicodeString(&Console->Title);
@ -188,6 +182,15 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
CloseHandle(Console->ActiveEvent);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* init screen buffer with defaults */
NewBuffer->CursorInfo.bVisible = TRUE;
NewBuffer->CursorInfo.dwSize = 5;
/* make console active, and insert into console list */
Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
Console->hActiveBuffer = INVALID_HANDLE_VALUE;
/* add a reference count because the buffer is tied to the console */
InterlockedIncrement(&Console->ActiveBuffer->Header.ReferenceCount);
if (! GuiMode)
{
@ -332,6 +335,7 @@ CSR_API(CsrAllocConsole)
ProcessData->Console = 0;
return Request->Status = Status;
}
Console->hActiveBuffer = Request->Data.AllocConsoleRequest.OutputHandle;
}
/* Duplicate the Event */
@ -1065,6 +1069,7 @@ ConioDeleteConsole(Object_t *Object)
#endif
Console->ActiveBuffer = NULL;
Console->hActiveBuffer = INVALID_HANDLE_VALUE;
ConioCleanupConsole(Console);
CloseHandle(Console->ActiveEvent);
@ -2272,6 +2277,7 @@ CSR_API(CsrSetScreenBuffer)
}
/* tie console to new buffer */
Console->ActiveBuffer = Buff;
Console->hActiveBuffer = Request->Data.SetScreenBufferRequest.OutputHandle;
/* inc ref count on new buffer */
InterlockedIncrement(&Buff->Header.ReferenceCount);
/* Redraw the console */

View file

@ -1614,7 +1614,15 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
{
DWORD windx, windy;
RECT rect;
PCSRSS_SCREEN_BUFFER ActiveBuffer;
PCSRSS_PROCESS_DATA ProcessData = NULL;
if (Console->ProcessList.Flink != &Console->ProcessList)
{
ProcessData = CONTAINING_RECORD(Console->ProcessList.Flink, CSRSS_PROCESS_DATA, ProcessEntry);
ConioLockScreenBuffer(ProcessData, Console->hActiveBuffer, (Object_t **)&ActiveBuffer);
}
/* apply text / background color */
GuiData->ScreenText = pConInfo->ScreenText;
GuiData->ScreenBackground = pConInfo->ScreenBackground;
@ -1625,38 +1633,51 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
windx = LOWORD(pConInfo->ScreenBuffer);
windy = HIWORD(pConInfo->ScreenBuffer);
if (windx != Console->ActiveBuffer->MaxX || windy != Console->ActiveBuffer->MaxY)
if (windx != ActiveBuffer->MaxX || windy != ActiveBuffer->MaxY)
{
BYTE * Buffer = HeapAlloc(Win32CsrApiHeap, 0, windx * windy * 2);
if (Buffer)
{
DWORD Offset = 0;
DWORD BufferOffset = 0;
USHORT CurrentY;
BYTE * OldBuffer;
USHORT value;
DWORD diff;
DWORD value = ((((DWORD)Console->ActiveBuffer->DefaultAttrib) << 16) | 0x20);
DWORD i;
value = MAKEWORD(' ', ActiveBuffer->DefaultAttrib);
OldBuffer = Console->ActiveBuffer->Buffer;
DPRINT("MaxX %d MaxY %d windx %d windy %d value %04x DefaultAttrib %d\n",ActiveBuffer->MaxX, ActiveBuffer->MaxY, windx, windy, value, ActiveBuffer->DefaultAttrib);
OldBuffer = ActiveBuffer->Buffer;
for (CurrentY = 0; CurrentY < min(Console->ActiveBuffer->MaxY, windy); CurrentY++)
for (CurrentY = 0; CurrentY < min(ActiveBuffer->MaxY, windy); CurrentY++)
{
if (windx < Console->ActiveBuffer->MaxX)
if (windx <= ActiveBuffer->MaxX)
{
/* reduce size */
RtlCopyMemory(&Buffer[Offset], &OldBuffer[BufferOffset], windx * 2);
Offset += (windx * 2);
BufferOffset += (Console->ActiveBuffer->MaxX * 2);
BufferOffset += (ActiveBuffer->MaxX * 2);
}
else
{
/* enlarge size */
diff = windx - Console->ActiveBuffer->MaxX;
RtlCopyMemory(&Buffer[Offset], &OldBuffer[BufferOffset], Console->ActiveBuffer->MaxX * 2);
Offset += (Console->ActiveBuffer->MaxX * 2);
RtlCopyMemory(&Buffer[Offset], &OldBuffer[BufferOffset], ActiveBuffer->MaxX * 2);
Offset += (ActiveBuffer->MaxX * 2);
diff = windx - ActiveBuffer->MaxX;
/* zero new part of it */
memset(&Buffer[Offset], value, (diff * 2));
#if HAVE_WMEMSET
wmemset((WCHAR*)&Buffer[Offset], value, diff);
#else
for (i = 0; i < diff * 2; i++)
{
Buffer[Offset * 2] = ' ';
Buffer[Offset * 2 + 1] = ActiveBuffer->DefaultAttrib;
}
#endif
Offset += (diff * 2);
BufferOffset += (Console->ActiveBuffer->MaxX * 2);
}
@ -1665,18 +1686,55 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
if (windy > Console->ActiveBuffer->MaxY)
{
diff = windy - Console->ActiveBuffer->MaxX;
memset(&Buffer[Offset], value, diff * 2 * windx);
#if HAVE_WMEMSET
wmemset((WCHAR*)&Buffer[Offset], value, diff * windx);
#else
for (i = 0; i < diff * 2; i++)
{
Buffer[Offset * 2] = ' ';
Buffer[Offset * 2 + 1] = ActiveBuffer->DefaultAttrib;
}
#endif
}
(void)InterlockedExchangePointer((PVOID volatile *)Console->ActiveBuffer->Buffer, Buffer);
(void)InterlockedExchangePointer((PVOID volatile *)&Console->ActiveBuffer->Buffer, Buffer);
HeapFree(Win32CsrApiHeap, 0, OldBuffer);
Console->ActiveBuffer->MaxX = windx;
Console->ActiveBuffer->MaxY = windy;
InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
}
else
{
if (ProcessData)
{
ConioUnlockScreenBuffer(ActiveBuffer);
}
return;
}
}
windx = LOWORD(pConInfo->WindowSize);
windy = HIWORD(pConInfo->WindowSize);
if (windx > Console->Size.X)
{
PWCHAR LineBuffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, windx * sizeof(WCHAR));
if (LineBuffer)
{
HeapFree(Win32CsrApiHeap, 0, GuiData->LineBuffer);
GuiData->LineBuffer = LineBuffer;
}
else
{
if (ProcessData)
{
ConioUnlockScreenBuffer(ActiveBuffer);
}
return;
}
}
if (windx != Console->Size.X || windy != Console->Size.Y)
{
/* resize window */
@ -1701,7 +1759,10 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
//ShowScrollBar(GuiData->hHScrollBar, SB_CTL, FALSE);
}
}
/* repaint window */
if (ProcessData)
{
ConioUnlockScreenBuffer(ActiveBuffer);
}
InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
}

View file

@ -23,6 +23,7 @@
#include <win32csr.h>
#include <tchar.h>
#include <wchar.h>
#include <cpl.h>
#include "resource.h"