Windows2000/private/ntos/w32/ntcon/server/private.c
2020-09-30 17:12:32 +02:00

3397 lines
112 KiB
C

/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
private.c
Abstract:
This file implements private APIs for Hardware Desktop Support.
Author:
Therese Stowell (thereses) 12-13-1991
--*/
#include "precomp.h"
#pragma hdrstop
#if defined(FE_SB)
BOOL fFullScreenGraphics ; // Do not trun graphics mode.
#if defined(i386)
extern ULONG gdwMachineId;
#endif // i386
#endif
// initial palette registers
#define PAL_BLACK 0
#define PAL_BLUE 1
#define PAL_GREEN 2
#define PAL_RED 4
#define PAL_YELLOW (PAL_RED | PAL_GREEN)
#define PAL_CYAN (PAL_GREEN | PAL_BLUE)
#define PAL_MAGENTA (PAL_BLUE | PAL_RED)
#define PAL_WHITE (PAL_RED | PAL_GREEN | PAL_BLUE)
#define PAL_I_BLACK (PAL_BLACK + (PAL_WHITE << 3))
#define PAL_I_RED (PAL_RED + (PAL_RED << 3))
#define PAL_I_GREEN (PAL_GREEN + (PAL_GREEN << 3))
#define PAL_I_YELLOW (PAL_YELLOW + (PAL_YELLOW << 3))
#define PAL_I_BLUE (PAL_BLUE + (PAL_BLUE << 3))
#define PAL_I_CYAN (PAL_CYAN + (PAL_CYAN << 3))
#define PAL_I_MAGENTA (PAL_MAGENTA + (PAL_MAGENTA << 3))
#define PAL_I_WHITE (PAL_WHITE + (PAL_WHITE << 3))
#define INITIAL_PALETTE_SIZE 18
USHORT InitialPalette[INITIAL_PALETTE_SIZE] = {
16, // 16 entries
0, // start with first palette register
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
#if defined(FE_SB)
PUSHORT RegInitialPalette = InitialPalette;
#endif
UCHAR ColorBuffer[] = {
16, // 16 entries
0,
0,
0, // start with first palette register
0x00, 0x00, 0x00, 0x00, // black
0x00, 0x00, 0x2A, 0x00, // blue
0x00, 0x2A, 0x00, 0x00, // green
0x00, 0x2A, 0x2A, 0x00, // cyan
0x2A, 0x00, 0x00, 0x00, // red
0x2A, 0x00, 0x2A, 0x00, // magenta
0x2A, 0x2A, 0x00, 0x00, // mustard/brown
0x36, 0x36, 0x36, 0x00, // light gray 39
0x28, 0x28, 0x28, 0x00, // dark gray 2A
0x00, 0x00, 0x3F, 0x00, // bright blue
0x00, 0x3F, 0x00, 0x00, // bright green
0x00, 0x3F, 0x3F, 0x00, // bright cyan
0x3F, 0x00, 0x00, 0x00, // bright red
0x3F, 0x00, 0x3F, 0x00, // bright magenta
0x3F, 0x3F, 0x00, 0x00, // bright yellow
0x3F, 0x3F, 0x3F, 0x00 // bright white
};
#if defined(FE_SB)
PUCHAR RegColorBuffer = ColorBuffer;
PUCHAR RegColorBufferNoTranslate = NULL;
#endif
#if defined(FE_SB)
MODE_FONT_PAIR ModeFontPairs[] = {
{FS_MODE_TEXT, 80, 21, 640, 350, 8, 16},
{FS_MODE_TEXT, 80, 25, 720, 400, 8, 16},
{FS_MODE_TEXT, 80, 28, 720, 400, 8, 14},
{FS_MODE_TEXT, 80, 43, 640, 350, 8, 8 },
{FS_MODE_TEXT, 80, 50, 720, 400, 8, 8 }
};
DWORD NUMBER_OF_MODE_FONT_PAIRS = sizeof(ModeFontPairs)/sizeof(MODE_FONT_PAIR);
PMODE_FONT_PAIR RegModeFontPairs = ModeFontPairs;
SINGLE_LIST_ENTRY gRegFullScreenCodePage; // This list contain FS_CODEPAGE data.
#else
typedef struct _MODE_FONT_PAIR {
ULONG Height;
COORD Resolution;
COORD FontSize;
} MODE_FONT_PAIR, PMODE_FONT_PAIR;
#define NUMBER_OF_MODE_FONT_PAIRS 5
MODE_FONT_PAIR ModeFontPairs[NUMBER_OF_MODE_FONT_PAIRS] = {
{21, 640, 350, 8, 16},
{25, 720, 400, 8, 16},
{28, 720, 400, 8, 14},
{43, 640, 350, 8, 8 },
{50, 720, 400, 8, 8 }
};
#endif
HANDLE hCPIFile; // handle to font file
typedef struct _FONTFILEHEADER {
BYTE ffhFileTag[8]; // SHOULD BE 0FFH,"FONT___"
BYTE ffhReserved[8];
WORD ffhPointers;
BYTE ffhPointerType;
BYTE ffhOffset1;
WORD ffhOffset2;
BYTE ffhOffset3;
} FONTFILEHEADER, *LPFONTFILEHEADER;
typedef struct _FONTINFOHEADER {
WORD fihCodePages;
} FONTINFOHEADER, *LPFONTINFOHEADER;
typedef struct _CPENTRYHEADER {
WORD cpeLength;
WORD cpeNext1;
WORD cpeNext2;
WORD cpeDevType;
BYTE cpeDevSubtype[8];
WORD cpeCodepageID;
BYTE cpeReserved[6];
DWORD cpeOffset;
} CPENTRYHEADER, *LPCPENTRYHEADER;
typedef struct _FONTDATAHEADER {
WORD fdhReserved;
WORD fdhFonts;
WORD fdhLength;
} FONTDATAHEADER, *LPFONTDATAHEADER;
typedef struct _SCREENFONTHEADER {
BYTE sfhHeight;
BYTE sfhWidth;
WORD sfhAspect;
WORD sfhCharacters;
} SCREENFONTHEADER, *LPSCREENFONTHEADER;
#define CONSOLE_WINDOWS_DIR_LENGTH 256
#define CONSOLE_EGACPI_LENGTH 9 // includes NULL
#define CONSOLE_EGACPI "\\ega.cpi"
#define CONSOLE_FONT_BUFFER_LENGTH 50
#define CONSOLE_DEFAULT_ROM_FONT 437
#ifdef i386
VOID ReverseMousePointer(IN PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT Region);
VOID ReadRectFromScreenBuffer(IN PSCREEN_INFORMATION ScreenInfo, IN COORD SourcePoint, IN PCHAR_INFO Target, IN COORD TargetSize, IN PSMALL_RECT TargetRect);
#endif
NTSTATUS MapViewOfSection(PHANDLE SectionHandle, ULONG CommitSize, PVOID *BaseAddress, PSIZE_T ViewSize, HANDLE ClientHandle, PVOID *BaseClientAddress);
NTSTATUS ConnectToEmulator(IN BOOL Connect, IN PCONSOLE_INFORMATION Console);
ULONG SrvSetConsoleCursor(IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus)
/*++
Description:
Sets the mouse pointer for the specified screen buffer.
Parameters:
hConsoleOutput - Supplies a console output handle.
hCursor - win32 cursor handle, should be NULL to set the default cursor.
Return value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available using GetLastError.
--*/
{
PCONSOLE_SETCURSOR_MSG a = (PCONSOLE_SETCURSOR_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
Status = ApiPreamble(a->ConsoleHandle, &Console);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), a->OutputHandle, CONSOLE_GRAPHICS_OUTPUT_HANDLE, GENERIC_WRITE, &HandleData);
if (NT_SUCCESS(Status)) {
if (a->CursorHandle == NULL) {
HandleData->Buffer.ScreenBuffer->CursorHandle = ghNormalCursor;
} else {
HandleData->Buffer.ScreenBuffer->CursorHandle = a->CursorHandle;
}
PostMessage(HandleData->Buffer.ScreenBuffer->Console->hWnd, WM_SETCURSOR, 0, -1);
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
#ifdef i386
VOID
FullScreenCursor(
IN PSCREEN_INFORMATION ScreenInfo,
IN BOOL On
)
{
if (On) {
if (ScreenInfo->CursorDisplayCount < 0) {
ScreenInfo->CursorDisplayCount = 0;
ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
}
} else {
if (ScreenInfo->CursorDisplayCount >= 0) {
ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
ScreenInfo->CursorDisplayCount = -1;
}
}
}
#endif
ULONG
SrvShowConsoleCursor(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
/*++
Description:
Sets the mouse pointer visibility counter. If the counter is less than
zero, the mouse pointer is not shown.
Parameters:
hOutput - Supplies a console output handle.
bShow - if TRUE, the display count is to be increased. if FALSE,
decreased.
Return value:
The return value specifies the new display count.
--*/
{
PCONSOLE_SHOWCURSOR_MSG a = (PCONSOLE_SHOWCURSOR_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
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)) {
if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) ) {
if (a->bShow) {
HandleData->Buffer.ScreenBuffer->CursorDisplayCount += 1;
} else {
HandleData->Buffer.ScreenBuffer->CursorDisplayCount -= 1;
}
if (HandleData->Buffer.ScreenBuffer == Console->CurrentScreenBuffer) {
PostMessage(HandleData->Buffer.ScreenBuffer->Console->hWnd,
WM_SETCURSOR,
0,
-1
);
}
} else {
#ifdef i386
if (HandleData->HandleType != CONSOLE_GRAPHICS_OUTPUT_HANDLE &&
Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
HandleData->Buffer.ScreenBuffer == Console->CurrentScreenBuffer) {
FullScreenCursor(HandleData->Buffer.ScreenBuffer,a->bShow);
}
#endif
}
a->DisplayCount = HandleData->Buffer.ScreenBuffer->CursorDisplayCount;
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvConsoleMenuControl(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
/*++
Description:
Sets the command id range for the current screen buffer and returns the
menu handle.
Parameters:
hConsoleOutput - Supplies a console output handle.
dwCommandIdLow - Specifies the lowest command id to store in the input buffer.
dwCommandIdHigh - Specifies the highest command id to store in the input
buffer.
Return value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
PCONSOLE_MENUCONTROL_MSG a = (PCONSOLE_MENUCONTROL_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
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)) {
a->hMenu = HandleData->Buffer.ScreenBuffer->Console->hMenu;
HandleData->Buffer.ScreenBuffer->CommandIdLow = a->CommandIdLow;
HandleData->Buffer.ScreenBuffer->CommandIdHigh = a->CommandIdHigh;
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvSetConsolePalette(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
/*++
Description:
Sets the palette for the console screen buffer.
Parameters:
hOutput - Supplies a console output handle.
hPalette - Supplies a handle to the palette to set.
dwUsage - Specifies use of the system palette.
SYSPAL_NOSTATIC - System palette contains no static colors
except black and white.
SYSPAL_STATIC - System palette contains static colors
which will not change when an application
realizes its logical palette.
Return value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
PCONSOLE_SETPALETTE_MSG a = (PCONSOLE_SETPALETTE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
HPALETTE hOldPalette;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_GRAPHICS_OUTPUT_HANDLE,
GENERIC_WRITE,
&HandleData
);
if (NT_SUCCESS(Status)) {
USERTHREAD_USEDESKTOPINFO utudi;
BOOL bReset = FALSE;
/*
* Palette handle was converted in the client.
*/
if (GetCurrentThreadId() != HandleData->Buffer.ScreenBuffer->
Console->InputThreadInfo->ThreadId) {
bReset = TRUE;
utudi.hThread = HandleData->Buffer.ScreenBuffer->Console->InputThreadInfo->ThreadHandle;
utudi.drdRestore.pdeskRestore = NULL;
NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop,
&utudi, sizeof(utudi));
}
NtUserConsoleControl(ConsolePublicPalette, &(a->hPalette), sizeof(HPALETTE));
hOldPalette = SelectPalette(
HandleData->Buffer.ScreenBuffer->Console->hDC,
a->hPalette,
FALSE);
if (hOldPalette == NULL) {
Status = STATUS_INVALID_PARAMETER;
} else {
if ((HandleData->Buffer.ScreenBuffer->hPalette != NULL) &&
(a->hPalette != HandleData->Buffer.ScreenBuffer->hPalette)) {
DeleteObject(HandleData->Buffer.ScreenBuffer->hPalette);
}
HandleData->Buffer.ScreenBuffer->hPalette = a->hPalette;
HandleData->Buffer.ScreenBuffer->dwUsage = a->dwUsage;
if (!(HandleData->Buffer.ScreenBuffer->Console->Flags & CONSOLE_IS_ICONIC) &&
HandleData->Buffer.ScreenBuffer->Console->FullScreenFlags == 0) {
SetSystemPaletteUse(HandleData->Buffer.ScreenBuffer->Console->hDC,
HandleData->Buffer.ScreenBuffer->dwUsage);
RealizePalette(HandleData->Buffer.ScreenBuffer->Console->hDC);
}
if (HandleData->Buffer.ScreenBuffer->Console->hSysPalette == NULL) {
HandleData->Buffer.ScreenBuffer->Console->hSysPalette = hOldPalette;
}
}
if (bReset) {
utudi.hThread = NULL;
NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop, &utudi, sizeof(utudi));
}
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
VOID
SetActivePalette(
IN PSCREEN_INFORMATION ScreenInfo
)
{
USERTHREAD_USEDESKTOPINFO utudi;
BOOL bReset = FALSE;
if (GetCurrentThreadId() != ScreenInfo->Console->InputThreadInfo->ThreadId) {
bReset = TRUE;
utudi.hThread = ScreenInfo->Console->InputThreadInfo->ThreadHandle;
utudi.drdRestore.pdeskRestore = NULL;
NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop,
&utudi, sizeof(utudi));
}
SetSystemPaletteUse(ScreenInfo->Console->hDC,
ScreenInfo->dwUsage
);
RealizePalette(ScreenInfo->Console->hDC);
if (bReset == TRUE) {
utudi.hThread = NULL;
NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop, &utudi, sizeof(utudi));
}
}
VOID
UnsetActivePalette(
IN PSCREEN_INFORMATION ScreenInfo
)
{
USERTHREAD_USEDESKTOPINFO utudi;
BOOL bReset = FALSE;
if (GetCurrentThreadId() != ScreenInfo->Console->InputThreadInfo->ThreadId) {
bReset = TRUE;
utudi.hThread = ScreenInfo->Console->InputThreadInfo->ThreadHandle;
utudi.drdRestore.pdeskRestore = NULL;
NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop,
&utudi, sizeof(utudi));
}
SetSystemPaletteUse(ScreenInfo->Console->hDC,
SYSPAL_STATIC
);
RealizePalette(ScreenInfo->Console->hDC);
if (bReset == TRUE) {
utudi.hThread = NULL;
NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop, &utudi, sizeof(utudi));
}
}
NTSTATUS
ConvertToFullScreen(
IN PCONSOLE_INFORMATION Console
)
{
#ifdef i386
PSCREEN_INFORMATION Cur;
COORD WindowedWindowSize, WindowSize;
// for each charmode screenbuffer
// match window size to a mode/font
// grow screen buffer if necessary
// save old window dimensions
// set new window dimensions
for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
if (Cur->Flags & CONSOLE_GRAPHICS_BUFFER) {
continue;
}
// save old window dimensions
WindowedWindowSize.X = CONSOLE_WINDOW_SIZE_X(Cur);
WindowedWindowSize.Y = CONSOLE_WINDOW_SIZE_Y(Cur);
Cur->BufferInfo.TextInfo.WindowedWindowSize = WindowedWindowSize;
Cur->BufferInfo.TextInfo.WindowedScreenSize = Cur->ScreenBufferSize;
// match window size to a mode/font
Cur->BufferInfo.TextInfo.ModeIndex = MatchWindowSize(
Console->OutputCP,
Cur->ScreenBufferSize, &WindowSize);
// grow screen buffer if necessary
if (WindowSize.X > Cur->ScreenBufferSize.X ||
WindowSize.Y > Cur->ScreenBufferSize.Y) {
COORD NewScreenSize;
NewScreenSize.X = max(WindowSize.X,Cur->ScreenBufferSize.X);
NewScreenSize.Y = max(WindowSize.Y,Cur->ScreenBufferSize.Y);
if (ResizeScreenBuffer(Cur, NewScreenSize, FALSE) == STATUS_INVALID_HANDLE) {
return STATUS_INVALID_HANDLE;
}
}
#if 0
DbgPrint("new window size is %d %d\n",WindowSize.X,WindowSize.Y);
DbgPrint("existing window size is %d %d\n",WindowedWindowSize.X,WindowedWindowSize.Y);
DbgPrint("existing window is %d %d %d %d\n",Cur->Window.Left,Cur->Window.Top,Cur->Window.Right,Cur->Window.Bottom);
DbgPrint("screenbuffersize is %d %d\n",Cur->ScreenBufferSize.X,Cur->ScreenBufferSize.Y);
#endif
// set new window dimensions
// we always resize horizontally from the right (change the
// right edge).
// we resize vertically from the bottom, keeping the cursor visible.
if (WindowedWindowSize.X != WindowSize.X) {
Cur->Window.Right -= WindowedWindowSize.X - WindowSize.X;
if (Cur->Window.Right >= Cur->ScreenBufferSize.X) {
Cur->Window.Left -= Cur->Window.Right - Cur->ScreenBufferSize.X + 1;
Cur->Window.Right -= Cur->Window.Right - Cur->ScreenBufferSize.X + 1;
}
}
if (WindowedWindowSize.Y > WindowSize.Y) {
Cur->Window.Bottom -= WindowedWindowSize.Y - WindowSize.Y;
if (Cur->Window.Bottom >= Cur->ScreenBufferSize.Y) {
Cur->Window.Top -= Cur->Window.Bottom - Cur->ScreenBufferSize.Y + 1;
Cur->Window.Bottom = Cur->ScreenBufferSize.Y - 1;
}
} else if (WindowedWindowSize.Y < WindowSize.Y) {
Cur->Window.Top -= WindowSize.Y - WindowedWindowSize.Y;
if (Cur->Window.Top < 0) {
Cur->Window.Bottom -= Cur->Window.Top;
Cur->Window.Top = 0;
}
}
if (Cur->BufferInfo.TextInfo.CursorPosition.Y > Cur->Window.Bottom) {
Cur->Window.Top += Cur->BufferInfo.TextInfo.CursorPosition.Y - Cur->Window.Bottom;
Cur->Window.Bottom = Cur->BufferInfo.TextInfo.CursorPosition.Y;
}
#if 0
DbgPrint("new window is %d %d %d %d\n",Cur->Window.Left,Cur->Window.Top,Cur->Window.Right,Cur->Window.Bottom);
DbgPrint("cursor is %d %d\n",Cur->BufferInfo.TextInfo.CursorPosition.X,Cur->BufferInfo.TextInfo.CursorPosition.Y);
#endif
ASSERT(WindowSize.X == CONSOLE_WINDOW_SIZE_X(Cur));
ASSERT(WindowSize.Y == CONSOLE_WINDOW_SIZE_Y(Cur));
Cur->BufferInfo.TextInfo.MousePosition.X = Cur->Window.Left;
Cur->BufferInfo.TextInfo.MousePosition.Y = Cur->Window.Top;
if (Cur->Flags & CONSOLE_OEMFONT_DISPLAY) {
DBGCHARS(("ConvertToFullScreen converts UnicodeOem -> Unicode\n"));
FalseUnicodeToRealUnicode(
Cur->BufferInfo.TextInfo.TextRows,
Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
Console->OutputCP);
} else {
DBGCHARS(("ConvertToFullScreen needs no conversion\n"));
}
DBGCHARS(("Cur->BufferInfo.TextInfo.Rows = %lx\n",
Cur->BufferInfo.TextInfo.Rows));
DBGCHARS(("Cur->BufferInfo.TextInfo.TextRows = %lx\n",
Cur->BufferInfo.TextInfo.TextRows));
}
Cur = Console->CurrentScreenBuffer;
if (Cur->Flags & CONSOLE_TEXTMODE_BUFFER) {
if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
PCONVERSIONAREA_INFORMATION ConvAreaInfo;
ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
while (ConvAreaInfo) {
NTSTATUS Status;
Status = StoreTextBufferFontInfo(ConvAreaInfo->ScreenBuffer,
SCR_FONTNUMBER(Cur),
SCR_FONTSIZE(Cur),
SCR_FAMILY(Cur),
SCR_FONTWEIGHT(Cur),
SCR_FACENAME(Cur),
SCR_FONTCODEPAGE(Cur));
if (!NT_SUCCESS(Status)) {
return((ULONG) Status);
}
ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = Cur->BufferInfo.TextInfo.ModeIndex;
ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
}
}
Cur->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
}
SetWindowSize(Cur);
WriteToScreen(Cur, &Console->CurrentScreenBuffer->Window);
#else
UNREFERENCED_PARAMETER(Console);
#endif
return STATUS_SUCCESS;
}
NTSTATUS
ConvertToWindowed(
IN PCONSOLE_INFORMATION Console
)
{
#ifdef i386
PSCREEN_INFORMATION Cur;
SMALL_RECT WindowedWindow;
// for each charmode screenbuffer
// restore window dimensions
for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
if ((Cur->Flags & CONSOLE_TEXTMODE_BUFFER) == 0) {
continue;
}
if (ResizeScreenBuffer(Cur,
Cur->BufferInfo.TextInfo.WindowedScreenSize,
FALSE) == STATUS_INVALID_HANDLE) {
/*
* Something really went wrong. All we can do is just to
* bail out.
*/
return STATUS_INVALID_HANDLE;
}
WindowedWindow.Right = Cur->Window.Right;
WindowedWindow.Bottom = Cur->Window.Bottom;
WindowedWindow.Left = Cur->Window.Right + 1 -
Cur->BufferInfo.TextInfo.WindowedWindowSize.X;
WindowedWindow.Top = Cur->Window.Bottom + 1 -
Cur->BufferInfo.TextInfo.WindowedWindowSize.Y;
if (WindowedWindow.Left > Cur->Window.Left) {
WindowedWindow.Right -= WindowedWindow.Left - Cur->Window.Left;
WindowedWindow.Left = Cur->Window.Left;
}
if (WindowedWindow.Right < Cur->BufferInfo.TextInfo.CursorPosition.X) {
WindowedWindow.Left += Cur->BufferInfo.TextInfo.CursorPosition.X - WindowedWindow.Right;
WindowedWindow.Right = Cur->BufferInfo.TextInfo.CursorPosition.X;
}
if (WindowedWindow.Top > Cur->Window.Top) {
WindowedWindow.Bottom -= WindowedWindow.Top - Cur->Window.Top;
WindowedWindow.Top = Cur->Window.Top;
}
if (WindowedWindow.Bottom < Cur->BufferInfo.TextInfo.CursorPosition.Y) {
WindowedWindow.Top += Cur->BufferInfo.TextInfo.CursorPosition.Y - WindowedWindow.Bottom;
WindowedWindow.Bottom = Cur->BufferInfo.TextInfo.CursorPosition.Y;
}
ResizeWindow(Cur, &WindowedWindow, FALSE);
if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
SetFont(Cur);
}
if (Cur->Flags & CONSOLE_OEMFONT_DISPLAY) {
DBGCHARS(("ConvertToWindowed converts Unicode -> UnicodeOem\n"));
RealUnicodeToFalseUnicode(
Cur->BufferInfo.TextInfo.TextRows,
Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
Console->OutputCP);
} else {
DBGCHARS(("ConvertToWindowed needs no conversion\n"));
}
DBGCHARS(("Cur->BufferInfo.TextInfo.Rows = %lx\n",
Cur->BufferInfo.TextInfo.Rows));
DBGCHARS(("Cur->BufferInfo.TextInfo.TextRows = %lx\n",
Cur->BufferInfo.TextInfo.TextRows));
}
Cur = Console->CurrentScreenBuffer;
if (Cur->Flags & CONSOLE_TEXTMODE_BUFFER) {
if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
PCONVERSIONAREA_INFORMATION ConvAreaInfo;
ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
while (ConvAreaInfo) {
NTSTATUS Status;
Status = StoreTextBufferFontInfo(ConvAreaInfo->ScreenBuffer,
SCR_FONTNUMBER(Cur),
SCR_FONTSIZE(Cur),
SCR_FAMILY(Cur),
SCR_FONTWEIGHT(Cur),
SCR_FACENAME(Cur),
SCR_FONTCODEPAGE(Cur));
if (!NT_SUCCESS(Status)) {
return((ULONG) Status);
}
ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = Cur->BufferInfo.TextInfo.ModeIndex;
ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
}
}
Cur->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
}
SetWindowSize(Cur);
WriteToScreen(Cur, &Console->CurrentScreenBuffer->Window);
#else
UNREFERENCED_PARAMETER(Console);
#endif
return STATUS_SUCCESS;
}
ULONG
SrvSetConsoleDisplayMode(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
/*++
Description:
This routine sets the console display mode for an output buffer.
This API is only supported on x86 machines. Jazz consoles are always
windowed.
Parameters:
hConsoleOutput - Supplies a console output handle.
dwFlags - Specifies the display mode. Options are:
CONSOLE_FULLSCREEN_MODE - data is displayed fullscreen
CONSOLE_WINDOWED_MODE - data is displayed in a window
lpNewScreenBufferDimensions - On output, contains the new dimensions of
the screen buffer. The dimensions are in rows and columns for
textmode screen buffers.
Return value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
PCONSOLE_SETDISPLAYMODE_MSG a = (PCONSOLE_SETDISPLAYMODE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
PSCREEN_INFORMATION ScreenInfo;
UINT State;
HANDLE hEvent = NULL;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
a->hEvent,
NtCurrentProcess(),
&hEvent,
0,
FALSE,
DUPLICATE_SAME_ACCESS
);
if (!NT_SUCCESS(Status)) {
goto SrvSetConsoleDisplayModeFailure;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
GENERIC_WRITE,
&HandleData
);
if (NT_SUCCESS(Status)) {
ScreenInfo = HandleData->Buffer.ScreenBuffer;
if (!ACTIVE_SCREEN_BUFFER(ScreenInfo)) {
Status = STATUS_INVALID_PARAMETER;
goto SrvSetConsoleDisplayModeFailure;
}
if (a->dwFlags == CONSOLE_FULLSCREEN_MODE) {
#if !defined(_X86_)
if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
Status = STATUS_INVALID_PARAMETER;
goto SrvSetConsoleDisplayModeFailure;
}
#else
if (!FullScreenInitialized) {
Status = STATUS_INVALID_PARAMETER;
goto SrvSetConsoleDisplayModeFailure;
}
#endif
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
KdPrint(("CONSRV: VDM converting to fullscreen twice\n"));
ASSERT(FALSE);
Status = STATUS_INVALID_PARAMETER;
goto SrvSetConsoleDisplayModeFailure;
}
State = FULLSCREEN;
} else {
if (Console->FullScreenFlags == 0) {
KdPrint(("CONSRV: VDM converting to windowed twice\n"));
ASSERT(FALSE);
Status = STATUS_INVALID_PARAMETER;
goto SrvSetConsoleDisplayModeFailure;
}
State = WINDOWED;
}
Status = QueueConsoleMessage(Console,
CM_MODE_TRANSITION,
State,
(LPARAM)hEvent
);
if (!NT_SUCCESS(Status)) {
goto SrvSetConsoleDisplayModeFailure;
}
}
UnlockConsole(Console);
return Status;
SrvSetConsoleDisplayModeFailure:
if (hEvent) {
NtSetEvent(hEvent, NULL);
NtClose(hEvent);
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
VOID
UnregisterVDM(
IN PCONSOLE_INFORMATION Console
)
{
// williamh, Feb 2 1994.
// catch multiple calls to unregister vdm. Believe it or not, this could
// happen
ASSERT(Console->Flags & CONSOLE_VDM_REGISTERED);
if (!(Console->Flags & CONSOLE_VDM_REGISTERED))
return;
#if defined(FE_SB) && defined(i386)
// When HDOS apps exit, console screen resolution is changed to 640*400. Because HBIOS set
// Screen resolution to 640*400. So, we should replace current screen resoultion(640*480).
// 09/11/96 bklee
{
if ((Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) &&
( Console->OutputCP == KOREAN_CP ||
(Console->OutputCP == JAPAN_CP && ISNECPC98(gdwMachineId) ) )) {
ULONG Index;
DEVMODEW Devmode;
BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
ZeroMemory(&Devmode, sizeof(Devmode));
Devmode.dmSize = sizeof(Devmode);
Devmode.dmDriverExtra = 0;
Devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFLAGS;
Devmode.dmBitsPerPel = 4;
Devmode.dmPelsWidth = RegModeFontPairs[Index].Resolution.X;
Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
GdiFullscreenControl(FullscreenControlSetMode,
&Devmode,
sizeof(Devmode),
NULL,
NULL);
}
}
#endif
#ifdef i386
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) {
NtUserConsoleControl(ConsoleSetVDMCursorBounds, NULL, 0);
// connect emulator
ConnectToEmulator(FALSE, Console);
}
if (FullScreenInitialized) {
CloseHandle(Console->VDMStartHardwareEvent);
CloseHandle(Console->VDMEndHardwareEvent);
NtUnmapViewOfSection(NtCurrentProcess(),Console->StateBuffer);
NtUnmapViewOfSection(Console->VDMProcessHandle,Console->StateBufferClient);
NtClose(Console->StateSectionHandle);
Console->StateLength = 0;
}
#endif
Console->Flags &= ~CONSOLE_VDM_REGISTERED;
if (Console->Flags & CONSOLE_HAS_FOCUS) {
USERTHREAD_FLAGS Flags;
Flags.dwFlags = 0;
Flags.dwMask = (TIF_VDMAPP | TIF_DOSEMULATOR);
NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
UserThreadFlags, &Flags, sizeof(Flags));
}
Console->Flags &= ~CONSOLE_WOW_REGISTERED;
ASSERT(Console->VDMBuffer != NULL);
if (Console->VDMBuffer != NULL) {
NtUnmapViewOfSection(Console->VDMProcessHandle,Console->VDMBufferClient);
NtUnmapViewOfSection(NtCurrentProcess(),Console->VDMBuffer);
NtClose(Console->VDMBufferSectionHandle);
Console->VDMBuffer = NULL;
}
#ifdef i386
if (Console->CurrentScreenBuffer &&
Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
Console->CurrentScreenBuffer->BufferInfo.TextInfo.MousePosition.X = 0;
Console->CurrentScreenBuffer->BufferInfo.TextInfo.MousePosition.Y = 0;
}
#endif
ASSERT(Console->VDMProcessHandle);
CloseHandle(Console->VDMProcessHandle);
Console->VDMProcessHandle = NULL;
#if defined(FE_SB) && defined(FE_IME) && defined(i386)
{
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
Console->Flags |= CONSOLE_JUST_VDM_UNREGISTERED ;
}
else if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
AdjustCursorPosition(Console->CurrentScreenBuffer,
Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorPosition,
TRUE,
NULL);
}
}
#endif
}
ULONG
SrvRegisterConsoleVDM(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_REGISTERVDM_MSG a = (PCONSOLE_REGISTERVDM_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
SIZE_T ViewSize;
#ifdef i386
VIDEO_REGISTER_VDM RegisterVdm;
ULONG RegisterVdmSize = sizeof(RegisterVdm);
VIDEO_VDM Vdm;
#endif //i386
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (!a->RegisterFlags) {
// williamh, Jan 28 1994
// do not do an assert here because we may have unregistered the ntvdm
// and the ntvdm doesn't necessarily know this(and it could post another
// unregistervdm). Return error here so NTVDM knows what to do
// ASSERT(Console->Flags & CONSOLE_VDM_REGISTERED);
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
ASSERT(!(Console->Flags & CONSOLE_FULLSCREEN_NOPAINT));
UnregisterVDM(Console);
#ifdef i386
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
// SetVideoMode(Console->CurrentScreenBuffer);
//set up cursor
SetCursorInformationHW(Console->CurrentScreenBuffer,
Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorSize,
Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorVisible);
SetCursorPositionHW(Console->CurrentScreenBuffer,
Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorPosition);
}
#endif
Status = STATUS_SUCCESS;
} else {
Status = STATUS_ACCESS_DENIED;
}
UnlockConsole(Console);
return Status;
}
if (!CsrValidateMessageBuffer(m, &a->StateSectionName, a->StateSectionNameLength, sizeof(BYTE)) ||
!CsrValidateMessageBuffer(m, &a->VDMBufferSectionName, a->VDMBufferSectionNameLength, sizeof(BYTE))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
// check it out. A console should have only one VDM registered.
ASSERT(!(Console->Flags & CONSOLE_VDM_REGISTERED));
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
UnlockConsole(Console);
return (ULONG) STATUS_ACCESS_DENIED;
}
ASSERT(!Console->VDMProcessHandle);
Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
NtCurrentProcess(), &Console->VDMProcessHandle,
0, FALSE, DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status)) {
UnlockConsole(Console);
return Status;
}
Console->VDMProcessId = CONSOLE_CLIENTPROCESSID();
#ifdef i386
Vdm.ProcessHandle = Console->VDMProcessHandle;
// Assume fullscreen initialization will fail.
// have state length set to zero so that NTVDM will know
// full screen is disabled.
a->StateLength = 0;
Console->StateLength = 0;
Console->StateBufferClient = NULL;
if (FullScreenInitialized) {
Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
a->StartEvent,
NtCurrentProcess(),
&Console->VDMStartHardwareEvent,
0,
FALSE,
DUPLICATE_SAME_ACCESS
);
if (NT_SUCCESS(Status)) {
Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
a->EndEvent,
NtCurrentProcess(),
&Console->VDMEndHardwareEvent,
0,
FALSE,
DUPLICATE_SAME_ACCESS
);
if (NT_SUCCESS(Status)) {
Status = GdiFullscreenControl(FullscreenControlRegisterVdm,
&Vdm,
sizeof(Vdm),
&RegisterVdm,
&RegisterVdmSize
);
if (NT_SUCCESS(Status)) {
// create state section and map a view of it into server and vdm.
// this section is used to get/set video hardware state during
// the fullscreen<->windowed transition. we create the section
// instead of the vdm for security purposes.
Status = MapViewOfSection(&Console->StateSectionHandle,
RegisterVdm.MinimumStateSize,
&Console->StateBuffer,
&ViewSize,
Console->VDMProcessHandle,
&a->StateBuffer
);
if (NT_SUCCESS(Status)) {
a->StateLength = RegisterVdm.MinimumStateSize;
Console->StateLength = RegisterVdm.MinimumStateSize;
Console->StateBufferClient = a->StateBuffer;
}
} else {
CloseHandle(Console->VDMStartHardwareEvent);
CloseHandle(Console->VDMEndHardwareEvent);
}
} else {
// ASSERT(FALSE);
CloseHandle(Console->VDMStartHardwareEvent);
CloseHandle(Console->VDMEndHardwareEvent);
}
} else {
CloseHandle(Console->VDMStartHardwareEvent);
}
// if failed to duplicate screen switch events or map view
// to video state shared buffer, fails this API
if (!NT_SUCCESS(Status)) {
UnlockConsole(Console);
return (Status);
}
}
#endif
// create vdm char section and map a view of it into server and vdm.
// this section is used by the vdm to update the screen when in a
// charmode window. this is a performance optimization. we create
// the section instead of the vdm for security purposes.
Status = MapViewOfSection(&Console->VDMBufferSectionHandle,
#ifdef i386
a->VDMBufferSize.X*a->VDMBufferSize.Y*2,
#else //risc
a->VDMBufferSize.X*a->VDMBufferSize.Y*4,
#endif
&Console->VDMBuffer,
&ViewSize,
Console->VDMProcessHandle,
&a->VDMBuffer
);
if (!NT_SUCCESS(Status)) {
Console->VDMBuffer = NULL;
#ifdef i386
if (FullScreenInitialized) {
NtUnmapViewOfSection(NtCurrentProcess(),Console->StateBuffer);
NtUnmapViewOfSection(Console->VDMProcessHandle,Console->StateBufferClient);
NtClose(Console->StateSectionHandle);
CloseHandle(Console->VDMStartHardwareEvent);
CloseHandle(Console->VDMEndHardwareEvent);
}
#endif
CloseHandle(Console->VDMProcessHandle);
Console->VDMProcessHandle = NULL;
UnlockConsole(Console);
return((ULONG) Status);
}
Console->VDMBufferClient = a->VDMBuffer;
Console->Flags |= CONSOLE_VDM_REGISTERED;
if (Console->Flags & CONSOLE_HAS_FOCUS) {
USERTHREAD_FLAGS Flags;
Flags.dwFlags = TIF_VDMAPP;
Flags.dwMask = TIF_VDMAPP;
NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
UserThreadFlags, &Flags, sizeof(Flags));
}
Console->VDMBufferSize = a->VDMBufferSize;
if (a->RegisterFlags & CONSOLE_REGISTER_WOW)
Console->Flags |= CONSOLE_WOW_REGISTERED;
else
Console->Flags &= ~CONSOLE_WOW_REGISTERED;
// if we're already in fullscreen and we run a DOS app for
// the first time, connect the emulator.
#ifdef i386
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
RECT CursorRect;
CursorRect.left = -32767;
CursorRect.top = -32767;
CursorRect.right = 32767;
CursorRect.bottom = 32767;
NtUserConsoleControl(ConsoleSetVDMCursorBounds, &CursorRect, sizeof(RECT));
// connect emulator
ASSERT(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR));
ConnectToEmulator(TRUE, Console);
}
#endif
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
NTSTATUS
SrvConsoleNotifyLastClose(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_NOTIFYLASTCLOSE_MSG a = (PCONSOLE_NOTIFYLASTCLOSE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
// williamh, Feb 2 1994.
// this non-X86 special case is not necessary. We expect
// ntvdm to call RegisterConsoleVDM API and there we do duplicate
// the vdm process handle and grab its process id.
// If we continue to do this we may hit the assert below
// because when RegisterConsoleVDM failed(short of memory, for example)
// the VDMProcessHandle may have been set and next time a vdm application
// was launched from the same console(ntvdm will do the NotifyLastClose
// before RegisterConsoleVDM).
#if 0
#if !defined(_X86_)
ASSERT(Console->VDMProcessHandle == NULL);
Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
NtCurrentProcess(), &Console->VDMProcessHandle,
0, FALSE, DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status)) {
return Status;
}
Console->VDMProcessId = CONSOLE_CLIENTPROCESSID();
#endif
#endif
// Doesn't allow two or more processes to have last-close notify on
// the same console
if (Console->Flags & CONSOLE_NOTIFY_LAST_CLOSE) {
UnlockConsole(Console);
return (ULONG)STATUS_ACCESS_DENIED;
}
Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
NtCurrentProcess(),
&Console->hProcessLastNotifyClose,
0, FALSE, DUPLICATE_SAME_ACCESS
);
if (!NT_SUCCESS(Status)) {
UnlockConsole(Console);
return Status;
}
Console->Flags |= CONSOLE_NOTIFY_LAST_CLOSE;
Console->ProcessIdLastNotifyClose = CONSOLE_CLIENTPROCESSID();
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
NTSTATUS MapViewOfSection(PHANDLE SectionHandle, ULONG CommitSize, PVOID *BaseAddress, PSIZE_T ViewSize, HANDLE ClientHandle, PVOID *BaseClientAddress)
{
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
LARGE_INTEGER secSize;
// open section and map a view of it.
InitializeObjectAttributes(&Obja, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
secSize.QuadPart = CommitSize;
Status = NtCreateSection (SectionHandle, SECTION_ALL_ACCESS, &Obja, &secSize, PAGE_READWRITE, SEC_RESERVE, NULL);
if (!NT_SUCCESS(Status)) {
return((ULONG) Status);
}
*BaseAddress = 0;
*ViewSize = 0;
Status = NtMapViewOfSection(*SectionHandle,
NtCurrentProcess(),
BaseAddress, // Receives the base
// address of the section.
0, // No specific type of
// address required.
CommitSize, // Commit size. It was
// passed by the caller.
// NULL for a save, and
// size of the section
// for a set.
NULL, // Section offset it NULL;
// Map from the start.
ViewSize, // View Size is NULL since
// we want to map the
// entire section.
ViewUnmap,
0L,
PAGE_READWRITE
);
if (!NT_SUCCESS(Status)) {
NtClose(*SectionHandle);
return Status;
}
*BaseClientAddress = 0;
*ViewSize = 0;
Status = NtMapViewOfSection(*SectionHandle,
ClientHandle,
BaseClientAddress, // Receives the base
// address of the section.
0, // No specific type of
// address required.
CommitSize, // Commit size. It was
// passed by the caller.
// NULL for a save, and
// size of the section
// for a set.
NULL, // Section offset it NULL;
// Map from the start.
ViewSize, // View Size is NULL since
// we want to map the
// entire section.
ViewUnmap,
// williamh, Jan 28 1994
// This MEM_TOP_DOWN is necessary.
// if the console has VDM registered, ntvdm would have released its video memory
// address space(0xA0000 ~ 0xBFFFF). Without the MEM_TOP_DOWN, the
// NtMapViewOfSection can grab the address space and we will have trouble of
// mapping the address space to the physical video ram. We don't do a test
// for VDM because there is no harm of doing this for non-vdm application.
MEM_TOP_DOWN,
PAGE_READWRITE
);
if (!NT_SUCCESS(Status)) {
NtClose(*SectionHandle);
}
return((ULONG) Status);
}
NTSTATUS
ConnectToEmulator(
IN BOOL Connect,
IN PCONSOLE_INFORMATION Console
)
{
NTSTATUS Status;
FULLSCREENCONTROL fsctl;
VIDEO_VDM ConnectInfo;
HANDLE ProcessHandle = Console->VDMProcessHandle;
USERTHREAD_FLAGS Flags;
DBGFULLSCR(("ConnectToEmulator : %s - entering\n", Connect ? "CONNECT" : "DISCONNECT"));
Flags.dwMask = TIF_DOSEMULATOR;
if (Connect) {
fsctl = FullscreenControlEnable;
Console->Flags |= CONSOLE_CONNECTED_TO_EMULATOR;
Flags.dwFlags = TIF_DOSEMULATOR;
} else {
fsctl = FullscreenControlDisable;
Console->Flags &= ~CONSOLE_CONNECTED_TO_EMULATOR;
Flags.dwFlags = 0;
}
if (Console->Flags & CONSOLE_HAS_FOCUS) {
NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
UserThreadFlags, &Flags, sizeof(Flags));
}
ConnectInfo.ProcessHandle = ProcessHandle;
Status = GdiFullscreenControl(fsctl,
&ConnectInfo,
sizeof(ConnectInfo),
NULL,
NULL);
ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PROCESS_IS_TERMINATING);
DBGFULLSCR(("ConnectToEmulator : leaving, staus = %08lx\n", Status));
return Status;
}
#define CONSOLE_VDM_TIMEOUT 200000
NTSTATUS
DisplayModeTransition(
IN BOOL bForeground,
IN PCONSOLE_INFORMATION Console,
IN PSCREEN_INFORMATION ScreenInfo
)
{
#ifdef i386
NTSTATUS Status;
LARGE_INTEGER li;
if (!FullScreenInitialized)
return STATUS_SUCCESS;
if (bForeground) {
PSCREEN_INFORMATION ScreenInfo = Console->CurrentScreenBuffer;
LARGE_INTEGER li;
NTSTATUS Status;
KdPrint((" CONSRV - Display Mode transition to fullscreen \n"));
if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
KdPrint(("CONSRV: received fullscreen message too early\n"));
return STATUS_UNSUCCESSFUL;
}
Console->FullScreenFlags |= CONSOLE_FULLSCREEN_HARDWARE;
if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
#if defined(FE_SB)
BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
#endif
#if 1
DEVMODEW Devmode;
ULONG Index;
KdPrint(("CONSRV: ChangeDispSettings fullscreen\n"));
Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
// set mode to go to full screen
ZeroMemory(&Devmode, sizeof(Devmode));
Devmode.dmSize = sizeof(Devmode);
Devmode.dmDriverExtra = 0;
Devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFLAGS;
Devmode.dmBitsPerPel = 4;
#if defined(FE_SB)
Devmode.dmPelsWidth = RegModeFontPairs[Index].Resolution.X;
Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
#else
Devmode.dmPelsWidth = ModeFontPairs[Index].Resolution.X;
Devmode.dmPelsHeight = ModeFontPairs[Index].Resolution.Y;
Devmode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
#endif
if (NT_SUCCESS(GdiFullscreenControl(FullscreenControlSetMode,
&Devmode,
sizeof(Devmode),
NULL,
NULL)))
{
#endif
// set video mode and font
if (SetVideoMode(ScreenInfo)) {
#if defined(FE_SB)
if (!(Console->Flags & CONSOLE_VDM_REGISTERED)) {
int i ;
for (i = 0 ; i < ScreenInfo->ScreenBufferSize.Y; i++) {
ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldLeft = INVALID_OLD_LENGTH ;
ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldRight = INVALID_OLD_LENGTH ;
}
}
#endif
//set up cursor
SetCursorInformationHW(ScreenInfo,
ScreenInfo->BufferInfo.TextInfo.CursorSize,
ScreenInfo->BufferInfo.TextInfo.CursorVisible);
SetCursorPositionHW(ScreenInfo,
ScreenInfo->BufferInfo.TextInfo.CursorPosition);
}
}
}
// tell VDM to unmap memory
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
Status = NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
Console->VDMEndHardwareEvent,
FALSE, &li);
if (Status != 0) {
Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
UnregisterVDM(Console);
KdPrint(("CONSRV: VDM not responding.\n"));
}
}
if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
WriteRegionToScreen(ScreenInfo,&ScreenInfo->Window);
}
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
// connect emulator and map memory into the VDMs address space.
ASSERT(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR));
Status = ConnectToEmulator(TRUE, Console);
if (NT_SUCCESS(Status)) {
VIDEO_HARDWARE_STATE State;
ULONG StateSize = sizeof(State);
State.StateHeader = Console->StateBuffer;
State.StateLength = Console->StateLength;
Status = GdiFullscreenControl(FullscreenControlRestoreHardwareState,
&State,
StateSize,
&State,
&StateSize);
}
if (Status != STATUS_SUCCESS) {
Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
UnregisterVDM(Console);
KdPrint(("CONSRV: set hardware state failed.\n"));
} else {
// tell VDM that it's getting the hardware.
RECT CursorRect;
CursorRect.left = -32767;
CursorRect.top = -32767;
CursorRect.right = 32767;
CursorRect.bottom = 32767;
NtUserConsoleControl(ConsoleSetVDMCursorBounds,
&CursorRect, sizeof(RECT));
// wait for vdm to say ok. We could initiate another switch
// (set hStartHardwareEvent which vdm is now waiting for to
// complete the handshaking) when we return(WM_FULLSCREEN
// could be in the message queue already). If we don't wait
// for vdm to get signaled here, the hStartHardwareEvent
// can get set twice and signaled once so the vdm will never
// gets the newly switch request we may post after return.
NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
Console->VDMEndHardwareEvent,
FALSE, &li);
// no need to check time out here
}
}
// let the app know that it has the focus.
HandleFocusEvent(Console,TRUE);
// unset palette
if (ScreenInfo->hPalette != NULL) {
SelectPalette(ScreenInfo->Console->hDC,
ScreenInfo->Console->hSysPalette,
FALSE);
UnsetActivePalette(ScreenInfo);
}
SetConsoleReserveKeys(Console->hWnd, Console->ReserveKeys);
HandleFocusEvent(Console,TRUE);
} else {
KdPrint((" CONSRV - Display Mode transition to windowed \n"));
// Check first to see if we're not already fullscreen. If we aren't,
// don't allow this. Temporary BETA fix till USER gets fixed.
if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
KdPrint(("CONSRV: received multiple windowed messages\n"));
return STATUS_SUCCESS;
}
// turn off mouse pointer so VDM doesn't see it when saving
// hardware
if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
}
Console->FullScreenFlags &= ~CONSOLE_FULLSCREEN_HARDWARE;
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
// tell vdm that it's losing the hardware
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
Status = NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
Console->VDMEndHardwareEvent,
FALSE, &li);
// if ntvdm didn't respond or we failed to save the video hardware
// states, kick ntvdm out of our world. The ntvdm process eventually
// would die but what choice do have here?
if (NT_SUCCESS(Status)) {
VIDEO_HARDWARE_STATE State;
ULONG StateSize = sizeof(State);
State.StateHeader = Console->StateBuffer;
State.StateLength = Console->StateLength;
Status = GdiFullscreenControl(FullscreenControlSaveHardwareState,
&State,
StateSize,
&State,
&StateSize);
}
if (NT_SUCCESS(Status)) {
NtUserConsoleControl(ConsoleSetVDMCursorBounds, NULL, 0);
// disconnect emulator and unmap video memory
ASSERT(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR);
ConnectToEmulator(FALSE, Console);
} else {
Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
UnregisterVDM(Console);
if (Status != 0) {
KdPrint(("CONSRV: VDM not responding.\n"));
}
else
KdPrint(("CONSRV: Save Video States Failed\n"));
}
}
// tell VDM to map memory
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
// make a special case for ntvdm during switching because
// ntvdm has to make console api calls. We don't want to
// unlock the console at this moment because as soon as
// we release the lock, other theads which are waiting
// for the lock will claim the lock and the ntvdm thread doing
// the screen switch will have to wait for the lock. In an
// extreme case, the following NtWaitForSingleObject will time
// out because the ntvdm may be still waiting for the lock.
// We keep this thing in a single global variable because
// there is only one process who can own the screen at any moment.
RtlEnterCriticalSection(&ConsoleVDMCriticalSection);
ConsoleVDMOnSwitching = Console;
RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
Status = NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
Console->VDMEndHardwareEvent,
FALSE, &li);
// time to go back to normal
RtlEnterCriticalSection(&ConsoleVDMCriticalSection);
ConsoleVDMOnSwitching = NULL;
RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
if (Status != 0) {
Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
UnregisterVDM(Console);
KdPrint(("CONSRV: VDM not responding. - second wait\n"));
return Status;
}
ScreenInfo = Console->CurrentScreenBuffer;
}
// set palette
if (ScreenInfo->hPalette != NULL) {
SelectPalette(ScreenInfo->Console->hDC,
ScreenInfo->hPalette,
FALSE);
SetActivePalette(ScreenInfo);
}
SetConsoleReserveKeys(Console->hWnd, CONSOLE_NOSHORTCUTKEY);
HandleFocusEvent(Console,FALSE);
}
/*
* Boost or lower the priority if we are going fullscreen or away.
* Note that console usually boosts and lowers its priority based
* on WM_FOCUSS and WM_KILLFOCUS but when you switch to full screen
* the implementation actually sends a WM_KILLFOCUS so we reboost the
* correct console here.
*/
ModifyConsoleProcessFocus(Console, bForeground);
#else
UNREFERENCED_PARAMETER(bForeground);
UNREFERENCED_PARAMETER(Console);
UNREFERENCED_PARAMETER(ScreenInfo);
#endif
return STATUS_SUCCESS;
}
#if defined(_X86_)
BOOL
SetVideoMode(
IN PSCREEN_INFORMATION ScreenInfo
)
{
NTSTATUS Status;
UINT i, j;
#if defined(FE_SB)
// load RAM font
Status = SetRAMFontCodePage(ScreenInfo);
#endif
// load ROM font
Status = SetROMFontCodePage(ScreenInfo->Console->OutputCP,
ScreenInfo->BufferInfo.TextInfo.ModeIndex);
if (Status == STATUS_INVALID_PARAMETER) {
Status = SetROMFontCodePage(GetOEMCP(),
ScreenInfo->BufferInfo.TextInfo.ModeIndex);
if (Status == STATUS_INVALID_PARAMETER) {
Status = SetROMFontCodePage(CONSOLE_DEFAULT_ROM_FONT,
ScreenInfo->BufferInfo.TextInfo.ModeIndex);
}
}
// initialize palette
#if defined(FE_SB)
Status = GdiFullscreenControl(FullscreenControlSetPalette,
(PVOID) RegInitialPalette,
RegInitialPalette[0] * sizeof(USHORT) + sizeof(DWORD),
NULL,
NULL);
#else
Status = GdiFullscreenControl(FullscreenControlSetPalette,
(PVOID) &InitialPalette,
sizeof (InitialPalette),
NULL,
NULL);
#endif
if (Status != STATUS_SUCCESS) {
KdPrint(("CONSRV: FullscreenControlSetPalette failed - status = %x\n",
Status));
ASSERT(FALSE);
return FALSE;
}
// initialize color table
#if defined(FE_SB)
if (RegColorBufferNoTranslate)
{
Status = GdiFullscreenControl(FullscreenControlSetColors,
(PVOID) RegColorBufferNoTranslate,
RegColorBufferNoTranslate[0] * sizeof(DWORD) + sizeof(DWORD),
NULL,
NULL);
}
else
{
for (i = 0, j = 4; i < 16; i++) {
RegColorBuffer[j++] = ((((GetRValue(ScreenInfo->Console->ColorTable[i]) +
0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
RegColorBuffer[j++] = ((((GetGValue(ScreenInfo->Console->ColorTable[i]) +
0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
RegColorBuffer[j++] = ((((GetBValue(ScreenInfo->Console->ColorTable[i]) +
0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
RegColorBuffer[j++] = 0;
}
Status = GdiFullscreenControl(FullscreenControlSetColors,
(PVOID) RegColorBuffer,
RegColorBuffer[0] * sizeof(DWORD) + sizeof(DWORD),
NULL,
NULL);
}
#else
for (i = 0, j = 4; i < 16; i++) {
ColorBuffer[j++] = ((((GetRValue(ScreenInfo->Console->ColorTable[i]) +
0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
ColorBuffer[j++] = ((((GetGValue(ScreenInfo->Console->ColorTable[i]) +
0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
ColorBuffer[j++] = ((((GetBValue(ScreenInfo->Console->ColorTable[i]) +
0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
ColorBuffer[j++] = 0;
}
Status = GdiFullscreenControl(FullscreenControlSetColors,
(PVOID) &ColorBuffer,
sizeof (ColorBuffer),
NULL,
NULL);
#endif
if (Status != STATUS_SUCCESS) {
KdPrint(("CONSRV: FullscreenControlSetColors failed - status = %x\n",
Status));
ASSERT(FALSE);
return FALSE;
}
return TRUE;
}
#endif
#if defined(_X86_)
NTSTATUS
ChangeDispSettings(
PCONSOLE_INFORMATION Console,
HWND hwnd,
DWORD dwFlags)
{
DEVMODEW Devmode;
ULONG Index;
CONSOLE_FULLSCREEN_SWITCH switchBlock;
if (dwFlags == CDS_FULLSCREEN)
{
#if defined(FE_SB)
BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
#endif
KdPrint(("CONSRV: ChangeDispSettings fullscreen\n"));
Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
// set mode to go to full screen
ZeroMemory(&Devmode, sizeof(Devmode));
Devmode.dmSize = sizeof(Devmode);
Devmode.dmDriverExtra = 0;
Devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFLAGS;
Devmode.dmBitsPerPel = 4;
#if defined(FE_SB)
Devmode.dmPelsWidth = RegModeFontPairs[Index].Resolution.X;
Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
#else
Devmode.dmPelsWidth = ModeFontPairs[Index].Resolution.X;
Devmode.dmPelsHeight = ModeFontPairs[Index].Resolution.Y;
Devmode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
#endif
switchBlock.bFullscreenSwitch = TRUE;
switchBlock.hwnd = hwnd;
switchBlock.pNewMode = &Devmode;
}
else
{
KdPrint(("CONSRV: ChangeDispSettings windowed\n"));
switchBlock.bFullscreenSwitch = FALSE;
switchBlock.hwnd = hwnd;
switchBlock.pNewMode = NULL;
}
return NtUserConsoleControl(ConsoleFullscreenSwitch,
&switchBlock,
sizeof(CONSOLE_FULLSCREEN_SWITCH));
}
#endif
BOOL
InitializeFullScreen( VOID )
{
UNICODE_STRING vgaString;
DEVMODEW devmode;
ULONG i;
#if !defined(FE_SB)
BOOLEAN mode1 = FALSE;
BOOLEAN mode2 = FALSE;
#else
DWORD mode1 = 0;
DWORD mode2 = 0;
#endif
CHAR WindowsDir[CONSOLE_WINDOWS_DIR_LENGTH+CONSOLE_EGACPI_LENGTH];
UINT WindowsDirLength;
// query number of available modes
ZeroMemory(&devmode, sizeof(DEVMODEW));
devmode.dmSize = sizeof(DEVMODEW);
RtlInitUnicodeString(&vgaString, L"VGACOMPATIBLE");
DBGCHARS(("Number of modes = %d\n", NUMBER_OF_MODE_FONT_PAIRS));
for (i=0; ; i++)
{
DBGCHARS(("EnumDisplaySettings %d\n", i));
if (!(NT_SUCCESS(NtUserEnumDisplaySettings(&vgaString,
i,
&devmode,
0))))
{
break;
}
#if defined(FE_SB)
{
ULONG Index;
DBGCHARS(("Mode X = %d, Y = %d\n",
devmode.dmPelsWidth, devmode.dmPelsHeight));
for (Index=0;Index<NUMBER_OF_MODE_FONT_PAIRS;Index++)
{
if ((SHORT)devmode.dmPelsWidth == RegModeFontPairs[Index].Resolution.X &&
(SHORT)devmode.dmPelsHeight == RegModeFontPairs[Index].Resolution.Y )
{
if (devmode.dmDisplayFlags & DMDISPLAYFLAGS_TEXTMODE)
{
if (RegModeFontPairs[Index].Mode & FS_MODE_TEXT)
{
RegModeFontPairs[Index].Mode |= FS_MODE_FIND;
mode1++;
}
}
else
{
if (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)
{
RegModeFontPairs[Index].Mode |= FS_MODE_FIND;
mode2++;
}
}
}
}
DBGCHARS(("mode1 = %d, mode2 = %d\n", mode1, mode2));
}
#else
if (devmode.dmPelsWidth == 720 &&
devmode.dmPelsHeight == 400)
{
mode1 = TRUE;
}
if (devmode.dmPelsWidth == 640 &&
devmode.dmPelsHeight == 350)
{
mode2 = TRUE;
}
#endif
}
#if !defined(FE_SB)
if (!(mode1 && mode2))
#else
if (mode1 < 2)
#endif
{
// One of the modes we expected to get was not returned.
// lets just fail fullscreen initialization.
KdPrint(("CONSRV: InitializeFullScreen Missing text mode\n"));
return FALSE;
}
#if defined(FE_SB)
if (mode2 > 0)
{
// Can do trun graphics mode.
fFullScreenGraphics = TRUE;
}
#endif
// open ega.cpi
WindowsDirLength = GetSystemDirectoryA(WindowsDir,
CONSOLE_WINDOWS_DIR_LENGTH);
if (WindowsDirLength == 0)
{
KdPrint(("CONSRV: InitializeFullScreen Finding Font file failed\n"));
return FALSE;
}
RtlCopyMemory(&WindowsDir[WindowsDirLength],
CONSOLE_EGACPI,
CONSOLE_EGACPI_LENGTH);
if ((hCPIFile = CreateFileA(WindowsDir,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL)) == (HANDLE)-1)
{
KdPrint(("CONSRV: InitializeFullScreen Opening Font file failed\n"));
return FALSE;
}
return TRUE;
}
ULONG
SrvGetConsoleHardwareState(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
#ifdef i386
PCONSOLE_GETHARDWARESTATE_MSG a = (PCONSOLE_GETHARDWARESTATE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
PSCREEN_INFORMATION ScreenInfo;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_READ,
&HandleData
);
if (NT_SUCCESS(Status)) {
ScreenInfo = HandleData->Buffer.ScreenBuffer;
if (ScreenInfo->BufferInfo.TextInfo.ModeIndex == -1) {
UnlockConsole(Console);
return (ULONG)STATUS_UNSUCCESSFUL;
}
#if defined(FE_SB)
a->Resolution = RegModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].Resolution;
a->FontSize = RegModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].FontSize;
#else
a->Resolution = ModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].Resolution;
a->FontSize = ModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].FontSize;
#endif
}
UnlockConsole(Console);
return Status;
#else
return (ULONG)STATUS_UNSUCCESSFUL;
UNREFERENCED_PARAMETER(m); // get rid of unreferenced parameter warning message
#endif
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvSetConsoleHardwareState(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
#ifdef i386
PCONSOLE_SETHARDWARESTATE_MSG a = (PCONSOLE_SETHARDWARESTATE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
PSCREEN_INFORMATION ScreenInfo;
ULONG Index;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
UnlockConsole(Console);
return (ULONG)STATUS_UNSUCCESSFUL;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_READ,
&HandleData
);
if (NT_SUCCESS(Status)) {
#if defined(FE_SB)
BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
#endif
ScreenInfo = HandleData->Buffer.ScreenBuffer;
// match requested mode
for (Index=0;Index<NUMBER_OF_MODE_FONT_PAIRS;Index++) {
#if defined(FE_SB)
if (a->Resolution.X == RegModeFontPairs[Index].Resolution.X &&
a->Resolution.Y == RegModeFontPairs[Index].Resolution.Y &&
a->FontSize.Y == RegModeFontPairs[Index].FontSize.Y &&
a->FontSize.X == RegModeFontPairs[Index].FontSize.X &&
( ( fGraphics && (RegModeFontPairs[Index].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
(!fGraphics && (RegModeFontPairs[Index].Mode & FS_TEXT)==FS_TEXT) )
) {
break;
}
#else
if (a->Resolution.X == ModeFontPairs[Index].Resolution.X &&
a->Resolution.Y == ModeFontPairs[Index].Resolution.Y &&
a->FontSize.Y == ModeFontPairs[Index].FontSize.Y &&
a->FontSize.X == ModeFontPairs[Index].FontSize.X) {
break;
}
#endif
}
if (Index == NUMBER_OF_MODE_FONT_PAIRS) {
Status = STATUS_INVALID_PARAMETER;
} else {
// set requested mode
ScreenInfo->BufferInfo.TextInfo.ModeIndex = Index;
SetVideoMode(ScreenInfo);
}
}
UnlockConsole(Console);
return Status;
#else
return (ULONG)STATUS_UNSUCCESSFUL;
UNREFERENCED_PARAMETER(m); // get rid of unreferenced parameter warning message
#endif
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvGetConsoleDisplayMode(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_GETDISPLAYMODE_MSG a = (PCONSOLE_GETDISPLAYMODE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (NT_SUCCESS(Status)) {
a->ModeFlags = Console->FullScreenFlags;
UnlockConsole(Console);
}
return Status;
UNREFERENCED_PARAMETER(ReplyStatus);
}
ULONG
SrvSetConsoleMenuClose(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_SETMENUCLOSE_MSG a = (PCONSOLE_SETMENUCLOSE_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (a->Enable) {
Console->Flags &= ~CONSOLE_DISABLE_CLOSE;
} else {
Console->Flags |= CONSOLE_DISABLE_CLOSE;
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
DWORD
ConvertHotKey(
IN LPAPPKEY UserAppKey
)
{
DWORD wParam;
wParam = MapVirtualKey(UserAppKey->ScanCode,1);
if (UserAppKey->Modifier & CONSOLE_MODIFIER_SHIFT) {
wParam |= 0x0100;
}
if (UserAppKey->Modifier & CONSOLE_MODIFIER_CONTROL) {
wParam |= 0x0200;
}
if (UserAppKey->Modifier & CONSOLE_MODIFIER_ALT) {
wParam |= 0x0400;
}
return wParam;
}
ULONG
SrvSetConsoleKeyShortcuts(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_SETKEYSHORTCUTS_MSG a = (PCONSOLE_SETKEYSHORTCUTS_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (!CsrValidateMessageBuffer(m, &a->AppKeys, a->NumAppKeys, sizeof(*a->AppKeys))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
if (a->NumAppKeys <= CONSOLE_MAX_APP_SHORTCUTS) {
Console->ReserveKeys = a->ReserveKeys;
if (Console->Flags & CONSOLE_HAS_FOCUS) {
if (!(SetConsoleReserveKeys(Console->hWnd,a->ReserveKeys))) {
Status = STATUS_INVALID_PARAMETER;
}
}
if (a->NumAppKeys) {
PostMessage(Console->hWnd,
WM_SETHOTKEY,
ConvertHotKey(a->AppKeys),
0
);
}
} else {
Status = STATUS_INVALID_PARAMETER;
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
#ifdef i386
ULONG
MatchWindowSize(
#if defined(FE_SB)
IN UINT CodePage,
#endif
IN COORD WindowSize,
OUT PCOORD pWindowSize
)
/*++
find the best match font. it's the one that's the same size
or slightly larger than the window size.
--*/
{
ULONG i;
#if defined(FE_SB)
BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(CodePage) : FALSE;
#endif
for (i=0;i<NUMBER_OF_MODE_FONT_PAIRS;i++) {
#if defined(FE_SB)
if (WindowSize.Y <= RegModeFontPairs[i].ScreenSize.Y &&
( ( fGraphics && (RegModeFontPairs[i].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
(!fGraphics && (RegModeFontPairs[i].Mode & FS_TEXT)==FS_TEXT) )
)
#else
if (WindowSize.Y <= (SHORT)ModeFontPairs[i].Height)
#endif
{
break;
}
}
if (i == NUMBER_OF_MODE_FONT_PAIRS)
#if defined(FE_SB)
{
DWORD Find;
ULONG FindIndex;
COORD WindowSizeDelta;
FindIndex = 0;
Find = (DWORD)-1;
for (i=0; i<NUMBER_OF_MODE_FONT_PAIRS;i++) {
if ( ( fGraphics && (RegModeFontPairs[i].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
(!fGraphics && (RegModeFontPairs[i].Mode & FS_TEXT)==FS_TEXT) )
{
WindowSizeDelta.Y = abs(WindowSize.Y - RegModeFontPairs[i].ScreenSize.Y);
if (Find > (DWORD)(WindowSizeDelta.Y))
{
Find = (DWORD)(WindowSizeDelta.Y);
FindIndex = i;
}
}
}
i = FindIndex;
}
#else
i-=1;
#endif
#if defined(FE_SB)
*pWindowSize = RegModeFontPairs[i].ScreenSize;
#else
pWindowSize->X = 80;
pWindowSize->Y = (SHORT)ModeFontPairs[i].Height;
#endif
return i;
}
VOID
ReadRegionFromScreenHW(
IN PSCREEN_INFORMATION ScreenInfo,
IN PSMALL_RECT Region,
IN PCHAR_INFO ReadBufPtr
)
{
ULONG CurFrameBufPtr; // offset in frame buffer
SHORT FrameY;
SHORT WindowY, WindowX, WindowSizeX;
// get pointer to start of region in frame buffer
WindowY = Region->Top - ScreenInfo->Window.Top;
WindowX = Region->Left - ScreenInfo->Window.Left;
WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
// copy the chars and attrs from the frame buffer
for (FrameY = Region->Top;
FrameY <= Region->Bottom;
FrameY++, WindowY++) {
CurFrameBufPtr = SCREEN_BUFFER_POINTER(WindowX,
WindowY,
WindowSizeX,
sizeof(VGA_CHAR));
GdiFullscreenControl(FullscreenControlReadFromFrameBuffer,
(PULONG) CurFrameBufPtr,
(Region->Right - Region->Left + 1) *
sizeof(VGA_CHAR),
ReadBufPtr, NULL);
ReadBufPtr += (Region->Right - Region->Left + 1);
}
}
VOID
ReverseMousePointer(
IN PSCREEN_INFORMATION ScreenInfo,
IN PSMALL_RECT Region
)
{
ULONG CurFrameBufPtr; // offset in frame buffer
SHORT WindowSizeX;
// if (ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
// ASSERT(FALSE);
// }
#ifdef FE_SB
// fail safe
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) {
return;
}
#endif
WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X < Region->Left ||
ScreenInfo->BufferInfo.TextInfo.MousePosition.X > Region->Right ||
ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < Region->Top ||
ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > Region->Bottom ||
ScreenInfo->CursorDisplayCount < 0 ||
!(ScreenInfo->Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT) ||
ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED) {
return;
}
#if defined(FE_SB)
{
FSVIDEO_REVERSE_MOUSE_POINTER MousePointer;
SHORT RowIndex;
PROW Row;
COORD TargetPoint;
TargetPoint.X = ScreenInfo->BufferInfo.TextInfo.MousePosition.X;
TargetPoint.Y = ScreenInfo->BufferInfo.TextInfo.MousePosition.Y;
RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
if (!CONSOLE_IS_DBCS_CP(ScreenInfo->Console))
MousePointer.dwType = CHAR_TYPE_SBCS;
else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE)
MousePointer.dwType = CHAR_TYPE_TRAILING;
else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_LEADING_BYTE)
MousePointer.dwType = CHAR_TYPE_LEADING;
else
MousePointer.dwType = CHAR_TYPE_SBCS;
MousePointer.Screen.Position.X = TargetPoint.X - ScreenInfo->Window.Left;
MousePointer.Screen.Position.Y = TargetPoint.Y - ScreenInfo->Window.Top;
MousePointer.Screen.ScreenSize.X = WindowSizeX;
MousePointer.Screen.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
MousePointer.Screen.nNumberOfChars = 0;
GdiFullscreenControl(FullscreenControlReverseMousePointerDB,
&MousePointer,
sizeof(MousePointer),
NULL,
NULL);
UNREFERENCED_PARAMETER(CurFrameBufPtr);
}
#else
CurFrameBufPtr = SCREEN_BUFFER_POINTER(ScreenInfo->BufferInfo.TextInfo.MousePosition.X - ScreenInfo->Window.Left,
ScreenInfo->BufferInfo.TextInfo.MousePosition.Y - ScreenInfo->Window.Top,
WindowSizeX,
sizeof(VGA_CHAR));
GdiFullscreenControl(FullscreenControlReverseMousePointer,
(PULONG) CurFrameBufPtr,
0,
NULL,
NULL);
#endif
}
VOID
CopyVideoMemory(
SHORT SourceY,
SHORT TargetY,
SHORT Length,
IN PSCREEN_INFORMATION ScreenInfo
)
/*++
Routine Description:
This routine copies rows of characters in video memory. It only copies
complete rows.
Arguments:
SourceY - Row to copy from.
TargetY - Row to copy to.
Length - Number of rows to copy.
Return Value:
--*/
{
ULONG SourcePtr, TargetPtr;
SHORT WindowSizeX, WindowSizeY;
WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
WindowSizeY = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
if (max(SourceY, TargetY) + Length > WindowSizeY) {
Length = WindowSizeY - max(SourceY, TargetY);
if (Length <= 0 ) {
return;
}
}
#if defined(FE_SB)
{
FSCNTL_SCREEN_INFO FsCntlSrc;
FSCNTL_SCREEN_INFO FsCntlDest;
FsCntlSrc.Position.X = 0;
FsCntlSrc.Position.Y = SourceY;
FsCntlSrc.ScreenSize.X = WindowSizeX;
FsCntlSrc.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
FsCntlSrc.nNumberOfChars = Length * WindowSizeX;
FsCntlDest.Position.X = 0;
FsCntlDest.Position.Y = TargetY;
FsCntlDest.ScreenSize.X = WindowSizeX;
FsCntlDest.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
FsCntlDest.nNumberOfChars = Length * WindowSizeX;
GdiFullscreenControl(FullscreenControlCopyFrameBufferDB,
&FsCntlSrc,
sizeof(FsCntlSrc),
&FsCntlDest,
(PULONG)sizeof(FsCntlDest));
UNREFERENCED_PARAMETER(SourcePtr);
UNREFERENCED_PARAMETER(TargetPtr);
}
#else
SourcePtr = SCREEN_BUFFER_POINTER(0,
SourceY,
WindowSizeX,
sizeof(VGA_CHAR));
TargetPtr = SCREEN_BUFFER_POINTER(0,
TargetY,
WindowSizeX,
sizeof(VGA_CHAR));
GdiFullscreenControl(FullscreenControlCopyFrameBuffer,
(PULONG) SourcePtr,
Length * WindowSizeX * sizeof(VGA_CHAR),
(PULONG) TargetPtr,
(PULONG) (Length * WindowSizeX * sizeof(VGA_CHAR)));
#endif
}
VOID
ScrollHW(
IN PSCREEN_INFORMATION ScreenInfo,
IN PSMALL_RECT ScrollRect,
IN PSMALL_RECT MergeRect,
IN COORD TargetPoint
)
{
SMALL_RECT TargetRectangle;
if (ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)
return;
TargetRectangle.Left = TargetPoint.X;
TargetRectangle.Top = TargetPoint.Y;
TargetRectangle.Right = TargetPoint.X + ScrollRect->Right - ScrollRect->Left;
TargetRectangle.Bottom = TargetPoint.Y + ScrollRect->Bottom - ScrollRect->Top;
// if the scroll region is as wide as the screen, we can update
// the screen by copying the video memory. if we scroll this
// way, we then must clip and update the fill region.
if (ScrollRect->Left == ScreenInfo->Window.Left &&
TargetRectangle.Left == ScreenInfo->Window.Left &&
ScrollRect->Right == ScreenInfo->Window.Right &&
TargetRectangle.Right == ScreenInfo->Window.Right &&
ScrollRect->Top >= ScreenInfo->Window.Top &&
TargetRectangle.Top >= ScreenInfo->Window.Top &&
ScrollRect->Bottom <= ScreenInfo->Window.Bottom &&
TargetRectangle.Bottom <= ScreenInfo->Window.Bottom) {
// we must first make the mouse pointer invisible because
// otherwise it would get copied to another place on the
// screen if it were part of the scroll region.
ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
CopyVideoMemory((SHORT) (ScrollRect->Top - ScreenInfo->Window.Top),
(SHORT) (TargetRectangle.Top - ScreenInfo->Window.Top),
(SHORT) (TargetRectangle.Bottom - TargetRectangle.Top + 1),
ScreenInfo);
// update the fill region. first we ensure that the scroll and
// target regions aren't the same. if they are, we don't fill.
if (TargetRectangle.Top != ScrollRect->Top) {
// if scroll and target regions overlap, with scroll
// region above target region, clip scroll region.
if (TargetRectangle.Top <= ScrollRect->Bottom &&
TargetRectangle.Bottom >= ScrollRect->Bottom) {
ScrollRect->Bottom = (SHORT)(TargetRectangle.Top-1);
}
else if (TargetRectangle.Top <= ScrollRect->Top &&
TargetRectangle.Bottom >= ScrollRect->Top) {
ScrollRect->Top = (SHORT)(TargetRectangle.Bottom+1);
}
WriteToScreen(ScreenInfo,ScrollRect);
// WriteToScreen should take care of writing the mouse pointer.
// however, the update region may be clipped so that the
// mouse pointer is not written. in that case, we draw the
// mouse pointer here.
if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < ScrollRect->Top ||
ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > ScrollRect->Bottom) {
ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
}
}
if (MergeRect) {
WriteToScreen(ScreenInfo,MergeRect);
}
}
else {
if (MergeRect) {
WriteToScreen(ScreenInfo,MergeRect);
}
WriteToScreen(ScreenInfo,ScrollRect);
WriteToScreen(ScreenInfo,&TargetRectangle);
}
}
VOID
UpdateMousePosition(
PSCREEN_INFORMATION ScreenInfo,
COORD Position
)
/*++
Routine Description:
This routine moves the mouse pointer.
Arguments:
ScreenInfo - Pointer to screen buffer information.
Position - Contains the new position of the mouse in screen buffer
coordinates.
Return Value:
none.
--*/
// Note: CurrentConsole lock must be held in share mode when calling this routine
{
SMALL_RECT CursorRegion;
#ifdef FE_SB
SHORT RowIndex;
PROW Row;
BOOL fOneMore = FALSE;
#endif
if ((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED) ||
(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
return;
}
if (Position.X < ScreenInfo->Window.Left ||
Position.X > ScreenInfo->Window.Right ||
Position.Y < ScreenInfo->Window.Top ||
Position.Y > ScreenInfo->Window.Bottom) {
return;
}
if (Position.X == ScreenInfo->BufferInfo.TextInfo.MousePosition.X &&
Position.Y == ScreenInfo->BufferInfo.TextInfo.MousePosition.Y) {
return;
}
#ifdef FE_SB
if (CONSOLE_IS_DBCS_CP(ScreenInfo->Console)) {
RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Position.Y) % ScreenInfo->ScreenBufferSize.Y;
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
if (Row->CharRow.KAttrs[Position.X] & ATTR_LEADING_BYTE) {
if (Position.X != ScreenInfo->ScreenBufferSize.X - 1) {
fOneMore = TRUE;
}
} else if (Row->CharRow.KAttrs[Position.X] & ATTR_TRAILING_BYTE) {
if (Position.X != 0) {
fOneMore = TRUE;
Position.X--;
}
}
}
#endif
if (ScreenInfo->CursorDisplayCount < 0 || !(ScreenInfo->Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT)) {
ScreenInfo->BufferInfo.TextInfo.MousePosition = Position;
return;
}
// turn off old mouse position.
CursorRegion.Left = CursorRegion.Right = ScreenInfo->BufferInfo.TextInfo.MousePosition.X;
CursorRegion.Top = CursorRegion.Bottom = ScreenInfo->BufferInfo.TextInfo.MousePosition.Y;
#ifdef FE_SB
if (CONSOLE_IS_DBCS_CP(ScreenInfo->Console)) {
RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+CursorRegion.Top) % ScreenInfo->ScreenBufferSize.Y;
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
if (Row->CharRow.KAttrs[CursorRegion.Left] & ATTR_LEADING_BYTE) {
if (CursorRegion.Left != ScreenInfo->ScreenBufferSize.X - 1) {
CursorRegion.Right++;
}
}
}
#endif
// store new mouse position
ScreenInfo->BufferInfo.TextInfo.MousePosition.X = Position.X;
ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = Position.Y;
WriteToScreen(ScreenInfo,&CursorRegion);
// turn on new mouse position
CursorRegion.Left = CursorRegion.Right = Position.X;
CursorRegion.Top = CursorRegion.Bottom = Position.Y;
#ifdef FE_SB
if (fOneMore)
CursorRegion.Right++;
#endif
WriteToScreen(ScreenInfo,&CursorRegion);
}
NTSTATUS
SetROMFontCodePage(
IN UINT wCodePage,
IN ULONG ModeIndex
)
/*
this function opens ega.cpi and looks for the desired font in the
specified codepage. if found, it loads it into the video ROM.
*/
{
BYTE Buffer[CONSOLE_FONT_BUFFER_LENGTH];
DWORD dwBytesRead;
LPFONTFILEHEADER lpFontFileHeader=(LPFONTFILEHEADER)Buffer;
LPFONTINFOHEADER lpFontInfoHeader=(LPFONTINFOHEADER)Buffer;
LPFONTDATAHEADER lpFontDataHeader=(LPFONTDATAHEADER)Buffer;
LPCPENTRYHEADER lpCPEntryHeader=(LPCPENTRYHEADER)Buffer;
LPSCREENFONTHEADER lpScreenFontHeader=(LPSCREENFONTHEADER)Buffer;
WORD NumEntries;
COORD FontDimensions;
NTSTATUS Status;
BOOL Found;
LONG FilePtr;
BOOL bDOS = FALSE;
FontDimensions = ModeFontPairs[ModeIndex].FontSize;
// read FONTINFOHEADER
// do {
// read CPENTRYHEADER
// if (correct codepage)
// break;
// } while (codepages)
// if (codepage found)
// read FONTDATAHEADER
// read FONTFILEHEADER
FilePtr = 0;
if (SetFilePointer(hCPIFile,FilePtr,NULL,FILE_BEGIN) == -1) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
if (!ReadFile(hCPIFile,Buffer,sizeof(FONTFILEHEADER),&dwBytesRead,NULL) ||
dwBytesRead != sizeof(FONTFILEHEADER)) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
// verify signature
if (memcmp(lpFontFileHeader->ffhFileTag, "\xFF""FONT.NT",8) ) {
if (memcmp(lpFontFileHeader->ffhFileTag, "\xFF""FONT ",8) ) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
} else {
bDOS = TRUE;
}
}
// seek to FONTINFOHEADER. jump through hoops to get the offset value.
FilePtr = lpFontFileHeader->ffhOffset1;
FilePtr |= (lpFontFileHeader->ffhOffset2 << 8);
FilePtr |= (lpFontFileHeader->ffhOffset3 << 24);
if (SetFilePointer(hCPIFile,FilePtr,NULL,FILE_BEGIN) == -1) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
// read FONTINFOHEADER
if (!ReadFile(hCPIFile,Buffer,sizeof(FONTINFOHEADER),&dwBytesRead,NULL) ||
dwBytesRead != sizeof(FONTINFOHEADER)) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
FilePtr += dwBytesRead;
NumEntries = lpFontInfoHeader->fihCodePages;
Found = FALSE;
while (NumEntries &&
ReadFile(hCPIFile,Buffer,sizeof(CPENTRYHEADER),&dwBytesRead,NULL) &&
dwBytesRead == sizeof(CPENTRYHEADER)) {
if (lpCPEntryHeader->cpeCodepageID == wCodePage) {
Found = TRUE;
break;
}
// seek to next CPEENTRYHEADER
if (bDOS) {
FilePtr = MAKELONG(lpCPEntryHeader->cpeNext1,lpCPEntryHeader->cpeNext2);
} else {
FilePtr += MAKELONG(lpCPEntryHeader->cpeNext1,lpCPEntryHeader->cpeNext2);
}
if (SetFilePointer(hCPIFile, FilePtr, NULL,FILE_BEGIN) == -1) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
NumEntries-=1;
}
if (!Found) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
// seek to FONTDATAHEADER
if (bDOS) {
FilePtr = lpCPEntryHeader->cpeOffset;
} else {
FilePtr += lpCPEntryHeader->cpeOffset;
}
if (SetFilePointer(hCPIFile, FilePtr, NULL,FILE_BEGIN) == -1) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
// read FONTDATAHEADER
if (!ReadFile(hCPIFile,Buffer,sizeof(FONTDATAHEADER),&dwBytesRead,NULL) ||
dwBytesRead != sizeof(FONTDATAHEADER)) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
FilePtr += dwBytesRead;
NumEntries = lpFontDataHeader->fdhFonts;
while (NumEntries) {
if (!ReadFile(hCPIFile,Buffer,sizeof(SCREENFONTHEADER),&dwBytesRead,NULL) ||
dwBytesRead != sizeof(SCREENFONTHEADER)) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
if (lpScreenFontHeader->sfhHeight == (BYTE)FontDimensions.Y &&
lpScreenFontHeader->sfhWidth == (BYTE)FontDimensions.X) {
PVIDEO_LOAD_FONT_INFORMATION FontInformation;
FontInformation = (PVIDEO_LOAD_FONT_INFORMATION)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),
lpScreenFontHeader->sfhCharacters*
lpScreenFontHeader->sfhHeight+
sizeof(VIDEO_LOAD_FONT_INFORMATION));
if (FontInformation == NULL) {
RIPMSG1(RIP_WARNING, "SetROMFontCodePage: failed to memory allocation %d bytes",
lpScreenFontHeader->sfhCharacters * lpScreenFontHeader->sfhHeight +
sizeof(VIDEO_LOAD_FONT_INFORMATION));
return STATUS_NO_MEMORY;
}
if (!ReadFile(hCPIFile,FontInformation->Font,
lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight,
&dwBytesRead,NULL) ||
dwBytesRead != (DWORD)(lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight)) {
ConsoleHeapFree(FontInformation);
return STATUS_INVALID_PARAMETER;
}
FontInformation->WidthInPixels = FontDimensions.X;
FontInformation->HeightInPixels = FontDimensions.Y;
FontInformation->FontSize = lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight;
Status = GdiFullscreenControl(FullscreenControlLoadFont,
FontInformation,
lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight+sizeof(VIDEO_LOAD_FONT_INFORMATION),
NULL,
NULL);
ConsoleHeapFree(FontInformation);
return Status;
} else {
FilePtr = lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight;
if (SetFilePointer(hCPIFile, FilePtr, NULL,FILE_CURRENT) == -1) {
Status = STATUS_INVALID_PARAMETER;
goto DoExit;
}
}
NumEntries -= 1;
}
DoExit:
return Status;
}
#endif
NTSTATUS
GetThreadConsoleDesktop(
DWORD dwThreadId,
HDESK *phdeskConsole)
{
PCSR_THREAD pcsrt;
PCONSOLE_PER_PROCESS_DATA ProcessData;
PCONSOLE_INFORMATION Console;
NTSTATUS Status;
HANDLE ConsoleHandle = NULL;
*phdeskConsole = NULL;
Status = CsrLockThreadByClientId((HANDLE)dwThreadId, &pcsrt);
if (NT_SUCCESS(Status)) {
ProcessData = CONSOLE_FROMTHREADPERPROCESSDATA(pcsrt);
ConsoleHandle = ProcessData->ConsoleHandle;
CsrUnlockThread(pcsrt);
}
// If this process is a console app, return the
// handle to its desktop. Otherwise, return NULL.
if (ConsoleHandle != NULL) {
Status = RevalidateConsole(ConsoleHandle, &Console);
if (NT_SUCCESS(Status)) {
*phdeskConsole = Console->hDesk;
}
UnlockConsole(Console);
}
return STATUS_SUCCESS;
}
NTSTATUS
SetRAMFontCodePage(
IN PSCREEN_INFORMATION ScreenInfo
)
{
FSVIDEO_SCREEN_INFORMATION ScreenInformation;
ULONG ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
COORD FontSize;
WCHAR wChar;
WCHAR wCharBuf[2];
LPSTRINGBITMAP StringBitmap;
DWORD BufferSize;
PWORD FontImage;
PFONT_CACHE_INFORMATION FontCache;
WCHAR AltFaceName[LF_FACESIZE];
COORD AltFontSize;
BYTE AltFontFamily;
ULONG AltFontIndex = 0;
HFONT hOldFont;
NTSTATUS Status;
ScreenInformation.ScreenSize = RegModeFontPairs[ModeIndex].ScreenSize;
ScreenInformation.FontSize = RegModeFontPairs[ModeIndex].FontSize;
if (ScreenInfo->Console->FontCacheInformation == NULL)
{
Status = CreateFontCache(&FontCache);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "SetRAMFontCodePage: failed in CreateFontCache. Status=%08x", Status);
return STATUS_UNSUCCESSFUL;
}
(PFONT_CACHE_INFORMATION)ScreenInfo->Console->FontCacheInformation = FontCache;
MakeAltRasterFont(SCR_FONTCODEPAGE(ScreenInfo),
RegModeFontPairs[ModeIndex].FontSize,
&AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
FontCache->FullScreenFontIndex = AltFontIndex;
FontCache->FullScreenFontSize = AltFontSize;
BufferSize = CalcBitmapBufferSize(FontCache->FullScreenFontSize,BYTE_ALIGN);
StringBitmap = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
sizeof(STRINGBITMAP) + sizeof(StringBitmap->ajBits) * BufferSize);
if (StringBitmap==NULL)
{
RIPMSG0(RIP_WARNING, "SetRAMFontCodePage: failed to allocate StringBitmap");
return STATUS_UNSUCCESSFUL;
}
/*
* Change GDI font to full screen font that best matched.
*/
hOldFont = SelectObject(ScreenInfo->Console->hDC,FontInfo[FontCache->FullScreenFontIndex].hFont);
for (wChar=0x00; wChar < 0x80; wChar++) {
wCharBuf[0] = wChar;
wCharBuf[1] = TEXT('\0');
GetStringBitmapW(ScreenInfo->Console->hDC,
wCharBuf,
1,
(ULONG)ConsoleHeapSize(StringBitmap),
(BYTE*)StringBitmap
);
FontSize.X = (SHORT)StringBitmap->uiWidth;
FontSize.Y = (SHORT)StringBitmap->uiHeight;
#if defined(LATER_DBCS_FOR_GRID_CHAR) // by kazum
BufferSize = CalcBitmapBufferSize(FontSize,BYTE_ALIGN);
*(StringBitmap->ajBits + BufferSize) = 0;
*(StringBitmap->ajBits + BufferSize + 1) = 0;
if (gpGridCharacter) {
PGRID_CHARACTER_INFORMATION GridCharacter;
PWCHAR CodePoint;
GridCharacter = gpGridCharacter;
do {
if (GridCharacter->CodePage == OEMCP) {
CodePoint = GridCharacter->CodePoint;
while (*CodePoint) {
if (*CodePoint == wChar) {
if (FontSize.X <= 8)
*(StringBitmap->ajBits + BufferSize) = *(StringBitmap->ajBits + BufferSize - 1);
else {
*(StringBitmap->ajBits + BufferSize) = *(StringBitmap->ajBits + BufferSize - 2);
*(StringBitmap->ajBits + BufferSize + 1) = *(StringBitmap->ajBits + BufferSize - 1);
}
break;
}
else
CodePoint++;
}
break;
}
} while (GridCharacter = GridCharacter->pNext);
}
#endif // LATER_DBCS_FOR_GRID_CHAR // by kazum
Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
wChar,
FontSize,
BYTE_ALIGN,
StringBitmap->ajBits
);
if (! NT_SUCCESS(Status)) {
RIPMSG3(RIP_WARNING, "SetRAMFontCodePage: failed to set font image. wc=%04x sz=(%x, %x).",
wChar, FontSize.X, FontSize.Y);
}
if (FontSize.X != ScreenInformation.FontSize.X ||
FontSize.Y != ScreenInformation.FontSize.Y)
{
BufferSize = CalcBitmapBufferSize(ScreenInformation.FontSize,WORD_ALIGN);
FontImage = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
BufferSize
);
if (FontImage!=NULL) {
GetExpandFontImage(ScreenInfo->Console->FontCacheInformation,
wChar,
FontSize,
ScreenInformation.FontSize,
FontImage
);
Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
wChar,
ScreenInformation.FontSize,
WORD_ALIGN,
FontImage
);
if (! NT_SUCCESS(Status)) {
RIPMSG3(RIP_WARNING, "SetRAMFontCodePage: failed to set font image. wc=%04x, sz=(%x,%x)",
wChar, ScreenInformation.FontSize.X, ScreenInformation.FontSize.Y);
}
ConsoleHeapFree(FontImage);
} else {
RIPMSG0(RIP_WARNING, "SetRAMFontCodePage: failed to allocate FontImage.");
}
}
}
ConsoleHeapFree(StringBitmap);
/*
* Back to GDI font
*/
SelectObject(ScreenInfo->Console->hDC,hOldFont);
}
Status = GdiFullscreenControl(FullscreenControlSetScreenInformation,
&ScreenInformation,
sizeof(ScreenInformation),
NULL,
NULL);
return Status;
}
NTSTATUS
SetRAMFont(
IN PSCREEN_INFORMATION ScreenInfo,
IN PCHAR_INFO ScreenBufPtr,
IN DWORD Length
)
{
ULONG ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
COORD FsFontSize1 = RegModeFontPairs[ModeIndex].FontSize;
COORD FsFontSize2 = FsFontSize1;
COORD GdiFontSize1;
COORD GdiFontSize2;
COORD RetFontSize;
WCHAR wCharBuf[2];
LPSTRINGBITMAP StringBitmap;
DWORD BufferSize;
PWORD FontImage;
PFONT_CACHE_INFORMATION FontCache;
HFONT hOldFont;
NTSTATUS Status;
FontCache = (PFONT_CACHE_INFORMATION)ScreenInfo->Console->FontCacheInformation;
if (FontCache==NULL)
{
RIPMSG0(RIP_ERROR, "SetRAMFont: ScreenInfo->Console->FontCacheInformation == NULL.");
return STATUS_UNSUCCESSFUL;
}
GdiFontSize1 = FontCache->FullScreenFontSize;
GdiFontSize2 = GdiFontSize1;
GdiFontSize2.X *= 2;
FsFontSize2.X *= 2;
BufferSize = CalcBitmapBufferSize(GdiFontSize2,BYTE_ALIGN);
StringBitmap = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
sizeof(STRINGBITMAP) + sizeof(StringBitmap->ajBits) * BufferSize);
if (StringBitmap==NULL)
{
RIPMSG0(RIP_WARNING, "SetRAMFont: failed to allocate StringBitmap");
return STATUS_UNSUCCESSFUL;
}
/*
* Change GDI font to full screen font that best matched.
*/
hOldFont = SelectObject(ScreenInfo->Console->hDC,FontInfo[FontCache->FullScreenFontIndex].hFont);
while (Length--)
{
Status = GetFontImage(ScreenInfo->Console->FontCacheInformation,
ScreenBufPtr->Char.UnicodeChar,
(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
0,
NULL);
if (! NT_SUCCESS(Status) )
{
wCharBuf[0] = ScreenBufPtr->Char.UnicodeChar;
wCharBuf[1] = TEXT('\0');
GetStringBitmapW(ScreenInfo->Console->hDC,
wCharBuf,
1,
(ULONG)ConsoleHeapSize(StringBitmap),
(BYTE*)StringBitmap
);
RetFontSize.X = (SHORT)StringBitmap->uiWidth;
RetFontSize.Y = (SHORT)StringBitmap->uiHeight;
Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
ScreenBufPtr->Char.UnicodeChar,
RetFontSize,
BYTE_ALIGN,
StringBitmap->ajBits
);
if (! NT_SUCCESS(Status)) {
RIPMSG3(RIP_WARNING, "SetRAMFont: failed to set font image. wc=%04x sz=(%x,%x)",
ScreenBufPtr->Char.UnicodeChar, RetFontSize.X, RetFontSize.Y);
}
if ( ( (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) &&
(GdiFontSize2.X != FsFontSize2.X || GdiFontSize2.Y != FsFontSize2.Y)) ||
(!(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) &&
(GdiFontSize1.X != FsFontSize1.X || GdiFontSize1.Y != FsFontSize1.Y)) )
{
BufferSize = CalcBitmapBufferSize(FsFontSize2,WORD_ALIGN);
FontImage = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
BufferSize
);
if (FontImage!=NULL) {
GetExpandFontImage(ScreenInfo->Console->FontCacheInformation,
ScreenBufPtr->Char.UnicodeChar,
(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? GdiFontSize2 : GdiFontSize1,
(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
FontImage
);
Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
ScreenBufPtr->Char.UnicodeChar,
(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
WORD_ALIGN,
FontImage
);
if (! NT_SUCCESS(Status)) {
RIPMSG3(RIP_WARNING, "SetRAMFont: failed to set font image. wc=%04x sz=(%x,%x)",
ScreenBufPtr->Char.UnicodeChar,
((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1).X,
((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1).Y);
}
ConsoleHeapFree(FontImage);
} else {
RIPMSG0(RIP_WARNING, "SetRAMFont: failed to allocate FontImage.");
}
}
}
if (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS)
{
ScreenBufPtr += 2;
if (Length >= 1)
Length -= 1;
else
break;
}
else
{
ScreenBufPtr++;
}
}
ConsoleHeapFree(StringBitmap);
/*
* Back to GDI font
*/
SelectObject(ScreenInfo->Console->hDC,hOldFont);
return Status;
}
#ifdef i386
#if defined(FE_SB)
#define WWSB_NOFE
#include "_priv.h"
#undef WWSB_NOFE
#define WWSB_FE
#include "_priv.h"
#undef WWSB_FE
#endif // FE_SB
#endif // i386