You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
364 lines
12 KiB
364 lines
12 KiB
/*++
|
|
|
|
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);
|
|
}
|