;*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.;
;*****************************************************************************/
        PAGE    58,132
        TITLE   WDHMAIN.Asm -- Windowable Device Handler

;/*****************************************************************************
;*
;* SOURCE FILE NAME = WDHMAIN.ASM
;*
;* DESCRIPTIVE NAME = BVS Device Handler for Windowable Sessions
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  This module contains the equivalent of the OS/2 1.1
;*              hooks for Windowable and Advanced VIO.
;*
;* FUNCTIONS    DevEnable, RetConfigInfo, InitEnv, WDHError
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;*   12/11/88  @T2        P3108   TPL, GreInitialize is necessary in DevEnable
;*   12/11/88  @T2                for VIO,
;*   12/19/88  @T7        P3258   TPL, Deadlock when MOUOPEN reenters VIOCALLS
;*   12/19/88  @T7                under DosStartSession when VIO or PM app is
;*   12/19/88  @T7                in a popup,
;*   02/17/89  @T17       SL01217 TPL, Save and restore AX around UpdateMode,
;*   02/21/89  @@A        B700261 STJ, Emulate GRows as 16*TRows,
;*   03/16/89  @T19       P6741   TPL, Avoid loading AVIO at boot time,
;*   03/22/89  @T22       B700622 TPL, Return codepage of 0 if DEVINFO is wrong
;*   03/25/89  @P1        D132     PL, DCR 132 changes
;*   04/10/89  D198               STJ, Install BvsPrtSc and BvsWrtTTY as
;*   04/10/89  D198               default VDH routines
;*   04/04/89  @T25       B700??? TPL, Sizzle work,
;*   04/20/89  @C16       B701177 CJJ, Stack parameters changed, PTR
;*   04/25/89  D261               STJ, Selector list moved to BVSGSEG
;*   05/09/89  @BB7       B702184 WKB, Restructure config data structure,
;*   05/11/89  @S10       B701174 STJ, Retain separate ENVB/LVB for each config
;*   05/18/89  @C22       HZ00183 CJJ, Update scrollable region in UpdateMode,
;*   05/30/89  @S13       B702717 STJ, Increase the ENVB size for AVio sessions
;*   07/19/89  @S18       B704913 STJ, Return ShieldInit return code,
;*   08/07/89  @C30       B706051 CJJ, Call DosGetCP to get prepared codepages
;*   08/18/89  @S25       B706860 STJ, Use 1.0 length as default for GetXXXX
;*   08/18/89  @S25               calls
;*   10/12/89  @B25       HM00772 WKB, Clear selector table data on DestroyPS
;*   10/24/89  @S38       B786295 STJ, Use 8-pel default size for non-25-line
;*   10/24/89  @S38       B786295 modes,
;*   11/02/89  @D549      D549    CJJ, Seltable changes due to rangeless sessions
;*   11/30/89  D811       D811    MS,  DCR 811
;*   01/22/90  @T52       D704    TPL, DCR 704 work
;*   03/16/90  @B48       B788584 WKB, Clear ax after use,
;*   07/06/90  @T71       B714347 TPL, Allow Shell to make AVIO calls, Hursley
;*   07/06/90  @T71       B714347 DCR 25177,
;*   09/14/90  AR07027    AR07027 WKB, Update PS attrbytes for avio
;*   09/14/90  AR07027            accordingly
;*   10/23/90  AR07042    AR07042 WKB, Handle WinInit and Gre errors,
;*   04/11/91  D1348      D1348   NAKADA, Enable DBCS support in Vio-Window
;*   06/05/91  @S38f      SM03642 WKB, Use 8-pel default size for > 25-line
;*   06/05/91  @S38f              modes
;*   02/06/92  @T80       B732479 TPL, Don't use the reserved register FS,
;*   02/21/92  @T83       AR12264 TPL, Avoid reallocation of the Env buffer
;*   02/21/92  @T83               for AVIO,
;*   09/14/94  @95837             WKB, pmwinp.inc -> pmwinx.inc
;****************************************************************************/

INCL_WINPROGRAMLIST  equ   1    ;needed for pmshl.inc defines      ;@D549
SESMGR               equ   1    ;needed for pmshl.inc defines      ;@D549

        include pmshl.inc               ;PM Shell equates for PROG_WIN  ;@D549
        include pmwinx.inc              ;@95837
        include pmaviop.inc
        include wdhequ.inc

        include bvscb.inc               ;BVS Control Blocks
        include bvsparms.inc            ;BVS Parameter Equates
        include error2.inc              ;CP/DOS Error Codes
        include infoseg.inc             ;DOS Info Seg
        .xlist
        include struc.inc               ;Structured Macros
        .list

        .386p                   ;@D549

        extrn   BUFFERUPDATE:FAR        ;Text Buffer Update
        extrn   GetCursorInfo:FAR       ;Get Cursor Info
        extrn   SetCursorInfo:FAR       ;Set Cursor Info
        extrn   GetMode:FAR             ;Get Mode
        extrn   SetMode:FAR             ;Set Mode
        extrn   GetVarInfo:FAR          ;Get Variable Info
        extrn   SetVarInfo:FAR          ;Set Variable Info
        extrn   GetDBCSInfo:FAR         ;Get DBCS Display Info          ;@P1
        extrn   GetLVBInfo:FAR          ;Get LVB size Info              ;@P1
        extrn   GetState:FAR            ;Get video date                 ;D811
        extrn   SetState:FAR            ;Set video state                ;D811

        extrn   DOSGETINFOSEG:FAR       ;Get InfoSeg selectors
        extrn   DOSGETCP:FAR            ;Dos Get CodePage

