;       SCCSID = @(#)ksg.asm	6.6 92/02/28
SCCSID  equ     "@(#)ksg.asm	6.6 92/02/28"
title Kernel Screen Group Services
page 55,132

; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

INCL_ERROR_H    EQU     1
INCL_ERROR2_H   EQU     1
.xcref
.xlist
include fnotask.inc
include dosseg.inc
include mi.inc
include basemaca.inc
include osmaca.inc
include osconst.inc
include dossymc.inc
include bseerr.inc
include protmode.inc
include seldesc.inc
include screen.inc
include struc.inc
include pgexport.inc
include vmexport.inc
include tkexport.inc
include except.inc
include sigdef.inc
include infoseg.inc
include curdir.inc
include dirent.inc
include find.inc
include sem.inc
include tkptda.inc
.list

        CpuMode 386
        ModName ksg,FNO_KSG_ASM


        ReferGlobal SISData,BYTE
        ReferGlobal _Sis2,BYTE
        ReferGlobal _Lis2,BYTE


        EXTRN   POST_SIGNAL: NEAR       ;to send terminate signal

        EXTRN32 VDMMSWITCHBGND
        EXTRN32 VDMMSWITCHFGND
        EXTRN32 _TKPidToPTDA
        EXTRN32 _TKScanTasks
        EXTRN32 _VMSGSValidate


CONSTANTS segment
        sgspid  dw      0               ;PID of screen-group switcher
CONSTANTS ends


        FARCODE HIGH3
HIGH3CODE segment

        ASSUME  DS:NOTHING, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING

page
;**********************************************************************
;*                                                                    *
;* SUBROUTINE NAME: w_DosSGSwitch                                     *
;*                                                                    *
;* DESCRIPTIVE NAME: Switch foreground Screen Group                   *
;*                                                                    *
;* FUNCTION:  This routine validates the physical video buffers'      *
;*            selectors for the new foreground screen group           *
;*            and invalidates the physical video buffers' selectors   *
;*            for the old foreground screen group.                    *
;*                                                                    *
;* NOTES:                                                             *
;*                                                                    *
;* ENTRY POINT: SGSwitch                                              *
;*    LINKAGE:  faronly                                               *
;*                                                                    *
;* INPUT:                                                             *
;*             AL     Old foreground screen group                     *
;*             AH     Flags:                                          *
;*                    10000000B (80H) - Don't do invaidation          *
;*                    01000000B (40H) - VDM Session                   *
;*             BL     New foreground screen group                     *
;*             BH     Flags:                                          *
;*                    10000000B (80H) - Don't do vaidation            *
;*                    01000000B (40H) - VDM Session                   *
;*             DX     Debugger screen group or ZERO                   *
;*                                                                    *
;* EXIT-NORMAL:    C  clear                                           *
;*                                                                    *
;* EXIT-ERROR:     AX = ERROR_INVALID_FUNCTION                        *
;*                 C  set                                             *
;*                                                                    *
;* EFFECTS:                                                           *
;*                                                                    *
;* INTERNAL REFERENCES:                                               *
;*    ROUTINES:    ksgTaskSearch                                      *
;*                                                                    *
;* EXTERNAL REFERENCES:                                               *
;*    ROUTINES:                                                       *
;*                                                                    *
;**********************************************************************
;
;  get caller's Pid
;  if first invocation
;    save Pid
;    set flag
;  else
;    if not shell Pid
;      return error
;    endif
;  endif
;
;  if to do outgoing invalidation
;    if not VDM
;      call ksgTaskSearch to do it
;    else (it is a VDM)
;      call VDMMSwitchBgnd
;    endif
;  endif
;
;  update global info seg's foreground SG
;
;  if to do incoming validation
;    if not VDM
;      call ksgTaskSearch to do it
;    else (it is a VDM)
;      call VDMMSwitchFgnd
;    endif
;  endif
;
;  if to do debugger validation/invalidation
;    if we're to validate
;      set up validate register
;    else
;      set up invalidate register
;    endif
;    call ksgTaskSearch to do it
;  endif
;
;  return success
;
;******************************************************************************
page

Procedure w_DosSGSwitch,faronly
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

        call    ksgValidate
        jc      sgs_exit
        ASSUME  DS:DOSGROUP, ES:TASKAREA

        push    dx                      ;save debugger SGID
        sub     dl,dl                   ; indicate remove access
        .ERRNZ  VMSGS_REMOVE
        call    ksgTaskSearch           ;AL=outgoing SGID, AH=flags, DL=selflag

        DosContext DS
        mov     ax,bx
        mov     SISData.SIS_CurScrnGrp,al
        mov     fs,[_Sis2].is_sel       ;set new foreground SG
        mov     fs:SIS_CurScrnGrp,al    ;update infoseg copy

        mov     dl,VMSGS_ADD            ; add access
        call    ksgTaskSearch           ;AL=incoming SGID, AH=flags, DL=selflag

        pop     ax                      ;restore debugger SGID
        or      ah,20h                  ;indicate this IS a debugger SGID
        sub     dl,dl
        .ERRNZ  VMSGS_REMOVE
        test    ah,40h                  ;do validation? (OVERLOADED BIT! -JTP)
        jz      sgs_dbg                 ;no
        inc     dx                      ;yes
        .ERRNZ  VMSGS_ADD-VMSGS_REMOVE NE 1
sgs_dbg:
        and     ah,not 40h              ;CLEAR OVERLOADED BIT
        call    ksgTaskSearch           ;go do it
        clc

sgs_exit:
        ret
EndProc w_DosSGSwitch


page
;**********************************************************************
;*                                                                    *
;* SUBROUTINE NAME: w_DosSGSwitchMe                                   *
;*                                                                    *
;* DESCRIPTIVE NAME: Put Process in Screen Group                      *
;*                                                                    *
;* FUNCTION:  Switch the caller into the specified screen group       *
;*                                                                    *
;* NOTES:                                                             *
;*                                                                    *
;* ENTRY POINT: SGSwitchMe                                            *
;*    LINKAGE:  faronly                                               *
;*                                                                    *
;* INPUT:                                                             *
;*             AX     Screen Group Number                             *
;*             BX     Option  0  SG is new foreground                 *
;*                            1  SG is not new foreground             *
;* EXIT-NORMAL:    C  clear                                           *
;*                                                                    *
;* EXIT-ERROR:     AX = ERROR_INVALID_FUNCTION                        *
;*                 C  set                                             *
;*                                                                    *
;* EFFECTS:                                                           *
;*                                                                    *
;* INTERNAL REFERENCES:                                               *
;*    ROUTINES:                                                       *
;*                                                                    *
;* EXTERNAL REFERENCES:                                               *
;*    ROUTINES:                                                       *
;*                                                                    *
;* CHANGE HISTORY:                                                    *
;*   J200434 01/14/92  Allow HardError to call this routine.          *
;*                                                                    *
;**********************************************************************

;
;
;  get caller's Pid
;  if first invocation
;    save Pid
;    set flag
;  else
;    if not shell Pid
;      return error
;    endif
;  end
;  save SGID in PTDA
;  if set foreground
;    update global info seg
;  end
;  return success
;

page
Procedure w_DosSGSwitchMe,faronly
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

        push    ax                                                      ;J200434
        call    ksgValidate
        pop     ax                                                      ;J200434
;J200434jc      swsm_exit
        ASSUME  DS:DOSGROUP, ES:TASKAREA

        .if  < c >                                 ;not Shell           ;J200434
            mov     fs, [_Lis2].is_sel             ;check if HardError  ;J200434
            .if   < fs:LIS_CurScrnGrp ne 0 >  or   ;FullScreen #0       ;J200434
            .if   < fs:LIS_ProcType ne LIS_PT_FULLSCRN >                ;J200434
                .if < nonzero ax >                                      ;J200434
                    mov     ax,ERROR_INVALID_FUNCTION                   ;J200434
                    stc                            ;not Shell or HardErr;J200434
                    jmp    short swsm_exit         ;return error        ;J200434
                .endif                                                  ;J200434
            .endif                                                      ;J200434
            clc                                    ;clear carry         ;J200434
        .endif                                                          ;J200434

        xor     ah,ah
        mov     es:[TKOPTDA.Cons_Loc].Scrn_Num,al
        mov     es:[TKOPTDA.ptda_infoseg].LIS_CurScrnGrp,ax
        mov     fs,[_Lis2].is_sel
        mov     fs:LIS_CurScrnGrp,ax

        .if  <zero bx>                  ;if set new foreground
          mov  SISData.SIS_CurScrnGrp,al
          mov  fs,[_Sis2].is_sel
          mov  fs:SIS_CurScrnGrp,al     ;update infoseg copy
        .endif

        ; carry remains clear

swsm_exit:
        ret
EndProc w_DosSGSwitchMe


page
;**********************************************************************
;*                                                                    *
;* SUBROUTINE NAME: w_DosSGSwitchProc2                                *
;*                                                                    *
;* DESCRIPTIVE NAME: Switch Process to a Screen Group                 *
;*                                                                    *
;* FUNCTION:  This routine marks a process as belonging to            *
;*            the specified screen group.                             *
;*                                                                    *
;* NOTES:                                                             *
;*                                                                    *
;* ENTRY POINT: SGSwitchProc                                          *
;*    LINKAGE:  faronly                                               *
;*                                                                    *
;* INPUT:                                                             *
;*             AX     Process ID                                      *
;*             BX     Screen Group Number                             *
;*             DX     Process Type                                    *
;*                                                                    *
;* EXIT-NORMAL:    C  clear                                           *
;*                                                                    *
;* EXIT-ERROR:     AX = ERROR_INVALID_FUNCTION                        *
;*                 C  set                                             *
;*                                                                    *
;* EFFECTS:                                                           *
;*                                                                    *
;* INTERNAL REFERENCES:                                               *
;*    ROUTINES:    None                                               *
;*                                                                    *
;* EXTERNAL REFERENCES:                                               *
;*    ROUTINES: _TKPidToPtda                                          *
;*                                                                    *
;* CHANGE HISTORY:                                                    *
;*   @D981 08/31/90  Allow HardError to call this routine.            *
;*                                                                    *
;**********************************************************************

;
;  call ksgValidate             ;check if Shell calling us
;  if ( not Shell )
;    if ( not HardError )
;      return error
;    endif
;  endif
;
;  call PidToPtda               ;get per task data area
;  if ( error )
;     return error
;  endif
;  update Ptda (current screen group and process type)
;  if ( we are current process )
;     update infoseg (current sg and process type)
;  endif
;  clear carry and AX
;
page

        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING
Procedure w_DosSGSwitchProc2,faronly
LocalVar pptda,DWORD
        EnterProc

        push    ax                                                      ;J200434
        call    ksgValidate
        pop     ax                                                      ;J200434
;@D981  jc      short sgsp_exit         ;return
        ASSUME  DS:DOSGROUP, ES:TASKAREA

        .if  < c >                                 ;not Shell           ;@D981
            mov     fs, [_Lis2].is_sel             ;check if HardError  ;@D981
            .if   < fs:LIS_CurScrnGrp ne 0 >  or   ;FullScreen #0       ;@D981
            .if   < fs:LIS_ProcType ne LIS_PT_FULLSCRN >                ;@D981
                 mov     ax,ERROR_INVALID_FUNCTION                      ;J200434
                 stc                            ;not Shell or HardError ;@D981
                 jmp    short sgsp_exit         ;return error           ;@D981
            .endif                                                      ;@D981
            clc                                    ;clear carry         ;J200434
        .endif                                                          ;@D981

;       (AX) = PID
;       (BX) = new screen group

        SaveReg <ds,dx>
        FlatContext <ds,es>,dx
        movzx   eax,ax
        SSToDS  edx,pptda
        CCALL32 _TKPidToPTDA,<eax,edx>
        RestoreReg <dx,ds>
        ASSUME  DS:DOSGROUP
        or      eax,eax
        mov     ax,ERROR_INVALID_PROCID ;in case PidToPtda failed
        jnz     sgsp_exit

        mov     ecx,pptda               ; (ECX) = ptda of process to mark

        xor     bh, bh
        mov     es:[ecx.Cons_Loc].Scrn_Num, bl
        mov     es:[ecx.ptda_infoseg].LIS_CurScrnGrp,bx
        mov     es:[ecx.ptda_infoseg].LIS_ProcType,dl ;set process type
        or      es:[ecx.ptda_ForcedActions],TK_FF_PIB ;force PIB update

        mov     ax, es:[ecx].ThisPTDA
        cmp     ax, ss:[TKOPTDA.ThisPTDA];are we marking ourself?
        jne     sgsp_noupdate           ;no, don't update copy

        mov     fs, [_Lis2].is_sel      ;update infoseg copy
        mov     fs:LIS_CurScrnGrp,bx
        mov     fs:LIS_ProcType,dl

sgsp_noupdate:
        clc
sgsp_exit:
        LeaveProc
        RETC
EndProc w_DosSGSwitchProc2


page
;**********************************************************************
;*                                                                    *
;* SUBROUTINE NAME: KSGKillProcess                                    *
;*                                                                    *
;* DESCRIPTIVE NAME: Screen group kill                                *
;*                                                                    *
;* FUNCTION:  This provides the system default response to            *
;*            SIGINTR and SIGBREAK (Ctrl-break) which is to terminate *
;*            all processes within a screen group                     *
;*                                                                    *
;* NOTES:                                                             *
;*                                                                    *
;* ENTRY POINT: KSGKillProcess                                        *
;*    LINKAGE:  Near                                                  *
;*                                                                    *
;* INPUT:                                                             *
;*             None                                                   *
;*                                                                    *
;* EXIT-NORMAL:                                                       *
;*                 C  clear - processes terminated                    *
;*                                                                    *
;* EXIT-ERROR:                                                        *
;*                 C  set - no action taken                           *
;*                                                                    *
;* EFFECTS:                                                           *
;*                                                                    *
;* INTERNAL REFERENCES:                                               *
;*    ROUTINES:    None                                               *
;*                                                                    *
;* EXTERNAL REFERENCES:                                               *
;*    ROUTINES:    w_KillProcess                                      *
;*                                                                    *
;**********************************************************************

;
;  if <SGID ae first user screen group> and
;  if <SGID b maximum screen group>
;    POST_SIGNAL (kill all processes in the screen group)
;    clear carry
;  else
;    stc
;  endif
;
page

Procedure KSGKillProcess
        ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING

        pusha
        push    ds
        push    es

        DosContext ds                   ;get foreground SGID
        mov     dl,SISData.SIS_CurScrnGrp
        xor     dh,dh
        .if     <dx ae 4> and           ;user screen group in foreground
        .if     <dl b <SISData.SIS_MaxScrnGrp>>
          xor   ah,ah                   ;Terminate signal
          mov   al,SIGTERM
          xor   cx,cx                   ;signal argument
          mov   bl,3                    ;all processes in screen group
          call  POST_SIGNAL             ;kill all processes in SG
          clc                           ;clear carry to indicate action taken
        .else
          stc                           ;set carry to indicate no action
        .endif

        pop     es
        pop     ds
        popa
        ret
EndProc KSGKillProcess


page
;**********************************************************************
;*                                                                    *
;* SUBROUTINE NAME: ksgTaskSearch                                     *
;*                                                                    *
;* DESCRIPTIVE NAME: Search for tasks in screen group                 *
;*                                                                    *
;* FUNCTION:  This routine searches the task table for all tasks      *
;*            in the specified screen group and calls _SELMarkVB      *
;*            to do the validation/invalidation of all physical       *
;*            video buffers'selectors.                                *
;*                                                                    *
;* NOTES:                                                             *
;*                                                                    *
;* ENTRY POINT: ksgTaskSearch                                         *
;*    LINKAGE:  Near                                                  *
;*                                                                    *
;* INPUT:                                                             *
;*             (AL)   SGID                                            *
;*             (AH)   Bit 8 clear for validation, set for none        *
;*                    Bit 7 set if VDM (no validation, just switch)   *
;*                    Bit 6 set if debugger SGID                      *
;*             (DL)   Type of validation, if any:                     *
;*                    SELVB_VALIDATE or SELVB_INVALIDATE              *
;*                                                                    *
;* EXIT-NORMAL:    None                                               *
;*                                                                    *
;* EXIT-ERROR:     None                                               *
;*                                                                    *
;* EFFECTS:    EAX, ECX, EDX, DS, ES, Flags                           *
;*                                                                    *
;* INTERNAL REFERENCES:                                               *
;*    ROUTINES:    _VMSGSValidate, via _TKScanTasks                   *
;*                                                                    *
;* EXTERNAL REFERENCES:                                               *
;*    ROUTINES:    _TKScanTasks                                       *
;*                                                                    *
;**********************************************************************


Procedure ksgTaskSearch,near,local
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

        LocalVar ts_fl,DWORD            ;_VMSGSValidate information

        EnterProc
        test    ah,80h                  ;do invalidation?
        jnz     tksrch_exit             ;no

        cmp     al,2                    ;harderr, shell or popup SG?
        jbe     tksrch_exit             ;yes

        FlatContext <ds,es>,cx          ;set up FLAT selectors

        test    ah,40h                  ;is SG a VDM?
        jz      tksrch_notvdm           ;no

        movzx   eax,al                  ;push SGID (only care about low byte)
        .if <zero dl>
         CCALL32 VDMMSWITCHBGND,<eax>,,pascal
        .else
         CCALL32 VDMMSWITCHFGND,<eax>,,pascal
        .endif

        .ERRNZ  VMSGS_REMOVE
        jmp     short tksrch_exit

tksrch_notvdm:
        movzx   ecx,al                  ;save SGID

        movzx   edx,dl
        mov     [ts_fl],edx            ;set up _VMSGSValidate information buffer

        test    ah,20h                  ;debugger SGID?
        jz      tksrch_notdbg           ;no

        or      [ts_fl], VMSGS_DBG      ; Turn on debugger flag

tksrch_notdbg:

;       scan all tasks in screen group:
;       _TKScanTasks(scanflags, groupid, &worker, &data)

        SSToDS  eax,[ts_fl]
        CCALL32 _TKScanTasks,\
            <<TK_TG_SCRN or TK_SF_EXEC>,ecx,<offset FLAT:_VMSGSValidate>,eax>

tksrch_exit:
        LeaveProc
        ret
EndProc ksgTaskSearch


page
;**********************************************************************
;*                                                                    *
;* SUBROUTINE NAME: ksgValidate                                       *
;*                                                                    *
;* DESCRIPTIVE NAME: KSG Caller Validation                            *
;*                                                                    *
;* FUNCTION:  This records the PID of the first caller, and verifies  *
;*            that subsequent callers are the same.                   *
;*                                                                    *
;* NOTES:                                                             *
;*                                                                    *
;* ENTRY POINT: ksgValidate                                           *
;*    LINKAGE:  Near                                                  *
;*                                                                    *
;* INPUT:                                                             *
;*              None                                                  *
;*                                                                    *
;* EXIT-NORMAL:                                                       *
;*              Carry is clear                                        *
;*              DS is DosContext                                      *
;*              ES is TaskContext                                     *
;*              CX is PID of caller                                   *
;*                                                                    *
;* EXIT-ERROR:                                                        *
;*              Carry is set                                          *
;*              AX contains error code                                *
;*                                                                    *
;* EFFECTS:                                                           *
;*                                                                    *
;* INTERNAL REFERENCES:                                               *
;*    ROUTINES:    None                                               *
;*                                                                    *
;* EXTERNAL REFERENCES:                                               *
;*    ROUTINES:    None                                               *
;*                                                                    *
;**********************************************************************

Procedure ksgValidate,near,local
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

        DosContext ds
        TaskContext es
        mov     cx,es:[TKOPTDA.ptda_Pid];get caller's PID

        cmp     [sgspid],0              ;is this first invocation?
        jne     ksgval_notfirst         ;no

        mov     [sgspid],cx             ;save caller's PID
        or      es:[TKOPTDA.ProcFlag],1 ;SG-switch process;  we should not
                                        ; get a rem-media buffer
ksgval_notfirst:
        cmp     cx,[sgspid]             ;are we the session manager?
        je      ksgval_exit             ;yes

        stc                             ;return carry set on error
        mov     ax,ERROR_INVALID_FUNCTION

ksgval_exit:
        ret
EndProc ksgValidate

HIGH3CODE ends
        end
