|
|
/*++
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
Revision History:
Notes:
--*/
#include "precomp.h"
#include "vdm.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;
UNREFERENCED_PARAMETER(ReplyStatus);
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; }
#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;
UNREFERENCED_PARAMETER(ReplyStatus);
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; }
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;
UNREFERENCED_PARAMETER(ReplyStatus);
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; }
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;
UNREFERENCED_PARAMETER(ReplyStatus);
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; }
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; } }
//
// 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; }
UserAssert(WindowSize.X == CONSOLE_WINDOW_SIZE_X(Cur)); UserAssert(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.
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;
UNREFERENCED_PARAMETER(ReplyStatus);
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 || GetSystemMetrics(SM_REMOTESESSION)) { Status = STATUS_INVALID_PARAMETER; goto SrvSetConsoleDisplayModeFailure; } #endif
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) { KdPrint(("CONSRV: VDM converting to fullscreen twice\n")); Status = STATUS_SUCCESS; goto SrvSetConsoleDisplayModeFailure; } State = FULLSCREEN; } else { if (Console->FullScreenFlags == 0) { KdPrint(("CONSRV: VDM converting to windowed twice\n")); Status = STATUS_SUCCESS; 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; }
VOID UnregisterVDM( IN PCONSOLE_INFORMATION Console ) { // williamh, Feb 2 1994.
// catch multiple calls to unregister vdm. Believe it or not, this could
// happen
//UserAssert(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); if (Console->VDMErrorHardwareEvent) { CloseHandle(Console->VDMErrorHardwareEvent); Console->VDMErrorHardwareEvent = NULL; } 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; UserAssert(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
UserAssert(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; VDM_QUERY_VDM_PROCESS_DATA QueryVdmProcessData; #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; }
//
// First make sure the caller is a VDM process
//
QueryVdmProcessData.ProcessHandle = CONSOLE_CLIENTPROCESSHANDLE(); Status = NtVdmControl(VdmQueryVdmProcess, &QueryVdmProcessData); if (!NT_SUCCESS(Status) || QueryVdmProcessData.IsVdmProcess == FALSE) { UnlockConsole(Console); return STATUS_ACCESS_DENIED; }
if (a->RegisterFlags & CONSOLE_REGISTER_VDM) { ConsoleNotifyWinEvent(Console, EVENT_CONSOLE_START_APPLICATION, HandleToUlong(CONSOLE_CLIENTPROCESSID()), CONSOLE_APPLICATION_16BIT); } else if (a->RegisterFlags == 0) { ConsoleNotifyWinEvent(Console, EVENT_CONSOLE_END_APPLICATION, HandleToUlong(CONSOLE_CLIENTPROCESSID()), CONSOLE_APPLICATION_16BIT); }
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
// UserAssert(Console->Flags & CONSOLE_VDM_REGISTERED);
if (Console->Flags & CONSOLE_VDM_REGISTERED) { UserAssert(!(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 // i386
Status = STATUS_SUCCESS; } else { Status = STATUS_ACCESS_DENIED; } UnlockConsole(Console); return Status; }
if (!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.
UserAssert(!(Console->Flags & CONSOLE_VDM_REGISTERED));
if (Console->Flags & CONSOLE_VDM_REGISTERED) { UnlockConsole(Console); return (ULONG) STATUS_ACCESS_DENIED; }
UserAssert(!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; Console->VDMErrorHardwareEvent = 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)) { if (a->ErrorEvent) { Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(), a->ErrorEvent, NtCurrentProcess(), &Console->VDMErrorHardwareEvent, 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); if (Console->VDMErrorHardwareEvent) { CloseHandle(Console->VDMErrorHardwareEvent); } }
} else {
CloseHandle(Console->VDMStartHardwareEvent); CloseHandle(Console->VDMEndHardwareEvent); if (Console->VDMErrorHardwareEvent) { CloseHandle(Console->VDMErrorHardwareEvent); } } } else { CloseHandle(Console->VDMStartHardwareEvent); CloseHandle(Console->VDMEndHardwareEvent); }
} else {
CloseHandle(Console->VDMStartHardwareEvent); }
}
//
// If we failed to duplicate screen switch events or map
// view to video state shared buffer, fail this API.
//
if (!NT_SUCCESS(Status)) { UnlockConsole(Console); return Status; } }
#endif // i386
//
// 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
a->VDMBufferSize.X * a->VDMBufferSize.Y * 4, #endif // i386
&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); if (Console->VDMErrorHardwareEvent) { CloseHandle(Console->VDMErrorHardwareEvent); } }
#endif // i386
CloseHandle(Console->VDMProcessHandle); Console->VDMProcessHandle = NULL; UnlockConsole(Console); return 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 = {-32767, -32767, 32767, 32767}; NtUserConsoleControl(ConsoleSetVDMCursorBounds, &CursorRect, sizeof(RECT));
UserAssert(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR)); ConnectToEmulator(TRUE, Console); } #endif
UnlockConsole(Console); return Status; UNREFERENCED_PARAMETER(ReplyStatus); }
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;
UNREFERENCED_PARAMETER(ReplyStatus);
Status = ApiPreamble(a->ConsoleHandle, &Console ); if (!NT_SUCCESS(Status)) { return Status; }
//
// Don'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 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; }
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)) { NtUnmapViewOfSection(NtCurrentProcess(), *BaseAddress); 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; UserAssert((Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) == 0); Console->Flags |= CONSOLE_CONNECTED_TO_EMULATOR; Flags.dwFlags = TIF_DOSEMULATOR; #if DBG
RtlWalkFrameChain(Console->ConnectStack, ARRAY_SIZE(Console->ConnectStack), 0); #endif
} else { fsctl = FullscreenControlDisable; UserAssert((Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) != 0); Console->Flags &= ~CONSOLE_CONNECTED_TO_EMULATOR; Flags.dwFlags = 0; #if DBG
RtlWalkFrameChain(Console->DisconnectStack, ARRAY_SIZE(Console->DisconnectStack), 0); #endif
}
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);
UserAssert(Status == STATUS_SUCCESS || Status == STATUS_CONFLICTING_ADDRESSES || Status == STATUS_PROCESS_IS_TERMINATING);
DBGFULLSCR(("ConnectToEmulator : leaving, staus = %08lx\n", Status));
return Status; }
#define CONSOLE_VDM_TIMEOUT 20000
#ifdef i386
VOID LockConsoleForCurrentThread( IN PCONSOLE_INFORMATION Console, IN DWORD Count) { while (Console->ConsoleLock.RecursionCount != Count) { LockConsole(Console); } } DWORD UnlockConsoleForCurrentThread( IN PCONSOLE_INFORMATION Console) { DWORD Count, i;
Count = Console->ConsoleLock.RecursionCount; ASSERT(Count > 0); for (i = 0; i < Count; i++) { UnlockConsole(Console); } return Count; } #endif
NTSTATUS DisplayModeTransition( IN BOOL bForeground, IN PCONSOLE_INFORMATION Console, IN PSCREEN_INFORMATION ScreenInfo ) { #ifdef i386
NTSTATUS Status; LARGE_INTEGER li; DWORD WaitCount; HANDLE WaitHandles[2];
if (!FullScreenInitialized || GetSystemMetrics(SM_REMOTESESSION)) { return STATUS_SUCCESS; }
WaitCount = 1; WaitHandles[0] = Console->VDMEndHardwareEvent; if (Console->VDMErrorHardwareEvent) { WaitHandles[1] = Console->VDMErrorHardwareEvent; WaitCount++; }
if (bForeground) { if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { KdPrint(("CONSRV: received fullscreen message too early\n")); return STATUS_UNSUCCESSFUL; }
} else {
//
// 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; } }
//
// Before actually doing any mode switching work, notify ntvdm to give it
// a chance to bring all threads to a stoppable state.
//
if (Console->Flags & CONSOLE_VDM_REGISTERED) {
//
// make a special case for ntvdm during switching because
// ntvdm has to suspend its main thread which may be making
// console api calls before it can be suspended.
//
HANDLE ConsoleHandle = Console->ConsoleHandle; NTSTATUS Statusx;
//
// Make timeout longer than usual. It will take long to
// stop ntvdm threads under stress.
//
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT * 3; Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL); if (NT_SUCCESS(Status)) { HANDLE OwningThread; DWORD RecursionCount;
//
// After notifying ntvdm to do screen switch, we must release
// console locks to avoid deadlock. Before doing so, we need to
// remember how many locks are released and who releases them, in
// case that we fail to get the locks back.
//
OwningThread = Console->ConsoleLock.OwningThread; Console->UnlockConsoleOwningThread = OwningThread; RecursionCount = UnlockConsoleForCurrentThread(Console); Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li); Statusx = RevalidateConsole(ConsoleHandle, &Console); if (!NT_SUCCESS(Statusx)) { Console->UnlockConsoleSkipCount = RecursionCount; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); return Statusx; }
//
// Get back the original number of locks. Since the lock is owned
// by us already (by calling RevalidateConsole), the following call
// simply increases the recursion count of the lock.
//
LockConsoleForCurrentThread(Console, RecursionCount); Console->UnlockConsoleOwningThread = NULL; }
if (Status != 0) { Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); UnregisterVDM(Console); KdPrint(("CONSRV: VDM not responding to initial request.\n")); } }
if (bForeground) { PSCREEN_INFORMATION ScreenInfo = Console->CurrentScreenBuffer; NTSTATUS Status;
KdPrint((" CONSRV - Display Mode transition to fullscreen \n"));
Console->FullScreenFlags |= CONSOLE_FULLSCREEN_HARDWARE;
//
// Fire off an event to let accessibility apps know the layout has
// changed. We only want to do this while going *to* full-screen;
// on the way back we'll send this event from InternalUpdateScrollBars.
//
ConsoleNotifyWinEvent(ScreenInfo->Console, EVENT_CONSOLE_LAYOUT, 0, 0); if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) { #if defined(FE_SB)
BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE; #endif
#if 1
DEVMODEW Devmode; ULONG Index;
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) {
//
// Increase the regular timeout value, since ntvdm needs to
// do A LOT of transitions between kernel mode and user mode
// to collect the video state information. (During stress, it may
// take a long time.)
//
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT * 3; Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL); if (NT_SUCCESS(Status)) { Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li); } if (Status != 0) { Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); UnregisterVDM(Console); KdPrint(("CONSRV: VDM not responding or in error state.\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.
UserAssert(!(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; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); 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.
//
// Also, we can not simply continue if timeout or error occurs.
// We could set hStartHardwareEvent twice if a new mode switch
// request is in our queue. This will cause us and ntvdm
// out of sync.
//
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT; NtSetEvent(Console->VDMStartHardwareEvent, NULL); Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li); if (Status != 0) { Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); UnregisterVDM(Console); KdPrint(("CONSRV: VDM not responding or in error state.\n")); } } }
//
// 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"));
// 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 = NtSetEvent(Console->VDMStartHardwareEvent, NULL); if (NT_SUCCESS(Status)) { Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li); if (Status == STATUS_TIMEOUT || Status == 1) { Status = STATUS_UNSUCCESSFUL; } }
// 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
UserAssert(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR); ConnectToEmulator(FALSE, Console);
} else {
Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); 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);
//
// Increase the regular timeout value, since ntvdm needs to
// do A LOT of transitions between kernel mode and user mode
// before it can signal console back. (During stress, it may
// take a long time.)
//
li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT * 3; Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL); if (NT_SUCCESS(Status)) { Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li); }
// time to go back to normal
RtlEnterCriticalSection(&ConsoleVDMCriticalSection); ConsoleVDMOnSwitching = NULL; RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
if (Status != 0) { Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT; NtSetEvent(Console->VDMErrorHardwareEvent, NULL); 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_FOCUS 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) { RIPMSG1(RIP_WARNING, "FullscreenControlSetPalette failed - Status = 0x%x", Status); 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) { RIPMSG1(RIP_WARNING, "FullscreenControlSetColors failed - Status = 0x%x", Status); 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
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 { 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; #ifdef FE_SB
DWORD mode1 = 0; DWORD mode2 = 0; #else
BOOLEAN mode1 = FALSE; BOOLEAN mode2 = FALSE; #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)) == INVALID_HANDLE_VALUE) { 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 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 STATUS_UNSUCCESSFUL; UNREFERENCED_PARAMETER(m); #endif
UNREFERENCED_PARAMETER(ReplyStatus); }
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 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 STATUS_UNSUCCESSFUL; UNREFERENCED_PARAMETER(m); #endif
UNREFERENCED_PARAMETER(ReplyStatus); }
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;
UNREFERENCED_PARAMETER(ReplyStatus);
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; }
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;
UNREFERENCED_PARAMETER(ReplyStatus);
Status = ApiPreamble(a->ConsoleHandle, &Console ); if (!NT_SUCCESS(Status)) { return Status; }
/*
* We only call CsrCaptureMessageBuffer() in SetConsoleKeyShortcuts if * a->NumAppKeys != 0, so we only want to call CsrValidateMessageBuffer when * that condition's true. */ if (a->NumAppKeys != 0 && !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; }
#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 = (SHORT) 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;
#ifdef FE_SB
// fail safe
UserAssert(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 = ConsoleHeapAlloc(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(LongToHandle(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(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(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(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(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
|