IFDEF D1348 ;get DBCS environment vectors.
        extrn   DOSGETDBCSEV:FAR        ; Get DBCS environment vectors
ENDIF ;D1348

        extrn   MOUGETEVENTMASK:FAR
        extrn   DOSOPEN:FAR             ;  @T7
        extrn   DOSCLOSE:FAR            ;  @T7
        extrn   DOSREALLOCSEG:FAR       ;@S13

        extrn   QueryConsole:NEAR
        extrn   ShieldInit:NEAR
        extrn   ShieldTerm:NEAR
        extrn   SecureSema4:NEAR
        extrn   ReleaseSema4:NEAR

        extrn   AVIOSUBS:FAR                                            ;@T52
        extrn   WININITIALIZE:FAR                                       ;@T52
        extrn   GREINITIALIZE:FAR                                       ;@T52

        extrn   BVHINSTANCE:WORD                                        ;@T52
        extrn   BVSGLOBAL:WORD                                          ;@T52

WDHGSEG SEGMENT WORD PUBLIC 'DATA' USE16 ;Global data segment for WDH   ;@T71

WDHGLOBAL       label   far                                             ;@T52
        PUBLIC  WDHGLOBAL                                               ;@T52
wdh_flags       dw      0               ;Global flags                   ;@T52
        PUBLIC  wdh_flags                                               ;@T52
wdh_LISsel      dw      0               ;Local Info Segment             ;@T52
        PUBLIC  wdh_LISsel                                              ;@T52
wdh_SISsel      dw      0               ;System Info Segment            ;@T52
        PUBLIC  wdh_SISsel                                              ;@T52
wdh_LastFS      dw      0               ;Last Full-screen Session   ;@T2;@T52
        PUBLIC  wdh_LastFS                                              ;@T52
wdh_keybufsize  dw      0               ;Keyboard Buffer Size           ;@T52
        PUBLIC  wdh_keybufsize                                          ;@T52
wdh_moubufsize  dw      0               ;Mouse Buffer Size              ;@T52
        PUBLIC  wdh_moubufsize                                          ;@T52
wdh_mouevntmask dw      0               ;Mouse Event Mask               ;@T52
        PUBLIC  wdh_mouevntmask                                         ;@T52
Mouse_Name      db      'MOUSE$',0,0    ;                 ;@T25;@T7;@T52;@T71
        PUBLIC  Mouse_Name                                              ;@T52
wdh_numcpids    dw      0               ;Number of prepared CPs     @C30;@T52
        PUBLIC  wdh_numcpids                                            ;@T52
wdh_cpidcurrnt  dw      0               ;current prepared codepage  @C30;@T52
        PUBLIC  wdh_cpidcurrnt                                          ;@T52
wdh_cpid1       dw      0               ;1st prepared codepage      @C30;@T52
        PUBLIC  wdh_cpid1                                               ;@T52
wdh_cpid2       dw      0               ;2nd prepared codepage      @C30;@T52
        PUBLIC  wdh_cpid2                                               ;@T52

ProtoEnv wdhenvironment <>              ;Prototype Environment
        PUBLIC  ProtoEnv                                                ;@T52

Config  configdata <,-1,-1,8000h,,,,size wdhenvironment,8000h,8000h,-8+size configdata,-4+size configdata,1,-1,1,-1> ;@BB7
        PUBLIC  Config                                                  ;@T52

bvh_instance    dd      BVHINSTANCE                                     ;@T52
        public  bvh_instance                                            ;@T52
bvs_global      dd      BVSGLOBAL                                       ;@T52
        public  bvs_global                                              ;@T52

;/*
;** Table of addresses of WDH functio
;*/

        public  FnTable
