|
|
/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
bitmap.c
Abstract:
This file implements bitmap video buffer management.
Author:
Therese Stowell (thereses) 4-Sept-1991
Revision History:
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
NTSTATUS CreateConsoleBitmap( IN OUT PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsInfo, IN OUT PSCREEN_INFORMATION ScreenInfo, OUT PVOID *lpBitmap, OUT HANDLE *hMutex ) { NTSTATUS Status; LARGE_INTEGER MaximumSize; SIZE_T ViewSize;
//
// adjust bitmap info
//
if (GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight > 0) { #if DBG
DbgPrint("*************** Negating biHeight\n"); #endif
GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight; }
if (GraphicsInfo->lpBitMapInfo->bmiHeader.biCompression != BI_RGB) { #if DBG
DbgPrint("*************** setting Compression to BI_RGB)\n"); #endif
GraphicsInfo->lpBitMapInfo->bmiHeader.biCompression = BI_RGB; }
//
// allocate screeninfo buffer data and copy it
//
ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo = ConsoleHeapAlloc(BMP_TAG, GraphicsInfo->dwBitMapInfoLength); if (ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo == NULL) { return STATUS_NO_MEMORY; } ScreenInfo->BufferInfo.GraphicsInfo.BitMapInfoLength = GraphicsInfo->dwBitMapInfoLength; RtlCopyMemory(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo, GraphicsInfo->lpBitMapInfo, GraphicsInfo->dwBitMapInfoLength ); ASSERT((GraphicsInfo->lpBitMapInfo->bmiHeader.biWidth * -GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight / 8 * GraphicsInfo->lpBitMapInfo->bmiHeader.biBitCount) == (LONG)GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage);
//
// create bitmap section
//
MaximumSize.QuadPart = GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage; Status = NtCreateSection(&ScreenInfo->BufferInfo.GraphicsInfo.hSection, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, NULL ); if (!NT_SUCCESS(Status)) { ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo); return Status; }
//
// map server view of section
//
ViewSize = GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage; ScreenInfo->BufferInfo.GraphicsInfo.BitMap = 0; Status = NtMapViewOfSection(ScreenInfo->BufferInfo.GraphicsInfo.hSection, NtCurrentProcess(), &ScreenInfo->BufferInfo.GraphicsInfo.BitMap, 0L, GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage, NULL, &ViewSize, ViewUnmap, 0L, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo); NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hSection); return Status; }
//
// map client view of section
//
ViewSize = GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage; *lpBitmap = 0; Status = NtMapViewOfSection(ScreenInfo->BufferInfo.GraphicsInfo.hSection, CONSOLE_CLIENTPROCESSHANDLE(), lpBitmap, 0L, GraphicsInfo->lpBitMapInfo->bmiHeader.biSizeImage, NULL, &ViewSize, ViewUnmap, 0L, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo); NtUnmapViewOfSection(NtCurrentProcess(),ScreenInfo->BufferInfo.GraphicsInfo.BitMap); NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hSection); return Status; } ScreenInfo->BufferInfo.GraphicsInfo.ClientProcess = CONSOLE_CLIENTPROCESSHANDLE(); ScreenInfo->BufferInfo.GraphicsInfo.ClientBitMap = *lpBitmap;
//
// create mutex to serialize access to bitmap, then map handle to mutex to client side
//
NtCreateMutant(&ScreenInfo->BufferInfo.GraphicsInfo.hMutex, MUTANT_ALL_ACCESS, NULL, FALSE); MapHandle(CONSOLE_CLIENTPROCESSHANDLE(), ScreenInfo->BufferInfo.GraphicsInfo.hMutex, hMutex );
ScreenInfo->BufferInfo.GraphicsInfo.dwUsage = GraphicsInfo->dwUsage; ScreenInfo->ScreenBufferSize.X = (WORD)GraphicsInfo->lpBitMapInfo->bmiHeader.biWidth; ScreenInfo->ScreenBufferSize.Y = (WORD)-GraphicsInfo->lpBitMapInfo->bmiHeader.biHeight; ScreenInfo->Window.Left = 0; ScreenInfo->Window.Top = 0; ScreenInfo->Window.Right = (SHORT)(ScreenInfo->Window.Left+ScreenInfo->ScreenBufferSize.X-1); ScreenInfo->Window.Bottom = (SHORT)(ScreenInfo->Window.Top+ScreenInfo->ScreenBufferSize.Y-1); return STATUS_SUCCESS; }
ULONG SrvInvalidateBitMapRect( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus )
/*++
Routine Description:
This routine is called to indicate that the application has modified a region in the bitmap. We update the region to the screen.
Arguments:
m - message containing api parameters
ReplyStatus - Indicates whether to reply to the dll port.
Return Value:
--*/
{ PCONSOLE_INVALIDATERECT_MSG a = (PCONSOLE_INVALIDATERECT_MSG)&m->u.ApiMessageData; PCONSOLE_INFORMATION Console; PHANDLE_DATA HandleData; NTSTATUS Status; UINT Codepage;
Status = ApiPreamble(a->ConsoleHandle, &Console ); if (!NT_SUCCESS(Status)) { return Status; }
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), a->OutputHandle, CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE, GENERIC_WRITE, &HandleData ); if (!NT_SUCCESS(Status)) { UnlockConsole(Console); return((ULONG) Status); } if (HandleData->HandleType & CONSOLE_OUTPUT_HANDLE) { //ASSERT(Console->Flags & CONSOLE_VDM_REGISTERED);
//ASSERT(!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE));
ASSERT(Console->VDMBuffer != NULL); if (Console->VDMBuffer != NULL) { //ASSERT(HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X <= Console->VDMBufferSize.X);
//ASSERT(HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y <= Console->VDMBufferSize.Y);
if (HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X <= Console->VDMBufferSize.X && HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y <= Console->VDMBufferSize.Y) { COORD TargetPoint;
TargetPoint.X = a->Rect.Left; TargetPoint.Y = a->Rect.Top; // VDM can sometimes get out of sync with window size
//ASSERT(a->Rect.Left >= 0);
//ASSERT(a->Rect.Top >= 0);
//ASSERT(a->Rect.Right < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X);
//ASSERT(a->Rect.Bottom < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y);
//ASSERT(a->Rect.Left <= a->Rect.Right);
//ASSERT(a->Rect.Top <= a->Rect.Bottom);
if ((a->Rect.Left >= 0) && (a->Rect.Top >= 0) && (a->Rect.Right < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.X) && (a->Rect.Bottom < HandleData->Buffer.ScreenBuffer->ScreenBufferSize.Y) && (a->Rect.Left <= a->Rect.Right) && (a->Rect.Top <= a->Rect.Bottom) ) {
if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { #if defined(FE_SB)
if (CONSOLE_IS_DBCS_ENABLED() && Console->OutputCP != WINDOWSCP ) { Codepage = USACP; } else
#endif
// we want UnicodeOem characters
Codepage = WINDOWSCP; } else { #if defined(FE_SB)
if (CONSOLE_IS_DBCS_ENABLED()) { Codepage = Console->OutputCP; } else #endif
// we want real Unicode characters
Codepage = Console->CP; }
WriteRectToScreenBuffer((PBYTE)Console->VDMBuffer, Console->VDMBufferSize, &a->Rect, HandleData->Buffer.ScreenBuffer, TargetPoint, Codepage); WriteToScreen(HandleData->Buffer.ScreenBuffer,&a->Rect); } else { Status = STATUS_INVALID_PARAMETER; } } else { Status = STATUS_INVALID_PARAMETER; } } else { Status = STATUS_INVALID_PARAMETER; } } else {
//
// write data to screen
//
WriteToScreen(HandleData->Buffer.ScreenBuffer,&a->Rect); }
UnlockConsole(Console); return Status; UNREFERENCED_PARAMETER(ReplyStatus); }
NTSTATUS WriteRegionToScreenBitMap( IN PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT Region ) { DWORD NumScanLines; int Height; //
// if we have a selection, turn it off.
//
InvertSelection(ScreenInfo->Console,TRUE);
NtWaitForSingleObject(ScreenInfo->BufferInfo.GraphicsInfo.hMutex, FALSE, NULL);
// The origin of (xSrc, ySrc) passed to SetDIBitsToDevice is located
// at the DIB's bottom-left corner no matter if the DIB is
// a top-down or bottom-up. Thus, if the DIB is a top-down, we have
// to translate ySrc accordingly:
// if (height < 0) { // top-down
// ySrc = abs(height) - rect.Bottom -1;
//
// else
// ySrc = rect.Bottom;
//
Height = ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo->bmiHeader.biHeight;
NumScanLines = SetDIBitsToDevice(ScreenInfo->Console->hDC, Region->Left - ScreenInfo->Window.Left, Region->Top - ScreenInfo->Window.Top, Region->Right - Region->Left + 1, Region->Bottom - Region->Top + 1, Region->Left, Height < 0 ? -Height - Region->Bottom - 1 : Region->Bottom, 0, ScreenInfo->ScreenBufferSize.Y, ScreenInfo->BufferInfo.GraphicsInfo.BitMap, ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo, ScreenInfo->BufferInfo.GraphicsInfo.dwUsage );
NtReleaseMutant(ScreenInfo->BufferInfo.GraphicsInfo.hMutex, NULL);
//
// if we have a selection, turn it on.
//
InvertSelection(ScreenInfo->Console,FALSE);
if (NumScanLines == 0) { return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
VOID FreeConsoleBitmap( IN PSCREEN_INFORMATION ScreenInfo ) { NtUnmapViewOfSection(NtCurrentProcess(), ScreenInfo->BufferInfo.GraphicsInfo.BitMap); NtUnmapViewOfSection(ScreenInfo->BufferInfo.GraphicsInfo.ClientProcess, ScreenInfo->BufferInfo.GraphicsInfo.ClientBitMap); NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hSection); NtClose(ScreenInfo->BufferInfo.GraphicsInfo.hMutex); ConsoleHeapFree(ScreenInfo->BufferInfo.GraphicsInfo.lpBitMapInfo); }
|