Miscellaneous console bugfixes. See Bug 3267 for details.

svn path=/trunk/; revision=34129
This commit is contained in:
Jeffrey Morlan 2008-06-27 12:34:08 +00:00
parent 4784315908
commit 3e39fd7d36
2 changed files with 116 additions and 197 deletions

View file

@ -1646,6 +1646,7 @@ BOOL STDCALL FreeConsole(VOID)
return FALSE; return FALSE;
} }
NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
return TRUE; return TRUE;
} }
@ -3215,6 +3216,7 @@ RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
} }
} }
} }
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE); return(FALSE);
} }
@ -3843,6 +3845,7 @@ GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer)
{ {
/* buffer is not large enough, return the required size */ /* buffer is not large enough, return the required size */
RtlLeaveCriticalSection(&ConsoleLock); RtlLeaveCriticalSection(&ConsoleLock);
SetLastError(ERROR_BUFFER_OVERFLOW);
return lenName + 1; return lenName + 1;
} }

View file

@ -27,11 +27,14 @@ Win32CsrInsertObject2(PCSRSS_PROCESS_DATA, PHANDLE, Object_t *);
#define ConioIsRectEmpty(Rect) \ #define ConioIsRectEmpty(Rect) \
(((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom)) (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \ #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
#define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \ #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1) MultiByteToWideChar((Console)->OutputCodePage, 0, (dChar), 1, (sWChar), 1)
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -398,20 +401,20 @@ CSR_API(CsrFreeConsole)
static VOID FASTCALL static VOID FASTCALL
ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines) ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines)
{ {
/* slide the viewable screen */ if (++Buff->CurrentY == Buff->MaxY)
if (((Buff->CurrentY - Buff->ShowY + Buff->MaxY) % Buff->MaxY) == (ULONG)Buff->MaxY - 1) {
Buff->CurrentY = 0;
}
/* If we hit bottom, slide the viewable screen */
if (Buff->CurrentY == Buff->ShowY)
{ {
if (++Buff->ShowY == Buff->MaxY) if (++Buff->ShowY == Buff->MaxY)
{ {
Buff->ShowY = 0; Buff->ShowY = 0;
} }
(*ScrolledLines)++; (*ScrolledLines)++;
ClearLineBuffer(Buff);
} }
if (++Buff->CurrentY == Buff->MaxY)
{
Buff->CurrentY = 0;
}
ClearLineBuffer(Buff);
UpdateRect->left = 0; UpdateRect->left = 0;
UpdateRect->right = Buff->MaxX - 1; UpdateRect->right = Buff->MaxX - 1;
if (UpdateRect->top == (LONG)Buff->CurrentY) if (UpdateRect->top == (LONG)Buff->CurrentY)
@ -510,6 +513,7 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
while (Buff->CurrentX < EndX) while (Buff->CurrentX < EndX)
{ {
Buff->Buffer[Offset] = ' '; Buff->Buffer[Offset] = ' ';
Buff->Buffer[Offset + 1] = Buff->DefaultAttrib;
Offset += 2; Offset += 2;
Buff->CurrentX++; Buff->CurrentX++;
} }
@ -726,14 +730,6 @@ ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff,
} }
} }
BOOLEAN __inline ConioIsEqualRect(
RECT *Rect1,
RECT *Rect2)
{
return ((Rect1->left == Rect2->left) && (Rect1->right == Rect2->right) &&
(Rect1->top == Rect2->top) && (Rect1->bottom == Rect2->bottom));
}
BOOLEAN __inline ConioGetIntersection( BOOLEAN __inline ConioGetIntersection(
RECT *Intersection, RECT *Intersection,
RECT *Rect1, RECT *Rect1,
@ -793,138 +789,65 @@ BOOLEAN __inline ConioGetUnion(
return TRUE; return TRUE;
} }
BOOLEAN __inline ConioSubtractRect( /* Move from one rectangle to another. We must be careful about the order that
RECT *Subtraction, * this is done, to avoid overwriting parts of the source before they are moved. */
RECT *Rect1,
RECT *Rect2)
{
RECT tmp;
if (ConioIsRectEmpty(Rect1))
{
ConioInitRect(Subtraction, 0, -1, 0, -1);
return FALSE;
}
*Subtraction = *Rect1;
if (ConioGetIntersection(&tmp, Rect1, Rect2))
{
if (ConioIsEqualRect(&tmp, Subtraction))
{
ConioInitRect(Subtraction, 0, -1, 0, -1);
return FALSE;
}
if ((tmp.top == Subtraction->top) && (tmp.bottom == Subtraction->bottom))
{
if (tmp.left == Subtraction->left)
{
Subtraction->left = tmp.right;
}
else if (tmp.right == Subtraction->right)
{
Subtraction->right = tmp.left;
}
}
else if ((tmp.left == Subtraction->left) && (tmp.right == Subtraction->right))
{
if (tmp.top == Subtraction->top)
{
Subtraction->top = tmp.bottom;
}
else if (tmp.bottom == Subtraction->bottom)
{
Subtraction->bottom = tmp.top;
}
}
}
return TRUE;
}
static VOID FASTCALL static VOID FASTCALL
ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer, ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
RECT *SrcRegion, RECT *SrcRegion,
RECT *DstRegion) RECT *DstRegion,
RECT *ClipRegion,
WORD Fill)
{ {
SHORT SrcY, DstY; int Width = ConioRectWidth(SrcRegion);
DWORD SrcOffset; int Height = ConioRectHeight(SrcRegion);
DWORD DstOffset; int SX, SY;
DWORD BytesPerLine; int DX, DY;
LONG i; int XDelta, YDelta;
int i, j;
DstY = DstRegion->top; SY = SrcRegion->top;
BytesPerLine = ConioRectWidth(DstRegion) * 2; DY = DstRegion->top;
YDelta = 1;
SrcY = (SrcRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; if (SY < DY)
DstY = (DstRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion->left + ScreenBuffer->ShowX) * 2;
DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion->left + ScreenBuffer->ShowX) * 2;
for (i = SrcRegion->top; i <= SrcRegion->bottom; i++)
{ {
RtlCopyMemory( /* Moving down: work from bottom up */
&ScreenBuffer->Buffer[DstOffset], SY = SrcRegion->bottom;
&ScreenBuffer->Buffer[SrcOffset], DY = DstRegion->bottom;
BytesPerLine); YDelta = -1;
if (++DstY == ScreenBuffer->MaxY)
{
DstY = 0;
DstOffset = (DstRegion->left + ScreenBuffer->ShowX) * 2;
}
else
{
DstOffset += ScreenBuffer->MaxX * 2;
}
if (++SrcY == ScreenBuffer->MaxY)
{
SrcY = 0;
SrcOffset = (SrcRegion->left + ScreenBuffer->ShowX) * 2;
}
else
{
SrcOffset += ScreenBuffer->MaxX * 2;
}
} }
} for (i = 0; i < Height; i++)
static VOID FASTCALL
ConioFillRegion(PCSRSS_CONSOLE Console,
PCSRSS_SCREEN_BUFFER ScreenBuffer,
RECT *Region,
CHAR_INFO *CharInfo,
BOOL bUnicode)
{
SHORT X, Y;
DWORD Offset;
DWORD Delta;
LONG i;
CHAR Char;
if(bUnicode)
ConsoleUnicodeCharToAnsiChar(Console, &Char, &CharInfo->Char.UnicodeChar);
else
Char = CharInfo->Char.AsciiChar;
Y = (Region->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
Offset = (Y * ScreenBuffer->MaxX + Region->left + ScreenBuffer->ShowX) * 2;
Delta = (ScreenBuffer->MaxX - ConioRectWidth(Region)) * 2;
for (i = Region->top; i <= Region->bottom; i++)
{ {
for (X = Region->left; X <= Region->right; X++) PWORD SRow = (PWORD)&ScreenBuffer->Buffer[((SY + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX * 2];
PWORD DRow = (PWORD)&ScreenBuffer->Buffer[((DY + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX * 2];
SX = SrcRegion->left;
DX = DstRegion->left;
XDelta = 1;
if (SX < DX)
{ {
SET_CELL_BUFFER(ScreenBuffer, Offset, Char, CharInfo->Attributes); /* Moving right: work from right to left */
SX = SrcRegion->right;
DX = DstRegion->right;
XDelta = -1;
} }
if (++Y == ScreenBuffer->MaxY) for (j = 0; j < Width; j++)
{ {
Y = 0; WORD Cell = SRow[SX];
Offset = (Region->left + ScreenBuffer->ShowX) * 2; if (SX >= ClipRegion->left && SX <= ClipRegion->right
} && SY >= ClipRegion->top && SY <= ClipRegion->bottom)
else {
{ SRow[SX] = Fill;
Offset += Delta; }
if (DX >= ClipRegion->left && DX <= ClipRegion->right
&& DY >= ClipRegion->top && DY <= ClipRegion->bottom)
{
DRow[DX] = Cell;
}
SX += XDelta;
DX += XDelta;
} }
SY += YDelta;
DY += YDelta;
} }
} }
@ -935,9 +858,9 @@ ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
{ {
WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar; WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0; InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
ConsoleUnicodeCharToAnsiChar(Console, ConsoleInputUnicodeCharToAnsiChar(Console,
&InputEvent->Event.KeyEvent.uChar.AsciiChar, &InputEvent->Event.KeyEvent.uChar.AsciiChar,
&UnicodeChar); &UnicodeChar);
} }
} }
@ -974,14 +897,14 @@ CSR_API(CsrWriteConsole)
if(Request->Data.WriteConsoleRequest.Unicode) if(Request->Data.WriteConsoleRequest.Unicode)
{ {
Length = WideCharToMultiByte(Console->CodePage, 0, Length = WideCharToMultiByte(Console->OutputCodePage, 0,
(PWCHAR)Request->Data.WriteConsoleRequest.Buffer, (PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
Request->Data.WriteConsoleRequest.NrCharactersToWrite, Request->Data.WriteConsoleRequest.NrCharactersToWrite,
NULL, 0, NULL, NULL); NULL, 0, NULL, NULL);
Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length); Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
if (Buffer) if (Buffer)
{ {
WideCharToMultiByte(Console->CodePage, 0, WideCharToMultiByte(Console->OutputCodePage, 0,
(PWCHAR)Request->Data.WriteConsoleRequest.Buffer, (PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
Request->Data.WriteConsoleRequest.NrCharactersToWrite, Request->Data.WriteConsoleRequest.NrCharactersToWrite,
Buffer, Length, NULL, NULL); Buffer, Length, NULL, NULL);
@ -1585,14 +1508,14 @@ CSR_API(CsrWriteConsoleOutputChar)
{ {
if(Request->Data.WriteConsoleOutputCharRequest.Unicode) if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
{ {
Length = WideCharToMultiByte(Console->CodePage, 0, Length = WideCharToMultiByte(Console->OutputCodePage, 0,
(PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String, (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
Request->Data.WriteConsoleOutputCharRequest.Length, Request->Data.WriteConsoleOutputCharRequest.Length,
NULL, 0, NULL, NULL); NULL, 0, NULL, NULL);
tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length); tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
if (String) if (String)
{ {
WideCharToMultiByte(Console->CodePage, 0, WideCharToMultiByte(Console->OutputCodePage, 0,
(PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String, (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
Request->Data.WriteConsoleOutputCharRequest.Length, Request->Data.WriteConsoleOutputCharRequest.Length,
String, Length, NULL, NULL); String, Length, NULL, NULL);
@ -2257,14 +2180,14 @@ CSR_API(CsrSetScreenBuffer)
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console); ConioUnlockConsole(Console);
return Request->Status; return Request->Status = Status;
} }
if (Buff == Console->ActiveBuffer) if (Buff == Console->ActiveBuffer)
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console); ConioUnlockConsole(Console);
return STATUS_SUCCESS; return Request->Status = STATUS_SUCCESS;
} }
/* drop reference to old buffer, maybe delete */ /* drop reference to old buffer, maybe delete */
@ -2528,15 +2451,15 @@ CSR_API(CsrScrollConsoleScreenBuffer)
RECT ScreenBuffer; RECT ScreenBuffer;
RECT SrcRegion; RECT SrcRegion;
RECT DstRegion; RECT DstRegion;
RECT FillRegion; RECT UpdateRegion;
RECT ScrollRectangle; RECT ScrollRectangle;
RECT ClipRectangle; RECT ClipRectangle;
NTSTATUS Status; NTSTATUS Status;
BOOLEAN DoFill;
HANDLE ConsoleHandle; HANDLE ConsoleHandle;
BOOLEAN UseClipRectangle; BOOLEAN UseClipRectangle;
COORD DestinationOrigin; COORD DestinationOrigin;
CHAR_INFO Fill; CHAR_INFO Fill;
CHAR FillChar;
DPRINT("CsrScrollConsoleScreenBuffer\n"); DPRINT("CsrScrollConsoleScreenBuffer\n");
@ -2567,10 +2490,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top; ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top;
ScrollRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Right; ScrollRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Right;
ScrollRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Bottom; ScrollRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Bottom;
ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left;
ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top;
ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right;
ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
/* Make sure source rectangle is inside the screen buffer */ /* Make sure source rectangle is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
@ -2581,63 +2500,60 @@ CSR_API(CsrScrollConsoleScreenBuffer)
{ {
ConioUnlockConsole(Console); ConioUnlockConsole(Console);
} }
return Request->Status = STATUS_INVALID_PARAMETER;
}
if (UseClipRectangle && ! ConioGetIntersection(&SrcRegion, &SrcRegion, &ClipRectangle))
{
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
ConioUnlockScreenBuffer(Buff);
return Request->Status = STATUS_SUCCESS; return Request->Status = STATUS_SUCCESS;
} }
/* If the source was clipped on the left or top, adjust the destination accordingly */
if (ScrollRectangle.left < 0)
{
DestinationOrigin.X -= ScrollRectangle.left;
}
if (ScrollRectangle.top < 0)
{
DestinationOrigin.Y -= ScrollRectangle.top;
}
if (UseClipRectangle)
{
ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left;
ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top;
ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right;
ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
{
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
ConioUnlockScreenBuffer(Buff);
return Request->Status = STATUS_SUCCESS;
}
}
else
{
ClipRectangle = ScreenBuffer;
}
ConioInitRect(&DstRegion, ConioInitRect(&DstRegion,
DestinationOrigin.Y, DestinationOrigin.Y,
DestinationOrigin.X, DestinationOrigin.X,
DestinationOrigin.Y + ConioRectHeight(&ScrollRectangle) - 1, DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1,
DestinationOrigin.X + ConioRectWidth(&ScrollRectangle) - 1); DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1);
/* Make sure destination rectangle is inside the screen buffer */ if (Request->Data.ScrollConsoleScreenBufferRequest.Unicode)
if (! ConioGetIntersection(&DstRegion, &DstRegion, &ScreenBuffer)) ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar);
{ else
if (NULL != Console) FillChar = Fill.Char.AsciiChar;
{
ConioUnlockConsole(Console);
}
ConioUnlockScreenBuffer(Buff);
return Request->Status = STATUS_INVALID_PARAMETER;
}
ConioCopyRegion(Buff, &SrcRegion, &DstRegion); ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar);
/* Get the region that should be filled with the specified character and attributes */
DoFill = FALSE;
ConioGetUnion(&FillRegion, &SrcRegion, &DstRegion);
if (ConioSubtractRect(&FillRegion, &FillRegion, &DstRegion))
{
/* FIXME: The subtracted rectangle is off by one line */
FillRegion.top += 1;
ConioFillRegion(Console, Buff, &FillRegion, &Fill, Request->Data.ScrollConsoleScreenBufferRequest.Unicode);
DoFill = TRUE;
}
if (NULL != Console && Buff == Console->ActiveBuffer) if (NULL != Console && Buff == Console->ActiveBuffer)
{ {
/* Draw destination region */ ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion);
ConioDrawRegion(Console, &DstRegion); if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle))
if (DoFill)
{ {
/* Draw filled region */ /* Draw update region */
ConioDrawRegion(Console, &FillRegion); ConioDrawRegion(Console, &UpdateRegion);
} }
} }