FnTable dd      BufferUpdate            ;Text Buffer Update
        dd      InitEnv                 ;Initialize Environment
        dd      WDHDummy                ;Save Environment
        dd      WDHDummy                ;Restore Environment
        dd      GetConfig               ;Return Config Info
        dd      GetDBCSInfo             ;Get DBCS Display Info          ;@P1
        dd      WDHError                ;Get Color Lookup Table
        dd      WDHError                ;Set Color Lookup Table
        dd      GetCursorInfo           ;Get Cursor Info
        dd      SetCursorInfo           ;Set Cursor Info
        dd      WDHError                ;Get Font
        dd      WDHError                ;Set Font
        dd      GetMode                 ;Get Mode
        dd      SetMode                 ;Set Mode
        dd      WDHError                ;Get Palette Registers
        dd      WDHError                ;Set Palette Registers
        dd      WDHError                ;Get Phys Buf
        dd      WDHError                ;Free Phys Buf
        dd      GetVarInfo              ;Get Variable Info
        dd      SetVarInfo              ;Set Variable Info
        dd      ExtVIO                  ;Extended VIO Calls
        dd      0                       ;Print Screen                   ;D198
        dd      0                       ;Write TTY                      ;D198
        dd      GetLVBInfo              ;Get LVB Info Call              ;@P1
        dd      GetState                ;Get video state                ;D811
        dd      SetState                ;Set video state                ;D811

WDHGSEG ENDS


R2CSEG  SEGMENT BYTE PUBLIC 'CODE' USE16                                ;@D549
        ASSUME  CS:R2CSEG

;/****************************************************************************
;*
;*  SUBROUTINE NAME: DevEnable
;*
;*  DESCRIPTIVE NAME: Initialize call vector table
;*
;*  FUNCTION: DevEnable is called via the Presentation Manager DDI
;*            interface.  The entry points of all VDH routines are
;*            appropriately entered into the call vector table.
;*            In addition, display adapter configuration is verified.
;*
;*  ENTRY POINT: DevEnable
;*    LINKAGE:   CALL FAR
;*
;*  INPUT: (Passed on stack)
;*             FAR * Parameter2  ( far pointer to parameter 2 packet )
;*                      FAR *Flags
;*                      FAR *CallVectorTable (BVS's call table)
;*             FAR * Parameter1  ( far pointer to parameter 1 packet )
;*                      ULONG EngineVersion ( Graphics engine ver. )
;*                      ULONG TableSize ( Length of call table )
;*             ULONG Subfunction ( Enable subfunction )
;*         (Referenced)
;*             VDHEntryPoint[] (global data - table of entry points )
;*             HugeShift (global data - huge shift value)
;*             hScreenDD (global data - screen device driver handle)
;*
;*  EXIT-NORMAL: AX = 0
;*               Entries in VDHEntryPoint table are copied to
;*                  CallVectorTable
;*
;*  EXIT-ERROR: AX = ERROR_VIO_BAD_ADAPTER or
;*                   DosGetHugeShift error or
;*                   DosOpen error
;*
;*  EFFECTS: Huge shift value is saved in HugeShift
;*           Screen device driver handle is saved in hScreenDD
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: RegSave, RegRest
;*
;****************************************************************************/

DEVENABLE PROC  FAR
        public  DEVENABLE

        Call    RegSave

        mov     ax,-1                   ;Preset PMERR_DEV_FUNC_NOT_INSTALLED
        .if     <<word ptr [bp].stk_function> eq 1> near and
        mov     ax,ERROR_VIO_INTERNAL_RESOURCE
        .if     <[si+4] ae fn_NextAvail> near ;Table large enough for this VDH

            push    WDHGSEG
            pop     ds
            .if     <ds:wdh_SISsel eq bx> ;This is 1st call by System ;@T52

                mov     si,offset FnTable ;DS:SI = local table
                les     di,dword ptr es:[di+4] ;Get Call Table Addr
                add     di,4*fn_BufferUpdate ;ES:DI = target table
                mov     cx,fn_NextAvail-fn_BufferUpdate ;# of entries ;D198
                .repeat             ;D198
                    .if     <<word ptr [si+2]> ne bx> ;Supported ;D198
                        movsd       ;Copy addr to table ;D198           ;@T71
                    .else           ;D198
                        add     si,4 ;D198
                        add     di,4 ;Skip this entry ;D198
                    .endif          ;D198
                .loop               ;D198

                push    ds
                push    offset wdh_SISsel  ;GDT selector save area  ;@T52
                push    ds
                push    offset wdh_LISsel  ;LDT selector save area  ;@T52
                Call    DOSGETINFOSEG ;Get selectors of info segments

                mov     es,ds:wdh_SISsel   ;ES = System Info Seg    ;@T52
                mov     al,es:[bx].SIS_MaxScrnGrp ;get max full-screen SGs
                cbw
                dec     al          ;determine the highest full-
                mov     ds:wdh_LastFS,ax ;@T2                       ;@T52

                push    6           ;Get Prepared CodePages      @C30
                push    ds          ;@C30
                push    offset wdh_cpidcurrnt ;@C30                 ;@T52
                push    ds          ;@C30
                push    offset wdh_numcpids ;@C30                   ;@T52
                Call    DOSGETCP    ;@C30
                shr     ds:wdh_numcpids,1 ;@C30                     ;@T52
            .endif

            lgs     si,ds:bvh_instance                              ;@T80

            mov     ax,ds:wdh_SISsel                                ;@T52
            mov     gs:[si].cmn_SISsel,ax                           ;@T80
            mov     gs:[si].ppbvs_gdtsel,ax                         ;@T80

            mov     ax,ds:wdh_LISsel                                ;@T52
            mov     gs:[si].cmn_LISsel,ax                           ;@T80
            mov     gs:[si].ppbvs_ldtsel,ax ;Setup for AVIO sessions;@T80

            mov     es,ax           ;@T2
            mov     ax,es:[bx].LIS_CurScrnGrp ;@T2
            .if     <ax a ds:wdh_LastFS> ;@T2                       ;@T52
                push    bx          ;@T2
                call    WININITIALIZE                               ;@T52
                .if     <zero ax>                                   ;AR07042
                    mov     ax,ERROR_VIO_INTERNAL_RESOURCE          ;AR07042
                .else                                               ;AR07042
                    sub     ax,ax                                   ;AR07042
                    sub     bx,bx       ;@T2                        ;AR07042
                    call    GREINITIALIZE                           ;@T52
                    .if     <zero ax>                               ;AR07042
                        mov     ax,ERROR_VIO_INTERNAL_RESOURCE      ;AR07042
                    .else                                           ;AR07042
                        sub     ax,ax                               ;AR07042
                    .endif                                          ;AR07042
                .endif
            .else                   ;@T2

                 sub     ax,ax
            .endif                  ;@T2
        .endif                                                      ;AR07042

        Call    RegRest
        ret     12
