/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = bvhinfo.c
 *
 * DESCRIPTIVE NAME = Super VGA specific routines.
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION Base video device handler  - Info functions.
 *
 *             This source is compiled to produce a video
 *             device handler for Super VGA.
 *             The video device handler depends on VIDEOPMI to
 *             perform hardware specific functions, such as
 *             mode set, font set, CLUT set and save/restore state.
 *             Cursor function assumes that hardware is VGA compatible.
 *
 *             Vital assumption: for all hardware-bound functions
 *             the environment buffer must be passed, so that
 *             VIDEOPMI relevant data can be setup.
 *
 * FUNCTIONS   GetCursorInfo,   SetCursorInfo
 *             GetVariableInfo, SetVariableInfo
 *             GetDBCSDisplayInfo, GetLVBInfo
 *             RetConfigInfo
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

/*
**      Include files
*/

#define  INCL_DOSDEVICES               /* Device specific, ring 2 support   */
#define  INCL_DOSINFOSEG
#include "bvhtype.h"                  /* Type definitions                  */
#include <memory.h>
#pragma  intrinsic(memcpy,memcmp,memset)


/*****************************************************************************
 *
 *  SUBROUTINE NAME: RetConfigInfo
 *
 *  DESCRIPTIVE NAME: Return video adapter configuration information
 *
 *  FUNCTION: RetConfigInfo is called by BVS to identify the current
 *            display adapter.
 *
 *  ENTRY POINT: RetConfigInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 260 )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 ( reserved )
 *                     FAR *ConfigData = VioGetConfig structure
 *             ULONG Function ( Call vector table entry = 260 )
 *         (Referenced)
 *
 *
 *  EXIT-NORMAL: AX = 0
 *               Configuration data is returned to caller
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  EFFECTS: If the length of ConfigData does not exactly fit a
 *           parameter, the length is adjusted and returned.
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 ****************************************************************************/

