test: private.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# private.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1985 - 1999, Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     private.c
    00008
    00009 Abstract:
    00010
    00011         This file implements private APIs for Hardware Desktop Support.
    00012
    00013 Author:
    00014
    00015     Therese Stowell (thereses) 12-13-1991
    00016
    00017 Revision History:
    00018
    00019 Notes:
    00020
    00021 --*/
    00022
    00023 #include "precomp.h"
    00024 #pragma hdrstop
    00025
    00026 #if defined(FE_SB)
    00027 BOOL fFullScreenGraphics ; // Do not trun graphics mode.
    00028 #if defined(i386)
    00029 extern ULONG  gdwMachineId;
    00030 #endif // i386
    00031 #endif
    00032
    00033 //
    00034 // initial palette registers
    00035 //
    00036
    00037 #define PAL_BLACK       0
    00038 #define PAL_BLUE        1
    00039 #define PAL_GREEN       2
    00040 #define PAL_RED         4
    00041 #define PAL_YELLOW      (PAL_RED | PAL_GREEN)
    00042 #define PAL_CYAN        (PAL_GREEN | PAL_BLUE)
    00043 #define PAL_MAGENTA     (PAL_BLUE | PAL_RED)
    00044 #define PAL_WHITE       (PAL_RED | PAL_GREEN | PAL_BLUE)
    00045
    00046 #define PAL_I_BLACK     (PAL_BLACK      + (PAL_WHITE    << 3))
    00047 #define PAL_I_RED       (PAL_RED        + (PAL_RED      << 3))
    00048 #define PAL_I_GREEN     (PAL_GREEN      + (PAL_GREEN    << 3))
    00049 #define PAL_I_YELLOW    (PAL_YELLOW     + (PAL_YELLOW   << 3))
    00050 #define PAL_I_BLUE      (PAL_BLUE       + (PAL_BLUE     << 3))
    00051 #define PAL_I_CYAN      (PAL_CYAN       + (PAL_CYAN     << 3))
    00052 #define PAL_I_MAGENTA   (PAL_MAGENTA    + (PAL_MAGENTA  << 3))
    00053 #define PAL_I_WHITE     (PAL_WHITE      + (PAL_WHITE    << 3))
    00054
    00055 #define INITIAL_PALETTE_SIZE 18
    00056
    00057 USHORT InitialPalette[INITIAL_PALETTE_SIZE] = {
    00058
    00059         16, // 16 entries
    00060         0,  // start with first palette register
    00061         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
    00062 };
    00063
    00064 #if defined(FE_SB)
    00065 PUSHORT RegInitialPalette = InitialPalette;
    00066 #endif
    00067
    00068 UCHAR ColorBuffer[] = {
    00069
    00070         16, // 16 entries
    00071         0,
    00072         0,
    00073         0,  // start with first palette register
    00074         0x00, 0x00, 0x00, 0x00, // black
    00075         0x00, 0x00, 0x2A, 0x00, // blue
    00076         0x00, 0x2A, 0x00, 0x00, // green
    00077         0x00, 0x2A, 0x2A, 0x00, // cyan
    00078         0x2A, 0x00, 0x00, 0x00, // red
    00079         0x2A, 0x00, 0x2A, 0x00, // magenta
    00080         0x2A, 0x2A, 0x00, 0x00, // mustard/brown
    00081         0x36, 0x36, 0x36, 0x00, // light gray  39
    00082         0x28, 0x28, 0x28, 0x00, // dark gray   2A
    00083         0x00, 0x00, 0x3F, 0x00, // bright blue
    00084         0x00, 0x3F, 0x00, 0x00, // bright green
    00085         0x00, 0x3F, 0x3F, 0x00, // bright cyan
    00086         0x3F, 0x00, 0x00, 0x00, // bright red
    00087         0x3F, 0x00, 0x3F, 0x00, // bright magenta
    00088         0x3F, 0x3F, 0x00, 0x00, // bright yellow
    00089         0x3F, 0x3F, 0x3F, 0x00  // bright white
    00090 };
    00091
    00092 #if defined(FE_SB)
    00093 PUCHAR RegColorBuffer = ColorBuffer;
    00094 PUCHAR RegColorBufferNoTranslate = NULL;
    00095 #endif
    00096
    00097 #if defined(FE_SB)
    00098 MODE_FONT_PAIR ModeFontPairs[] = {
    00099     {FS_MODE_TEXT, 80, 21, 640, 350, 8, 16},
    00100     {FS_MODE_TEXT, 80, 25, 720, 400, 8, 16},
    00101     {FS_MODE_TEXT, 80, 28, 720, 400, 8, 14},
    00102     {FS_MODE_TEXT, 80, 43, 640, 350, 8, 8 },
    00103     {FS_MODE_TEXT, 80, 50, 720, 400, 8, 8 }
    00104 };
    00105
    00106 DWORD NUMBER_OF_MODE_FONT_PAIRS = sizeof(ModeFontPairs)/sizeof(MODE_FONT_PAIR);
    00107 PMODE_FONT_PAIR RegModeFontPairs = ModeFontPairs;
    00108
    00109 SINGLE_LIST_ENTRY gRegFullScreenCodePage;    // This list contain FS_CODEPAGE data.
    00110
    00111 #else
    00112 typedef struct _MODE_FONT_PAIR {
    00113     ULONG Height;
    00114     COORD Resolution;
    00115     COORD FontSize;
    00116 } MODE_FONT_PAIR, PMODE_FONT_PAIR;
    00117
    00118 #define NUMBER_OF_MODE_FONT_PAIRS 5
    00119
    00120 MODE_FONT_PAIR ModeFontPairs[NUMBER_OF_MODE_FONT_PAIRS] = {
    00121     {21, 640, 350, 8, 16},
    00122     {25, 720, 400, 8, 16},
    00123     {28, 720, 400, 8, 14},
    00124     {43, 640, 350, 8, 8 },
    00125     {50, 720, 400, 8, 8 }
    00126 };
    00127 #endif
    00128
    00129
    00130 HANDLE hCPIFile;    // handle to font file
    00131
    00132 typedef struct _FONTFILEHEADER {
    00133     BYTE  ffhFileTag[8]; // SHOULD BE 0FFH,"FONT___"
    00134     BYTE  ffhReserved[8];
    00135     WORD  ffhPointers;
    00136     BYTE  ffhPointerType;
    00137     BYTE  ffhOffset1;
    00138     WORD  ffhOffset2;
    00139     BYTE  ffhOffset3;
    00140 } FONTFILEHEADER, *LPFONTFILEHEADER;
    00141
    00142 typedef struct _FONTINFOHEADER {
    00143     WORD  fihCodePages;
    00144 } FONTINFOHEADER, *LPFONTINFOHEADER;
    00145
    00146 typedef struct _CPENTRYHEADER {
    00147     WORD  cpeLength;
    00148     WORD  cpeNext1;
    00149     WORD  cpeNext2;
    00150     WORD  cpeDevType;
    00151     BYTE  cpeDevSubtype[8];
    00152     WORD  cpeCodepageID;
    00153     BYTE  cpeReserved[6];
    00154     DWORD cpeOffset;
    00155 } CPENTRYHEADER, *LPCPENTRYHEADER;
    00156
    00157 typedef struct _FONTDATAHEADER {
    00158     WORD  fdhReserved;
    00159     WORD  fdhFonts;
    00160     WORD  fdhLength;
    00161 } FONTDATAHEADER, *LPFONTDATAHEADER;
    00162
    00163 typedef struct _SCREENFONTHEADER {
    00164     BYTE  sfhHeight;
    00165     BYTE  sfhWidth;
    00166     WORD  sfhAspect;
    00167     WORD  sfhCharacters;
    00168 } SCREENFONTHEADER, *LPSCREENFONTHEADER;
    00169
    00170 #define CONSOLE_WINDOWS_DIR_LENGTH 256
    00171 #define CONSOLE_EGACPI_LENGTH 9 // includes NULL
    00172 #define CONSOLE_EGACPI "\\ega.cpi"
    00173 #define CONSOLE_FONT_BUFFER_LENGTH 50
    00174 #define CONSOLE_DEFAULT_ROM_FONT 437
    00175
    00176
    00177 #ifdef i386
    00178 VOID
    00179 ReverseMousePointer(
    00180     IN PSCREEN_INFORMATION ScreenInfo,
    00181     IN PSMALL_RECT Region
    00182     );
    00183
    00184 VOID
    00185 ReadRectFromScreenBuffer(
    00186     IN PSCREEN_INFORMATION ScreenInfo,
    00187     IN COORD SourcePoint,
    00188     IN PCHAR_INFO Target,
    00189     IN COORD TargetSize,
    00190     IN PSMALL_RECT TargetRect
    00191     );
    00192
    00193 #endif
    00194
    00195 NTSTATUS
    00196 MapViewOfSection(
    00197     PHANDLE SectionHandle,
    00198     ULONG CommitSize,
    00199     PVOID *BaseAddress,
    00200     PSIZE_T ViewSize,
    00201     HANDLE ClientHandle,
    00202     PVOID *BaseClientAddress
    00203     );
    00204
    00205 NTSTATUS
    00206 ConnectToEmulator(
    00207     IN BOOL Connect,
    00208     IN PCONSOLE_INFORMATION Console
    00209     );
    00210
    00211
    00212 ULONG
    00213 SrvSetConsoleCursor(
    00214     IN OUT PCSR_API_MSG m,
    00215     IN OUT PCSR_REPLY_STATUS ReplyStatus
    00216     )
    00217
    00218 /*++
    00219
    00220 Description:
    00221
    00222     Sets the mouse pointer for the specified screen buffer.
    00223
    00224 Parameters:
    00225
    00226     hConsoleOutput - Supplies a console output handle.
    00227
    00228     hCursor - win32 cursor handle, should be NULL to set the default
    00229         cursor.
    00230
    00231 Return value:
    00232
    00233     TRUE - The operation was successful.
    00234
    00235     FALSE/NULL - The operation failed. Extended error status is available
    00236         using GetLastError.
    00237
    00238 --*/
    00239
    00240 {
    00241     PCONSOLE_SETCURSOR_MSG a = (PCONSOLE_SETCURSOR_MSG)&m->u.ApiMessageData;
    00242     NTSTATUS Status;
    00243     PCONSOLE_INFORMATION Console;
    00244     PHANDLE_DATA HandleData;
    00245
    00246     Status = ApiPreamble(a->ConsoleHandle,
    00247                          &Console
    00248                         );
    00249     if (!NT_SUCCESS(Status)) {
    00250         return Status;
    00251     }
    00252     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    00253                                  a->OutputHandle,
    00254                                  CONSOLE_GRAPHICS_OUTPUT_HANDLE,
    00255                                  GENERIC_WRITE,
    00256                                  &HandleData
    00257                                 );
    00258     if (NT_SUCCESS(Status)) {
    00259         if (a->CursorHandle == NULL) {
    00260             HandleData->Buffer.ScreenBuffer->CursorHandle = ghNormalCursor;
    00261         } else {
    00262             HandleData->Buffer.ScreenBuffer->CursorHandle = a->CursorHandle;
    00263         }
    00264         PostMessage(HandleData->Buffer.ScreenBuffer->Console->hWnd,
    00265                      WM_SETCURSOR,
    00266                      0,
    00267                      -1
    00268                     );
    00269     }
    00270     UnlockConsole(Console);
    00271     return Status;
    00272     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    00273 }
    00274
    00275 #ifdef i386
    00276 VOID
    00277 FullScreenCursor(
    00278     IN PSCREEN_INFORMATION ScreenInfo,
    00279     IN BOOL On
    00280     )
    00281 {
    00282     if (On) {
    00283         if (ScreenInfo->CursorDisplayCount < 0) {
    00284             ScreenInfo->CursorDisplayCount = 0;
    00285             ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
    00286         }
    00287     } else {
    00288         if (ScreenInfo->CursorDisplayCount >= 0) {
    00289             ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
    00290             ScreenInfo->CursorDisplayCount = -1;
    00291         }
    00292     }
    00293
    00294 }
    00295 #endif
    00296
    00297 ULONG
    00298 SrvShowConsoleCursor(
    00299     IN OUT PCSR_API_MSG m,
    00300     IN OUT PCSR_REPLY_STATUS ReplyStatus
    00301     )
    00302
    00303 /*++
    00304
    00305 Description:
    00306
    00307     Sets the mouse pointer visibility counter.  If the counter is less than
    00308     zero, the mouse pointer is not shown.
    00309
    00310 Parameters:
    00311
    00312     hOutput - Supplies a console output handle.
    00313
    00314     bShow - if TRUE, the display count is to be increased. if FALSE,
    00315         decreased.
    00316
    00317 Return value:
    00318
    00319     The return value specifies the new display count.
    00320
    00321 --*/
    00322
    00323 {
    00324     PCONSOLE_SHOWCURSOR_MSG a = (PCONSOLE_SHOWCURSOR_MSG)&m->u.ApiMessageData;
    00325     NTSTATUS Status;
    00326     PCONSOLE_INFORMATION Console;
    00327     PHANDLE_DATA HandleData;
    00328
    00329     Status = ApiPreamble(a->ConsoleHandle,
    00330                          &Console
    00331                         );
    00332     if (!NT_SUCCESS(Status)) {
    00333         return Status;
    00334     }
    00335     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    00336                                  a->OutputHandle,
    00337                                  CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
    00338                                  GENERIC_WRITE,
    00339                                  &HandleData
    00340                                 );
    00341     if (NT_SUCCESS(Status)) {
    00342         if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) ) {
    00343             if (a->bShow) {
    00344                 HandleData->Buffer.ScreenBuffer->CursorDisplayCount += 1;
    00345             } else {
    00346                 HandleData->Buffer.ScreenBuffer->CursorDisplayCount -= 1;
    00347             }
    00348             if (HandleData->Buffer.ScreenBuffer == Console->CurrentScreenBuffer) {
    00349                 PostMessage(HandleData->Buffer.ScreenBuffer->Console->hWnd,
    00350                              WM_SETCURSOR,
    00351                              0,
    00352                              -1
    00353                             );
    00354             }
    00355         } else {
    00356 #ifdef i386
    00357             if (HandleData->HandleType != CONSOLE_GRAPHICS_OUTPUT_HANDLE &&
    00358                 Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
    00359                 HandleData->Buffer.ScreenBuffer == Console->CurrentScreenBuffer) {
    00360                 FullScreenCursor(HandleData->Buffer.ScreenBuffer,a->bShow);
    00361             }
    00362 #endif
    00363         }
    00364         a->DisplayCount = HandleData->Buffer.ScreenBuffer->CursorDisplayCount;
    00365     }
    00366     UnlockConsole(Console);
    00367     return Status;
    00368     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    00369 }
    00370
    00371
    00372 ULONG
    00373 SrvConsoleMenuControl(
    00374     IN OUT PCSR_API_MSG m,
    00375     IN OUT PCSR_REPLY_STATUS ReplyStatus
    00376     )
    00377
    00378 /*++
    00379
    00380 Description:
    00381
    00382     Sets the command id range for the current screen buffer and returns the
    00383     menu handle.
    00384
    00385 Parameters:
    00386
    00387     hConsoleOutput - Supplies a console output handle.
    00388
    00389     dwCommandIdLow - Specifies the lowest command id to store in the input buffer.
    00390
    00391     dwCommandIdHigh - Specifies the highest command id to store in the input
    00392         buffer.
    00393
    00394 Return value:
    00395
    00396     TRUE - The operation was successful.
    00397
    00398     FALSE/NULL - The operation failed. Extended error status is available
    00399         using GetLastError.
    00400
    00401 --*/
    00402
    00403 {
    00404     PCONSOLE_MENUCONTROL_MSG a = (PCONSOLE_MENUCONTROL_MSG)&m->u.ApiMessageData;
    00405     NTSTATUS Status;
    00406     PCONSOLE_INFORMATION Console;
    00407     PHANDLE_DATA HandleData;
    00408
    00409     Status = ApiPreamble(a->ConsoleHandle,
    00410                          &Console
    00411                         );
    00412     if (!NT_SUCCESS(Status)) {
    00413         return Status;
    00414     }
    00415     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    00416                                  a->OutputHandle,
    00417                                  CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
    00418                                  GENERIC_WRITE,
    00419                                  &HandleData
    00420                                 );
    00421     if (NT_SUCCESS(Status)) {
    00422         a->hMenu = HandleData->Buffer.ScreenBuffer->Console->hMenu;
    00423         HandleData->Buffer.ScreenBuffer->CommandIdLow = a->CommandIdLow;
    00424         HandleData->Buffer.ScreenBuffer->CommandIdHigh = a->CommandIdHigh;
    00425     }
    00426     UnlockConsole(Console);
    00427     return Status;
    00428     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    00429 }
    00430
    00431 ULONG
    00432 SrvSetConsolePalette(
    00433     IN OUT PCSR_API_MSG m,
    00434     IN OUT PCSR_REPLY_STATUS ReplyStatus
    00435     )
    00436
    00437 /*++
    00438
    00439 Description:
    00440
    00441     Sets the palette for the console screen buffer.
    00442
    00443 Parameters:
    00444
    00445     hOutput - Supplies a console output handle.
    00446
    00447     hPalette - Supplies a handle to the palette to set.
    00448
    00449     dwUsage - Specifies use of the system palette.
    00450
    00451         SYSPAL_NOSTATIC - System palette contains no static colors
    00452                           except black and white.
    00453
    00454         SYSPAL_STATIC -   System palette contains static colors
    00455                           which will not change when an application
    00456                           realizes its logical palette.
    00457
    00458 Return value:
    00459
    00460     TRUE - The operation was successful.
    00461
    00462     FALSE/NULL - The operation failed. Extended error status is available
    00463         using GetLastError.
    00464
    00465 --*/
    00466
    00467 {
    00468     PCONSOLE_SETPALETTE_MSG a = (PCONSOLE_SETPALETTE_MSG)&m->u.ApiMessageData;
    00469     NTSTATUS Status;
    00470     PCONSOLE_INFORMATION Console;
    00471     PHANDLE_DATA HandleData;
    00472     HPALETTE hOldPalette;
    00473
    00474     Status = ApiPreamble(a->ConsoleHandle,
    00475                          &Console
    00476                         );
    00477     if (!NT_SUCCESS(Status)) {
    00478         return Status;
    00479     }
    00480     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    00481                                  a->OutputHandle,
    00482                                  CONSOLE_GRAPHICS_OUTPUT_HANDLE,
    00483                                  GENERIC_WRITE,
    00484                                  &HandleData
    00485                                 );
    00486     if (NT_SUCCESS(Status)) {
    00487         USERTHREAD_USEDESKTOPINFO utudi;
    00488         BOOL bReset = FALSE;
    00489
    00490         /*
    00491          * Palette handle was converted in the client.
    00492          */
    00493         if (GetCurrentThreadId() != HandleData->Buffer.ScreenBuffer->
    00494                 Console->InputThreadInfo->ThreadId) {
    00495             bReset = TRUE;
    00496             utudi.hThread = HandleData->Buffer.ScreenBuffer->Console->InputThreadInfo->ThreadHandle;
    00497             utudi.drdRestore.pdeskRestore = NULL;
    00498             NtUserSetInformationThread(NtCurrentThread(),
    00499                     UserThreadUseDesktop,
    00500                     &utudi, sizeof(utudi));
    00501         }
    00502
    00503         NtUserConsoleControl(ConsolePublicPalette, &(a->hPalette), sizeof(HPALETTE));
    00504
    00505         hOldPalette = SelectPalette(
    00506                 HandleData->Buffer.ScreenBuffer->Console->hDC,
    00507                 a->hPalette,
    00508                 FALSE);
    00509
    00510         if (hOldPalette == NULL) {
    00511             Status = STATUS_INVALID_PARAMETER;
    00512         } else {
    00513             if ((HandleData->Buffer.ScreenBuffer->hPalette != NULL) &&
    00514                     (a->hPalette != HandleData->Buffer.ScreenBuffer->hPalette)) {
    00515                 DeleteObject(HandleData->Buffer.ScreenBuffer->hPalette);
    00516             }
    00517             HandleData->Buffer.ScreenBuffer->hPalette = a->hPalette;
    00518             HandleData->Buffer.ScreenBuffer->dwUsage = a->dwUsage;
    00519             if (!(HandleData->Buffer.ScreenBuffer->Console->Flags & CONSOLE_IS_ICONIC) &&
    00520                     HandleData->Buffer.ScreenBuffer->Console->FullScreenFlags == 0) {
    00521
    00522                 SetSystemPaletteUse(HandleData->Buffer.ScreenBuffer->Console->hDC,
    00523                         HandleData->Buffer.ScreenBuffer->dwUsage);
    00524                 RealizePalette(HandleData->Buffer.ScreenBuffer->Console->hDC);
    00525             }
    00526             if (HandleData->Buffer.ScreenBuffer->Console->hSysPalette == NULL) {
    00527                     HandleData->Buffer.ScreenBuffer->Console->hSysPalette = hOldPalette;
    00528             }
    00529         }
    00530
    00531         if (bReset) {
    00532             utudi.hThread = NULL;
    00533             NtUserSetInformationThread(NtCurrentThread(),
    00534                     UserThreadUseDesktop, &utudi, sizeof(utudi));
    00535         }
    00536     }
    00537     UnlockConsole(Console);
    00538     return Status;
    00539     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    00540 }
    00541
    00542
    00543 VOID
    00544 SetActivePalette(
    00545     IN PSCREEN_INFORMATION ScreenInfo
    00546     )
    00547 {
    00548     USERTHREAD_USEDESKTOPINFO utudi;
    00549     BOOL bReset = FALSE;
    00550
    00551     if (GetCurrentThreadId() != ScreenInfo->Console->InputThreadInfo->ThreadId) {
    00552         bReset = TRUE;
    00553         utudi.hThread = ScreenInfo->Console->InputThreadInfo->ThreadHandle;
    00554         utudi.drdRestore.pdeskRestore = NULL;
    00555         NtUserSetInformationThread(NtCurrentThread(),
    00556                 UserThreadUseDesktop,
    00557                 &utudi, sizeof(utudi));
    00558     }
    00559
    00560     SetSystemPaletteUse(ScreenInfo->Console->hDC,
    00561                         ScreenInfo->dwUsage
    00562                        );
    00563     RealizePalette(ScreenInfo->Console->hDC);
    00564
    00565     if (bReset == TRUE) {
    00566         utudi.hThread = NULL;
    00567         NtUserSetInformationThread(NtCurrentThread(),
    00568                 UserThreadUseDesktop, &utudi, sizeof(utudi));
    00569     }
    00570 }
    00571
    00572 VOID
    00573 UnsetActivePalette(
    00574     IN PSCREEN_INFORMATION ScreenInfo
    00575     )
    00576 {
    00577     USERTHREAD_USEDESKTOPINFO utudi;
    00578     BOOL bReset = FALSE;
    00579
    00580     if (GetCurrentThreadId() != ScreenInfo->Console->InputThreadInfo->ThreadId) {
    00581         bReset = TRUE;
    00582         utudi.hThread = ScreenInfo->Console->InputThreadInfo->ThreadHandle;
    00583         utudi.drdRestore.pdeskRestore = NULL;
    00584         NtUserSetInformationThread(NtCurrentThread(),
    00585                 UserThreadUseDesktop,
    00586                 &utudi, sizeof(utudi));
    00587     }
    00588
    00589     SetSystemPaletteUse(ScreenInfo->Console->hDC,
    00590                         SYSPAL_STATIC
    00591                        );
    00592     RealizePalette(ScreenInfo->Console->hDC);
    00593
    00594
    00595     if (bReset == TRUE) {
    00596         utudi.hThread = NULL;
    00597         NtUserSetInformationThread(NtCurrentThread(),
    00598                 UserThreadUseDesktop, &utudi, sizeof(utudi));
    00599     }
    00600 }
    00601
    00602 NTSTATUS
    00603 ConvertToFullScreen(
    00604     IN PCONSOLE_INFORMATION Console
    00605     )
    00606 {
    00607 #ifdef i386
    00608     PSCREEN_INFORMATION Cur;
    00609     COORD WindowedWindowSize, WindowSize;
    00610
    00611     // for each charmode screenbuffer
    00612     //     match window size to a mode/font
    00613     //     grow screen buffer if necessary
    00614     //     save old window dimensions
    00615     //     set new window dimensions
    00616
    00617     for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
    00618
    00619         if (Cur->Flags & CONSOLE_GRAPHICS_BUFFER) {
    00620             continue;
    00621         }
    00622
    00623         // save old window dimensions
    00624
    00625         WindowedWindowSize.X = CONSOLE_WINDOW_SIZE_X(Cur);
    00626         WindowedWindowSize.Y = CONSOLE_WINDOW_SIZE_Y(Cur);
    00627
    00628         Cur->BufferInfo.TextInfo.WindowedWindowSize = WindowedWindowSize;
    00629         Cur->BufferInfo.TextInfo.WindowedScreenSize = Cur->ScreenBufferSize;
    00630
    00631         // match window size to a mode/font
    00632
    00633         Cur->BufferInfo.TextInfo.ModeIndex = MatchWindowSize(
    00634                 Console->OutputCP,
    00635                 Cur->ScreenBufferSize, &WindowSize);
    00636
    00637         // grow screen buffer if necessary
    00638
    00639         if (WindowSize.X > Cur->ScreenBufferSize.X ||
    00640             WindowSize.Y > Cur->ScreenBufferSize.Y) {
    00641             COORD NewScreenSize;
    00642
    00643             NewScreenSize.X = max(WindowSize.X,Cur->ScreenBufferSize.X);
    00644             NewScreenSize.Y = max(WindowSize.Y,Cur->ScreenBufferSize.Y);
    00645
    00646             if (ResizeScreenBuffer(Cur, NewScreenSize, FALSE) == STATUS_INVALID_HANDLE) {
    00647                 return STATUS_INVALID_HANDLE;
    00648             }
    00649         }
    00650
    00651 #if 0
    00652 DbgPrint("new window size is %d %d\n",WindowSize.X,WindowSize.Y);
    00653 DbgPrint("existing window size is %d %d\n",WindowedWindowSize.X,WindowedWindowSize.Y);
    00654 DbgPrint("existing window is %d %d %d %d\n",Cur->Window.Left,Cur->Window.Top,Cur->Window.Right,Cur->Window.Bottom);
    00655 DbgPrint("screenbuffersize is %d %d\n",Cur->ScreenBufferSize.X,Cur->ScreenBufferSize.Y);
    00656 #endif
    00657         // set new window dimensions
    00658         // we always resize horizontally from the right (change the
    00659         // right edge).
    00660         // we resize vertically from the bottom, keeping the cursor visible.
    00661
    00662         if (WindowedWindowSize.X != WindowSize.X) {
    00663             Cur->Window.Right -= WindowedWindowSize.X - WindowSize.X;
    00664             if (Cur->Window.Right >= Cur->ScreenBufferSize.X) {
    00665                 Cur->Window.Left -= Cur->Window.Right - Cur->ScreenBufferSize.X + 1;
    00666                 Cur->Window.Right -= Cur->Window.Right - Cur->ScreenBufferSize.X + 1;
    00667             }
    00668         }
    00669         if (WindowedWindowSize.Y > WindowSize.Y) {
    00670             Cur->Window.Bottom -= WindowedWindowSize.Y - WindowSize.Y;
    00671             if (Cur->Window.Bottom >= Cur->ScreenBufferSize.Y) {
    00672                 Cur->Window.Top -= Cur->Window.Bottom - Cur->ScreenBufferSize.Y + 1;
    00673                 Cur->Window.Bottom = Cur->ScreenBufferSize.Y - 1;
    00674             }
    00675         } else if (WindowedWindowSize.Y < WindowSize.Y) {
    00676             Cur->Window.Top -= WindowSize.Y - WindowedWindowSize.Y;
    00677             if (Cur->Window.Top < 0) {
    00678                 Cur->Window.Bottom -= Cur->Window.Top;
    00679                 Cur->Window.Top = 0;
    00680             }
    00681         }
    00682         if (Cur->BufferInfo.TextInfo.CursorPosition.Y > Cur->Window.Bottom) {
    00683             Cur->Window.Top += Cur->BufferInfo.TextInfo.CursorPosition.Y - Cur->Window.Bottom;
    00684             Cur->Window.Bottom = Cur->BufferInfo.TextInfo.CursorPosition.Y;
    00685         }
    00686 #if 0
    00687 DbgPrint("new window is %d %d %d %d\n",Cur->Window.Left,Cur->Window.Top,Cur->Window.Right,Cur->Window.Bottom);
    00688 DbgPrint("cursor is %d %d\n",Cur->BufferInfo.TextInfo.CursorPosition.X,Cur->BufferInfo.TextInfo.CursorPosition.Y);
    00689 #endif
    00690         ASSERT(WindowSize.X == CONSOLE_WINDOW_SIZE_X(Cur));
    00691         ASSERT(WindowSize.Y == CONSOLE_WINDOW_SIZE_Y(Cur));
    00692         Cur->BufferInfo.TextInfo.MousePosition.X = Cur->Window.Left;
    00693         Cur->BufferInfo.TextInfo.MousePosition.Y = Cur->Window.Top;
    00694
    00695         if (Cur->Flags & CONSOLE_OEMFONT_DISPLAY) {
    00696             DBGCHARS(("ConvertToFullScreen converts UnicodeOem -> Unicode\n"));
    00697             FalseUnicodeToRealUnicode(
    00698                     Cur->BufferInfo.TextInfo.TextRows,
    00699                     Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
    00700                     Console->OutputCP);
    00701         } else {
    00702             DBGCHARS(("ConvertToFullScreen needs no conversion\n"));
    00703         }
    00704         DBGCHARS(("Cur->BufferInfo.TextInfo.Rows = %lx\n",
    00705                 Cur->BufferInfo.TextInfo.Rows));
    00706         DBGCHARS(("Cur->BufferInfo.TextInfo.TextRows = %lx\n",
    00707                 Cur->BufferInfo.TextInfo.TextRows));
    00708     }
    00709
    00710     Cur = Console->CurrentScreenBuffer;
    00711
    00712     if (Cur->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00713         if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
    00714             PCONVERSIONAREA_INFORMATION ConvAreaInfo;
    00715             ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
    00716             while (ConvAreaInfo) {
    00717                 NTSTATUS Status;
    00718
    00719                 Status = StoreTextBufferFontInfo(ConvAreaInfo->ScreenBuffer,
    00720                                                  SCR_FONTNUMBER(Cur),
    00721                                                  SCR_FONTSIZE(Cur),
    00722                                                  SCR_FAMILY(Cur),
    00723                                                  SCR_FONTWEIGHT(Cur),
    00724                                                  SCR_FACENAME(Cur),
    00725                                                  SCR_FONTCODEPAGE(Cur));
    00726                 if (!NT_SUCCESS(Status)) {
    00727                     return((ULONG) Status);
    00728                 }
    00729
    00730                 ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = Cur->BufferInfo.TextInfo.ModeIndex;
    00731                 ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
    00732             }
    00733         }
    00734         Cur->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
    00735     }
    00736
    00737     SetWindowSize(Cur);
    00738     WriteToScreen(Cur, &Console->CurrentScreenBuffer->Window);
    00739
    00740 #else
    00741     UNREFERENCED_PARAMETER(Console);
    00742 #endif
    00743     return STATUS_SUCCESS;
    00744 }
    00745
    00746 NTSTATUS
    00747 ConvertToWindowed(
    00748     IN PCONSOLE_INFORMATION Console
    00749     )
    00750 {
    00751 #ifdef i386
    00752     PSCREEN_INFORMATION Cur;
    00753     SMALL_RECT WindowedWindow;
    00754
    00755     // for each charmode screenbuffer
    00756     //     restore window dimensions
    00757
    00758     for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
    00759         if ((Cur->Flags & CONSOLE_TEXTMODE_BUFFER) == 0) {
    00760             continue;
    00761         }
    00762
    00763         if (ResizeScreenBuffer(Cur,
    00764                            Cur->BufferInfo.TextInfo.WindowedScreenSize,
    00765                            FALSE) == STATUS_INVALID_HANDLE) {
    00766             /*
    00767              * Something really went wrong. All we can do is just to
    00768              * bail out.
    00769              */
    00770             return STATUS_INVALID_HANDLE;
    00771         }
    00772
    00773         WindowedWindow.Right  = Cur->Window.Right;
    00774         WindowedWindow.Bottom = Cur->Window.Bottom;
    00775         WindowedWindow.Left   = Cur->Window.Right + 1 -
    00776                                 Cur->BufferInfo.TextInfo.WindowedWindowSize.X;
    00777         WindowedWindow.Top    = Cur->Window.Bottom + 1 -
    00778                                 Cur->BufferInfo.TextInfo.WindowedWindowSize.Y;
    00779         if (WindowedWindow.Left > Cur->Window.Left) {
    00780             WindowedWindow.Right -= WindowedWindow.Left - Cur->Window.Left;
    00781             WindowedWindow.Left = Cur->Window.Left;
    00782         }
    00783         if (WindowedWindow.Right < Cur->BufferInfo.TextInfo.CursorPosition.X) {
    00784             WindowedWindow.Left += Cur->BufferInfo.TextInfo.CursorPosition.X - WindowedWindow.Right;
    00785             WindowedWindow.Right = Cur->BufferInfo.TextInfo.CursorPosition.X;
    00786         }
    00787         if (WindowedWindow.Top > Cur->Window.Top) {
    00788             WindowedWindow.Bottom -= WindowedWindow.Top - Cur->Window.Top;
    00789             WindowedWindow.Top = Cur->Window.Top;
    00790         }
    00791         if (WindowedWindow.Bottom < Cur->BufferInfo.TextInfo.CursorPosition.Y) {
    00792             WindowedWindow.Top += Cur->BufferInfo.TextInfo.CursorPosition.Y - WindowedWindow.Bottom;
    00793             WindowedWindow.Bottom = Cur->BufferInfo.TextInfo.CursorPosition.Y;
    00794         }
    00795         ResizeWindow(Cur, &WindowedWindow, FALSE);
    00796
    00797         if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
    00798             SetFont(Cur);
    00799         }
    00800
    00801         if (Cur->Flags & CONSOLE_OEMFONT_DISPLAY) {
    00802             DBGCHARS(("ConvertToWindowed converts Unicode -> UnicodeOem\n"));
    00803             RealUnicodeToFalseUnicode(
    00804                     Cur->BufferInfo.TextInfo.TextRows,
    00805                     Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
    00806                     Console->OutputCP);
    00807         } else {
    00808             DBGCHARS(("ConvertToWindowed needs no conversion\n"));
    00809         }
    00810         DBGCHARS(("Cur->BufferInfo.TextInfo.Rows = %lx\n",
    00811                 Cur->BufferInfo.TextInfo.Rows));
    00812         DBGCHARS(("Cur->BufferInfo.TextInfo.TextRows = %lx\n",
    00813                 Cur->BufferInfo.TextInfo.TextRows));
    00814     }
    00815
    00816     Cur = Console->CurrentScreenBuffer;
    00817
    00818     if (Cur->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00819         if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
    00820             PCONVERSIONAREA_INFORMATION ConvAreaInfo;
    00821             ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
    00822             while (ConvAreaInfo) {
    00823                 NTSTATUS Status;
    00824
    00825                 Status = StoreTextBufferFontInfo(ConvAreaInfo->ScreenBuffer,
    00826                                                  SCR_FONTNUMBER(Cur),
    00827                                                  SCR_FONTSIZE(Cur),
    00828                                                  SCR_FAMILY(Cur),
    00829                                                  SCR_FONTWEIGHT(Cur),
    00830                                                  SCR_FACENAME(Cur),
    00831                                                  SCR_FONTCODEPAGE(Cur));
    00832                 if (!NT_SUCCESS(Status)) {
    00833                     return((ULONG) Status);
    00834                 }
    00835
    00836                 ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = Cur->BufferInfo.TextInfo.ModeIndex;
    00837                 ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
    00838             }
    00839         }
    00840         Cur->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
    00841     }
    00842
    00843     SetWindowSize(Cur);
    00844     WriteToScreen(Cur, &Console->CurrentScreenBuffer->Window);
    00845
    00846 #else
    00847     UNREFERENCED_PARAMETER(Console);
    00848 #endif
    00849     return STATUS_SUCCESS;
    00850 }
    00851
    00852 ULONG
    00853 SrvSetConsoleDisplayMode(
    00854     IN OUT PCSR_API_MSG m,
    00855     IN OUT PCSR_REPLY_STATUS ReplyStatus
    00856     )
    00857
    00858 /*++
    00859
    00860 Description:
    00861
    00862     This routine sets the console display mode for an output buffer.
    00863     This API is only supported on x86 machines.  Jazz consoles are always
    00864     windowed.
    00865
    00866 Parameters:
    00867
    00868     hConsoleOutput - Supplies a console output handle.
    00869
    00870     dwFlags - Specifies the display mode. Options are:
    00871
    00872         CONSOLE_FULLSCREEN_MODE - data is displayed fullscreen
    00873
    00874         CONSOLE_WINDOWED_MODE - data is displayed in a window
    00875
    00876     lpNewScreenBufferDimensions - On output, contains the new dimensions of
    00877         the screen buffer.  The dimensions are in rows and columns for
    00878         textmode screen buffers.
    00879
    00880 Return value:
    00881
    00882     TRUE - The operation was successful.
    00883
    00884     FALSE/NULL - The operation failed. Extended error status is available
    00885         using GetLastError.
    00886
    00887 --*/
    00888
    00889 {
    00890     PCONSOLE_SETDISPLAYMODE_MSG a = (PCONSOLE_SETDISPLAYMODE_MSG)&m->u.ApiMessageData;
    00891     NTSTATUS Status;
    00892     PCONSOLE_INFORMATION Console;
    00893     PHANDLE_DATA HandleData;
    00894     PSCREEN_INFORMATION ScreenInfo;
    00895     UINT State;
    00896     HANDLE  hEvent = NULL;
    00897
    00898     Status = ApiPreamble(a->ConsoleHandle,
    00899                          &Console
    00900                         );
    00901     if (!NT_SUCCESS(Status)) {
    00902         return Status;
    00903     }
    00904
    00905     Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
    00906                                a->hEvent,
    00907                                NtCurrentProcess(),
    00908                                &hEvent,
    00909                                0,
    00910                                FALSE,
    00911                                DUPLICATE_SAME_ACCESS
    00912                                );
    00913     if (!NT_SUCCESS(Status)) {
    00914         goto SrvSetConsoleDisplayModeFailure;
    00915     }
    00916     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    00917                                  a->OutputHandle,
    00918                                  CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
    00919                                  GENERIC_WRITE,
    00920                                  &HandleData
    00921                                 );
    00922     if (NT_SUCCESS(Status)) {
    00923         ScreenInfo = HandleData->Buffer.ScreenBuffer;
    00924         if (!ACTIVE_SCREEN_BUFFER(ScreenInfo))  {
    00925             Status = STATUS_INVALID_PARAMETER;
    00926             goto SrvSetConsoleDisplayModeFailure;
    00927         }
    00928         if (a->dwFlags == CONSOLE_FULLSCREEN_MODE) {
    00929 #if !defined(_X86_)
    00930             if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
    00931                 Status = STATUS_INVALID_PARAMETER;
    00932                 goto SrvSetConsoleDisplayModeFailure;
    00933             }
    00934 #else
    00935             if (!FullScreenInitialized) {
    00936                 Status = STATUS_INVALID_PARAMETER;
    00937                 goto SrvSetConsoleDisplayModeFailure;
    00938             }
    00939 #endif
    00940             if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
    00941                 KdPrint(("CONSRV: VDM converting to fullscreen twice\n"));
    00942                 ASSERT(FALSE);
    00943                 Status = STATUS_INVALID_PARAMETER;
    00944                 goto SrvSetConsoleDisplayModeFailure;
    00945             }
    00946             State = FULLSCREEN;
    00947         } else {
    00948             if (Console->FullScreenFlags == 0) {
    00949                 KdPrint(("CONSRV: VDM converting to windowed twice\n"));
    00950                 ASSERT(FALSE);
    00951                 Status = STATUS_INVALID_PARAMETER;
    00952                 goto SrvSetConsoleDisplayModeFailure;
    00953             }
    00954             State = WINDOWED;
    00955         }
    00956         Status = QueueConsoleMessage(Console,
    00957                     CM_MODE_TRANSITION,
    00958                     State,
    00959                     (LPARAM)hEvent
    00960                     );
    00961         if (!NT_SUCCESS(Status)) {
    00962             goto SrvSetConsoleDisplayModeFailure;
    00963         }
    00964     }
    00965     UnlockConsole(Console);
    00966     return Status;
    00967
    00968 SrvSetConsoleDisplayModeFailure:
    00969     if (hEvent) {
    00970         NtSetEvent(hEvent, NULL);
    00971         NtClose(hEvent);
    00972     }
    00973     UnlockConsole(Console);
    00974     return Status;
    00975
    00976     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    00977 }
    00978
    00979 VOID
    00980 UnregisterVDM(
    00981     IN PCONSOLE_INFORMATION Console
    00982     )
    00983 {
    00984 // williamh, Feb 2 1994.
    00985 // catch multiple calls to unregister vdm. Believe it or not, this could
    00986 // happen
    00987     ASSERT(Console->Flags & CONSOLE_VDM_REGISTERED);
    00988     if (!(Console->Flags & CONSOLE_VDM_REGISTERED))
    00989         return;
    00990
    00991 #if defined(FE_SB) && defined(i386)
    00992 // When HDOS apps exit, console screen resolution is changed to 640*400. Because HBIOS set
    00993 // Screen resolution to 640*400. So, we should replace current screen resoultion(640*480).
    00994 // 09/11/96 bklee
    00995     {
    00996
    00997     if ((Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)  &&
    00998         ( Console->OutputCP == KOREAN_CP ||
    00999          (Console->OutputCP == JAPAN_CP && ISNECPC98(gdwMachineId) ) )) {
    01000
    01001          ULONG Index;
    01002          DEVMODEW Devmode;
    01003          BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
    01004
    01005          Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
    01006
    01007          ZeroMemory(&Devmode, sizeof(Devmode));
    01008
    01009          Devmode.dmSize = sizeof(Devmode);
    01010          Devmode.dmDriverExtra = 0;
    01011          Devmode.dmFields = DM_BITSPERPEL   |
    01012                             DM_PELSWIDTH    |
    01013                             DM_PELSHEIGHT   |
    01014                             DM_DISPLAYFLAGS;
    01015
    01016          Devmode.dmBitsPerPel   = 4;
    01017
    01018          Devmode.dmPelsWidth  = RegModeFontPairs[Index].Resolution.X;
    01019          Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
    01020          Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
    01021
    01022          GdiFullscreenControl(FullscreenControlSetMode,
    01023                               &Devmode,
    01024                               sizeof(Devmode),
    01025                               NULL,
    01026                               NULL);
    01027     }
    01028     }
    01029 #endif
    01030 #ifdef i386
    01031     if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
    01032         Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) {
    01033     NtUserConsoleControl(ConsoleSetVDMCursorBounds, NULL, 0);
    01034         // connect emulator
    01035         ConnectToEmulator(FALSE, Console);
    01036     }
    01037
    01038     if (FullScreenInitialized) {
    01039         CloseHandle(Console->VDMStartHardwareEvent);
    01040         CloseHandle(Console->VDMEndHardwareEvent);
    01041         NtUnmapViewOfSection(NtCurrentProcess(),Console->StateBuffer);
    01042         NtUnmapViewOfSection(Console->VDMProcessHandle,Console->StateBufferClient);
    01043         NtClose(Console->StateSectionHandle);
    01044         Console->StateLength = 0;
    01045     }
    01046
    01047 #endif
    01048
    01049     Console->Flags &= ~CONSOLE_VDM_REGISTERED;
    01050
    01051     if (Console->Flags & CONSOLE_HAS_FOCUS) {
    01052         USERTHREAD_FLAGS Flags;
    01053
    01054         Flags.dwFlags = 0;
    01055         Flags.dwMask = (TIF_VDMAPP | TIF_DOSEMULATOR);
    01056         NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
    01057                 UserThreadFlags, &Flags, sizeof(Flags));
    01058     }
    01059     Console->Flags &= ~CONSOLE_WOW_REGISTERED;
    01060     ASSERT(Console->VDMBuffer != NULL);
    01061     if (Console->VDMBuffer != NULL) {
    01062         NtUnmapViewOfSection(Console->VDMProcessHandle,Console->VDMBufferClient);
    01063         NtUnmapViewOfSection(NtCurrentProcess(),Console->VDMBuffer);
    01064         NtClose(Console->VDMBufferSectionHandle);
    01065         Console->VDMBuffer = NULL;
    01066     }
    01067 #ifdef i386
    01068     if (Console->CurrentScreenBuffer &&
    01069         Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
    01070         Console->CurrentScreenBuffer->BufferInfo.TextInfo.MousePosition.X = 0;
    01071         Console->CurrentScreenBuffer->BufferInfo.TextInfo.MousePosition.Y = 0;
    01072     }
    01073 #endif
    01074     ASSERT(Console->VDMProcessHandle);
    01075     CloseHandle(Console->VDMProcessHandle);
    01076     Console->VDMProcessHandle = NULL;
    01077
    01078 #if defined(FE_SB) && defined(FE_IME) && defined(i386)
    01079     {
    01080         if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
    01081             Console->Flags |= CONSOLE_JUST_VDM_UNREGISTERED ;
    01082         }
    01083         else if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
    01084             AdjustCursorPosition(Console->CurrentScreenBuffer,
    01085                                  Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorPosition,
    01086                                  TRUE,
    01087                                  NULL);
    01088         }
    01089     }
    01090 #endif
    01091 }
    01092
    01093 ULONG
    01094 SrvRegisterConsoleVDM(
    01095     IN OUT PCSR_API_MSG m,
    01096     IN OUT PCSR_REPLY_STATUS ReplyStatus
    01097     )
    01098 {
    01099     PCONSOLE_REGISTERVDM_MSG a = (PCONSOLE_REGISTERVDM_MSG)&m->u.ApiMessageData;
    01100     NTSTATUS Status;
    01101     PCONSOLE_INFORMATION Console;
    01102     SIZE_T ViewSize;
    01103 #ifdef i386
    01104     VIDEO_REGISTER_VDM RegisterVdm;
    01105     ULONG RegisterVdmSize = sizeof(RegisterVdm);
    01106     VIDEO_VDM Vdm;
    01107 #endif  //i386
    01108     Status = ApiPreamble(a->ConsoleHandle,
    01109                          &Console
    01110                         );
    01111     if (!NT_SUCCESS(Status)) {
    01112         return Status;
    01113     }
    01114
    01115
    01116     if (!a->RegisterFlags) {
    01117 //      williamh, Jan 28 1994
    01118 //      do not do an assert here because we may have unregistered the ntvdm
    01119 //      and the ntvdm doesn't necessarily know this(and it could post another
    01120 //      unregistervdm). Return error here so NTVDM knows what to do
    01121 //      ASSERT(Console->Flags & CONSOLE_VDM_REGISTERED);
    01122
    01123         if (Console->Flags & CONSOLE_VDM_REGISTERED) {
    01124             ASSERT(!(Console->Flags & CONSOLE_FULLSCREEN_NOPAINT));
    01125             UnregisterVDM(Console);
    01126 #ifdef i386
    01127             if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
    01128                 Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
    01129             //    SetVideoMode(Console->CurrentScreenBuffer);
    01130                 //set up cursor
    01131                 SetCursorInformationHW(Console->CurrentScreenBuffer,
    01132                                        Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorSize,
    01133                                        Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorVisible);
    01134                 SetCursorPositionHW(Console->CurrentScreenBuffer,
    01135                                     Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorPosition);
    01136             }
    01137 #endif
    01138             Status = STATUS_SUCCESS;
    01139         } else {
    01140             Status = STATUS_ACCESS_DENIED;
    01141         }
    01142         UnlockConsole(Console);
    01143         return Status;
    01144     }
    01145
    01146     if (!CsrValidateMessageBuffer(m, &a->StateSectionName, a->StateSectionNameLength, sizeof(BYTE)) ||
    01147         !CsrValidateMessageBuffer(m, &a->VDMBufferSectionName, a->VDMBufferSectionNameLength, sizeof(BYTE))) {
    01148
    01149         UnlockConsole(Console);
    01150         return STATUS_INVALID_PARAMETER;
    01151     }
    01152
    01153     // check it out. A console should have only one VDM registered.
    01154     ASSERT(!(Console->Flags & CONSOLE_VDM_REGISTERED));
    01155
    01156     if (Console->Flags & CONSOLE_VDM_REGISTERED) {
    01157         UnlockConsole(Console);
    01158         return (ULONG) STATUS_ACCESS_DENIED;
    01159     }
    01160
    01161     ASSERT(!Console->VDMProcessHandle);
    01162
    01163     Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
    01164                                NtCurrentProcess(), &Console->VDMProcessHandle,
    01165                                0, FALSE, DUPLICATE_SAME_ACCESS);
    01166     if (!NT_SUCCESS(Status)) {
    01167         UnlockConsole(Console);
    01168         return Status;
    01169     }
    01170     Console->VDMProcessId = CONSOLE_CLIENTPROCESSID();
    01171
    01172 #ifdef i386
    01173
    01174     Vdm.ProcessHandle = Console->VDMProcessHandle;
    01175
    01176     //
    01177     // Assume fullscreen initialization will fail.
    01178     // have state length set to zero so that NTVDM will know
    01179     // full screen is disabled.
    01180     //
    01181
    01182     a->StateLength = 0;
    01183     Console->StateLength = 0;
    01184     Console->StateBufferClient = NULL;
    01185
    01186     if (FullScreenInitialized) {
    01187
    01188     Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
    01189                    a->StartEvent,
    01190                    NtCurrentProcess(),
    01191                    &Console->VDMStartHardwareEvent,
    01192                    0,
    01193                    FALSE,
    01194                    DUPLICATE_SAME_ACCESS
    01195                   );
    01196     if (NT_SUCCESS(Status)) {
    01197         Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
    01198                        a->EndEvent,
    01199                        NtCurrentProcess(),
    01200                        &Console->VDMEndHardwareEvent,
    01201                        0,
    01202                        FALSE,
    01203                        DUPLICATE_SAME_ACCESS
    01204                       );
    01205         if (NT_SUCCESS(Status)) {
    01206                 Status = GdiFullscreenControl(FullscreenControlRegisterVdm,
    01207                                          &Vdm,
    01208                                          sizeof(Vdm),
    01209                                          &RegisterVdm,
    01210                                          &RegisterVdmSize
    01211                                         );
    01212
    01213           if (NT_SUCCESS(Status)) {
    01214
    01215                     //
    01216                     // create state section and map a view of it into server and vdm.
    01217                     // this section is used to get/set video hardware state during
    01218                     // the fullscreen<->windowed transition.  we create the section
    01219                     // instead of the vdm for security purposes.
    01220                     //
    01221
    01222             Status = MapViewOfSection(&Console->StateSectionHandle,
    01223                           RegisterVdm.MinimumStateSize,
    01224                           &Console->StateBuffer,
    01225                           &ViewSize,
    01226                           Console->VDMProcessHandle,
    01227                           &a->StateBuffer
    01228                          );
    01229
    01230             if (NT_SUCCESS(Status)) {
    01231                         a->StateLength = RegisterVdm.MinimumStateSize;
    01232                         Console->StateLength = RegisterVdm.MinimumStateSize;
    01233                         Console->StateBufferClient = a->StateBuffer;
    01234             }
    01235
    01236           } else {
    01237
    01238             CloseHandle(Console->VDMStartHardwareEvent);
    01239             CloseHandle(Console->VDMEndHardwareEvent);
    01240           }
    01241
    01242         } else {
    01243
    01244         // ASSERT(FALSE);
    01245         CloseHandle(Console->VDMStartHardwareEvent);
    01246         CloseHandle(Console->VDMEndHardwareEvent);
    01247        }
    01248
    01249     } else {
    01250         CloseHandle(Console->VDMStartHardwareEvent);
    01251     }
    01252     //
    01253     // if failed to duplicate screen switch events or  map view
    01254     // to video state shared buffer, fails this API
    01255     //
    01256     if (!NT_SUCCESS(Status)) {
    01257         UnlockConsole(Console);
    01258         return (Status);
    01259     }
    01260     }
    01261
    01262 #endif
    01263     //
    01264     // create vdm char section and map a view of it into server and vdm.
    01265     // this section is used by the vdm to update the screen when in a
    01266     // charmode window.  this is a performance optimization.  we create
    01267     // the section instead of the vdm for security purposes.
    01268     //
    01269
    01270     Status = MapViewOfSection(&Console->VDMBufferSectionHandle,
    01271 #ifdef i386
    01272                               a->VDMBufferSize.X*a->VDMBufferSize.Y*2,
    01273 #else //risc
    01274                               a->VDMBufferSize.X*a->VDMBufferSize.Y*4,
    01275 #endif
    01276                               &Console->VDMBuffer,
    01277                               &ViewSize,
    01278                               Console->VDMProcessHandle,
    01279                               &a->VDMBuffer
    01280                              );
    01281     if (!NT_SUCCESS(Status)) {
    01282
    01283         Console->VDMBuffer = NULL;
    01284
    01285 #ifdef i386
    01286
    01287         if (FullScreenInitialized) {
    01288
    01289             NtUnmapViewOfSection(NtCurrentProcess(),Console->StateBuffer);
    01290             NtUnmapViewOfSection(Console->VDMProcessHandle,Console->StateBufferClient);
    01291             NtClose(Console->StateSectionHandle);
    01292             CloseHandle(Console->VDMStartHardwareEvent);
    01293             CloseHandle(Console->VDMEndHardwareEvent);
    01294         }
    01295
    01296 #endif
    01297         CloseHandle(Console->VDMProcessHandle);
    01298         Console->VDMProcessHandle = NULL;
    01299         UnlockConsole(Console);
    01300         return((ULONG) Status);
    01301     }
    01302     Console->VDMBufferClient = a->VDMBuffer;
    01303
    01304     Console->Flags |= CONSOLE_VDM_REGISTERED;
    01305
    01306     if (Console->Flags & CONSOLE_HAS_FOCUS) {
    01307         USERTHREAD_FLAGS Flags;
    01308
    01309         Flags.dwFlags = TIF_VDMAPP;
    01310         Flags.dwMask = TIF_VDMAPP;
    01311         NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
    01312                 UserThreadFlags, &Flags, sizeof(Flags));
    01313     }
    01314     Console->VDMBufferSize = a->VDMBufferSize;
    01315
    01316     if (a->RegisterFlags & CONSOLE_REGISTER_WOW)
    01317         Console->Flags |= CONSOLE_WOW_REGISTERED;
    01318     else
    01319         Console->Flags &= ~CONSOLE_WOW_REGISTERED;
    01320
    01321     //
    01322     // if we're already in fullscreen and we run a DOS app for
    01323     // the first time, connect the emulator.
    01324     //
    01325
    01326 #ifdef i386
    01327     if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
    01328         RECT CursorRect;
    01329         CursorRect.left = -32767;
    01330         CursorRect.top = -32767;
    01331         CursorRect.right = 32767;
    01332         CursorRect.bottom = 32767;
    01333         NtUserConsoleControl(ConsoleSetVDMCursorBounds, &CursorRect, sizeof(RECT));
    01334         // connect emulator
    01335         ASSERT(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR));
    01336         ConnectToEmulator(TRUE, Console);
    01337     }
    01338 #endif
    01339
    01340     UnlockConsole(Console);
    01341     return Status;
    01342     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    01343 }
    01344
    01345 NTSTATUS
    01346 SrvConsoleNotifyLastClose(
    01347     IN OUT PCSR_API_MSG m,
    01348     IN OUT PCSR_REPLY_STATUS ReplyStatus
    01349     )
    01350 {
    01351     PCONSOLE_NOTIFYLASTCLOSE_MSG a = (PCONSOLE_NOTIFYLASTCLOSE_MSG)&m->u.ApiMessageData;
    01352     NTSTATUS Status;
    01353     PCONSOLE_INFORMATION Console;
    01354
    01355     Status = ApiPreamble(a->ConsoleHandle,
    01356                          &Console
    01357                         );
    01358     if (!NT_SUCCESS(Status)) {
    01359         return Status;
    01360     }
    01361 // williamh, Feb 2 1994.
    01362 // this non-X86 special case is not necessary. We expect
    01363 // ntvdm to call RegisterConsoleVDM API and there we do duplicate
    01364 // the vdm process handle and grab its process id.
    01365 // If we continue to do this we may hit the assert below
    01366 // because when RegisterConsoleVDM failed(short of memory, for example)
    01367 // the VDMProcessHandle may have been set and next time a vdm application
    01368 // was launched from the same console(ntvdm will do the NotifyLastClose
    01369 // before RegisterConsoleVDM).
    01370 #if 0
    01371 #if !defined(_X86_)
    01372     ASSERT(Console->VDMProcessHandle == NULL);
    01373     Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
    01374             NtCurrentProcess(), &Console->VDMProcessHandle,
    01375             0, FALSE, DUPLICATE_SAME_ACCESS);
    01376     if (!NT_SUCCESS(Status)) {
    01377         return Status;
    01378     }
    01379     Console->VDMProcessId = CONSOLE_CLIENTPROCESSID();
    01380 #endif
    01381 #endif
    01382     // Doesn't allow two or more processes to have last-close notify on
    01383     // the same console
    01384     if (Console->Flags & CONSOLE_NOTIFY_LAST_CLOSE) {
    01385         UnlockConsole(Console);
    01386         return (ULONG)STATUS_ACCESS_DENIED;
    01387     }
    01388
    01389     Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
    01390                                NtCurrentProcess(),
    01391                                &Console->hProcessLastNotifyClose,
    01392                                0, FALSE, DUPLICATE_SAME_ACCESS
    01393                                );
    01394     if (!NT_SUCCESS(Status)) {
    01395         UnlockConsole(Console);
    01396         return Status;
    01397     }
    01398
    01399     Console->Flags |= CONSOLE_NOTIFY_LAST_CLOSE;
    01400     Console->ProcessIdLastNotifyClose = CONSOLE_CLIENTPROCESSID();
    01401     UnlockConsole(Console);
    01402     return Status;
    01403     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    01404 }
    01405
    01406 NTSTATUS
    01407 MapViewOfSection(
    01408     PHANDLE SectionHandle,
    01409     ULONG CommitSize,
    01410     PVOID *BaseAddress,
    01411     PSIZE_T ViewSize,
    01412     HANDLE ClientHandle,
    01413     PVOID *BaseClientAddress
    01414     )
    01415 {
    01416
    01417     OBJECT_ATTRIBUTES Obja;
    01418     NTSTATUS Status;
    01419     LARGE_INTEGER secSize;
    01420
    01421     //
    01422     // open section and map a view of it.
    01423     //
    01424     InitializeObjectAttributes(
    01425         &Obja,
    01426         NULL,
    01427         OBJ_CASE_INSENSITIVE,
    01428         NULL,
    01429         NULL
    01430         );
    01431
    01432     secSize.QuadPart = CommitSize;
    01433     Status = NtCreateSection (SectionHandle,
    01434                               SECTION_ALL_ACCESS,
    01435                               &Obja,
    01436                               &secSize,
    01437                               PAGE_READWRITE,
    01438                               SEC_RESERVE,
    01439                               NULL
    01440                              );
    01441     if (!NT_SUCCESS(Status)) {
    01442         return((ULONG) Status);
    01443     }
    01444
    01445     *BaseAddress = 0;
    01446     *ViewSize = 0;
    01447
    01448     Status = NtMapViewOfSection(*SectionHandle,
    01449                                 NtCurrentProcess(),
    01450                                 BaseAddress,        // Receives the base
    01451                                                     // address of the section.
    01452
    01453                                 0,                  // No specific type of
    01454                                                     // address required.
    01455
    01456                                 CommitSize,         // Commit size. It was
    01457                                                     // passed by the caller.
    01458                                                     // NULL for a save, and
    01459                                                     // size of the section
    01460                                                     // for a set.
    01461
    01462                                 NULL,               // Section offset it NULL;
    01463                                                     // Map from the start.
    01464
    01465                                 ViewSize,           // View Size is NULL since
    01466                                                     // we want to map the
    01467                                                     // entire section.
    01468
    01469                                 ViewUnmap,
    01470                                 0L,
    01471                                 PAGE_READWRITE
    01472                                );
    01473     if (!NT_SUCCESS(Status)) {
    01474         NtClose(*SectionHandle);
    01475         return Status;
    01476     }
    01477
    01478     *BaseClientAddress = 0;
    01479     *ViewSize = 0;
    01480     Status = NtMapViewOfSection(*SectionHandle,
    01481                                 ClientHandle,
    01482                                 BaseClientAddress,  // Receives the base
    01483                                                     // address of the section.
    01484
    01485                                 0,                  // No specific type of
    01486                                                     // address required.
    01487
    01488                                 CommitSize,         // Commit size. It was
    01489                                                     // passed by the caller.
    01490                                                     // NULL for a save, and
    01491                                                     // size of the section
    01492                                                     // for a set.
    01493
    01494                                 NULL,               // Section offset it NULL;
    01495                                                     // Map from the start.
    01496
    01497                                 ViewSize,           // View Size is NULL since
    01498                                                     // we want to map the
    01499                                                     // entire section.
    01500
    01501                                 ViewUnmap,
    01502 // williamh, Jan 28 1994
    01503 // This MEM_TOP_DOWN is necessary.
    01504 // if the console has VDM registered, ntvdm would have released its video memory
    01505 // address space(0xA0000 ~ 0xBFFFF). Without the MEM_TOP_DOWN, the
    01506 // NtMapViewOfSection can grab the address space and we will have trouble of
    01507 // mapping the address space to the physical video ram. We don't do a test
    01508 // for VDM because there is no harm of doing this for non-vdm application.
    01509                                 MEM_TOP_DOWN,
    01510                                 PAGE_READWRITE
    01511                                );
    01512     if (!NT_SUCCESS(Status)) {
    01513         NtClose(*SectionHandle);
    01514     }
    01515     return((ULONG) Status);
    01516 }
    01517
    01518 NTSTATUS
    01519 ConnectToEmulator(
    01520     IN BOOL Connect,
    01521     IN PCONSOLE_INFORMATION Console
    01522     )
    01523 {
    01524     NTSTATUS Status;
    01525     FULLSCREENCONTROL fsctl;
    01526     VIDEO_VDM ConnectInfo;
    01527     HANDLE ProcessHandle = Console->VDMProcessHandle;
    01528     USERTHREAD_FLAGS Flags;
    01529
    01530     DBGFULLSCR(("ConnectToEmulator :  %s - entering\n", Connect ? "CONNECT" : "DISCONNECT"));
    01531
    01532     Flags.dwMask = TIF_DOSEMULATOR;
    01533     if (Connect) {
    01534         fsctl = FullscreenControlEnable;
    01535         Console->Flags |= CONSOLE_CONNECTED_TO_EMULATOR;
    01536         Flags.dwFlags = TIF_DOSEMULATOR;
    01537     } else {
    01538         fsctl = FullscreenControlDisable;
    01539         Console->Flags &= ~CONSOLE_CONNECTED_TO_EMULATOR;
    01540         Flags.dwFlags = 0;
    01541     }
    01542
    01543     if (Console->Flags & CONSOLE_HAS_FOCUS) {
    01544         NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
    01545                 UserThreadFlags, &Flags, sizeof(Flags));
    01546     }
    01547
    01548     ConnectInfo.ProcessHandle = ProcessHandle;
    01549
    01550
    01551     Status = GdiFullscreenControl(fsctl,
    01552                                      &ConnectInfo,
    01553                                      sizeof(ConnectInfo),
    01554                                      NULL,
    01555                                      NULL);
    01556
    01557     ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PROCESS_IS_TERMINATING);
    01558
    01559     DBGFULLSCR(("ConnectToEmulator : leaving, staus = %08lx\n", Status));
    01560
    01561     return Status;
    01562 }
    01563
    01564 #define CONSOLE_VDM_TIMEOUT 200000
    01565
    01566 NTSTATUS
    01567 DisplayModeTransition(
    01568     IN BOOL bForeground,
    01569     IN PCONSOLE_INFORMATION Console,
    01570     IN PSCREEN_INFORMATION ScreenInfo
    01571     )
    01572 {
    01573 #ifdef i386
    01574     NTSTATUS Status;
    01575     LARGE_INTEGER li;
    01576
    01577     if (!FullScreenInitialized)
    01578         return STATUS_SUCCESS;
    01579
    01580     if (bForeground) {
    01581
    01582         PSCREEN_INFORMATION ScreenInfo = Console->CurrentScreenBuffer;
    01583         LARGE_INTEGER li;
    01584         NTSTATUS Status;
    01585
    01586         KdPrint(("    CONSRV - Display Mode transition to fullscreen \n"));
    01587
    01588         if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
    01589             KdPrint(("CONSRV: received fullscreen message too early\n"));
    01590             return STATUS_UNSUCCESSFUL;
    01591         }
    01592
    01593         Console->FullScreenFlags |= CONSOLE_FULLSCREEN_HARDWARE;
    01594
    01595         if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
    01596 #if defined(FE_SB)
    01597             BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
    01598 #endif
    01599 #if 1
    01600             DEVMODEW Devmode;
    01601             ULONG Index;
    01602
    01603             KdPrint(("CONSRV: ChangeDispSettings fullscreen\n"));
    01604
    01605             Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
    01606
    01607             //
    01608             // set mode to go to full screen
    01609             //
    01610
    01611             ZeroMemory(&Devmode, sizeof(Devmode));
    01612
    01613             Devmode.dmSize = sizeof(Devmode);
    01614             Devmode.dmDriverExtra = 0;
    01615             Devmode.dmFields = DM_BITSPERPEL   |
    01616                                DM_PELSWIDTH    |
    01617                                DM_PELSHEIGHT   |
    01618                                DM_DISPLAYFLAGS;
    01619
    01620             Devmode.dmBitsPerPel   = 4;
    01621 #if defined(FE_SB)
    01622             Devmode.dmPelsWidth    = RegModeFontPairs[Index].Resolution.X;
    01623             Devmode.dmPelsHeight   = RegModeFontPairs[Index].Resolution.Y;
    01624             Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
    01625 #else
    01626             Devmode.dmPelsWidth    = ModeFontPairs[Index].Resolution.X;
    01627             Devmode.dmPelsHeight   = ModeFontPairs[Index].Resolution.Y;
    01628             Devmode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
    01629 #endif
    01630
    01631             if (NT_SUCCESS(GdiFullscreenControl(FullscreenControlSetMode,
    01632                                                    &Devmode,
    01633                                                    sizeof(Devmode),
    01634                                                    NULL,
    01635                                                    NULL)))
    01636             {
    01637 #endif
    01638                 // set video mode and font
    01639                 if (SetVideoMode(ScreenInfo)) {
    01640
    01641 #if defined(FE_SB)
    01642                     if (!(Console->Flags & CONSOLE_VDM_REGISTERED)) {
    01643                         int     i ;
    01644                         for (i = 0 ; i < ScreenInfo->ScreenBufferSize.Y; i++) {
    01645                             ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldLeft = INVALID_OLD_LENGTH ;
    01646                             ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldRight = INVALID_OLD_LENGTH ;
    01647                         }
    01648                     }
    01649 #endif
    01650                     //set up cursor
    01651
    01652                     SetCursorInformationHW(ScreenInfo,
    01653                                     ScreenInfo->BufferInfo.TextInfo.CursorSize,
    01654                                     ScreenInfo->BufferInfo.TextInfo.CursorVisible);
    01655                     SetCursorPositionHW(ScreenInfo,
    01656                                     ScreenInfo->BufferInfo.TextInfo.CursorPosition);
    01657                 }
    01658             }
    01659         }
    01660
    01661         // tell VDM to unmap memory
    01662
    01663         if (Console->Flags & CONSOLE_VDM_REGISTERED) {
    01664             li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
    01665             Status = NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
    01666                                                     Console->VDMEndHardwareEvent,
    01667                                                     FALSE, &li);
    01668              if (Status != 0) {
    01669                 Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
    01670                 UnregisterVDM(Console);
    01671                 KdPrint(("CONSRV: VDM not responding.\n"));
    01672              }
    01673         }
    01674
    01675         if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
    01676
    01677             WriteRegionToScreen(ScreenInfo,&ScreenInfo->Window);
    01678         }
    01679
    01680         if (Console->Flags & CONSOLE_VDM_REGISTERED) {
    01681
    01682             // connect emulator and map memory into the VDMs address space.
    01683             ASSERT(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR));
    01684
    01685             Status = ConnectToEmulator(TRUE, Console);
    01686
    01687             if (NT_SUCCESS(Status)) {
    01688
    01689                 VIDEO_HARDWARE_STATE State;
    01690                 ULONG StateSize = sizeof(State);
    01691
    01692                 State.StateHeader = Console->StateBuffer;
    01693                 State.StateLength = Console->StateLength;
    01694
    01695
    01696                 Status = GdiFullscreenControl(FullscreenControlRestoreHardwareState,
    01697                                                  &State,
    01698                                                  StateSize,
    01699                                                  &State,
    01700                                                  &StateSize);
    01701             }
    01702
    01703             if (Status != STATUS_SUCCESS) {
    01704                 Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
    01705                 UnregisterVDM(Console);
    01706                 KdPrint(("CONSRV: set hardware state failed.\n"));
    01707             } else {
    01708
    01709                 //
    01710                 // tell VDM that it's getting the hardware.
    01711                 //
    01712
    01713                 RECT CursorRect;
    01714                 CursorRect.left = -32767;
    01715                 CursorRect.top = -32767;
    01716                 CursorRect.right = 32767;
    01717                 CursorRect.bottom = 32767;
    01718                 NtUserConsoleControl(ConsoleSetVDMCursorBounds,
    01719                         &CursorRect, sizeof(RECT));
    01720
    01721                 // wait for vdm to say ok. We could initiate another switch
    01722                 // (set hStartHardwareEvent which vdm is now waiting for to
    01723                 //  complete the handshaking) when we return(WM_FULLSCREEN
    01724                 // could be in the message queue already). If we don't wait
    01725                 // for vdm to get signaled here, the hStartHardwareEvent
    01726                 // can get set twice and signaled once so the vdm will never
    01727                 // gets the newly switch request we may post after return.
    01728                 NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
    01729                                                Console->VDMEndHardwareEvent,
    01730                                                FALSE, &li);
    01731                 // no need to check time out here
    01732
    01733             }
    01734
    01735         }
    01736
    01737         //
    01738         // let the app know that it has the focus.
    01739         //
    01740
    01741         HandleFocusEvent(Console,TRUE);
    01742
    01743         // unset palette
    01744
    01745         if (ScreenInfo->hPalette != NULL) {
    01746             SelectPalette(ScreenInfo->Console->hDC,
    01747                              ScreenInfo->Console->hSysPalette,
    01748                              FALSE);
    01749             UnsetActivePalette(ScreenInfo);
    01750         }
    01751         SetConsoleReserveKeys(Console->hWnd, Console->ReserveKeys);
    01752         HandleFocusEvent(Console,TRUE);
    01753
    01754     } else {
    01755
    01756         KdPrint(("    CONSRV - Display Mode transition to windowed \n"));
    01757
    01758         //
    01759         // Check first to see if we're not already fullscreen. If we aren't,
    01760         // don't allow this. Temporary BETA fix till USER gets fixed.
    01761         //
    01762         if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
    01763             KdPrint(("CONSRV: received multiple windowed messages\n"));
    01764             return STATUS_SUCCESS;
    01765         }
    01766
    01767         // turn off mouse pointer so VDM doesn't see it when saving
    01768         // hardware
    01769         if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
    01770             ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
    01771         }
    01772
    01773
    01774         Console->FullScreenFlags &= ~CONSOLE_FULLSCREEN_HARDWARE;
    01775         if (Console->Flags & CONSOLE_VDM_REGISTERED) {
    01776
    01777             //
    01778             // tell vdm that it's losing the hardware
    01779             //
    01780
    01781             li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
    01782             Status = NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
    01783                                                     Console->VDMEndHardwareEvent,
    01784                                                     FALSE, &li);
    01785
    01786             // if ntvdm didn't respond or we failed to save the video hardware
    01787             // states, kick ntvdm out of our world. The ntvdm process eventually
    01788             // would die but what choice do have here?
    01789
    01790             if (NT_SUCCESS(Status)) {
    01791
    01792                 VIDEO_HARDWARE_STATE State;
    01793                 ULONG StateSize = sizeof(State);
    01794
    01795                 State.StateHeader = Console->StateBuffer;
    01796                 State.StateLength = Console->StateLength;
    01797
    01798
    01799                 Status = GdiFullscreenControl(FullscreenControlSaveHardwareState,
    01800                                                  &State,
    01801                                                  StateSize,
    01802                                                  &State,
    01803                                                  &StateSize);
    01804             }
    01805
    01806             if (NT_SUCCESS(Status)) {
    01807
    01808
    01809                 NtUserConsoleControl(ConsoleSetVDMCursorBounds, NULL, 0);
    01810
    01811                 // disconnect emulator and unmap video memory
    01812
    01813                 ASSERT(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR);
    01814                 ConnectToEmulator(FALSE, Console);
    01815
    01816             } else {
    01817
    01818                 Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
    01819                 UnregisterVDM(Console);
    01820                 if (Status != 0) {
    01821                     KdPrint(("CONSRV: VDM not responding.\n"));
    01822                 }
    01823                 else
    01824                     KdPrint(("CONSRV: Save Video States Failed\n"));
    01825
    01826             }
    01827         }
    01828
    01829         // tell VDM to map memory
    01830
    01831         if (Console->Flags & CONSOLE_VDM_REGISTERED) {
    01832
    01833             // make a special case for ntvdm during switching because
    01834             // ntvdm has to make console api calls. We don't want to
    01835             // unlock the console at this moment because as soon as
    01836             // we release the lock, other theads which are waiting
    01837             // for the lock will claim the lock and the ntvdm thread doing
    01838             // the screen switch will have to wait for the lock. In an
    01839             // extreme case, the following NtWaitForSingleObject will time
    01840             // out because the ntvdm may be still waiting for the lock.
    01841             // We keep this thing in a single global variable because
    01842             // there is only one process who can own the screen at any moment.
    01843
    01844             RtlEnterCriticalSection(&ConsoleVDMCriticalSection);
    01845             ConsoleVDMOnSwitching = Console;
    01846             RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
    01847             li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
    01848             Status = NtSignalAndWaitForSingleObject(Console->VDMStartHardwareEvent,
    01849                                                     Console->VDMEndHardwareEvent,
    01850                                                     FALSE, &li);
    01851
    01852             // time to go back to normal
    01853             RtlEnterCriticalSection(&ConsoleVDMCriticalSection);
    01854             ConsoleVDMOnSwitching = NULL;
    01855             RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
    01856
    01857             if (Status != 0) {
    01858                 Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
    01859                 UnregisterVDM(Console);
    01860                 KdPrint(("CONSRV: VDM not responding. - second wait\n"));
    01861                 return Status;
    01862             }
    01863             ScreenInfo = Console->CurrentScreenBuffer;
    01864         }
    01865
    01866         // set palette
    01867
    01868         if (ScreenInfo->hPalette != NULL) {
    01869             SelectPalette(ScreenInfo->Console->hDC,
    01870                              ScreenInfo->hPalette,
    01871                              FALSE);
    01872             SetActivePalette(ScreenInfo);
    01873         }
    01874         SetConsoleReserveKeys(Console->hWnd, CONSOLE_NOSHORTCUTKEY);
    01875         HandleFocusEvent(Console,FALSE);
    01876
    01877     }
    01878
    01879     /*
    01880      * Boost or lower the priority if we are going fullscreen or away.
    01881      *
    01882      * Note that console usually boosts and lowers its priority based
    01883      * on WM_FOCUSS and WM_KILLFOCUS but when you switch to full screen
    01884      * the implementation actually sends a WM_KILLFOCUS so we reboost the
    01885      * correct console here.
    01886      */
    01887     ModifyConsoleProcessFocus(Console, bForeground);
    01888
    01889
    01890 #else
    01891     UNREFERENCED_PARAMETER(bForeground);
    01892     UNREFERENCED_PARAMETER(Console);
    01893     UNREFERENCED_PARAMETER(ScreenInfo);
    01894 #endif
    01895     return STATUS_SUCCESS;
    01896 }
    01897
    01898 #if defined(_X86_)
    01899
    01900 BOOL
    01901 SetVideoMode(
    01902     IN PSCREEN_INFORMATION ScreenInfo
    01903     )
    01904 {
    01905     NTSTATUS Status;
    01906     UINT i, j;
    01907
    01908 #if defined(FE_SB)
    01909     //
    01910     // load RAM font
    01911     //
    01912
    01913     Status = SetRAMFontCodePage(ScreenInfo);
    01914 #endif
    01915
    01916     //
    01917     // load ROM font
    01918     //
    01919
    01920     Status = SetROMFontCodePage(ScreenInfo->Console->OutputCP,
    01921                                 ScreenInfo->BufferInfo.TextInfo.ModeIndex);
    01922
    01923     if (Status == STATUS_INVALID_PARAMETER) {
    01924         Status = SetROMFontCodePage(GetOEMCP(),
    01925                                     ScreenInfo->BufferInfo.TextInfo.ModeIndex);
    01926
    01927         if (Status == STATUS_INVALID_PARAMETER) {
    01928             Status = SetROMFontCodePage(CONSOLE_DEFAULT_ROM_FONT,
    01929                                         ScreenInfo->BufferInfo.TextInfo.ModeIndex);
    01930         }
    01931     }
    01932
    01933     //
    01934     // initialize palette
    01935     //
    01936
    01937 #if defined(FE_SB)
    01938     Status = GdiFullscreenControl(FullscreenControlSetPalette,
    01939                                   (PVOID) RegInitialPalette,
    01940                                   RegInitialPalette[0] * sizeof(USHORT) + sizeof(DWORD),
    01941                                   NULL,
    01942                                   NULL);
    01943 #else
    01944     Status = GdiFullscreenControl(FullscreenControlSetPalette,
    01945                                   (PVOID) &InitialPalette,
    01946                                   sizeof (InitialPalette),
    01947                                   NULL,
    01948                                   NULL);
    01949 #endif
    01950
    01951     if (Status != STATUS_SUCCESS) {
    01952         KdPrint(("CONSRV: FullscreenControlSetPalette failed - status = %x\n",
    01953                  Status));
    01954         ASSERT(FALSE);
    01955         return FALSE;
    01956     }
    01957
    01958     //
    01959     // initialize color table
    01960     //
    01961
    01962 #if defined(FE_SB)
    01963     if (RegColorBufferNoTranslate)
    01964     {
    01965         Status = GdiFullscreenControl(FullscreenControlSetColors,
    01966                                       (PVOID) RegColorBufferNoTranslate,
    01967                                       RegColorBufferNoTranslate[0] * sizeof(DWORD) + sizeof(DWORD),
    01968                                       NULL,
    01969                                       NULL);
    01970     }
    01971     else
    01972     {
    01973         for (i = 0, j = 4; i < 16; i++) {
    01974             RegColorBuffer[j++] = ((((GetRValue(ScreenInfo->Console->ColorTable[i]) +
    01975                                       0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
    01976             RegColorBuffer[j++] = ((((GetGValue(ScreenInfo->Console->ColorTable[i]) +
    01977                                       0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
    01978             RegColorBuffer[j++] = ((((GetBValue(ScreenInfo->Console->ColorTable[i]) +
    01979                                       0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
    01980             RegColorBuffer[j++] = 0;
    01981         }
    01982
    01983         Status = GdiFullscreenControl(FullscreenControlSetColors,
    01984                                       (PVOID) RegColorBuffer,
    01985                                       RegColorBuffer[0] * sizeof(DWORD) + sizeof(DWORD),
    01986                                       NULL,
    01987                                       NULL);
    01988     }
    01989 #else
    01990     for (i = 0, j = 4; i < 16; i++) {
    01991         ColorBuffer[j++] = ((((GetRValue(ScreenInfo->Console->ColorTable[i]) +
    01992                                0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
    01993         ColorBuffer[j++] = ((((GetGValue(ScreenInfo->Console->ColorTable[i]) +
    01994                                0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
    01995         ColorBuffer[j++] = ((((GetBValue(ScreenInfo->Console->ColorTable[i]) +
    01996                                0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
    01997         ColorBuffer[j++] = 0;
    01998     }
    01999
    02000     Status = GdiFullscreenControl(FullscreenControlSetColors,
    02001                                      (PVOID) &ColorBuffer,
    02002                                      sizeof (ColorBuffer),
    02003                                      NULL,
    02004                                      NULL);
    02005 #endif
    02006
    02007     if (Status != STATUS_SUCCESS) {
    02008         KdPrint(("CONSRV: FullscreenControlSetColors failed - status = %x\n",
    02009                  Status));
    02010         ASSERT(FALSE);
    02011         return FALSE;
    02012     }
    02013
    02014
    02015     return TRUE;
    02016 }
    02017
    02018 #endif
    02019
    02020
    02021 #if defined(_X86_)
    02022
    02023 NTSTATUS
    02024 ChangeDispSettings(
    02025     PCONSOLE_INFORMATION Console,
    02026     HWND hwnd,
    02027     DWORD dwFlags)
    02028 {
    02029     DEVMODEW Devmode;
    02030     ULONG Index;
    02031     CONSOLE_FULLSCREEN_SWITCH switchBlock;
    02032
    02033     if (dwFlags == CDS_FULLSCREEN)
    02034     {
    02035 #if defined(FE_SB)
    02036         BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
    02037 #endif
    02038
    02039         KdPrint(("CONSRV: ChangeDispSettings fullscreen\n"));
    02040
    02041         Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
    02042
    02043         //
    02044         // set mode to go to full screen
    02045         //
    02046
    02047         ZeroMemory(&Devmode, sizeof(Devmode));
    02048
    02049         Devmode.dmSize = sizeof(Devmode);
    02050         Devmode.dmDriverExtra = 0;
    02051         Devmode.dmFields = DM_BITSPERPEL   |
    02052                            DM_PELSWIDTH    |
    02053                            DM_PELSHEIGHT   |
    02054                            DM_DISPLAYFLAGS;
    02055
    02056         Devmode.dmBitsPerPel   = 4;
    02057 #if defined(FE_SB)
    02058         Devmode.dmPelsWidth    = RegModeFontPairs[Index].Resolution.X;
    02059         Devmode.dmPelsHeight   = RegModeFontPairs[Index].Resolution.Y;
    02060         Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
    02061 #else
    02062         Devmode.dmPelsWidth    = ModeFontPairs[Index].Resolution.X;
    02063         Devmode.dmPelsHeight   = ModeFontPairs[Index].Resolution.Y;
    02064         Devmode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
    02065 #endif
    02066
    02067         switchBlock.bFullscreenSwitch = TRUE;
    02068         switchBlock.hwnd              = hwnd;
    02069         switchBlock.pNewMode          = &Devmode;
    02070
    02071     }
    02072     else
    02073     {
    02074         KdPrint(("CONSRV: ChangeDispSettings windowed\n"));
    02075
    02076         switchBlock.bFullscreenSwitch = FALSE;
    02077         switchBlock.hwnd              = hwnd;
    02078         switchBlock.pNewMode          = NULL;
    02079     }
    02080
    02081     return NtUserConsoleControl(ConsoleFullscreenSwitch,
    02082                                 &switchBlock,
    02083                                 sizeof(CONSOLE_FULLSCREEN_SWITCH));
    02084 }
    02085
    02086 #endif
    02087
    02088 BOOL
    02089 InitializeFullScreen( VOID )
    02090 {
    02091     UNICODE_STRING vgaString;
    02092     DEVMODEW devmode;
    02093     ULONG   i;
    02094 #if !defined(FE_SB)
    02095     BOOLEAN mode1 = FALSE;
    02096     BOOLEAN mode2 = FALSE;
    02097 #else
    02098     DWORD mode1 = 0;
    02099     DWORD mode2 = 0;
    02100 #endif
    02101
    02102     CHAR WindowsDir[CONSOLE_WINDOWS_DIR_LENGTH+CONSOLE_EGACPI_LENGTH];
    02103     UINT WindowsDirLength;
    02104
    02105     //
    02106     // query number of available modes
    02107     //
    02108
    02109     ZeroMemory(&devmode, sizeof(DEVMODEW));
    02110     devmode.dmSize = sizeof(DEVMODEW);
    02111
    02112     RtlInitUnicodeString(&vgaString, L"VGACOMPATIBLE");
    02113
    02114     DBGCHARS(("Number of modes = %d\n", NUMBER_OF_MODE_FONT_PAIRS));
    02115
    02116     for (i=0; ; i++)
    02117     {
    02118         DBGCHARS(("EnumDisplaySettings %d\n", i));
    02119
    02120         if (!(NT_SUCCESS(NtUserEnumDisplaySettings(&vgaString,
    02121                                                    i,
    02122                                                    &devmode,
    02123                                                    0))))
    02124         {
    02125             break;
    02126         }
    02127
    02128 #if defined(FE_SB)
    02129         {
    02130             ULONG Index;
    02131
    02132             DBGCHARS(("Mode X = %d, Y = %d\n",
    02133                      devmode.dmPelsWidth, devmode.dmPelsHeight));
    02134
    02135             for (Index=0;Index<NUMBER_OF_MODE_FONT_PAIRS;Index++)
    02136             {
    02137                 if ((SHORT)devmode.dmPelsWidth == RegModeFontPairs[Index].Resolution.X &&
    02138                     (SHORT)devmode.dmPelsHeight == RegModeFontPairs[Index].Resolution.Y  )
    02139                 {
    02140                     if (devmode.dmDisplayFlags & DMDISPLAYFLAGS_TEXTMODE)
    02141                     {
    02142                         if (RegModeFontPairs[Index].Mode & FS_MODE_TEXT)
    02143                         {
    02144                             RegModeFontPairs[Index].Mode |= FS_MODE_FIND;
    02145                             mode1++;
    02146                         }
    02147                     }
    02148                     else
    02149                     {
    02150                         if (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)
    02151                         {
    02152                             RegModeFontPairs[Index].Mode |= FS_MODE_FIND;
    02153                             mode2++;
    02154                         }
    02155                     }
    02156                 }
    02157             }
    02158
    02159             DBGCHARS(("mode1 = %d, mode2 = %d\n", mode1, mode2));
    02160         }
    02161 #else
    02162
    02163         if (devmode.dmPelsWidth == 720 &&
    02164             devmode.dmPelsHeight == 400)
    02165         {
    02166             mode1 = TRUE;
    02167         }
    02168         if (devmode.dmPelsWidth == 640 &&
    02169             devmode.dmPelsHeight == 350)
    02170         {
    02171             mode2 = TRUE;
    02172         }
    02173 #endif
    02174     }
    02175
    02176 #if !defined(FE_SB)
    02177     if (!(mode1 && mode2))
    02178 #else
    02179     if (mode1 < 2)
    02180 #endif
    02181     {
    02182         //
    02183         // One of the modes we expected to get was not returned.
    02184         // lets just fail fullscreen initialization.
    02185         //
    02186
    02187         KdPrint(("CONSRV: InitializeFullScreen Missing text mode\n"));
    02188         return FALSE;
    02189     }
    02190
    02191 #if defined(FE_SB)
    02192     if (mode2 > 0)
    02193     {
    02194         // Can do trun graphics mode.
    02195         fFullScreenGraphics = TRUE;
    02196     }
    02197 #endif
    02198
    02199     //
    02200     // open ega.cpi
    02201     //
    02202
    02203     WindowsDirLength = GetSystemDirectoryA(WindowsDir,
    02204                                            CONSOLE_WINDOWS_DIR_LENGTH);
    02205     if (WindowsDirLength == 0)
    02206     {
    02207         KdPrint(("CONSRV: InitializeFullScreen Finding Font file failed\n"));
    02208         return FALSE;
    02209     }
    02210
    02211     RtlCopyMemory(&WindowsDir[WindowsDirLength],
    02212                   CONSOLE_EGACPI,
    02213                   CONSOLE_EGACPI_LENGTH);
    02214
    02215     if ((hCPIFile = CreateFileA(WindowsDir,
    02216                                 GENERIC_READ,
    02217                                 FILE_SHARE_READ,
    02218                                 NULL,
    02219                                 OPEN_EXISTING,
    02220                                 0,
    02221                                 NULL)) == (HANDLE)-1)
    02222     {
    02223         KdPrint(("CONSRV: InitializeFullScreen Opening Font file failed\n"));
    02224         return FALSE;
    02225     }
    02226
    02227     return TRUE;
    02228 }
    02229
    02230
    02231 ULONG
    02232 SrvGetConsoleHardwareState(
    02233     IN OUT PCSR_API_MSG m,
    02234     IN OUT PCSR_REPLY_STATUS ReplyStatus
    02235     )
    02236 {
    02237 #ifdef i386
    02238     PCONSOLE_GETHARDWARESTATE_MSG a = (PCONSOLE_GETHARDWARESTATE_MSG)&m->u.ApiMessageData;
    02239     NTSTATUS Status;
    02240     PCONSOLE_INFORMATION Console;
    02241     PHANDLE_DATA HandleData;
    02242     PSCREEN_INFORMATION ScreenInfo;
    02243
    02244     Status = ApiPreamble(a->ConsoleHandle,
    02245                          &Console
    02246                         );
    02247     if (!NT_SUCCESS(Status)) {
    02248         return Status;
    02249     }
    02250     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    02251                                  a->OutputHandle,
    02252                                  CONSOLE_OUTPUT_HANDLE,
    02253                                  GENERIC_READ,
    02254                                  &HandleData
    02255                                 );
    02256     if (NT_SUCCESS(Status)) {
    02257         ScreenInfo = HandleData->Buffer.ScreenBuffer;
    02258         if (ScreenInfo->BufferInfo.TextInfo.ModeIndex == -1) {
    02259             UnlockConsole(Console);
    02260             return (ULONG)STATUS_UNSUCCESSFUL;
    02261         }
    02262 #if defined(FE_SB)
    02263         a->Resolution = RegModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].Resolution;
    02264         a->FontSize = RegModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].FontSize;
    02265 #else
    02266         a->Resolution = ModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].Resolution;
    02267         a->FontSize = ModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].FontSize;
    02268 #endif
    02269     }
    02270     UnlockConsole(Console);
    02271     return Status;
    02272 #else
    02273     return (ULONG)STATUS_UNSUCCESSFUL;
    02274     UNREFERENCED_PARAMETER(m);    // get rid of unreferenced parameter warning message
    02275 #endif
    02276     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    02277 }
    02278
    02279 ULONG
    02280 SrvSetConsoleHardwareState(
    02281     IN OUT PCSR_API_MSG m,
    02282     IN OUT PCSR_REPLY_STATUS ReplyStatus
    02283     )
    02284 {
    02285 #ifdef i386
    02286     PCONSOLE_SETHARDWARESTATE_MSG a = (PCONSOLE_SETHARDWARESTATE_MSG)&m->u.ApiMessageData;
    02287     NTSTATUS Status;
    02288     PCONSOLE_INFORMATION Console;
    02289     PHANDLE_DATA HandleData;
    02290     PSCREEN_INFORMATION ScreenInfo;
    02291     ULONG Index;
    02292
    02293     Status = ApiPreamble(a->ConsoleHandle,
    02294                          &Console
    02295                         );
    02296     if (!NT_SUCCESS(Status)) {
    02297         return Status;
    02298     }
    02299     if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
    02300         UnlockConsole(Console);
    02301         return (ULONG)STATUS_UNSUCCESSFUL;
    02302     }
    02303     Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
    02304                                  a->OutputHandle,
    02305                                  CONSOLE_OUTPUT_HANDLE,
    02306                                  GENERIC_READ,
    02307                                  &HandleData
    02308                                 );
    02309     if (NT_SUCCESS(Status)) {
    02310 #if defined(FE_SB)
    02311         BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
    02312 #endif
    02313         ScreenInfo = HandleData->Buffer.ScreenBuffer;
    02314
    02315         // match requested mode
    02316
    02317         for (Index=0;Index<NUMBER_OF_MODE_FONT_PAIRS;Index++) {
    02318 #if defined(FE_SB)
    02319             if (a->Resolution.X == RegModeFontPairs[Index].Resolution.X &&
    02320                 a->Resolution.Y == RegModeFontPairs[Index].Resolution.Y &&
    02321                 a->FontSize.Y == RegModeFontPairs[Index].FontSize.Y &&
    02322                 a->FontSize.X == RegModeFontPairs[Index].FontSize.X &&
    02323                 ( ( fGraphics && (RegModeFontPairs[Index].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
    02324                   (!fGraphics && (RegModeFontPairs[Index].Mode & FS_TEXT)==FS_TEXT)           )
    02325                ) {
    02326                 break;
    02327             }
    02328 #else
    02329             if (a->Resolution.X == ModeFontPairs[Index].Resolution.X &&
    02330                 a->Resolution.Y == ModeFontPairs[Index].Resolution.Y &&
    02331                 a->FontSize.Y == ModeFontPairs[Index].FontSize.Y &&
    02332                 a->FontSize.X == ModeFontPairs[Index].FontSize.X) {
    02333                 break;
    02334             }
    02335 #endif
    02336         }
    02337         if (Index == NUMBER_OF_MODE_FONT_PAIRS) {
    02338             Status = STATUS_INVALID_PARAMETER;
    02339         } else {
    02340             // set requested mode
    02341             ScreenInfo->BufferInfo.TextInfo.ModeIndex = Index;
    02342             SetVideoMode(ScreenInfo);
    02343         }
    02344     }
    02345     UnlockConsole(Console);
    02346     return Status;
    02347 #else
    02348     return (ULONG)STATUS_UNSUCCESSFUL;
    02349     UNREFERENCED_PARAMETER(m);    // get rid of unreferenced parameter warning message
    02350 #endif
    02351     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    02352 }
    02353
    02354 ULONG
    02355 SrvGetConsoleDisplayMode(
    02356     IN OUT PCSR_API_MSG m,
    02357     IN OUT PCSR_REPLY_STATUS ReplyStatus
    02358     )
    02359 {
    02360     PCONSOLE_GETDISPLAYMODE_MSG a = (PCONSOLE_GETDISPLAYMODE_MSG)&m->u.ApiMessageData;
    02361     NTSTATUS Status;
    02362     PCONSOLE_INFORMATION Console;
    02363
    02364     Status = ApiPreamble(a->ConsoleHandle,
    02365                          &Console
    02366                         );
    02367     if (NT_SUCCESS(Status)) {
    02368         a->ModeFlags = Console->FullScreenFlags;
    02369         UnlockConsole(Console);
    02370     }
    02371     return Status;
    02372     UNREFERENCED_PARAMETER(ReplyStatus);
    02373 }
    02374
    02375 ULONG
    02376 SrvSetConsoleMenuClose(
    02377     IN OUT PCSR_API_MSG m,
    02378     IN OUT PCSR_REPLY_STATUS ReplyStatus
    02379     )
    02380 {
    02381     PCONSOLE_SETMENUCLOSE_MSG a = (PCONSOLE_SETMENUCLOSE_MSG)&m->u.ApiMessageData;
    02382     NTSTATUS Status;
    02383     PCONSOLE_INFORMATION Console;
    02384
    02385     Status = ApiPreamble(a->ConsoleHandle,
    02386                          &Console
    02387                         );
    02388     if (!NT_SUCCESS(Status)) {
    02389         return Status;
    02390     }
    02391     if (a->Enable) {
    02392         Console->Flags &= ~CONSOLE_DISABLE_CLOSE;
    02393     } else {
    02394         Console->Flags |= CONSOLE_DISABLE_CLOSE;
    02395     }
    02396     UnlockConsole(Console);
    02397     return Status;
    02398     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    02399 }
    02400
    02401
    02402 DWORD
    02403 ConvertHotKey(
    02404     IN LPAPPKEY UserAppKey
    02405     )
    02406 {
    02407     DWORD wParam;
    02408
    02409     wParam = MapVirtualKey(UserAppKey->ScanCode,1);
    02410     if (UserAppKey->Modifier & CONSOLE_MODIFIER_SHIFT) {
    02411         wParam |= 0x0100;
    02412     }
    02413     if (UserAppKey->Modifier & CONSOLE_MODIFIER_CONTROL) {
    02414         wParam |= 0x0200;
    02415     }
    02416     if (UserAppKey->Modifier & CONSOLE_MODIFIER_ALT) {
    02417         wParam |= 0x0400;
    02418     }
    02419     return wParam;
    02420 }
    02421
    02422 ULONG
    02423 SrvSetConsoleKeyShortcuts(
    02424     IN OUT PCSR_API_MSG m,
    02425     IN OUT PCSR_REPLY_STATUS ReplyStatus
    02426     )
    02427 {
    02428     PCONSOLE_SETKEYSHORTCUTS_MSG a = (PCONSOLE_SETKEYSHORTCUTS_MSG)&m->u.ApiMessageData;
    02429     NTSTATUS Status;
    02430     PCONSOLE_INFORMATION Console;
    02431
    02432     Status = ApiPreamble(a->ConsoleHandle,
    02433                          &Console
    02434                         );
    02435     if (!NT_SUCCESS(Status)) {
    02436         return Status;
    02437     }
    02438
    02439     if (!CsrValidateMessageBuffer(m, &a->AppKeys, a->NumAppKeys, sizeof(*a->AppKeys))) {
    02440         UnlockConsole(Console);
    02441         return STATUS_INVALID_PARAMETER;
    02442     }
    02443
    02444     if (a->NumAppKeys <= CONSOLE_MAX_APP_SHORTCUTS) {
    02445         Console->ReserveKeys = a->ReserveKeys;
    02446         if (Console->Flags & CONSOLE_HAS_FOCUS) {
    02447             if (!(SetConsoleReserveKeys(Console->hWnd,a->ReserveKeys))) {
    02448                 Status = STATUS_INVALID_PARAMETER;
    02449             }
    02450         }
    02451         if (a->NumAppKeys) {
    02452             PostMessage(Console->hWnd,
    02453                          WM_SETHOTKEY,
    02454                          ConvertHotKey(a->AppKeys),
    02455                          0
    02456                         );
    02457         }
    02458     } else {
    02459         Status = STATUS_INVALID_PARAMETER;
    02460     }
    02461     UnlockConsole(Console);
    02462     return Status;
    02463     UNREFERENCED_PARAMETER(ReplyStatus);    // get rid of unreferenced parameter warning message
    02464 }
    02465
    02466 #ifdef i386
    02467 ULONG
    02468 MatchWindowSize(
    02469 #if defined(FE_SB)
    02470     IN UINT CodePage,
    02471 #endif
    02472     IN COORD WindowSize,
    02473     OUT PCOORD pWindowSize
    02474     )
    02475
    02476 /*++
    02477
    02478     find the best match font.  it's the one that's the same size
    02479     or slightly larger than the window size.
    02480
    02481 --*/
    02482 {
    02483     ULONG i;
    02484 #if defined(FE_SB)
    02485     BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(CodePage) : FALSE;
    02486 #endif
    02487
    02488     for (i=0;i<NUMBER_OF_MODE_FONT_PAIRS;i++) {
    02489 #if defined(FE_SB)
    02490         if (WindowSize.Y <= RegModeFontPairs[i].ScreenSize.Y &&
    02491             ( ( fGraphics && (RegModeFontPairs[i].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
    02492               (!fGraphics && (RegModeFontPairs[i].Mode & FS_TEXT)==FS_TEXT)           )
    02493            )
    02494 #else
    02495         if (WindowSize.Y <= (SHORT)ModeFontPairs[i].Height)
    02496 #endif
    02497         {
    02498             break;
    02499         }
    02500     }
    02501     if (i == NUMBER_OF_MODE_FONT_PAIRS)
    02502 #if defined(FE_SB)
    02503     {
    02504         DWORD Find;
    02505         ULONG FindIndex;
    02506         COORD WindowSizeDelta;
    02507
    02508         FindIndex = 0;
    02509         Find = (DWORD)-1;
    02510         for (i=0; i<NUMBER_OF_MODE_FONT_PAIRS;i++) {
    02511             if ( ( fGraphics && (RegModeFontPairs[i].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
    02512                  (!fGraphics && (RegModeFontPairs[i].Mode & FS_TEXT)==FS_TEXT)           )
    02513             {
    02514                 WindowSizeDelta.Y = abs(WindowSize.Y - RegModeFontPairs[i].ScreenSize.Y);
    02515                 if (Find > (DWORD)(WindowSizeDelta.Y))
    02516                 {
    02517                     Find = (DWORD)(WindowSizeDelta.Y);
    02518                     FindIndex = i;
    02519                 }
    02520             }
    02521         }
    02522
    02523         i = FindIndex;
    02524     }
    02525 #else
    02526         i-=1;
    02527 #endif
    02528 #if defined(FE_SB)
    02529     *pWindowSize = RegModeFontPairs[i].ScreenSize;
    02530 #else
    02531     pWindowSize->X = 80;
    02532     pWindowSize->Y = (SHORT)ModeFontPairs[i].Height;
    02533 #endif
    02534     return i;
    02535 }
    02536
    02537 VOID
    02538 ReadRegionFromScreenHW(
    02539     IN PSCREEN_INFORMATION ScreenInfo,
    02540     IN PSMALL_RECT Region,
    02541     IN PCHAR_INFO ReadBufPtr
    02542     )
    02543 {
    02544     ULONG CurFrameBufPtr;   // offset in frame buffer
    02545     SHORT FrameY;
    02546     SHORT WindowY, WindowX, WindowSizeX;
    02547
    02548     //
    02549     // get pointer to start of region in frame buffer
    02550     //
    02551
    02552     WindowY = Region->Top - ScreenInfo->Window.Top;
    02553     WindowX = Region->Left - ScreenInfo->Window.Left;
    02554     WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
    02555
    02556     //
    02557     // copy the chars and attrs from the frame buffer
    02558     //
    02559
    02560     for (FrameY = Region->Top;
    02561          FrameY <= Region->Bottom;
    02562          FrameY++, WindowY++) {
    02563
    02564         CurFrameBufPtr = SCREEN_BUFFER_POINTER(WindowX,
    02565                                                WindowY,
    02566                                                WindowSizeX,
    02567                                                sizeof(VGA_CHAR));
    02568
    02569         GdiFullscreenControl(FullscreenControlReadFromFrameBuffer,
    02570                                 (PULONG) CurFrameBufPtr,
    02571                                 (Region->Right - Region->Left + 1) *
    02572                                     sizeof(VGA_CHAR),
    02573                                 ReadBufPtr, NULL);
    02574         ReadBufPtr += (Region->Right - Region->Left + 1);
    02575     }
    02576 }
    02577
    02578 VOID
    02579 ReverseMousePointer(
    02580     IN PSCREEN_INFORMATION ScreenInfo,
    02581     IN PSMALL_RECT Region
    02582     )
    02583 {
    02584     ULONG CurFrameBufPtr;   // offset in frame buffer
    02585     SHORT WindowSizeX;
    02586
    02587     // if (ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
    02588     //     ASSERT(FALSE);
    02589     // }
    02590
    02591 #ifdef FE_SB
    02592     // fail safe
    02593     ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
    02594     if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) {
    02595         return;
    02596     }
    02597 #endif
    02598
    02599     WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
    02600
    02601     if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X < Region->Left ||
    02602         ScreenInfo->BufferInfo.TextInfo.MousePosition.X > Region->Right ||
    02603         ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < Region->Top ||
    02604         ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > Region->Bottom ||
    02605         ScreenInfo->CursorDisplayCount < 0 ||
    02606         !(ScreenInfo->Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT) ||
    02607         ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED) {
    02608         return;
    02609     }
    02610
    02611 #if defined(FE_SB)
    02612     {
    02613         FSVIDEO_REVERSE_MOUSE_POINTER MousePointer;
    02614         SHORT RowIndex;
    02615         PROW Row;
    02616         COORD TargetPoint;
    02617
    02618         TargetPoint.X = ScreenInfo->BufferInfo.TextInfo.MousePosition.X;
    02619         TargetPoint.Y = ScreenInfo->BufferInfo.TextInfo.MousePosition.Y;
    02620
    02621         RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
    02622         Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
    02623         if (!CONSOLE_IS_DBCS_CP(ScreenInfo->Console))
    02624             MousePointer.dwType = CHAR_TYPE_SBCS;
    02625         else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE)
    02626             MousePointer.dwType = CHAR_TYPE_TRAILING;
    02627         else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_LEADING_BYTE)
    02628             MousePointer.dwType = CHAR_TYPE_LEADING;
    02629         else
    02630             MousePointer.dwType = CHAR_TYPE_SBCS;
    02631
    02632         MousePointer.Screen.Position.X = TargetPoint.X - ScreenInfo->Window.Left;
    02633         MousePointer.Screen.Position.Y = TargetPoint.Y - ScreenInfo->Window.Top;
    02634         MousePointer.Screen.ScreenSize.X = WindowSizeX;
    02635         MousePointer.Screen.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
    02636         MousePointer.Screen.nNumberOfChars = 0;
    02637
    02638         GdiFullscreenControl(FullscreenControlReverseMousePointerDB,
    02639                              &MousePointer,
    02640                              sizeof(MousePointer),
    02641                              NULL,
    02642                              NULL);
    02643
    02644         UNREFERENCED_PARAMETER(CurFrameBufPtr);
    02645     }
    02646 #else
    02647     CurFrameBufPtr = SCREEN_BUFFER_POINTER(ScreenInfo->BufferInfo.TextInfo.MousePosition.X - ScreenInfo->Window.Left,
    02648                                            ScreenInfo->BufferInfo.TextInfo.MousePosition.Y - ScreenInfo->Window.Top,
    02649                                            WindowSizeX,
    02650                                            sizeof(VGA_CHAR));
    02651
    02652     GdiFullscreenControl(FullscreenControlReverseMousePointer,
    02653                             (PULONG) CurFrameBufPtr,
    02654                             0,
    02655                             NULL,
    02656                             NULL);
    02657 #endif
    02658 }
    02659
    02660 VOID
    02661 CopyVideoMemory(
    02662     SHORT SourceY,
    02663     SHORT TargetY,
    02664     SHORT Length,
    02665     IN PSCREEN_INFORMATION ScreenInfo
    02666     )
    02667
    02668 /*++
    02669
    02670 Routine Description:
    02671
    02672     This routine copies rows of characters in video memory.  It only copies
    02673     complete rows.
    02674
    02675 Arguments:
    02676
    02677     SourceY - Row to copy from.
    02678
    02679     TargetY - Row to copy to.
    02680
    02681     Length - Number of rows to copy.
    02682
    02683 Return Value:
    02684
    02685 --*/
    02686
    02687 {
    02688     ULONG SourcePtr, TargetPtr;
    02689     SHORT WindowSizeX, WindowSizeY;
    02690
    02691     WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
    02692     WindowSizeY = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
    02693
    02694     if (max(SourceY, TargetY) + Length > WindowSizeY) {
    02695         Length = WindowSizeY - max(SourceY, TargetY);
    02696         if (Length <= 0 ) {
    02697             return;
    02698         }
    02699     }
    02700
    02701 #if defined(FE_SB)
    02702     {
    02703         FSCNTL_SCREEN_INFO FsCntlSrc;
    02704         FSCNTL_SCREEN_INFO FsCntlDest;
    02705
    02706         FsCntlSrc.Position.X = 0;
    02707         FsCntlSrc.Position.Y = SourceY;
    02708         FsCntlSrc.ScreenSize.X = WindowSizeX;
    02709         FsCntlSrc.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
    02710         FsCntlSrc.nNumberOfChars = Length * WindowSizeX;
    02711
    02712         FsCntlDest.Position.X = 0;
    02713         FsCntlDest.Position.Y = TargetY;
    02714         FsCntlDest.ScreenSize.X = WindowSizeX;
    02715         FsCntlDest.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
    02716         FsCntlDest.nNumberOfChars = Length * WindowSizeX;
    02717
    02718         GdiFullscreenControl(FullscreenControlCopyFrameBufferDB,
    02719                              &FsCntlSrc,
    02720                              sizeof(FsCntlSrc),
    02721                              &FsCntlDest,
    02722                              (PULONG)sizeof(FsCntlDest));
    02723
    02724         UNREFERENCED_PARAMETER(SourcePtr);
    02725         UNREFERENCED_PARAMETER(TargetPtr);
    02726     }
    02727 #else
    02728     SourcePtr = SCREEN_BUFFER_POINTER(0,
    02729                                       SourceY,
    02730                                       WindowSizeX,
    02731                                       sizeof(VGA_CHAR));
    02732
    02733     TargetPtr = SCREEN_BUFFER_POINTER(0,
    02734                                       TargetY,
    02735                                       WindowSizeX,
    02736                                       sizeof(VGA_CHAR));
    02737
    02738     GdiFullscreenControl(FullscreenControlCopyFrameBuffer,
    02739                             (PULONG) SourcePtr,
    02740                             Length * WindowSizeX * sizeof(VGA_CHAR),
    02741                             (PULONG) TargetPtr,
    02742                             (PULONG) (Length * WindowSizeX * sizeof(VGA_CHAR)));
    02743 #endif
    02744 }
    02745
    02746 VOID
    02747 ScrollHW(
    02748     IN PSCREEN_INFORMATION ScreenInfo,
    02749     IN PSMALL_RECT ScrollRect,
    02750     IN PSMALL_RECT MergeRect,
    02751     IN COORD TargetPoint
    02752     )
    02753 {
    02754     SMALL_RECT TargetRectangle;
    02755     if (ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)
    02756         return;
    02757
    02758     TargetRectangle.Left = TargetPoint.X;
    02759     TargetRectangle.Top = TargetPoint.Y;
    02760     TargetRectangle.Right = TargetPoint.X + ScrollRect->Right - ScrollRect->Left;
    02761     TargetRectangle.Bottom = TargetPoint.Y + ScrollRect->Bottom - ScrollRect->Top;
    02762
    02763     //
    02764     // if the scroll region is as wide as the screen, we can update
    02765     // the screen by copying the video memory.  if we scroll this
    02766     // way, we then must clip and update the fill region.
    02767     //
    02768
    02769     if (ScrollRect->Left == ScreenInfo->Window.Left &&
    02770         TargetRectangle.Left == ScreenInfo->Window.Left &&
    02771         ScrollRect->Right == ScreenInfo->Window.Right &&
    02772         TargetRectangle.Right == ScreenInfo->Window.Right &&
    02773         ScrollRect->Top >= ScreenInfo->Window.Top &&
    02774         TargetRectangle.Top >= ScreenInfo->Window.Top &&
    02775         ScrollRect->Bottom <= ScreenInfo->Window.Bottom &&
    02776         TargetRectangle.Bottom <= ScreenInfo->Window.Bottom) {
    02777
    02778         //
    02779         // we must first make the mouse pointer invisible because
    02780         // otherwise it would get copied to another place on the
    02781         // screen if it were part of the scroll region.
    02782         //
    02783
    02784         ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
    02785
    02786         CopyVideoMemory((SHORT) (ScrollRect->Top - ScreenInfo->Window.Top),
    02787                         (SHORT) (TargetRectangle.Top - ScreenInfo->Window.Top),
    02788                         (SHORT) (TargetRectangle.Bottom - TargetRectangle.Top + 1),
    02789                         ScreenInfo);
    02790
    02791         //
    02792         // update the fill region.  first we ensure that the scroll and
    02793         // target regions aren't the same.  if they are, we don't fill.
    02794         //
    02795
    02796         if (TargetRectangle.Top != ScrollRect->Top) {
    02797
    02798             //
    02799             // if scroll and target regions overlap, with scroll
    02800             // region above target region, clip scroll region.
    02801             //
    02802
    02803             if (TargetRectangle.Top <= ScrollRect->Bottom &&
    02804                 TargetRectangle.Bottom >= ScrollRect->Bottom) {
    02805                 ScrollRect->Bottom = (SHORT)(TargetRectangle.Top-1);
    02806             }
    02807             else if (TargetRectangle.Top <= ScrollRect->Top &&
    02808                 TargetRectangle.Bottom >= ScrollRect->Top) {
    02809                 ScrollRect->Top = (SHORT)(TargetRectangle.Bottom+1);
    02810             }
    02811             WriteToScreen(ScreenInfo,ScrollRect);
    02812
    02813             //
    02814             // WriteToScreen should take care of writing the mouse pointer.
    02815             // however, the update region may be clipped so that the
    02816             // mouse pointer is not written. in that case, we draw the
    02817             // mouse pointer here.
    02818             //
    02819
    02820             if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < ScrollRect->Top ||
    02821                 ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > ScrollRect->Bottom) {
    02822                 ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
    02823             }
    02824         }
    02825         if (MergeRect) {
    02826             WriteToScreen(ScreenInfo,MergeRect);
    02827         }
    02828     }
    02829     else {
    02830         if (MergeRect) {
    02831             WriteToScreen(ScreenInfo,MergeRect);
    02832         }
    02833         WriteToScreen(ScreenInfo,ScrollRect);
    02834         WriteToScreen(ScreenInfo,&TargetRectangle);
    02835     }
    02836 }
    02837
    02838 VOID
    02839 UpdateMousePosition(
    02840     PSCREEN_INFORMATION ScreenInfo,
    02841     COORD Position
    02842     )
    02843
    02844 /*++
    02845
    02846 Routine Description:
    02847
    02848     This routine moves the mouse pointer.
    02849
    02850 Arguments:
    02851
    02852     ScreenInfo - Pointer to screen buffer information.
    02853
    02854     Position - Contains the new position of the mouse in screen buffer
    02855     coordinates.
    02856
    02857 Return Value:
    02858
    02859     none.
    02860
    02861 --*/
    02862
    02863 // Note: CurrentConsole lock must be held in share mode when calling this routine
    02864 {
    02865     SMALL_RECT CursorRegion;
    02866 #ifdef FE_SB
    02867     SHORT RowIndex;
    02868     PROW  Row;
    02869     BOOL  fOneMore = FALSE;
    02870 #endif
    02871
    02872     if ((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED) ||
    02873             (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
    02874         return;
    02875     }
    02876
    02877     if (Position.X < ScreenInfo->Window.Left ||
    02878         Position.X > ScreenInfo->Window.Right ||
    02879         Position.Y < ScreenInfo->Window.Top ||
    02880         Position.Y > ScreenInfo->Window.Bottom) {
    02881         return;
    02882     }
    02883
    02884     if (Position.X == ScreenInfo->BufferInfo.TextInfo.MousePosition.X &&
    02885         Position.Y == ScreenInfo->BufferInfo.TextInfo.MousePosition.Y) {
    02886         return;
    02887     }
    02888
    02889 #ifdef FE_SB
    02890     if (CONSOLE_IS_DBCS_CP(ScreenInfo->Console)) {
    02891         RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Position.Y) % ScreenInfo->ScreenBufferSize.Y;
    02892         Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
    02893         if (Row->CharRow.KAttrs[Position.X] & ATTR_LEADING_BYTE) {
    02894             if (Position.X != ScreenInfo->ScreenBufferSize.X - 1) {
    02895                 fOneMore = TRUE;
    02896             }
    02897         } else if (Row->CharRow.KAttrs[Position.X] & ATTR_TRAILING_BYTE) {
    02898             if (Position.X != 0) {
    02899                 fOneMore = TRUE;
    02900                 Position.X--;
    02901             }
    02902         }
    02903
    02904     }
    02905 #endif
    02906
    02907     if (ScreenInfo->CursorDisplayCount < 0 || !(ScreenInfo->Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT)) {
    02908         ScreenInfo->BufferInfo.TextInfo.MousePosition = Position;
    02909         return;
    02910     }
    02911
    02912
    02913     // turn off old mouse position.
    02914
    02915     CursorRegion.Left = CursorRegion.Right = ScreenInfo->BufferInfo.TextInfo.MousePosition.X;
    02916     CursorRegion.Top = CursorRegion.Bottom = ScreenInfo->BufferInfo.TextInfo.MousePosition.Y;
    02917
    02918 #ifdef FE_SB
    02919     if (CONSOLE_IS_DBCS_CP(ScreenInfo->Console)) {
    02920         RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+CursorRegion.Top) % ScreenInfo->ScreenBufferSize.Y;
    02921         Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
    02922         if (Row->CharRow.KAttrs[CursorRegion.Left] & ATTR_LEADING_BYTE) {
    02923             if (CursorRegion.Left != ScreenInfo->ScreenBufferSize.X - 1) {
    02924                 CursorRegion.Right++;
    02925             }
    02926         }
    02927     }
    02928 #endif
    02929
    02930     // store new mouse position
    02931
    02932     ScreenInfo->BufferInfo.TextInfo.MousePosition.X = Position.X;
    02933     ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = Position.Y;
    02934     WriteToScreen(ScreenInfo,&CursorRegion);
    02935
    02936     // turn on new mouse position
    02937
    02938     CursorRegion.Left = CursorRegion.Right = Position.X;
    02939     CursorRegion.Top = CursorRegion.Bottom = Position.Y;
    02940 #ifdef FE_SB
    02941     if (fOneMore)
    02942         CursorRegion.Right++;
    02943 #endif
    02944     WriteToScreen(ScreenInfo,&CursorRegion);
    02945 }
    02946
    02947 NTSTATUS
    02948 SetROMFontCodePage(
    02949     IN UINT wCodePage,
    02950     IN ULONG ModeIndex
    02951     )
    02952
    02953 /*
    02954
    02955     this function opens ega.cpi and looks for the desired font in the
    02956     specified codepage.  if found, it loads it into the video ROM.
    02957
    02958 */
    02959
    02960 {
    02961     BYTE Buffer[CONSOLE_FONT_BUFFER_LENGTH];
    02962     DWORD dwBytesRead;
    02963     LPFONTFILEHEADER lpFontFileHeader=(LPFONTFILEHEADER)Buffer;
    02964     LPFONTINFOHEADER lpFontInfoHeader=(LPFONTINFOHEADER)Buffer;
    02965     LPFONTDATAHEADER lpFontDataHeader=(LPFONTDATAHEADER)Buffer;
    02966     LPCPENTRYHEADER lpCPEntryHeader=(LPCPENTRYHEADER)Buffer;
    02967     LPSCREENFONTHEADER lpScreenFontHeader=(LPSCREENFONTHEADER)Buffer;
    02968     WORD NumEntries;
    02969     COORD FontDimensions;
    02970     NTSTATUS Status;
    02971     BOOL Found;
    02972     LONG FilePtr;
    02973     BOOL bDOS = FALSE;
    02974
    02975     FontDimensions = ModeFontPairs[ModeIndex].FontSize;
    02976
    02977     //
    02978     // read FONTINFOHEADER
    02979     //
    02980     // do {
    02981     //     read CPENTRYHEADER
    02982     //     if (correct codepage)
    02983     //         break;
    02984     // } while (codepages)
    02985     // if (codepage found)
    02986     //     read FONTDATAHEADER
    02987     //
    02988
    02989     // read FONTFILEHEADER
    02990
    02991     FilePtr = 0;
    02992     if (SetFilePointer(hCPIFile,FilePtr,NULL,FILE_BEGIN) == -1) {
    02993         Status = STATUS_INVALID_PARAMETER;
    02994         goto DoExit;
    02995     }
    02996
    02997     if (!ReadFile(hCPIFile,Buffer,sizeof(FONTFILEHEADER),&dwBytesRead,NULL) ||
    02998         dwBytesRead != sizeof(FONTFILEHEADER)) {
    02999         Status = STATUS_INVALID_PARAMETER;
    03000         goto DoExit;
    03001     }
    03002
    03003     // verify signature
    03004
    03005     if (memcmp(lpFontFileHeader->ffhFileTag, "\xFF""FONT.NT",8) ) {
    03006         if (memcmp(lpFontFileHeader->ffhFileTag, "\xFF""FONT   ",8) ) {
    03007             Status = STATUS_INVALID_PARAMETER;
    03008             goto DoExit;
    03009         } else {
    03010             bDOS = TRUE;
    03011         }
    03012     }
    03013
    03014     // seek to FONTINFOHEADER.  jump through hoops to get the offset value.
    03015
    03016     FilePtr = lpFontFileHeader->ffhOffset1;
    03017     FilePtr |= (lpFontFileHeader->ffhOffset2 << 8);
    03018     FilePtr |= (lpFontFileHeader->ffhOffset3 << 24);
    03019
    03020     if (SetFilePointer(hCPIFile,FilePtr,NULL,FILE_BEGIN) == -1) {
    03021         Status = STATUS_INVALID_PARAMETER;
    03022         goto DoExit;
    03023     }
    03024
    03025     // read FONTINFOHEADER
    03026
    03027     if (!ReadFile(hCPIFile,Buffer,sizeof(FONTINFOHEADER),&dwBytesRead,NULL) ||
    03028         dwBytesRead != sizeof(FONTINFOHEADER)) {
    03029         Status = STATUS_INVALID_PARAMETER;
    03030         goto DoExit;
    03031     }
    03032     FilePtr += dwBytesRead;
    03033     NumEntries = lpFontInfoHeader->fihCodePages;
    03034
    03035     Found = FALSE;
    03036     while (NumEntries &&
    03037            ReadFile(hCPIFile,Buffer,sizeof(CPENTRYHEADER),&dwBytesRead,NULL) &&
    03038            dwBytesRead == sizeof(CPENTRYHEADER)) {
    03039         if (lpCPEntryHeader->cpeCodepageID == wCodePage) {
    03040             Found = TRUE;
    03041             break;
    03042         }
    03043         // seek to next CPEENTRYHEADER
    03044
    03045         if (bDOS) {
    03046             FilePtr = MAKELONG(lpCPEntryHeader->cpeNext1,lpCPEntryHeader->cpeNext2);
    03047         } else {
    03048             FilePtr += MAKELONG(lpCPEntryHeader->cpeNext1,lpCPEntryHeader->cpeNext2);
    03049         }
    03050         if (SetFilePointer(hCPIFile, FilePtr, NULL,FILE_BEGIN) == -1) {
    03051             Status = STATUS_INVALID_PARAMETER;
    03052             goto DoExit;
    03053         }
    03054         NumEntries-=1;
    03055     }
    03056     if (!Found) {
    03057         Status = STATUS_INVALID_PARAMETER;
    03058         goto DoExit;
    03059     }
    03060
    03061     // seek to FONTDATAHEADER
    03062
    03063     if (bDOS) {
    03064         FilePtr = lpCPEntryHeader->cpeOffset;
    03065     } else {
    03066         FilePtr += lpCPEntryHeader->cpeOffset;
    03067     }
    03068     if (SetFilePointer(hCPIFile, FilePtr, NULL,FILE_BEGIN) == -1) {
    03069         Status = STATUS_INVALID_PARAMETER;
    03070         goto DoExit;
    03071     }
    03072
    03073     // read FONTDATAHEADER
    03074
    03075     if (!ReadFile(hCPIFile,Buffer,sizeof(FONTDATAHEADER),&dwBytesRead,NULL) ||
    03076         dwBytesRead != sizeof(FONTDATAHEADER)) {
    03077         Status = STATUS_INVALID_PARAMETER;
    03078         goto DoExit;
    03079     }
    03080     FilePtr += dwBytesRead;
    03081
    03082     NumEntries = lpFontDataHeader->fdhFonts;
    03083
    03084     while (NumEntries) {
    03085         if (!ReadFile(hCPIFile,Buffer,sizeof(SCREENFONTHEADER),&dwBytesRead,NULL) ||
    03086             dwBytesRead != sizeof(SCREENFONTHEADER)) {
    03087             Status = STATUS_INVALID_PARAMETER;
    03088             goto DoExit;
    03089         }
    03090
    03091         if (lpScreenFontHeader->sfhHeight == (BYTE)FontDimensions.Y &&
    03092             lpScreenFontHeader->sfhWidth == (BYTE)FontDimensions.X) {
    03093             PVIDEO_LOAD_FONT_INFORMATION FontInformation;
    03094
    03095             FontInformation = (PVIDEO_LOAD_FONT_INFORMATION)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),
    03096                                     lpScreenFontHeader->sfhCharacters*
    03097                                     lpScreenFontHeader->sfhHeight+
    03098                                     sizeof(VIDEO_LOAD_FONT_INFORMATION));
    03099             if (FontInformation == NULL) {
    03100                 RIPMSG1(RIP_WARNING, "SetROMFontCodePage: failed to memory allocation %d bytes",
    03101                     lpScreenFontHeader->sfhCharacters * lpScreenFontHeader->sfhHeight +
    03102                     sizeof(VIDEO_LOAD_FONT_INFORMATION));
    03103                 return STATUS_NO_MEMORY;
    03104             }
    03105             if (!ReadFile(hCPIFile,FontInformation->Font,
    03106                           lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight,
    03107                           &dwBytesRead,NULL) ||
    03108                           dwBytesRead != (DWORD)(lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight)) {
    03109                 ConsoleHeapFree(FontInformation);
    03110                 return STATUS_INVALID_PARAMETER;
    03111             }
    03112             FontInformation->WidthInPixels = FontDimensions.X;
    03113             FontInformation->HeightInPixels = FontDimensions.Y;
    03114             FontInformation->FontSize = lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight;
    03115
    03116             Status = GdiFullscreenControl(FullscreenControlLoadFont,
    03117                                              FontInformation,
    03118                                              lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight+sizeof(VIDEO_LOAD_FONT_INFORMATION),
    03119                                              NULL,
    03120                                              NULL);
    03121
    03122             ConsoleHeapFree(FontInformation);
    03123             return Status;
    03124         } else {
    03125             FilePtr = lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight;
    03126             if (SetFilePointer(hCPIFile, FilePtr, NULL,FILE_CURRENT) == -1) {
    03127                 Status = STATUS_INVALID_PARAMETER;
    03128                 goto DoExit;
    03129             }
    03130         }
    03131         NumEntries -= 1;
    03132     }
    03133 DoExit:
    03134     return Status;
    03135 }
    03136 #endif
    03137
    03138 NTSTATUS
    03139 GetThreadConsoleDesktop(
    03140     DWORD dwThreadId,
    03141     HDESK *phdeskConsole)
    03142 {
    03143     PCSR_THREAD pcsrt;
    03144     PCONSOLE_PER_PROCESS_DATA ProcessData;
    03145     PCONSOLE_INFORMATION Console;
    03146     NTSTATUS Status;
    03147     HANDLE ConsoleHandle = NULL;
    03148
    03149     *phdeskConsole = NULL;
    03150     Status = CsrLockThreadByClientId((HANDLE)dwThreadId, &pcsrt);
    03151     if (NT_SUCCESS(Status)) {
    03152         ProcessData = CONSOLE_FROMTHREADPERPROCESSDATA(pcsrt);
    03153         ConsoleHandle = ProcessData->ConsoleHandle;
    03154         CsrUnlockThread(pcsrt);
    03155     }
    03156
    03157     //
    03158     // If this process is a console app, return the
    03159     // handle to its desktop.  Otherwise, return NULL.
    03160     //
    03161
    03162     if (ConsoleHandle != NULL) {
    03163         Status = RevalidateConsole(ConsoleHandle, &Console);
    03164         if (NT_SUCCESS(Status)) {
    03165             *phdeskConsole = Console->hDesk;
    03166         }
    03167         UnlockConsole(Console);
    03168     }
    03169
    03170     return STATUS_SUCCESS;
    03171 }
    03172
    03173
    03174 NTSTATUS
    03175 SetRAMFontCodePage(
    03176     IN PSCREEN_INFORMATION ScreenInfo
    03177     )
    03178 {
    03179     FSVIDEO_SCREEN_INFORMATION ScreenInformation;
    03180     ULONG ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
    03181     COORD FontSize;
    03182     WCHAR wChar;
    03183     WCHAR wCharBuf[2];
    03184     LPSTRINGBITMAP StringBitmap;
    03185     DWORD BufferSize;
    03186     PWORD FontImage;
    03187     PFONT_CACHE_INFORMATION FontCache;
    03188     WCHAR AltFaceName[LF_FACESIZE];
    03189     COORD AltFontSize;
    03190     BYTE  AltFontFamily;
    03191     ULONG AltFontIndex = 0;
    03192     HFONT hOldFont;
    03193     NTSTATUS Status;
    03194
    03195     ScreenInformation.ScreenSize = RegModeFontPairs[ModeIndex].ScreenSize;
    03196     ScreenInformation.FontSize = RegModeFontPairs[ModeIndex].FontSize;
    03197     if (ScreenInfo->Console->FontCacheInformation == NULL)
    03198     {
    03199         Status = CreateFontCache(&FontCache);
    03200         if (!NT_SUCCESS(Status)) {
    03201             RIPMSG1(RIP_WARNING, "SetRAMFontCodePage: failed in CreateFontCache. Status=%08x", Status);
    03202             return STATUS_UNSUCCESSFUL;
    03203         }
    03204         (PFONT_CACHE_INFORMATION)ScreenInfo->Console->FontCacheInformation = FontCache;
    03205
    03206         MakeAltRasterFont(SCR_FONTCODEPAGE(ScreenInfo),
    03207                           RegModeFontPairs[ModeIndex].FontSize,
    03208                           &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
    03209         FontCache->FullScreenFontIndex = AltFontIndex;
    03210         FontCache->FullScreenFontSize  = AltFontSize;
    03211
    03212         BufferSize = CalcBitmapBufferSize(FontCache->FullScreenFontSize,BYTE_ALIGN);
    03213         StringBitmap = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
    03214                                  sizeof(STRINGBITMAP) + sizeof(StringBitmap->ajBits) * BufferSize);
    03215         if (StringBitmap==NULL)
    03216         {
    03217             RIPMSG0(RIP_WARNING, "SetRAMFontCodePage: failed to allocate StringBitmap");
    03218             return STATUS_UNSUCCESSFUL;
    03219         }
    03220
    03221
    03222         /*
    03223          * Change GDI font to full screen font that best matched.
    03224          */
    03225         hOldFont = SelectObject(ScreenInfo->Console->hDC,FontInfo[FontCache->FullScreenFontIndex].hFont);
    03226
    03227
    03228         for (wChar=0x00; wChar < 0x80; wChar++) {
    03229             wCharBuf[0] = wChar;
    03230             wCharBuf[1] = TEXT('\0');
    03231             GetStringBitmapW(ScreenInfo->Console->hDC,
    03232                              wCharBuf,
    03233                              1,
    03234                              (ULONG)ConsoleHeapSize(StringBitmap),
    03235                              (BYTE*)StringBitmap
    03236                             );
    03237
    03238             FontSize.X = (SHORT)StringBitmap->uiWidth;
    03239             FontSize.Y = (SHORT)StringBitmap->uiHeight;
    03240
    03241 #if defined(LATER_DBCS_FOR_GRID_CHAR)  // by kazum
    03242             BufferSize = CalcBitmapBufferSize(FontSize,BYTE_ALIGN);
    03243             *(StringBitmap->ajBits + BufferSize) = 0;
    03244             *(StringBitmap->ajBits + BufferSize + 1) = 0;
    03245
    03246             if (gpGridCharacter) {
    03247                 PGRID_CHARACTER_INFORMATION GridCharacter;
    03248                 PWCHAR CodePoint;
    03249
    03250                 GridCharacter = gpGridCharacter;
    03251                 do {
    03252                     if (GridCharacter->CodePage == OEMCP) {
    03253                         CodePoint = GridCharacter->CodePoint;
    03254                         while (*CodePoint) {
    03255                             if (*CodePoint == wChar) {
    03256                                 if (FontSize.X <= 8)
    03257                                     *(StringBitmap->ajBits + BufferSize) = *(StringBitmap->ajBits + BufferSize - 1);
    03258                                 else {
    03259                                     *(StringBitmap->ajBits + BufferSize) = *(StringBitmap->ajBits + BufferSize - 2);
    03260                                     *(StringBitmap->ajBits + BufferSize + 1) = *(StringBitmap->ajBits + BufferSize - 1);
    03261                                 }
    03262                                 break;
    03263                             }
    03264                             else
    03265                                 CodePoint++;
    03266                         }
    03267                         break;
    03268                     }
    03269                 } while (GridCharacter = GridCharacter->pNext);
    03270             }
    03271 #endif // LATER_DBCS_FOR_GRID_CHAR  // by kazum
    03272
    03273             Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
    03274                                   wChar,
    03275                                   FontSize,
    03276                                   BYTE_ALIGN,
    03277                                   StringBitmap->ajBits
    03278                                  );
    03279             if (! NT_SUCCESS(Status)) {
    03280                 RIPMSG3(RIP_WARNING, "SetRAMFontCodePage: failed to set font image. wc=%04x sz=(%x, %x).",
    03281                         wChar, FontSize.X, FontSize.Y);
    03282             }
    03283
    03284             if (FontSize.X != ScreenInformation.FontSize.X ||
    03285                 FontSize.Y != ScreenInformation.FontSize.Y)
    03286             {
    03287                 BufferSize = CalcBitmapBufferSize(ScreenInformation.FontSize,WORD_ALIGN);
    03288                 FontImage = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
    03289                                       BufferSize
    03290                                      );
    03291                 if (FontImage!=NULL) {
    03292
    03293                     GetExpandFontImage(ScreenInfo->Console->FontCacheInformation,
    03294                                        wChar,
    03295                                        FontSize,
    03296                                        ScreenInformation.FontSize,
    03297                                        FontImage
    03298                                       );
    03299
    03300                     Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
    03301                                           wChar,
    03302                                           ScreenInformation.FontSize,
    03303                                           WORD_ALIGN,
    03304                                           FontImage
    03305                                          );
    03306                     if (! NT_SUCCESS(Status)) {
    03307                         RIPMSG3(RIP_WARNING, "SetRAMFontCodePage: failed to set font image. wc=%04x, sz=(%x,%x)",
    03308                                 wChar, ScreenInformation.FontSize.X, ScreenInformation.FontSize.Y);
    03309                     }
    03310
    03311                     ConsoleHeapFree(FontImage);
    03312                 } else {
    03313                     RIPMSG0(RIP_WARNING, "SetRAMFontCodePage: failed to allocate FontImage.");
    03314                 }
    03315             }
    03316         }
    03317
    03318         ConsoleHeapFree(StringBitmap);
    03319
    03320         /*
    03321          * Back to GDI font
    03322          */
    03323         SelectObject(ScreenInfo->Console->hDC,hOldFont);
    03324     }
    03325
    03326     Status = GdiFullscreenControl(FullscreenControlSetScreenInformation,
    03327                                   &ScreenInformation,
    03328                                   sizeof(ScreenInformation),
    03329                                   NULL,
    03330                                   NULL);
    03331
    03332     return Status;
    03333 }
    03334
    03335 NTSTATUS
    03336 SetRAMFont(
    03337     IN PSCREEN_INFORMATION ScreenInfo,
    03338     IN PCHAR_INFO ScreenBufPtr,
    03339     IN DWORD Length
    03340     )
    03341 {
    03342     ULONG ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
    03343     COORD FsFontSize1 = RegModeFontPairs[ModeIndex].FontSize;
    03344     COORD FsFontSize2 = FsFontSize1;
    03345     COORD GdiFontSize1;
    03346     COORD GdiFontSize2;
    03347     COORD RetFontSize;
    03348     WCHAR wCharBuf[2];
    03349     LPSTRINGBITMAP StringBitmap;
    03350     DWORD BufferSize;
    03351     PWORD FontImage;
    03352     PFONT_CACHE_INFORMATION FontCache;
    03353     HFONT hOldFont;
    03354     NTSTATUS Status;
    03355
    03356     FontCache = (PFONT_CACHE_INFORMATION)ScreenInfo->Console->FontCacheInformation;
    03357     if (FontCache==NULL)
    03358     {
    03359         RIPMSG0(RIP_ERROR, "SetRAMFont: ScreenInfo->Console->FontCacheInformation == NULL.");
    03360         return STATUS_UNSUCCESSFUL;
    03361     }
    03362
    03363     GdiFontSize1 = FontCache->FullScreenFontSize;
    03364     GdiFontSize2 = GdiFontSize1;
    03365     GdiFontSize2.X *= 2;
    03366     FsFontSize2.X *= 2;
    03367
    03368     BufferSize = CalcBitmapBufferSize(GdiFontSize2,BYTE_ALIGN);
    03369     StringBitmap = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
    03370                              sizeof(STRINGBITMAP) + sizeof(StringBitmap->ajBits) * BufferSize);
    03371     if (StringBitmap==NULL)
    03372     {
    03373         RIPMSG0(RIP_WARNING, "SetRAMFont: failed to allocate StringBitmap");
    03374         return STATUS_UNSUCCESSFUL;
    03375     }
    03376
    03377     /*
    03378      * Change GDI font to full screen font that best matched.
    03379      */
    03380     hOldFont = SelectObject(ScreenInfo->Console->hDC,FontInfo[FontCache->FullScreenFontIndex].hFont);
    03381
    03382     while (Length--)
    03383     {
    03384         Status = GetFontImage(ScreenInfo->Console->FontCacheInformation,
    03385                               ScreenBufPtr->Char.UnicodeChar,
    03386                               (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
    03387                               0,
    03388                               NULL);
    03389         if (! NT_SUCCESS(Status) )
    03390         {
    03391             wCharBuf[0] = ScreenBufPtr->Char.UnicodeChar;
    03392             wCharBuf[1] = TEXT('\0');
    03393             GetStringBitmapW(ScreenInfo->Console->hDC,
    03394                              wCharBuf,
    03395                              1,
    03396                              (ULONG)ConsoleHeapSize(StringBitmap),
    03397                              (BYTE*)StringBitmap
    03398                             );
    03399
    03400             RetFontSize.X = (SHORT)StringBitmap->uiWidth;
    03401             RetFontSize.Y = (SHORT)StringBitmap->uiHeight;
    03402
    03403             Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
    03404                                   ScreenBufPtr->Char.UnicodeChar,
    03405                                   RetFontSize,
    03406                                   BYTE_ALIGN,
    03407                                   StringBitmap->ajBits
    03408                                  );
    03409             if (! NT_SUCCESS(Status)) {
    03410                 RIPMSG3(RIP_WARNING, "SetRAMFont: failed to set font image. wc=%04x sz=(%x,%x)",
    03411                         ScreenBufPtr->Char.UnicodeChar, RetFontSize.X, RetFontSize.Y);
    03412             }
    03413
    03414             if ( ( (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) &&
    03415                     (GdiFontSize2.X != FsFontSize2.X || GdiFontSize2.Y != FsFontSize2.Y)) ||
    03416                  (!(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) &&
    03417                     (GdiFontSize1.X != FsFontSize1.X || GdiFontSize1.Y != FsFontSize1.Y))    )
    03418             {
    03419                 BufferSize = CalcBitmapBufferSize(FsFontSize2,WORD_ALIGN);
    03420                 FontImage = ConsoleHeapAlloc( MAKE_TAG(TMP_DBCS_TAG),
    03421                                       BufferSize
    03422                                      );
    03423                 if (FontImage!=NULL) {
    03424
    03425                     GetExpandFontImage(ScreenInfo->Console->FontCacheInformation,
    03426                                        ScreenBufPtr->Char.UnicodeChar,
    03427                                        (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? GdiFontSize2 : GdiFontSize1,
    03428                                        (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
    03429                                        FontImage
    03430                                       );
    03431
    03432                     Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
    03433                                           ScreenBufPtr->Char.UnicodeChar,
    03434                                           (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
    03435                                           WORD_ALIGN,
    03436                                           FontImage
    03437                                          );
    03438                     if (! NT_SUCCESS(Status)) {
    03439                         RIPMSG3(RIP_WARNING, "SetRAMFont: failed to set font image. wc=%04x sz=(%x,%x)",
    03440                                 ScreenBufPtr->Char.UnicodeChar,
    03441                                 ((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1).X,
    03442                                 ((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1).Y);
    03443                     }
    03444
    03445                     ConsoleHeapFree(FontImage);
    03446                 } else {
    03447                     RIPMSG0(RIP_WARNING, "SetRAMFont: failed to allocate FontImage.");
    03448                 }
    03449             }
    03450         }
    03451
    03452         if (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS)
    03453         {
    03454             ScreenBufPtr += 2;
    03455             if (Length >= 1)
    03456                 Length -= 1;
    03457             else
    03458                 break;
    03459         }
    03460         else
    03461         {
    03462             ScreenBufPtr++;
    03463         }
    03464     }
    03465
    03466     ConsoleHeapFree(StringBitmap);
    03467
    03468     /*
    03469      * Back to GDI font
    03470      */
    03471     SelectObject(ScreenInfo->Console->hDC,hOldFont);
    03472
    03473     return Status;
    03474 }
    03475
    03476 #ifdef i386
    03477 #if defined(FE_SB)
    03478
    03479 #define WWSB_NOFE
    03480 #include "_priv.h"
    03481 #undef  WWSB_NOFE
    03482 #define WWSB_FE
    03483 #include "_priv.h"
    03484 #undef  WWSB_FE
    03485
    03486 #endif  // FE_SB
    03487 #endif  // i386