DEVENABLE ENDP

;/****************************************************************************
;*
;*  SUBROUTINE NAME: InitEnv
;*
;*  DESCRIPTIVE NAME: Initialize environment
;*
;*  FUNCTION: InitEnv is called by BVS to initialize the video
;*            environment during the creation of a new session.  This
;*            includes initializing the adapter hardware and/or the
;*            environment buffer.
;*
;*  ENTRY POINT: InitEnv
;*    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 257 )
;*
;*  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
;*             ULONG Function ( Call vector table entry = 257 )
;*         (Referenced)
;*             Modes[] (global data - table of supported video modes )
;*
;*  EXIT-NORMAL: AX = 0
;*               Environment buffer is initialized
;*
;*  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
;*
;*  EFFECTS: If requested, display adapter hardware is initialized to
;*           highest resolution mode supported.
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

InitEnv PROC    FAR
        public  InitEnv
        Call    RegSave

        mov     ax,[si].vp_ev_session   ;Session Id for ShellInit       ;@T71
        mov     dx,[si].vp_ev_selector  ;LVB selector

        push    WDHGSEG
        pop     ds
        .if     <ah eq PROG_WINDOWABLEVIO> near ;Windowed session?  ;@D549,@T71

            cbw                         ;Clear session tyye       ;@D549,@T71
            mov     si,offset ProtoEnv
            sub     di,di
            mov     cx,size wdhenvironment
            push    cx                  ;Save environment size          ;@T71
            shr     cx,2                ;Prepare to move dwords         ;@T71
            rep     movsd               ;Copy prototype enviroment      ;@T71
            pop     cx                  ;Restore environment size       ;@T71
            and     cx,3                ;                               ;@T71
            .if     <nz>                ;Has remainder?                 ;@T71
                rep     movsb           ;Move them 1 byte at a time     ;@T71
            .endif                      ;                               ;@T71
            mov     si,ax               ;Setup Session # for ShieldInit ;@T71

            mov     es:[bx].viops_Sel_LogicalVideoBuffer,dx

            mov     es:[bx].viops_CellByteSize,2
            mov     dword ptr es:[bx].viops_BufferRowCount,0500019h     ;@T71

            mov     dword ptr es:[bx].viops_TextCursorStartLine,070006h ;@T71

IFDEF D1348 ;get DBCS environment vector.

            mov     es:[bx].viops_FormatID,DefaultFormat
            mov     es:[bx].env_attrbytes,DefaultAttrCount

            mov     es:[bx].env_funcindx,DefaultFmtIndx

            ;/Get dbcs env vectors and set them to environment.
            push    ds                                      ;@A0p
            push    WDHGSEG                                 ;@A0p
            pop     ds                                      ;@A0p
            mov     ax,ds:[wdh_cpid1]                       ;@A0p
            pop     ds                                      ;@A0p
            mov     word ptr es:[bx].env_CtryCode+2,ax      ;@A0p

            mov     word ptr es:[bx].env_CtryCode,0
            push    DBCSEvBufSiz
            push    es
            mov     ax,offset env_CtryCode
            push    ax
            push    es
            mov     ax,offset env_DBCSEvBuff
            push    ax
            call    DosGetDBCSEv
                                        ;Ignore the r/c
                                        ;If r/c !=0 ==> env_DBCSEvBuff
                                        ;remains to be zero.

                                        ; env_DBCSEvBuff db DBCSEvBufSiz dup (0)
                                        ; env_CtryCode   dw 2 dup (0)
                                        ; env_CodePage   dw ?
            mov     ax,offset env_DBCSEvBuff
            mov     word ptr es:[bx].viops_lpNLSExt,ax  ;make pmavio.dll &
                                                        ;display.dll accesible
                                                        ;to dbcs env.
            mov     ax,es
            mov     word ptr es:[bx].viops_lpNLSExt+2,ax


            mov     ax,es:[bx].viops_BufferRowCount     ; calc LVB size
            mul     es:[bx].viops_BufferColumnCount
            mul     es:[bx].viops_CellByteSize
            mov     cx,ax                               ; if 64KB, cx = 0000h
            sub     ax,dx                               ; if 64KB, set 0FFFFh
            mov     es:[bx].env_lvbsize,ax

ENDIF ;D1348

;/*
;** Setup a one word work area and get the mouse event mask for the PSC
;*/

            push    bx                  ;Push work area on stack
            mov     di,sp               ;Get ptr to work area
            sub     eax,eax                                             ;@T71
            push    bx                  ;Reserve a word for Action Taken   @T7
            mov     dx,sp               ;                                  @T7
            push    ds                  ;Pointer to Device Name            @T7
            push    offset Mouse_Name   ;                             @T7;@T52
            push    ss                  ;Pointer to Device Handle returned @T7
            push    di                  ;                                  @T7
            push    ss                  ;Pointer to Action Taken returned  @T7
            push    dx                  ;                                  @T7
            push    eax                 ;                             @T7,@T71
            push    dword ptr 001h      ;Open Flag - fail if not there@T7,@T71
            push    0C2h                ;Open Mode - Private               @T7
            push    eax                 ;                             @T7,@T71
            call    DOSOPEN             ;                                  @T7

            .if     <zero ax>
                mov     dx,ss:[di]

                push    ds
                push    offset wdh_mouevntmask ;@ of returned event mask;@T52
                push    dx
                Call    MOUGETEVENTMASK

                push    dx              ;                                  @T7
                call    DOSCLOSE        ;                                  @T7
            .endif
            add     sp,4                ;Discard reserved word        @T7,@T71