USHORT APIENTRY FAR RetConfigInfo(PENVIRONMENT Environment,PVDHCONFIG
                                   ParmBlock,ULONG Function)
{

  USHORT rc;
  VDHCONFIGINFO far *pReqConfig;          /* Reduce level of indirection, */
  unsigned register ReqConfigLen;         /* Eliminate segment loading, */

#ifdef  CHAIN_VGA   /* @TSU00 */
  /*
   * The only reason to chain the VGA RetConfigInfo here is to obtain the
   * HWBufferSize of VGA, which is size of the VGA environment.
   */
  VDHCONFIG     VDHConf;
  VDHCONFIGINFO VDHConfInfo;

  VDHConf = *ParmBlock;
  if (ParmBlock->ConfigDataPTR)
  {
     /*           
      * ParmBlock->ConfigDataPTR is of variable length.
      * The number of bytes to be copied depend on
      * ParmBlock->ConfigDataPTR->cb.
      */
     memcpy (&VDHConfInfo,
             ParmBlock->ConfigDataPTR,
             ParmBlock->ConfigDataPTR->cb);
     VDHConf.ConfigDataPTR = &VDHConfInfo;
  }
  else
     VDHConf.ConfigDataPTR = NULL;

  if ((rc = ChainedRetConfigInfo (Environment, &VDHConf, Function)) !=
      NO_ERROR)
     return rc;
#endif

  rc = ERROR_VIO_INVALID_PARMS;                         /* Initialize to error    */

  if ( ( Function == FnReturnConfigInfo )            && /* Valid function request */
     ( ParmBlock->Length >= sizeof( VDHCONFIG ) ) && /* Valid packet length    */
     ( !ParmBlock->Flags ) )
  {                        /* Valid flags            */

    rc = NO_ERROR;                      /* Initialize no error */

    ReqConfigLen = (pReqConfig = ParmBlock->ConfigDataPTR)->cb;

    if ( ReqConfigLen > sizeof(VDHCONFIGINFO) )
    {
      ReqConfigLen = MinDLen_Config_Memory;
    }

    if ( ( ReqConfigLen < MinDLen_Config_Adapter ) &&
         ( ReqConfigLen != Config_Return_Length ) )
      rc = ERROR_VIO_INVALID_LENGTH;

    /*
    **  Structure length of 2 means set structure length and return
    */

    else if ( ReqConfigLen == Config_Return_Length )
      ReqConfigLen = sizeof( VDHCONFIGINFO );

    else
    {

      /*
      **  Adapter types:
      **                 3 - VGA or PS/2 adapter
      **                 A - SVGA
      */


      if (fNoVideopmi)
        pReqConfig->adapter  = TYPE_VGA;
      else
        pReqConfig->adapter  = DISPLAY_SVGA;

      if ( ReqConfigLen < MinDLen_Config_Display )
        ReqConfigLen = MinDLen_Config_Adapter;

      else
      {
        /*
        **  Display types:
        **   0 - 5151 mono             5 - IBM Japan 5550 mono
        **   1 - 5153 color            6 - IBM Japan 5550 color
        **   2 - 5154 enhanced         7 - IBM Japan 5570 color
        **   3 - 8503 mono             8 - IBM Japan 5570 full page
        **   4 - 8512/8513 color       9 - 8514 color
        */

        pReqConfig->display = CurrentDisplay;

        if ( ReqConfigLen < MinDLen_Config_Memory )
          ReqConfigLen = MinDLen_Config_Display;

        else
        {
          /*
          **  Video memory size:
          **  For VGA only, this may not be accurate!
          */

          pReqConfig->cbMemory = ulTotalMemory;

          if ( ReqConfigLen < MinDLen_Config_ConfigNum )
            ReqConfigLen = MinDLen_Config_Memory;

          else
          {

            /*
            **  Configuration number: always return unknown
            */

            pReqConfig->Configuration = 0;      /* unknown */

            if ( ReqConfigLen < MinDLen_Config_Version )
              ReqConfigLen = MinDLen_Config_ConfigNum;

            else
            {

              /*
              **  Video device driver version number
              */

              pReqConfig->DeviceDriver = 0;

              if ( ReqConfigLen < MinDLen_Config_Flag )
                ReqConfigLen = MinDLen_Config_Version;

              else
              {

                /*
                **  Configuration flag: xxxxxxxb  1 = Power-up display
                */

                pReqConfig->Flags = 1;

                if ( ReqConfigLen < MinDLen_Config_HWBufLen )
                  ReqConfigLen = MinDLen_Config_Flag;

                else
                {

                  /*
                  **  Size of hardware state buffer
                  */

#ifdef  CHAIN_VGA   /* @TSU00 */
                  /*
                   * size of the environment variable not including
                   * VGA environment.
                   */
//                  ulEnvLength = sizeof(ENVIRONMENT) + ulMaxListSize;

                  pReqConfig->HWBufferSize = ulEnvLength +
                       VDHConfInfo.HWBufferSize; /* VGA environment size */
#else
                  pReqConfig->HWBufferSize = sizeof(ENVIRONMENT)+ulMaxListSize;
#endif


                  if ( ReqConfigLen < MinDLen_Config_FullSaveSz )
                    ReqConfigLen = MinDLen_Config_HWBufLen;

                  else
                  {

                    /*
                    ** Size of entire physical display memory.
                    ** For VGA only, this may not be accurate!
                    */

                    pReqConfig->FullSaveSize = ulTotalMemory;

                    if ( ReqConfigLen < MinDLen_Config_PartSaveSz )
                      ReqConfigLen = MinDLen_Config_FullSaveSz;

                    else
                    {

                      /*
                      **  Size of entire physical display buffer
                      **  for the popup mode (page 0 only)
                      */

                      if (!fNoVideopmi)
                        pReqConfig->PartSaveSize = SVGA_PARTSAVESIZE;
                      else
                        pReqConfig->PartSaveSize = VGA_PARTSAVESIZE;

                      if ( ReqConfigLen < MinDLen_Config_EMAdapter )
                        ReqConfigLen = MinDLen_Config_PartSaveSz;

                      else
                      {

                        /*
                        ** Emulated adapter type and offset its offset
                        ** in ConfigData structure
                        */

                        pReqConfig->EMAdaptersOFF = (USHORT)
                              ((ULONG) &pReqConfig->LEMAdapterdata -
                               (ULONG) &pReqConfig->cb );

                                       /* length of Emulated adapter data */
                        pReqConfig->LEMAdapterdata = 1;
                        /*
                        **  Emulated adapter types:
                        **  b0 - MPA adapter         b3 - VGA or PS/2 adapter
                        **  b1 - CGA adapter         b7 - 8514/A adapter
                        **  b2 - EGA adapter
                        */

                        pReqConfig->EMAdapters =
                                 EMULATE_TYPE_MPA + EMULATE_TYPE_CGA +
                                 EMULATE_TYPE_EGA + EMULATE_TYPE_VGA;

                        if ( ReqConfigLen < MinDLen_Config_EMDisplay )
                          ReqConfigLen = MinDLen_Config_EMAdapter;

                        else
                        {

                          /*
                          **  Emulated display type and offset its
                          **  offset in ConfigData structure
                          */

                          pReqConfig->EMDisplaysOFF =(USHORT)
                              ((ULONG) &pReqConfig->LEMDisplaydata -
                               (ULONG) &pReqConfig->cb );

                                       /* length of Emulated display data*/
                          pReqConfig->LEMDisplaydata = 1;

                          /*
                          **  Emulated display types:
                          **  b0 - 5151 mono            b3 - 8503 mono
                          **  b1 - 5153 color           b4 - 8512/8513 color
                          **  b2 - 5154 enhanced        b9 - 8514 color
                          */
                          pReqConfig->EMDisplays =
                            pReqConfig->EMAdapters & EMULATE_TYPE_MPA
                            ? EmDisp_MPA : 0;

                          pReqConfig->EMDisplays |=
                            pReqConfig->EMAdapters & EMULATE_TYPE_VGA
                            ? EmDisp_VGA + EmDisp_EGA : 0;

                          ReqConfigLen = MinDLen_Config_EMDisplay;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  if (!rc)
  {
    pReqConfig->cb = ReqConfigLen;
  }
  return( rc );
}
/*****************************************************************************
 *
 *  SUBROUTINE NAME: GetLVBInfo
 *
 *  DESCRIPTIVE NAME: Return LVB size and default attribute information
 *
 *  FUNCTION: GetLVBInfo is called by BVS to determine the size of the
 *            LVB required for a given display size.  Based on the
 *            mode and its associated LVB format the allocation size
 *            of the LVB is returned.  Also a default attribute may
 *            be returned.
 *
 *  ENTRY POINT: GetLVBInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 2xx )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 - Environment buffer only
 *                                     1 - Hardware also
 *                     UCHAR  FormatId;
 *                     UCHAR  AttrCount;
 *                     USHORT LVBWidth;
 *                     USHORT LVBHeight;
 *                     ULONG  LVBSize;
 *                     USHORT AttrBufSize;
 *                     UCHAR far *AttrBufAddr;
 *             ULONG Function ( Call vector table entry = 261 )
 *
 *  EXIT-NORMAL: AX = 0
 *               The correct size of the LVB is returned
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
*****************************************************************************/


USHORT EXPENTRY GetLVBInfo (PENVIRONMENT Environment,
                            PVDH_LVB ParmBlock,
                            ULONG Function)

{
  USHORT rc;
  USHORT i;
  USHORT size;                         
                                       /* another C runtime                 */

#ifdef CHAIN_VGA   /* @TSU00 */
  if (Environment->EnvFlags & ENVFLAG_VGAMODE)          //          
    return (ChainedGetLVBInfo ( VGA_ENV(Environment),
                                ParmBlock,
                                Function));
#endif
  INT3();
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */

  if ((Function == FnGetLVBInfo))
  {                                    /* Valid function request            */

    if (ParmBlock->Length >= MINSLEN_LVB_SIZE)
    {                                  /* user wants LVB size               */
      rc = NO_ERROR;                   /* Initialize no error               */
      size = 2;

      if (((ParmBlock->FormatId  == WorldFormat) &&
           (ParmBlock->AttrCount == WorldAttrCount)) ||
          ((ParmBlock->FormatId  == 0) &&
           (ParmBlock->AttrCount == 0) &&
           (Environment->ModeData.fmt_ID == WorldFormat) &&
           (Environment->ModeData.attrib == WorldAttrCount)))
      {
        size = 4;
      }

      if (ParmBlock->LVBWidth == 0)    /* cells width of LVB                */
        size *= Environment->ModeData.col;

      else
        size *= ParmBlock->LVBWidth;

      if (ParmBlock->LVBHeight == 0)   /* cells width of LVB                */
        size *= Environment->ModeData.row;

      else
        size *= ParmBlock->LVBHeight;

      ParmBlock->LVBSize = size;       /* size of the LVB                   */

      if (ParmBlock->Length >= MINSLEN_LVB_ATTRBUFSIZE)
      {

        if (ParmBlock->AttrBufSize == 0)
          ParmBlock->AttrBufSize = Environment->AttrBufSize;

        else

          if (ParmBlock->AttrBufSize >= Environment->AttrBufSize)
          {

            if (ParmBlock->Length >= MINSLEN_LVB_ATTRBUFADDR)
            {

              for (i = 0; i < Environment->AttrBufSize; i++)
                ParmBlock->AttrBufAddr[i] = Environment->AttrBuf[i];
            }

            else
              rc = ERROR_VIO_INVALID_LENGTH;
          }

          else
            rc = ERROR_VIO_INVALID_PARMS;
      }
    }
  }

  return (rc);
}

/*****************************************************************************
 *
 *  SUBROUTINE NAME: GetCursorInfo
 *
 *  DESCRIPTIVE NAME: Get cursor position and/or cursor type
 *
 *  FUNCTION: GetCursorInfo is called by BVS to return selected
 *            information about either the cursor position or the
 *            cursor type.  If the request specifies hardware and the
 *            hardware is readable, the actual hardware setting will
 *            be read and returned.  Otherwise the returned
 *            information will be taken from the environment buffer,
 *            if it has been passed.
 *
 *  ENTRY POINT: GetCursorInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 265 )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 - Environment buffer only
 *                                     1 - Hardware also
 *                     USHORT Row
 *                     USHORT Column
 *                     USHORT TopScanLine
 *                     USHORT BottomScanLine
 *                     USHORT Width
 *                     USHORT Attribute
 *             ULONG Function ( Call vector table entry = 265 )
 *
 *  EXIT-NORMAL: AX = 0
 *               Cursor information is returned.
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  EFFECTS: If hardware specified and hardware is readable, the
 *           environment buffer is updated, if passed.
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: AccessCursorPos, AccessCursorType
 *
 ****************************************************************************/


USHORT EXPENTRY GetCursorInfo(PENVIRONMENT Environment,
                              PVDH_CURSOR ParmBlock,
                              ULONG Function)
{
  USHORT rc,ModeColumns,ColorMode,EnvBufferPassed;
  USHORT ReqFlags = ParmBlock->Flags;
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */

#ifdef CHAIN_VGA   /* @TSU00 */
  if (Environment->EnvFlags & ENVFLAG_VGAMODE)         //          
    return (ChainedGetCursorInfo ( VGA_ENV(Environment),
                                   ParmBlock,
                                   Function));
#endif
  if ((EnvBufferPassed) && (Function == FnGetCursorInfo) && /* Valid funct  */
     !(ReqFlags&~VALID_CURSOR_FLAG) &&                      /* valid flg    */
     (ParmBlock->Length >= MINSLEN_CURSOR_POS))             /* min length   */
  {

    /*
    **  Flags are valid - Get cursor type if enough room provided
    **                    Get cursor position if enough room provided
    */

    rc = ERROR_VIO_MODE;               /* Preset invalid mode               */

    if (!(Environment->ModeData.fbType&MODE_FLAG_GRAPHICS))
    {                                  /* Text mode only                    */
      rc = NO_ERROR;                   /* Initialize no error               */


      /*
      **  Get cursor position -
      **   If requesting application is running in foreground,
      **     - Return hardware value
      **   If requesting application is running in background,
      **     - Return environment buffer value
      */

      if (ReqFlags&CURSOR_POSITION)
      {

        if (ReqFlags&UPDATE_HARDWARE)
        {

          ModeColumns = Environment->ModeData.col;/* Current # of columns   */
          ColorMode = HardwareColor();    /* color/mono mode ( hardware )   */

          /*
          **  Get cursor position directly from the hardware
          */

          AccessCursorPos(ModeColumns, ColorMode, GET, ParmBlock);
        }

        else
        {

          /*
          **  Requesting application is running in the background -
          **  Copy cursor position from env buffer to caller's parameter area
          */

          ParmBlock->Row = Environment->Cursor.Position/Environment->ModeData.col;
          ParmBlock->Column = Environment->Cursor.Position-Environment->ModeData.col
                 * ParmBlock->Row;
        }
      }

      if (ParmBlock->Length >= MINSLEN_CURSOR_TYPE && ReqFlags&CURSOR_TYPE)
      {

        /*
        **  Get cursor type -
        **   If requesting application is running in foreground,
        **     - Return hardware value if hardware can be read
        **     - Otherwise return environment buffer value
        **      ( Do nothing if write-only hardware and no env buffer passed )
        **   If requesting application is running in background,
        **     - Return environment buffer value
        */

        if (ReqFlags&UPDATE_HARDWARE)
        {

          /*
          **  Get type position directly from the hardware
          */

          AccessCursorType(HardwareColor(), GET, ParmBlock);

          /*
          **  Copy cursor type from caller's parmeter area to the env buffer
          **  Since -1 indicates hidden cursor and any other value means
          **  cursor is not hidden, return the exact value that the caller
          **  specified last to indicate not hidden
          */

          if ((ParmBlock->Attribute != 0xFFFF) &&
             (Environment->Cursor.Attribute != 0xFFFF))
            ParmBlock->Attribute = Environment->Cursor.Attribute;
          Environment->Cursor.TopScanLine = ParmBlock->TopScanLine;
          Environment->Cursor.BottomScanLine = ParmBlock->BottomScanLine;

        }

        else
        {

          /*
          **  Requesting application is running in the background
          **  Copy cursor type from env buffer to the caller's parameter area
          */

          ParmBlock->TopScanLine =
             Environment->Cursor.TopScanLine;

          ParmBlock->BottomScanLine =
             Environment->Cursor.BottomScanLine;

          ParmBlock->Width = 1;
          ParmBlock->Attribute = Environment->Cursor.Attribute;
        }
      }
    }
  }

  return (rc);
}

/*****************************************************************************
 *
 *  SUBROUTINE NAME: SetCursorInfo
 *
 *  DESCRIPTIVE NAME: Set cursor position and/or cursor type
 *
 *  FUNCTION: SetCursorInfo is called by BVS to set selected
 *            information about either the cursor position or the
 *            cursor type.  If the request specifies hardware, the
 *            hardware and the environment buffer, if passed, will be
 *            updated.  Otherwise just the environment buffer, if
 *            passed, will be updated.
 *
 *  ENTRY POINT: SetCursorInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 266 )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 - Environment buffer only
 *                                     1 - Hardware also
 *                     USHORT Row
 *                     USHORT Column
 *                     USHORT TopScanLine
 *                     USHORT BottomScanLine
 *                     USHORT Width
 *                     USHORT Attribute
 *             ULONG Function ( Call vector table entry = 266 )
 *
 *  EXIT-NORMAL: AX = 0
 *               Cursor information is set
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: AccessCursorPos, AccessCursorType
 *
 ****************************************************************************/


USHORT EXPENTRY SetCursorInfo(PENVIRONMENT Environment,
                              PVDH_CURSOR ParmBlock,
                              ULONG Function)
{
  USHORT rc,ModeColumns,ColorMode,EnvBufferPassed;

  USHORT register ReqRow,ReqCol;         /*                             @S11*/
  USHORT ReqFlags;                       /*                             @S11*/

#ifdef CHAIN_VGA   /* @TSU00 */
  if (Environment->EnvFlags & ENVFLAG_VGAMODE)      //          
    return (ChainedSetCursorInfo ( VGA_ENV(Environment),
                                   ParmBlock,
                                   Function));
#endif
  ReqFlags = ParmBlock->Flags;           /*                             @S11*/
  rc = ERROR_VIO_INVALID_PARMS;          /* Initialize to error             */
  EnvBufferPassed = SEG(Environment);    /* Non-zero = TRUE                 */

  if ((EnvBufferPassed) && (Function == FnSetCursorInfo) && /* Valid funct  */
     ((ReqFlags & ~UPDATE_HARDWARE) ||   /* An option specified             */
     (ReqFlags & UPDATE_HARDWARE)) &&    /* Foreground                      */
     !(ReqFlags & ~VALID_CURSOR_FLAG) && /* No illegal options              */
     (ParmBlock->Length >= MINSLEN_CURSOR_POS))
  {                                      /* At least min length             */

    /*
    **  Flags are valid - Set cursor type if requested
    **                    Set cursor position if requested
    */

    rc = ERROR_VIO_MODE;               /* Preset invalid mode               */

    if (!(Environment->ModeData.fbType&MODE_FLAG_GRAPHICS))
    {                                  /* Text mode only                    */
      rc = NO_ERROR;                   /* Initialize no error               */

      /*
      **  Parameter checking
      */

      if ((ReqFlags&CURSOR_POSITION))
      {
        ReqRow = ParmBlock->Row;
        ReqCol = ParmBlock->Column;

        /*
        **  Check set cursor position parameters:
        **   validate using env buf mode data
        */

        if ((ReqCol >= Environment->ModeData.col) || (ReqCol >
           Environment->ScrollRect.Right) ||
           (ReqCol < Environment->ScrollRect.Left))

          rc = ERROR_VIO_COL;

        else
        {

          if ((ReqRow >= Environment->ModeData.row) || (ReqRow >
             Environment->ScrollRect.Bottom) ||
             (ReqRow < Environment->ScrollRect.Top))

            rc = ERROR_VIO_ROW;
        }
      }
    }

    if ((ReqFlags&CURSOR_TYPE) && !rc)
    {                                  /* No errors encounted          */

      /*
      **  Check set cursor type parameters
      */
      if ((ParmBlock->Length < MINSLEN_CURSOR_TYPE) || /*Missing parameters*/
         (ParmBlock->TopScanLine >=
         (Environment->ModeData.vres/Environment->ModeData.row)) ||
         (ParmBlock->BottomScanLine > (MAX_FONT_SIZE-1)))
                                                        /* Invalid parameters */
        rc = ERROR_VIO_INVALID_PARMS;

      if (!rc && (ParmBlock->Width > 1))
        rc = ERROR_VIO_WIDTH;
    }

    if (!rc)
    {                                  /* No errors encountered             */

      /*
      **  Parameters are valid - Update environment buffer if it was passed
      **                       - Update hardware if in foreground
      */

      if (ReqFlags&CURSOR_POSITION)
      {

        /*
        **  Copy cursor position from caller's parmeter area to the env buffer
        */

        Environment->Cursor.Position = Environment->ModeData.col * ReqRow+ReqCol;
      }

      if (ReqFlags&CURSOR_TYPE)
      {

        /*
        **  Copy cursor type from caller's parmeter area to the env buffer
        */
        Environment->Cursor.TopScanLine =
           ParmBlock->TopScanLine;

        Environment->Cursor.BottomScanLine =
           ParmBlock->BottomScanLine;

        /*
        ** This must be saved separately so that it can be returned
        */
        Environment->Cursor.Attribute = ParmBlock->Attribute;
      }

      if (ReqFlags&UPDATE_HARDWARE)
      {

        ColorMode = HardwareColor();   /* color/mono mode ( hardware )      */
        if (ReqFlags&CURSOR_POSITION)
        {

          ModeColumns = Environment->ModeData.col;
          /*
          **  Set cursor position directly on the hardware
          */
          AccessCursorPos(ModeColumns, ColorMode, SET, ParmBlock);
        }

        if (ReqFlags&CURSOR_TYPE)
          /*
          **  Set cursor type directly on the hardware
          */

          AccessCursorType(ColorMode, SET, ParmBlock);
      }
    }
  }

  return (rc);
}

/*****************************************************************************
 *
 *  SUBROUTINE NAME: GetVariableInfo
 *
 *  DESCRIPTIVE NAME: Get selected variable information
 *
 *  FUNCTION: GetVariableInfo is called by BVS to return selected
 *            information about video state - blink versus background
 *            intensity, overscan color, underscore scan line, video
 *            enable. If the request specifies hardware, the actual
 *            the hardware setting will be read and returned. Otherwise
 *            the returned information will be taken from the
 *            environment buffer, if it has been passed.
 *
 *  ENTRY POINT: GetVariableInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 269 )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 - Environment buffer only
 *                                     1 - Hardware also
 *                     USHORT Blink
 *                     USHORT Overscan
 *                     USHORT Underscore
 *                     USHORT VideoEnable
 *                     ULONG  DisplayMask
 *                     USHORT CodePageID
 *                     USHORT ScrollLeft
 *                     USHORT ScrollTop
 *                     USHORT ScrollRight
 *                     USHORT ScrollBottom
 *                     USHORT ScreenRows
 *                     USHORT ScreenCols
 *             ULONG Function ( Call vector table entry = 269 )
 *
 *  EXIT-NORMAL: AX = 0
 *               Selected variable information is returned
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  EFFECTS: If hardware specified and hardware is readable, the
 *           environment buffer is updated, if passed.
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: AccessCursorBlink, AccessCursorOverscan
 *              AccessCursorUnderscore, AccessCursorVideoEnable
 *              AccessDisplayMask
 *
 ****************************************************************************/


USHORT EXPENTRY GetVariableInfo(PENVIRONMENT Environment,
                                PVDH_VARIABLE ParmBlock,
                                ULONG Function)
{

  USHORT rc,EnvBufferPassed;
  USHORT ReqFlags;

#ifdef CHAIN_VGA   /* @TSU00 */
  if (Environment->EnvFlags & ENVFLAG_VGAMODE)         //          
    return (ChainedGetVarInfo ( VGA_ENV(Environment),
                                ParmBlock,
                                Function));
#endif
  ReqFlags = ParmBlock->Flags;
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */

  if ((Function == FnGetVariableInfo) &&
     (ReqFlags&VALID_VARIABLE_FLAG) &&
     (EnvBufferPassed ||               /* Env buffer passed                 */
     (ReqFlags&UPDATE_HARDWARE)) &&    /* or is foreground                  */
     (ParmBlock->Length >= MINSLEN_VAR_BLINK))
  {                                    /* At least min length               */

    /*
    **   Get blink versus background if enough room provided
    **   Get overscan color if enough room provided
    **   Get underscore scan line if enough room provided
    **   Get video enable if enough room provided
    **   Get display mask if enough room provided
    **   Get code page ID if enough room provided
    **   Get scrollable region of the screen@P1   |
    **   GET ACTUAL SCREEN HEIGHT AND WIDTH
    */

    rc = NO_ERROR;                     /* Initialize no error               */


    /*
    **  If requesting DISPLAYMASK for non-8514/A, set error
    */

    if (ReqFlags&VARIABLE_DISPLAYMASK)
      rc = ERROR_VIO_INVALID_PARMS;

    if (ReqFlags&UPDATE_HARDWARE)
    {

      /*
      **  Get blink versus background intensity directly from the hardware
      */

      if (ReqFlags&VARIABLE_BLINK)
      {

        if (Environment->ModeData.fbType&MODE_FLAG_GRAPHICS)
          rc = ERROR_VIO_MODE;
        else
          AccessBlink(HardwareColor(), GET, &ParmBlock->Blink);
      }

      /*
      **  Get overscan color directly from the hardware
      */

      if ((ReqFlags&VARIABLE_OVERSCAN) && !rc)
      {

        if (ParmBlock->Length >= MINSLEN_VAR_OVERSCAN)
          AccessOverscan(HardwareColor(), GET, &ParmBlock->Overscan);
        else
          rc = ERROR_VIO_INVALID_LENGTH;
      }

      /*
      **  Get underscore scan line directly from the hardware
      */

      if ((ReqFlags&VARIABLE_UNDERSCORE) && !rc)
      {

        if (ParmBlock->Length >= MINSLEN_VAR_UNDERSCORE)
          AccessUnderscore(HardwareColor(), GET, &ParmBlock->Underscore);
        else
          rc = ERROR_VIO_INVALID_LENGTH;
      }

      /*
      **  Get Video enable directly from the hardware
      */

      if ((ReqFlags&VARIABLE_VIDEOENABLE) && !rc)
      {

        if (ParmBlock->Length >= MINSLEN_VAR_VIDEOENABLE)
          AccessVideoEnable(HardwareColor(), GET, &ParmBlock->VideoEnable);
        else
          rc = ERROR_VIO_INVALID_LENGTH;
      }


      if (!rc && EnvBufferPassed)
      {

        /*
        **  Copy blink setting from caller's parmeter area to the env buffer
        */

        if (ReqFlags&VARIABLE_BLINK)
          Environment->CharAttrib.Blink = ParmBlock->Blink;

        /*
        **  Copy overscan from caller's parmeter area to the env buffer
        */

        if (ReqFlags&VARIABLE_OVERSCAN)
          Environment->CharAttrib.Overscan = ParmBlock->Overscan;

        /*
        **  Copy underscore from caller's parmeter area to the env buffer
        */

        if (ReqFlags&VARIABLE_UNDERSCORE)
          Environment->CharAttrib.Underscore =  ParmBlock->Underscore;

        /*
        **  Copy video enable from caller's parmeter area to the env buffer
        */

        if (ReqFlags&VARIABLE_VIDEOENABLE)
        {
          Environment->VideoEnable = ParmBlock->VideoEnable;
        }
      }
    }

    else
    {

      /*
      **  Requesting application is running in the background.
      */

      if (EnvBufferPassed)
      {

        /*
        **  Copy blink setting from env buffer to caller's parameter area
        */

        if (ReqFlags&VARIABLE_BLINK)
        {

          if (Environment->ModeData.fbType&MODE_FLAG_GRAPHICS)
            rc = ERROR_VIO_MODE;

          else
            ParmBlock->Blink = Environment->CharAttrib.Blink;
        }

        /*
        **  Copy overscan from env buffer to the caller's parameter area
        */

        if ((ReqFlags&VARIABLE_OVERSCAN) && !rc)
        {

          if (ParmBlock->Length >= MINSLEN_VAR_OVERSCAN)
          {
             ParmBlock->Overscan = Environment->CharAttrib.Overscan;
          }

          else
            rc = ERROR_VIO_INVALID_LENGTH;

        }

        /*
        **  Copy underscore from env buffer to the caller's parameter area
        */

        if ((ReqFlags&VARIABLE_UNDERSCORE) && !rc)
        {

          if (ParmBlock->Length >= MINSLEN_VAR_UNDERSCORE)
            ParmBlock->Underscore = Environment->CharAttrib.Underscore;

          else
            rc = ERROR_VIO_INVALID_LENGTH;

        }

        /*
        **  Copy video enable from env buffer to the caller's parameter area
        */

        if ((ReqFlags&VARIABLE_VIDEOENABLE) && !rc)
        {

          if (ParmBlock->Length >= MINSLEN_VAR_VIDEOENABLE)
            ParmBlock->VideoEnable = Environment->VideoEnable;

          else
            rc = ERROR_VIO_INVALID_LENGTH;

        }
      }

      else
        rc = ERROR_VIO_INVALID_PARMS;  /* Write-only, no env buffer         */

    }

/*
**  Copy code page ID
*/

    if ((ReqFlags&VARIABLE_CODEPAGE) && !rc)
    {

      if (ParmBlock->Length >= MINSLEN_VAR_CODEPAGE && EnvBufferPassed)
      {

        if (Environment->UserFont == USER_FONT_SELECTABLE)
          rc = ERROR_VIO_USER_FONT;

        else
          ParmBlock->CodePageID = Environment->CodePageID;
      }

      else
        rc = ERROR_VIO_INVALID_LENGTH;
    }

    /*
    **  Scrollable rectangle
    */

    if ((ReqFlags&VARIABLE_SCROLLRECT) && !rc)
    {

      if (ParmBlock->Length >= MINSLEN_VAR_SCROLLRECT && EnvBufferPassed)
      {
        ParmBlock->ScrlLeft = Environment->ScrollRect.Left;
        ParmBlock->ScrlTop = Environment->ScrollRect.Top;
        ParmBlock->ScrlRight = Environment->ScrollRect.Right;
        ParmBlock->ScrlBottom = Environment->ScrollRect.Bottom;
      }

      else
        rc = ERROR_VIO_INVALID_LENGTH;
    }

    /*
    **  Actual Screen Dimensions
    */

    if ((ReqFlags&VARIABLE_SCREENDIM) && !rc)
    {

      if (ParmBlock->Length >= MINSLEN_VAR_SCREENDIM && EnvBufferPassed)
      {
        ParmBlock->ScreenRows = Environment->ModeData.row;
        ParmBlock->ScreenCols = Environment->ModeData.col;
      }

      else
        rc = ERROR_VIO_INVALID_LENGTH;
    }
  }

  return (rc);
}

/*****************************************************************************
 *
 *  SUBROUTINE NAME: SetVariableInfo
 *
 *  DESCRIPTIVE NAME: Set selected variable information
 *
 *  FUNCTION: SetVariableInfo is called by BVS to set selected
 *            information about video state - blink versus background
 *            intensity, overscan color, underscore scan line, video
 *            enable. If the request specifies
 *            hardware the hardware and the environment buffer, if
 *            passed, will be updated.  Otherwise just the environment
 *            buffer, if passed, will be updated.
 *
 *  ENTRY POINT: SetVariableInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 270 )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 - Environment buffer only
 *                                     1 - Hardware also
 *                     USHORT Blink
 *                     USHORT Overscan
 *                     USHORT Underscore
 *                     USHORT VideoEnable
 *                     ULONG  DisplayMask
 *                     USHORT CodePageID
 *             ULONG Function ( Call vector table entry = 270 )
 *
 *  EXIT-NORMAL: AX = 0
 *               Selected variable information is set
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: AccessCursorBlink, AccessCursorOverscan
 *              AccessCursorUnderscore, AccessCursorVideoEnable
 *              AccessDisplayMask
 *
 ****************************************************************************/


USHORT EXPENTRY SetVariableInfo(PENVIRONMENT Environment,
                                PVDH_VARIABLE ParmBlock,
                                ULONG Function)

{
  USHORT rc,EnvBufferPassed;
  VDH_CURSOR CurParmBlock;
  USHORT DoSet;
  USHORT ReqFlags;


#ifdef CHAIN_VGA   /* @TSU00 */
  if (Environment->EnvFlags & ENVFLAG_VGAMODE)          //          
    return (ChainedSetVarInfo ( VGA_ENV(Environment),
                                ParmBlock,
                                Function));
#endif
  ReqFlags = ParmBlock->Flags;
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */

  if ((Function == FnSetVariableInfo) && /* Valid function request          */
     (ReqFlags & ~UPDATE_HARDWARE) &&    /* An option specified             */
     (EnvBufferPassed ||                 /* Env buffer passed               */
     (ReqFlags & UPDATE_HARDWARE)) &&    /* or is foreground                */
     !(ReqFlags & ~VALID_VARIABLE_FLAG))
  {                                      /* No illegal options              */

    /*
    **  Set blink versus background intensity if requested
    **  Set overscan (border) color if requested
    **  Set scan line for underscore if requested
    **  Set video enable if requested
    **  Set display mask (8514/A) if requested
    **  Set codepage if requested
    **  FORCE CODEPAGE SET (OVERRIDE MODE) IF REQUESTED
    **  SET SCROLLABLE REGION OF THE SCREEN
    */

    rc = NO_ERROR;                     /* Initialize no error               */

    /*
    **  If requesting DISPLAYMASK for non-8514/A, set error
    */

    if (ReqFlags&VARIABLE_DISPLAYMASK)
      rc = ERROR_VIO_INVALID_PARMS;

    /*
    **  Parameter checking for non-8514A adapters
    **  Check set blink versus background parameters
    */

    if (ReqFlags&VARIABLE_BLINK)
    {                                  /* No errors encountered,        */

      if (Environment->ModeData.fbType&MODE_FLAG_GRAPHICS)
        rc = ERROR_VIO_MODE;

      else
      {

        if (ParmBlock->Length < MINSLEN_VAR_BLINK)/* Missing parameter      */
          rc = ERROR_VIO_INVALID_LENGTH;

        else
          if (ParmBlock->Blink > 1)    /* Invalid parameter                 */
            rc = ERROR_VIO_INVALID_PARMS;
      }
    }

    /*
    **  Check set overscan (border) color parameters
    */

    if ((ReqFlags&VARIABLE_OVERSCAN) && !rc)
    {                                  /* No errors                         */

      if (ParmBlock->Length < MINSLEN_VAR_OVERSCAN)/* Missing parm          */
        rc = ERROR_VIO_INVALID_LENGTH;

      else

        if (ParmBlock->Overscan&~0x00FF)/* Invalid parm                     */
          rc = ERROR_VIO_INVALID_PARMS;

    }

    /*
    **  Check set scan line for underscore parameters
    */

    if ((ReqFlags&VARIABLE_UNDERSCORE) && !rc)
    {                                  /* No errors                         */

      if (ParmBlock->Length < MINSLEN_VAR_UNDERSCORE)/* Missing parm        */
        rc = ERROR_VIO_INVALID_LENGTH;

      else

        if (ParmBlock->Underscore > (MAX_FONT_SIZE-1))/* Invalid parm       */
          rc = ERROR_VIO_INVALID_PARMS;

    }

    /*
    **  Check set video enable parameters
    */

    if ((ReqFlags&VARIABLE_VIDEOENABLE) && !rc)
    {                                  /* No errors                         */

      if (ParmBlock->Length < MINSLEN_VAR_VIDEOENABLE)/* Missing parameter  */
        rc = ERROR_VIO_INVALID_LENGTH;

      if (!rc && (ParmBlock->VideoEnable > 1))/* Invalid parameter          */
        rc = ERROR_VIO_INVALID_PARMS;
    }

    /*
    **  Check set code page parameters
    */


    if ((ReqFlags&VARIABLE_CODEPAGE) && !rc)
    {                                  /* No errors                         */

      if (ParmBlock->Length < MINSLEN_VAR_CODEPAGE)
      {                                /* Missing parameter                 */

        rc = ERROR_VIO_INVALID_LENGTH;

      }

      else

        if (ParmBlock->CodePageID != ROM_FONT)
        {

          if ((ParmBlock->CodePageID != USER_FONT_SELECTABLE)
             && (ParmBlock->CodePageID != USER_FONT_NOT_SELECTABLE))
          {

            rc = ERROR_VIO_BAD_CP;     /* Code page not prepared            */
            /*
            ** Search for the appropiate code page font. If found, current
            ** environment font pointer will be set.
            */
            if (FindCPFont(Environment,
                           (USHORT) Environment->CharAttrib.YCharSize,  /* rows */
                           (USHORT) Environment->CharAttrib.XCharSize,  /* cols */
                           ParmBlock->CodePageID))
              rc = NO_ERROR;
          }
        }
    }

    /*
    **  Scrollable rectangle
    */

    if ((ReqFlags&VARIABLE_SCROLLRECT) && !rc)
    {

      if ((ParmBlock->Length >= MINSLEN_VAR_SCROLLRECT) &&
         (Environment->ModeData.col > ParmBlock->ScrlLeft) &&
         (Environment->ModeData.col > ParmBlock->ScrlRight) &&
         (Environment->ModeData.row > ParmBlock->ScrlTop) &&
         (Environment->ModeData.row > ParmBlock->ScrlBottom) &&
         (ParmBlock->ScrlLeft <= ParmBlock->ScrlRight) &&
         (ParmBlock->ScrlTop <= ParmBlock->ScrlBottom))

      {
        Environment->ScrollRect.Left = ParmBlock->ScrlLeft;
        Environment->ScrollRect.Top = ParmBlock->ScrlTop;
        Environment->ScrollRect.Right = ParmBlock->ScrlRight;
        Environment->ScrollRect.Bottom = ParmBlock->ScrlBottom;
        CurParmBlock.Length = sizeof(VDH_CURSOR);
        CurParmBlock.Flags = (ReqFlags&UPDATE_HARDWARE)|CURSOR_POSITION;

        DoSet = FALSE;

        if (!GetCursorInfo(Environment, &CurParmBlock, FnGetCursorInfo))
        {

          if (CurParmBlock.Column < Environment->ScrollRect.Left)
          {
            CurParmBlock.Column = Environment->ScrollRect.Left;
            DoSet = TRUE;
          }

          if (CurParmBlock.Column > Environment->ScrollRect.Right)
          {
            CurParmBlock.Column = Environment->ScrollRect.Right;
            DoSet = TRUE;
          }

          if (CurParmBlock.Row < Environment->ScrollRect.Top)
          {
            CurParmBlock.Row = Environment->ScrollRect.Top;
            DoSet = TRUE;
          }

          if (CurParmBlock.Row > Environment->ScrollRect.Bottom)
          {
            CurParmBlock.Row = Environment->ScrollRect.Bottom;
            DoSet = TRUE;
          }

          if (DoSet)
            SetCursorInfo(Environment, &CurParmBlock, FnSetCursorInfo);
        }
      }

      else
        rc = ERROR_VIO_INVALID_LENGTH;
    }


    if (!rc)
    {                                  /* No errors encountered             */

      /*
      **  Parameters are valid - Update environment buffer if it was passed
      **                       - Update hardware if in foreground
      */

      if (ReqFlags&VARIABLE_BLINK)
      {
        /*
        **  Set blink versus background intensity
        */
        if (EnvBufferPassed)
          Environment->CharAttrib.Blink = ParmBlock->Blink;
        if (ReqFlags&UPDATE_HARDWARE)
          AccessBlink(HardwareColor(), SET, &ParmBlock->Blink);

      }
      if (ReqFlags&VARIABLE_OVERSCAN)
      {
        if (EnvBufferPassed)
          Environment->CharAttrib.Overscan = ParmBlock->Overscan;
        if (ReqFlags&UPDATE_HARDWARE)
          AccessOverscan(HardwareColor(), SET, &ParmBlock->Overscan);
      }

      if (ReqFlags&VARIABLE_UNDERSCORE)
      {
        if (EnvBufferPassed)
          Environment->CharAttrib.Underscore = ParmBlock->Underscore;
        if (ReqFlags&UPDATE_HARDWARE)
          AccessUnderscore(HardwareColor(), SET, &ParmBlock->Underscore);
      }

      if (ReqFlags&VARIABLE_VIDEOENABLE)
      {
        if (EnvBufferPassed)
          Environment->VideoEnable = ParmBlock->VideoEnable;
        if (ReqFlags&UPDATE_HARDWARE)
          AccessVideoEnable(HardwareColor(), SET, &ParmBlock->VideoEnable);
      }
      if (ReqFlags&VARIABLE_CODEPAGE)
      {
        /*
        **  Copy code page ID from caller's parmeter area to the Environment buffer.
        **  Setting the CodePage makes the user font unselectable.
        */

        if ((ParmBlock->CodePageID != USER_FONT_SELECTABLE) &&
           (ParmBlock->CodePageID != USER_FONT_NOT_SELECTABLE))

        {
          Environment->CodePageID = ParmBlock->CodePageID;
          Environment->UserFont = USER_FONT_NOT_SELECTABLE;
        }
        if (ReqFlags&UPDATE_HARDWARE)
          rc = BVHAccessFont(SET,Environment->pFontData);
      }
    }
  }

  return (rc);
}
/*****************************************************************************
 *
 *  SUBROUTINE NAME: GetDBCSDisplayInfo
 *
 *  DESCRIPTIVE NAME: Return DBCS display infromation for current mode
 *
 *  FUNCTION: GetDBCSDisplayInfo is called by BVS to get information
 *            about the display width of characters on the screen.
 *            Characters may be one or two cells wide.  This routine
 *            returns the range of characters that require two cells
 *            on the screen to be displayed.
 *
 *  ENTRY POINT: GetDBCSDisplayInfo
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 261 )
 *
 *  INPUT: (Passed on stack)
 *             FAR *Environment ( Environment buffer for the session )
 *             FAR *ParmBlock
 *                     USHORT Length = length of this packet
 *                     USHORT Flags  = 0 - Environment buffer only
 *                                     1 - Hardware also
 *                     USHORT TableLen
 *                     USHORT TableOffset
 *             ULONG Function ( Call vector table entry = 261 )
 *
 *  EXIT-NORMAL: AX = 0
 *               The DBCS display information is returned
 *
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES: NONE
 *
 ****************************************************************************/


USHORT EXPENTRY GetDBCSInfo(PENVIRONMENT Environment,
                            PVDH_DBCS ParmBlock,
                            ULONG Function)
{
  USHORT rc;

  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */

  if ((Function == FnGetDBCSDisplayInfo))
  {                                    /* Valid function request            */
    rc = NO_ERROR;                     /* Initialize no error               */

    if (ParmBlock->Length == 2)        /* user wants table size             */
      ParmBlock->Length = 6;           /* return ParmBlock size             */

    else

      if (ParmBlock->Length >= 6)      /* user wants info                   */
        ParmBlock->CellTableLen = 0;   /* no Double cell characters         */

      else
        rc = ERROR_VIO_INVALID_PARMS;  /* Initialize to error               */
  }
  return rc;
}
