;       SCCSID = @(#)smrstpev.asm       6.1 90/11/18
;       SCCSID @(#)smrstpev.asm 6.5 90/05/18
PAGE 60,132                             ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SMRSTPEV.ASM
;
; Subroutine Name:      APPSTOPSESSION
;
; Descriptive Name:     Process an Application Stop Session Request
;
; Function:     Process an applications request to terminate one or
;               all child sessions.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
;       Change History:
;
; Entry Point:
;       Linkage:  EXTRN APPSTOPSESSION:NEAR
;                       CALL    APPSTOPSESSION
; Inputs:
;       ES:DI   ReqBlock   Address to an application start request
;                          block.
;       DS      RDATA
;
; Exit Normal:
;       AX      ReturnCode Value = 0, Application request successful
;
; Exit Errors:
;       AX      ReturnCode error_smg_bad_reserve
;                          error_smg_not_baseshell
;                          error_smg_session_not_found
;
;                          DOSSMSGTERMINATE errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:        QDATA - Common data segment
;                                reqblock (SMRREQB.INC)
;                                     reqsessionid - Parent session ID
;                                     reqreturncode - Return code
;                                     rqtrmoption - Kill one or all children
;                                     rqtrmsessionid - Select option
;                       SESDATA - Commom segment with active session data
;                                 returned from DOSSMGETSTATUS (SMRSTAT.INC)
;                                 sessionchild - parent sessions first child
;                                 sessionrelative - next child/parent
;                       RDATA   - Common segment with router data
;                                 statusindex table (See SMRQSTAT.ASM)
;          Routines:
;
; External References:
;          Routines:    DOSSMSGTERMINATE
;
;************************************************************************
ifdef I1
;
;   IF (Kill all children)
;      DOSSMGETSGCB
;     ************************************************
;     *  If the requesting session is a debugger,    *
;     *  then look at ALL SGCBs to see if their      *
;     *  Debugger ID is the requesting session's ID  *
;     *  If not, then loop through the family chain  *
;     *  (ie. use SGCB_Relative to get to the next   *
;     *  session.                                    *
;     ************************************************
;     If Debugger
;       Get the Next SGCB
;     Else
;       Get First Child
;     EndIf
;
;     Repeat
;       CALL DOSSMGETSGCB
;
;       If No Error
;         If Parent isn't a debugger, OR
;         If this session is being debugged by the debugger
;           DOSKILLPROCESS
;         EndIf
;
;         Get the next SG to terminate
;         If Debugger
;           Get Next SGCB
;         Else
;           Get Next Relative
;         Endif
;       EndIf
;     Until we're back to Requestor OR
;     Until we didn't find a SGCB
;
;   Else                                ; Only kill 1 child
;     DOSSMGETSGCB
;     If No Error
;       DOSKILLPROCESS
;     EndIf
;   EndIf                               ; 1/all children to kill test
;************************************************************************
else

.386C
    EXTRN UsedScrnGrps : WORD

    EXTRN DOSSMGETSGCB     : FAR
    EXTRN DOSKILLPROCESS   : FAR
.xlist
    INCLUDE SMRSGCB.INC
    INCLUDE SMRREQB.INC                 ; Request block data definitions
.xcref
    INCLUDE ERROR2.INC                  ; Error code equates
    INCLUDE SMRRDATA.INC                ; Router data declarations
    INCLUDE STRUC.INC
.cref
.list

CODE SEGMENT WORD PUBLIC 'CODE' USE16
    ASSUME CS:CODE,DS:RDATA,SS:NOTHING,ES:NOTHING

    PUBLIC APPSTOPSESSION
APPSTOPSESSION PROC NEAR

    Local_Bytes EQU 4
    Local_Var1 EQU SS:[BP][-2]          ; Local variable on stack
    Local_Var2 EQU SS:[BP][-4]          ; Local variable on stack

    ENTER Local_Bytes,0
    PUSHA                               ; Save registers

    MOV  AX, ES:[DI].RqTrmOptions       ; Kill 1 or all children
    MOV  CX, ES:[DI].ReqSessionID       ; Requesting Session's ID
    MOV  DX, ES:[DI].RqTrmSessionID     ; Target Session's ID

    .IF  < AX eq 1 >                    ; If for all children
;     **************************************
;     *  Get address to ReqSessionID SGCB  *
;     **************************************
      LEA  SI, Local_Var2               ; @ return @ of SGCB
      PUSH SS
      PUSH SI
      PUSH CX                           ; Requesting Session's SGID
      PUSH SGID_Lookup + 8000H          ; Look up SGID not PID and      ;CJ10
      CALL DOSSMGETSGCB                 ;   don't serialize QueueRamSem

      LFS  SI, Local_Var2               ; FS:[SI] --> Requesting SGCB
;     ************************************************
;     *  If the requesting session is a debugger,    *
;     *  then look at ALL SGCBs to see if their      *
;     *  Debugger ID is the requesting session's ID  *
;     *  If not, then loop through the family chain  *
;     *  (ie. use SGCB_Relative to get to the next   *
;     *  session.                                    *
;     ************************************************
      MOV  DI, FS:[SI].SGCB_ParentExit  ; Get this flag into a register
      AND  DI, Parent_Is_Debugger       ; Is it a debugger? 0=No, 1=Yes
      .IF  < nz >                       ; Yes - look at ALL SGCB's
        LFS  SI, FS:[SI].SGCB_Next      ; Get next guy in queue
        MOV  DX, FS:[SI].SGCB_ID        ; Get it's SGID
      .ELSE                             ; Look only through family tree
        MOV  DX, FS:[SI].SGCB_FirstChild
      .ENDIF                            ; Debugger test

;     *****************************************
;     *  DX = SGID to possibly terminate      *
;     *  DI = Parent is Debugger?  YES or NO  *
;     *****************************************
      .REPEAT
        LEA  SI, Local_Var2
        PUSH SS
        PUSH SI
        PUSH DX                         ; 1st SG to terminate
        PUSH SGID_Lookup + 8000H        ; Look up SGID not PID and      ;CJ10
        CALL DOSSMGETSGCB               ;   don't serialize QueueRamSem

        .IF  < zero AX >                ; Found the SGCB                ;CJ10
          LFS  SI, Local_Var2           ; FS:[SI] --> SGCB to terminate

          .IF  < DI ne Parent_Is_Debugger > OR ; If Term. just family, OR
          .IF  < DI e Parent_Is_Debugger > AND ; If looking at ALL SGs, AND
          .IF  < FS:[SI].SGCB_DebuggerSID e BX > ; this guy is being debugged?
            PUSH AX                     ; Kill process and descendants  ;CJ10
            PUSH FS:[SI].SGCB_PID       ; Proc ID/command subtree ID
            CALL DOSKILLPROCESS
          .ENDIF

;         **********************************
;         *  Get the next SG to terminate  *
;         **********************************
          .IF  < DI e Parent_Is_Debugger >   ; Requesting Session is a debugger
            LFS  SI, FS:[SI].SGCB_Next       ; Get next guy in queue
            MOV  DX, FS:[SI].SGCB_ID         ; Get it's SGID
          .ELSE                              ; Look only through family tree
            MOV  DX, FS:[SI].SGCB_Relative   ; Next session in family
          .ENDIF                        ; Debugger test
        .ENDIF                          ; Found SGCB test
      .UNTIL < DL e BL > OR             ; Until we're back to Requestor OR
      .UNTIL < nonzero AX >             ; We didn't find a SGCB         ;CJ10

    .ELSE                               ; Only kill 1 child
      LEA  SI, Local_Var2
      PUSH SS
      PUSH SI
      PUSH DX                           ; Terminating SGID
      PUSH SGID_Lookup + 8000H          ; Look up SGID not PID and      ;CJ10
      CALL DOSSMGETSGCB                 ;   don't serialize QueueRamSem

      .IF  < zero AX >                  ; If asking for valid session   ;CJ10
        LFS  SI, Local_Var2             ; FS:[SI] --> Requesting SGCB
        PUSH 0                          ; Kill process and descendants
        PUSH FS:[SI].SGCB_PID           ; Proc ID/command subtree ID
        CALL DOSKILLPROCESS
      .ENDIF                            ; Found SGCB check
    .ENDIF                              ; 1/all children to kill test

    MOV  AX_Reg[-Local_Bytes], AX       ; Save AX on stack

    POPA

    LEAVE
    RET

APPSTOPSESSION ENDP

CODE ENDS
endif
    END