;/*
;** Perform shield initialization for this sessi
;*/

            Call    ShieldInit          ;Get console handle

;/*
;** Perform initialization for AVIO session
;*/

        .else   near                    ;AVIO session

            mov     si,offset ProtoEnv+env_conhandle
            mov     di,env_conhandle
            mov     cx,(size wdhenvironment)-env_conhandle
            push    cx                  ;Save original size             ;@T71
            shr     cx,2                ;Prepare to move dwords         ;@T71
            rep     movsd               ;Copy end of prototype env.     ;@T71
            pop     cx                  ;Restore original size          ;@T71
            and     cx,3                ;                               ;@T71
            .if     <nz>                ;Has remainder?                 ;@T71
                rep     movsb           ;Move them 1 byte at a time     ;@T71
            .endif                      ;                               ;@T71

            Call    UpdateMode          ;Update the mode data

IFDEF D1348 ;initialize the attr count for AVIO

            mov     ax,es:[bx].viops_CellByteSize       ;get cell size
            dec     ax                                  ;conv to attrib count
            mov     es:[bx].env_attrbytes,al            ;save attrib count

                                                        ;function index for DBCS
                                                        ;BufferUpdate
            .if     <es:[bx].viops_CellByteSize eq PSCellSize>
                mov     es:[bx].env_funcindx,PSFmtIndx
            .elseif <es:[bx].viops_FormatID eq ExtPSFormat>
                mov     es:[bx].env_funcindx,ExtPSFmtIndx
            .else
                mov     es:[bx].env_funcindx,WorldFmtIndx
            .endif

            mov     ax,es:word ptr [bx].env_fullbufsz
            mov     cx,ax                               ;if 64KB, cx = 0000h
            sub     ax,es:word ptr [bx].env_fullbufsz+2 ;if 64KB, set 0FFFFh
            mov     es:[bx].env_lvbsize,ax

            ;/Get a default dbcs env vectors and set them to environment.
            ; These vectors are for lcid = 0(default).
            push    ds                                      ;@A0p
            push    WDHGSEG                                 ;@A0p
            pop     ds                                      ;@A0p
            mov     ax,ds:[wdh_cpid1]                       ;@A0p
            pop     ds                                      ;@A0p
            mov     word ptr es:[bx].env_CtryCode+2,ax      ;@A0p

            mov     word ptr es:[bx].env_CtryCode,0
            push    DBCSEvBufSiz
            push    es
            mov     ax,offset env_CtryCode
            push    ax
            push    es
            mov     ax,offset env_DBCSEvBuff
            push    ax
            call    DosGetDBCSEv
                                        ;Ignore the r/c
                                        ;If r/c !=0 ==> env_DBCSEvBuff
                                        ;remains to be zero.

                                        ; env_DBCSEvBuff db DBCSEvBufSiz dup (0)
                                        ; env_CtryCode   dw 2 dup (0)
                                        ; env_CodePage   dw ?
            mov     ax,offset env_DBCSEvBuff
            mov     word ptr es:[bx].viops_lpNLSExt,ax  ;make pmaviod.ll &
                                                        ;display.dll accesible
                                                        ;to dbcs env.
            mov     ax,es
            mov     word ptr es:[bx].viops_lpNLSExt+2,ax

