VOID FASTCALL ConioDrawConsole(PCONSOLE Console) { SMALL_RECT Region; PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer; if (ActiveBuffer) { ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); ConioDrawRegion(Console, &Region); } }
NTSTATUS NTAPI ConDrvInvalidateBitMapRect(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer, IN PSMALL_RECT Region) { if (Console == NULL || Buffer == NULL || Region == NULL) return STATUS_INVALID_PARAMETER; /* Validity check */ ASSERT(Console == Buffer->Header.Console); /* If the output buffer is the current one, redraw the correct portion of the screen */ if (Buffer == Console->ActiveBuffer) ConioDrawRegion(Console, Region); return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN PVOID StringBuffer, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord /*, OUT PCOORD EndCoord, OUT PULONG CodesWritten */) { NTSTATUS Status = STATUS_SUCCESS; PVOID WriteBuffer = NULL; PWCHAR tmpString = NULL; DWORD X, Y, Length; // , Written = 0; ULONG CodeSize; SMALL_RECT UpdateRect; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL || CodesWritten == NULL */) { return STATUS_INVALID_PARAMETER; } /* Validity checks */ ASSERT(Console == Buffer->Header.Console); ASSERT( (StringBuffer != NULL && NumCodesToWrite >= 0) || (StringBuffer == NULL && NumCodesToWrite == 0) ); switch (CodeType) { case CODE_ASCII: CodeSize = sizeof(CHAR); break; case CODE_UNICODE: CodeSize = sizeof(WCHAR); break; case CODE_ATTRIBUTE: CodeSize = sizeof(WORD); break; default: return STATUS_INVALID_PARAMETER; } if (CodeType == CODE_ASCII) { /* Convert the ASCII string into Unicode before writing it to the console */ Length = MultiByteToWideChar(Console->OutputCodePage, 0, (PCHAR)StringBuffer, NumCodesToWrite, NULL, 0); tmpString = WriteBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR)); if (WriteBuffer) { MultiByteToWideChar(Console->OutputCodePage, 0, (PCHAR)StringBuffer, NumCodesToWrite, (PWCHAR)WriteBuffer, Length); } else { Status = STATUS_NO_MEMORY; } } else { /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */ WriteBuffer = StringBuffer; } if (WriteBuffer == NULL || !NT_SUCCESS(Status)) goto Cleanup; X = WriteCoord->X; Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Length = NumCodesToWrite; // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work while (Length--) { // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; switch (CodeType) { case CODE_ASCII: case CODE_UNICODE: Ptr->Char.UnicodeChar = *(PWCHAR)WriteBuffer; break; case CODE_ATTRIBUTE: Ptr->Attributes = *(PWORD)WriteBuffer; break; } WriteBuffer = (PVOID)((ULONG_PTR)WriteBuffer + CodeSize); // ++Ptr; // Written++; if (++X == Buffer->ScreenBufferSize.X) { X = 0; if (++Y == Buffer->ScreenBufferSize.Y) { Y = 0; } } } if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); ConioDrawRegion(Console, &UpdateRect); } // EndCoord->X = X; // EndCoord->Y = (Y + Buffer->ScreenBufferSize.Y - Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Cleanup: if (tmpString) RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString); // CodesWritten = Written; return Status; }
NTSTATUS NTAPI ConDrvWriteConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, IN PCOORD BufferSize, IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion) { SHORT i, X, Y, SizeX, SizeY; SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; SMALL_RECT CapturedWriteRegion; PCHAR_INFO Ptr; if (Console == NULL || Buffer == NULL || CharInfo == NULL || BufferSize == NULL || BufferCoord == NULL || WriteRegion == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedWriteRegion = *WriteRegion; SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedWriteRegion)); SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedWriteRegion)); CapturedWriteRegion.Right = CapturedWriteRegion.Left + SizeX - 1; CapturedWriteRegion.Bottom = CapturedWriteRegion.Top + SizeY - 1; /* Make sure WriteRegion is inside the screen buffer */ ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion)) { /* * It is okay to have a WriteRegion completely outside * the screen buffer. No data is written then. */ return STATUS_SUCCESS; } for (i = 0, Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; i++, Y++) { CurCharInfo = CharInfo + (i + BufferCoord->Y) * BufferSize->X + BufferCoord->X; Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y); for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; X++) { if (Unicode) { Ptr->Char.UnicodeChar = CurCharInfo->Char.UnicodeChar; } else { ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar); } Ptr->Attributes = CurCharInfo->Attributes; ++Ptr; ++CurCharInfo; } } ConioDrawRegion(Console, &CapturedWriteRegion); WriteRegion->Left = CapturedWriteRegion.Left; WriteRegion->Top = CapturedWriteRegion.Top ; WriteRegion->Right = CapturedWriteRegion.Left + SizeX - 1; WriteRegion->Bottom = CapturedWriteRegion.Top + SizeY - 1; return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PSMALL_RECT ScrollRectangle, IN BOOLEAN UseClipRectangle, IN PSMALL_RECT ClipRectangle OPTIONAL, IN PCOORD DestinationOrigin, IN CHAR_INFO FillChar) { COORD CapturedDestinationOrigin; SMALL_RECT ScreenBuffer; SMALL_RECT SrcRegion; SMALL_RECT DstRegion; SMALL_RECT UpdateRegion; SMALL_RECT CapturedClipRectangle; if (Console == NULL || Buffer == NULL || ScrollRectangle == NULL || (UseClipRectangle ? ClipRectangle == NULL : FALSE) || DestinationOrigin == NULL) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); CapturedDestinationOrigin = *DestinationOrigin; /* Make sure the source rectangle is inside the screen buffer */ ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, ScrollRectangle)) { return STATUS_SUCCESS; } /* If the source was clipped on the left or top, adjust the destination accordingly */ if (ScrollRectangle->Left < 0) { CapturedDestinationOrigin.X -= ScrollRectangle->Left; } if (ScrollRectangle->Top < 0) { CapturedDestinationOrigin.Y -= ScrollRectangle->Top; } if (UseClipRectangle) { CapturedClipRectangle = *ClipRectangle; if (!ConioGetIntersection(&CapturedClipRectangle, &CapturedClipRectangle, &ScreenBuffer)) { return STATUS_SUCCESS; } } else { CapturedClipRectangle = ScreenBuffer; } ConioInitRect(&DstRegion, CapturedDestinationOrigin.Y, CapturedDestinationOrigin.X, CapturedDestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1, CapturedDestinationOrigin.X + ConioRectWidth(&SrcRegion ) - 1); if (!Unicode) ConsoleAnsiCharToUnicodeChar(Console, &FillChar.Char.UnicodeChar, &FillChar.Char.AsciiChar); ConioMoveRegion(Buffer, &SrcRegion, &DstRegion, &CapturedClipRectangle, FillChar); if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion); if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &CapturedClipRectangle)) { /* Draw update region */ ConioDrawRegion(Console, &UpdateRegion); } } return STATUS_SUCCESS; }
NTSTATUS NTAPI ConDrvFillConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN PVOID Code, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord /*, OUT PULONG CodesWritten */) { DWORD X, Y, Length; // , Written = 0; PCHAR_INFO Ptr; SMALL_RECT UpdateRect; if (Console == NULL || Buffer == NULL || Code == NULL || WriteCoord == NULL /* || CodesWritten == NULL */) { return STATUS_INVALID_PARAMETER; } /* Validity check */ ASSERT(Console == Buffer->Header.Console); #if 0 switch (CodeType) { case CODE_ASCII: /* On-place conversion from the ASCII char to the UNICODE char */ ConsoleAnsiCharToUnicodeChar(Console, &Code->UnicodeChar, &Code->AsciiChar); /* Fall through */ case CODE_UNICODE: Code = &Code->UnicodeChar; break; case CODE_ATTRIBUTE: Code = &Code->Attribute; break; } #else if (CodeType == CODE_ASCII) { /* On-place conversion from the ASCII char to the UNICODE char */ // FIXME: What if Code points to an invalid memory zone ?? ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)Code, (PCHAR)Code); } #endif X = WriteCoord->X; Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; Length = NumCodesToWrite; // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work while (Length--) { // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; switch (CodeType) { case CODE_ASCII: case CODE_UNICODE: Ptr->Char.UnicodeChar = *(PWCHAR)Code; break; case CODE_ATTRIBUTE: Ptr->Attributes = *(PWORD)Code; break; } // ++Ptr; // Written++; if (++X == Buffer->ScreenBufferSize.X) { X = 0; if (++Y == Buffer->ScreenBufferSize.Y) { Y = 0; } } } if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) { ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); ConioDrawRegion(Console, &UpdateRect); } // CodesWritten = Written; // NumCodesToWrite; return STATUS_SUCCESS; }