ENDIF ;D1348

            sub     ax,ax               ;Force a good return code ;@S18
        .endif

        Call    RegRest
        ret     12
InitEnv ENDP

;/****************************************************************************
;*
;*  FUNCTION NAME: UpdateMode
;*
;*  DESCRIPTION  = Update the mode data from the PSCB
;*
;*  INPUT        =
;*  OUTPUT       =
;*
;*  EXIT-NORMAL  =
;*  EXIT-ERROR   =
;*
;****************************************************************************/

UpdateMode PROC NEAR
        public  UpdateMode
        push    ax                      ;@T17
        push    ds

        push    WDHGSEG                                                 ;@T52
        pop     ds
        lds     bx,ds:bvh_instance                                      ;@T52
        mov     ds,[bx].wdhi_pssel
        sub     bx,bx                                                   ;@T52
        mov     ax,[bx].viops_BufferRowCount ;Get number of rows        ;@@A
        mov     [bx].env_scrlbottom,ax  ;@C22
        dec     [bx].env_scrlbottom     ;@C22
        mov     [bx].env_rows,ax        ;Update mode data               ;@@A
        .if     <ax be 25>              ;@S38;@S38f
            shl     ax,1                ;Simulate 16*TRows=GRows ;@S38
        .endif                          ;@S38
        shl     ax,3                    ;Simulate 8*TRows=GRows ;@S38   ;@@A
        mov     [bx].env_grows,ax       ;Update mode data               ;@@A
        mov     ax,[bx].viops_BufferColumnCount ;Get number of cols
        mov     [bx].env_scrlright,ax   ;@C22
        dec     [bx].env_scrlright      ;@C22
        mov     [bx].env_cols,ax        ;Update mode data
        mul     [bx].env_rows           ;                               ;@@A
        mul     [bx].viops_CellByteSize ;Compute new buffer size

        mov     word ptr [bx].env_bufsize,ax
        mov     word ptr [bx].env_bufsize+2,dx
        mov     word ptr [bx].env_fullbufsz,ax
        mov     word ptr [bx].env_fullbufsz+2,dx ;Update mode data

        mov     ax,[bx].viops_CellByteSize                              ;AR07027
        dec     al                                                      ;AR07027
        mov     [bx].env_attrbytes,al                                   ;AR07027

IFDEF D1348 ;reset formatid.
            ;These two line are applied to the portion other than D2061.
        mov     ax,[bx].viops_FormatID
        mov     byte ptr [bx].env_attrformat,al ;Update mode data
ENDIF ;D1348

        pop     ds
        pop     ax                      ;@T17
        ret
UpdateMode ENDP

;/****************************************************************************
;*
;*  SUBROUTINE NAME: GetConfig
;*
;*  DESCRIPTIVE NAME: Return video adapter configuration information
;*
;*  FUNCTION: GetConfig 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)
;*             MemorySize (global data - amount of video memory)
;*
;*  EXIT-NORMAL: AX = 0
;*               Configuration data is returned to caller
;*
;*  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
;*
;*  EFFECTS: NONE
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

GetConfig PROC  FAR
        public  GetConfig
        Call    RegSave

        mov     ax,ERROR_VIO_INVALID_LENGTH
        .if     <[si].vp_parmlength eq 8> and
        les     di,dword ptr [si].vp_offset ;Get address of config data
        push    WDHGSEG
        pop     ds
        mov     si,offset Config        ;Get offset of config data
        mov     cx,es:[di].cf_length    ;Get length of config data
        .if     <cx a 1>

            mov     ax,cx
            .if     <al a <size configdata>> ;@S25
                mov     al,cf_confignum ;@S25
            .endif                      ;@S25

            push    di
            sub     al,size cf_length
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_adapter
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_display
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_memory
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size cf_confignum
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_version
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_flags
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_envsize
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size cf_fullsize
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size cf_partsize
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size cf_adapteroff
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_displayoff
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_emadapters
            .if     <ns>
                movsw
            .endif

            sub     al,size cf_emdisplays
            .if     <ns>
                movsw
            .endif

            mov     ax,di
            pop     di
            sub     ax,di
            .if     <al a 2>            ;More than just a length request
                stosw                   ;Update length in Mode data
            .endif

            sub     ax,ax               ;Set good return code
        .endif

        Call    RegRest
        ret     12
GetConfig ENDP

;/****************************************************************************
;*
;*  SUBROUTINE NAME: ExtVIO
;*
;*  DESCRIPTIVE NAME: Extended VIO subroutines
;*
;*  FUNCTION:  This routine processes the following Extended VIO
;*             functions:
;*
;*             43h     (067)   VioFree
;*             50h     (080)   VioAssociate
;*             51h     (081)   VioCreatePS
;*             52h     (082)   VioDeleteSetId
;*             53h     (083)   VioDestroyPS
;*             54h     (084)   VioGetDeviceCellSize
;*             55h     (085)   VioGetOrg
;*             56h     (086)   VioCreateLogFont
;*             57h     (087)   VioQuerySetIds
;*             58h     (088)   VioQueryFonts
;*             59h     (089)   VioSetDeviceCellSize
;*             5Ah     (090)   VioSetOrg
;*             5Bh     (091)   VioShowPS
;*             5Ch     (092)   VioGetPSAddress
;*             61h     (097)   Shield Termination
;*             62h     (098)   Query Console
;*
;*  ENTRY POINT: ExtVIO
;*    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entries )
;*
;*  INPUT: (Passed on stack)
;*             FAR *Environment ( Environment buffer for the session )
;*             FAR *ParmBlock
;*             ULONG Function ( Call vector table entry )
;*
;*  EXIT-NORMAL: AX = return code from Extended VIO function
;*
;*  EXIT-ERROR: None
;*
;*  EFFECTS: Reports that function is not valid for extended sessions.
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

ExtVIO  PROC    FAR
        public  ExtVIO
        Call    RegSave

        mov     dx,[si].p_viofunc
        .if     <dl eq -1>              ;Validate AVIO handle
            mov     ax,ERROR_VIO_INVALID_HANDLE ;Preset error

            push    WDHGSEG                                             ;@T52
            pop     gs                                                  ;@T80
            les     bx,gs:bvh_instance                                  ;@T80

            mov     di,[si].p_viohandle ;Get the handle number
            add     di,di
            mov     cx,es:[bx][di].addr_list ;Locate the PS selector    ;@T52
            .if     <ncxz>              ;PS selector in instance data
                mov     si,[si].vp_ev_session                      ;@T52,@T71
                mov     ds,cx                                           ;@T52
                mov     ax,ds:[viops_Sel_BVSControlBlock]               ;@T52
                mov     dx,ds:[viops_Sel_LogicalVideoBuffer]            ;@T52

                mov     es:[bx].ppbvs_bvssel,ax
                mov     es:[bx].ppbvs_pssel,cx
                mov     es:[bx].ppbvs_lvbsel,dx ;Local selectors for AVIO

                shl     si,2            ;adjust for dword offset  ;@D549,@T71
                lds     di,gs:bvs_global                          ;@D549;@T80
                add     di,si                                      ;@T52,@T71
                lds     di,ds:[di].bvsgSelTable                         ;@T52

                mov     ds:[di].selt_bvscb,ax                      ;@S10,@D549
                mov     ds:[di].selt_envb,cx                       ;@S10,@D549
                mov     ds:[di].selt_lvb,dx ;Update the BVS SelSeg ;@S10,@D549

                mov     es:[bx].bvsi_bvs,ax                             ;@T52
                mov     es:[bx].bvsi_env,cx                             ;@T52
                mov     es:[bx].bvsi_lvb,dx ;Update BVS Instance data   ;@T52

                sub     ax,ax
            .endif

        .else   near

            .if     <dl eq vf_QueryConsole>
                Call    QueryConsole
            .else   near
                .if     <dl eq vf_Free> or
                .if     <dl eq vf_ShieldTerm>
                    Call    ShieldTerm
                .else   near            ;AVIO calls
                    push    bp
                    .if     <dl e vf_DestroyPS> ;@B25
                        push    ds              ;@B25
                        push    si              ;@B25
                    .endif                      ;@B25


                    ;/*
                    ;****** AVIO depends on BP setup with the first    *****
                    ;****** struc member of oldstackframe in BVSCB.INC *****
                    ;*/

                    lea     bp,[si].p_regfs     ;@c16;@D549 needs to change from
                    mov     di,[si].vp_ev_selector
                    mov     si,dx       ;AVIO expects SI = function number

                    push    WDHGSEG
                    pop     ds
                    lds     bx,ds:bvh_instance                          ;@T52

                    mov     ax,ERROR_VIO_EXTENDED_SG
                    .if     <dl eq vf_CreatePS>

                        Call    AVIOSUBS                                ;@T52
                    .else               ;All other AVIO calls need CX = INSTSEG

                        .if     <dl ae vf_AssociateDC> and
                        .if     <dl be vf_GetPSAddress>

                            Call    SecureSema4
                            push    dx
                            Call    AVIOSUBS                            ;@T52
                            pop     dx
                            .if     <dl ne vf_DestroyPS>
                                .if     <dl eq vf_SetDevCellSz>
                                    Call    UpdateMode
                                .endif
                                Call    ReleaseSema4
                            .else               ;@B25
                                pop     si      ;@B25 recover ds,si if DestroyPS
                                pop     ds      ;@B25
                                mov     ax,[si].vp_ev_session ;Get SG # ;@B25;@T52
                                push    WDHGSEG                         ;@T52
                                pop     ds                              ;@T52
                                shl     ax,2    ;align dword offset ;@D549;@T52
                                lds     di,ds:bvs_global          ;@D549;@T52
                                add     di,ax                           ;@T52
                                lds     di,ds:[di].bvsgSelTable         ;@T52
                                sub     bx,bx                           ;@T52
                                mov     ds:[di].selt_bvscb,bx;@B25,@D549,@T71
                                mov     ds:[di].selt_envb,bx ;@B25,@D549,@T71
                                mov     ds:[di].selt_lvb,bx  ;@B25,@D549,@T71

                                sub     ax,ax                           ;@B48

                            .endif
                        .endif
                    .endif
                    pop     bp
                .endif
            .endif
        .endif

        Call    RegRest
        ret     12
ExtVIO  ENDP

;/****************************************************************************
;*
;*  SUBROUTINE NAME: WDHError
;*
;*  DESCRIPTIVE NAME: WDH Error Stub for unsupported functions
;*
;*  FUNCTION: This routine returns ERROR_VIO_EXTENDED_SG in response
;*            to all of the following functions:
;*
;*             106h   (262)   Get Color Lookup Table
;*             107h   (263)   Set Color Lookup Table
;*             10Ah   (266)   Get Font
;*             10Bh   (267)   Set Font
;*             10Eh   (270)   Get Palette Registers
;*             10Fh   (271)   Set Palette Registers
;*             110h   (272)   Get Phys Buf
;*             111h   (273)   Free Phys Buf
;*
;*  ENTRY POINT: WDHError
;*    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entries )
;*
;*  INPUT: (Passed on stack)
;*             FAR *Environment ( Environment buffer for the session )
;*             FAR *ParmBlock
;*             ULONG Function ( Call vector table entry )
;*
;*  EXIT-NORMAL: AX = ERROR_VIO_EXTENDED_SG
;*
;*  EXIT-ERROR: None
;*
;*  EFFECTS: Reports that function is not valid for extended sessions.
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

WDHError PROC   FAR
        public  WDHError

        mov     ax,ERROR_VIO_EXTENDED_SG
        ret     12
WDHError ENDP

;/****************************************************************************
;*
;*  SUBROUTINE NAME: WDHDummy
;*
;*  DESCRIPTIVE NAME: WDH Dummy Stub for unsupported functions
;*
;*  FUNCTION: This routine returns AX = 0 in response to all of the
;*            following functions, while actually doing nothing:
;*
;*             102h   (258)   Save Environment
;*             103h   (259)   Restore Environment
;*
;*  ENTRY POINT: WDHDummy
;*    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entries )
;*
;*  INPUT: (Passed on stack)
;*             FAR *Environment ( Environment buffer for the session )
;*             FAR *ParmBlock
;*             ULONG Function ( Call vector table entry )
;*
;*  EXIT-NORMAL: AX = 0
;*
;*  EXIT-ERROR: None
;*
;*  EFFECTS: Reports that function is was successful, but does nothing.
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

WDHDummy PROC   FAR
        public  WDHDummy

        sub     ax,ax
        ret     12
WDHDummy ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = RegSave/RegRest
;*
;* DESCRIPTION   = Save and Restore all registers and flags for VDH routines.
;*                 RegSave also sets BX=0, DS:SI=ParmBlock, and ES:DI=EnvBlock
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

RegSave PROC    NEAR                    ;Routine to save regs
        public  RegSave

        pop     ax                      ;Get return address
        pushf
        pushad                          ;changed from pusha, because if
                                        ;we call PM, high 16-bits can be trashed
        push    ds
        push    es                      ;Save all registers and flags
        push    gs                                                       ;@T80
        cld
        mov     bp,sp
        push    ax                      ;Restore return address

        les     di,dword ptr [bp].stk_envblock ;ES:DI = Environment Block

        push    WDHGSEG                                                 ;@T52
        pop     ds
        lds     bx,ds:bvh_instance                                      ;@T52
        mov     [bx].wdhi_pssel,es      ;Save PS selector in instance data

        lds     si,dword ptr [bp].stk_parmblock ;DS:SI = Parameter Block
        sub     bx,bx                   ;Get zero reg for code optimization

        ret
RegSave ENDP

RegSav2 PROC    NEAR                    ;Routine to save regs
        public  RegSav2

        pop     ax                      ;Get return address
        pushf
        pushad                          ;changed from pusha, because if
                                        ;we call PM, high 16-bits can be trashed
        push    ds
        push    es                      ;Save all registers and flags
        push    gs                                                      ;@T80
        cld
        mov     bp,sp
        push    ax                      ;Restore return address

        ret
RegSav2 ENDP

RegRest PROC    NEAR                    ;Routine to restore regs
        public  RegRest

        mov     [bp].stk_regax,ax       ;Save return code
        pop     ax
        xchg    [bp].stk_flags,ax       ;Swap return address w/flags
        push    ax

        popf
        pop     gs                                                      ;@T80
        pop     es
        pop     ds
        popad                           ;Restore all registers and flags

        ret
RegRest ENDP

R2CSEG  ENDS
        END

