;       SCCSID = @(#)smgcexit.asm       6.5 92/02/21
PAGE 60,132                             ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;**************************************************************************
;
; Source File Name:     SMGCEXIT.ASM
;
; Subroutine Name:      DOSSMCHILDEXIT
;
; Descriptive Name:     Session Manager's child process died.
;
; Function:     Receives notification that all processes associated
;               with a screen group have terminated. The screen group
;               is marked available for use and the queue element
;               associated with the screen group is removed from the
;               active screen group queue.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   The queue must be protected by a RAM
;                       semaphore from the calling subroutine.
;
; Change History:
;  @TL7 - 04/05/90  PTR B712376 - Enable for MMIO
;  @CJ10  05/04/90  PTR B712103 Hot Keying performance too slow.
;  @D1088 07/07/90  DCR 1088 Add support for special needs.
;  @MHW   09/13/90  PTR B715818 In-line performance (MMIO) hook support
;  CJ28   05/30/91  PTR J200265 Fix to allow DBCS monitor installation.
;  @GDW   08/26/91  PTR B725436 Fix to allow semaphore loop on INTERUPT
;  CJ42   09/09/91  PTR B725639 DosSGFree calls VioFree so we don't need to.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMCHILDEXIT : NEAR
;                       CALL    DOSSMCHILDEXIT
;
; Inputs:
;       DX      SGID       Terminated screen group ID
;       BX      RetCode    Terminated process return code
;       ES:DI   TermSGCB   Terminated screen group queue element
;       DS      RDATA
;
; Exit Normal:
;       None
;
; Exit Errors:
;       None
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Routines:    DOSSMGETSGQUEUE
;                       DOSSMDELSGQUEUE
;
; External References:
;          Routines:    DOSSMAPPNOTIFY
;                       DOSSGFREE
;                       DOSSEMCLEAR
;                       DOSSEMREQUEST
;                       DOSDEVIOCTL
;                       DOSSMNOTIFYDD
;
;************************************************************************
ifdef I1
;
;   DOSSETPRTY (Boost priority by 1)
;   DOSSEMCLEAR (Access queue semaphore)
;
;   IF (exec failure)
;      Push exec failure parameter
;   ELSE
;      DOSSEMREQUEST (Get Popup PopUpBlockSem)
;      DOSSEMREQUEST (Block router on qhshellramsem)
;      Push Normal Termination Parameter
;   ENDIF
;
;   DOSSMAPPNOTIFY (Notify Shell with appropriate parameter from above)
;
;   DOSSEMREQUEST (Wait for active session queue)
;   DOSSETPRTY (Lower priority by 1)
;
;   IF (familytype e parent)
;      DOSSMGETSGCB (Get first child's SGID)
;      REPEAT
;         Change type to NOT child
;         DOSSMGETSGCB
;         Next relative
;      UNTIL (sgid e parent sgid)
;   ENDIF
;
;   DOSSMDELSGCB (Remove session from SGCB queue)
;
;   IF (Winthorn is present)
;     WINENDSESSION(Notify Winthorn of termination)
;   ENDIF
;   IF (Not a windowed session) AND
;   IF (Not a PM session)
;     IF (Full Screen session)
;       DOSSGFREE (Notify screen switcher session terminated)
;     ELSEIF (VDM session) OR
;     IF (Windowed VDM type)
;       IF (WinDestroyyconsole is there)
;         WINDESTROYCONSOLE
;       ENDIF
;     ENDIF
;     IF (mousehandle <> 0)
;         DOSDEVIOCTL (Free mouse)
;     ENDIF
;         DOSDEVIOCTL (Free keyboard)
;     ENDIF
;   ELSE
;      VIOFREE (notify VIO on termination)
;   ENDIF
;
;   DOSSMNOTIFYDD (Termination notification)
;   IF (Not an exec failure)
;      DOSSFSRAMSEMCLEAR (Unblock Popups)
;      DOSSFSRAMSEMCLEAR (Unblock router)
;   ENDIF
;
;**************************************************************************
else

.386C
    EXTRN PM_Present              : BYTE   ; Check for presence of PM
    EXTRN QHKEYBDHANDLE           : WORD   ; Handle to the keyboard
    EXTRN QHMOUSEHANDLE           : WORD   ; Handle to the mouse
    EXTRN PopUpBlockSem           : BYTE
    EXTRN SMRoutSem               : BYTE
    EXTRN WinDestroyConsole       : DWORD  ; PMVIOP routine
    EXTRN WinEndSession           : DWORD  ; Tell PM that session died
    EXTRN XitMseParm1             : WORD   ; mouse parm., screen group ID
    EXTRN XitMseParm2             : WORD   ; mouse parm., terminate func.
    EXTRN NotDD_DosDev_Data_Len   : WORD   ; Data for DosSMNotifyDD     ;@D1088
    EXTRN NotDD_Notification_Type : WORD                                ;@D1088
    EXTRN NotDD_InSG_or_OutType   : WORD                                ;@D1088
    EXTRN NotDD_InType_or_OutSG   : WORD                                ;@D1088
    EXTRN NotDD_OutSG             : WORD                                ;@D1088
    EXTRN NotDD_OutType           : WORD                                ;@D1088
    EXTRN PopUpScrnGrp2           : WORD                                ;AVCO
    EXTRN TopMost                 : DWORD                               ;AVCO

    EXTRN DOSSMDELSGCB       : NEAR     ; Delete SGCB
    EXTRN DOSSMGETSGCB       : FAR
    EXTRN DOSDEVIOCTL        : FAR      ; Notify mouse device driver
    EXTRN DOSFSRAMSEMREQUEST : FAR      ; Request semaphore owner
    EXTRN DOSFSRAMSEMCLEAR   : FAR      ; Request semaphore owner
    EXTRN DOSSETPRTY         : FAR      ; Adjust cwait thread prty
    EXTRN DOSSGFREE          : FAR      ; Notify screen switcher
    EXTRN DOSSMAPPNOTIFY     : FAR      ; Notify shell or parent
    EXTRN VIOFREE            : FAR      ; Notify vio router
    EXTRN DOSSMNOTIFYDD      : FAR

.xlist
    INCLUDE SMRSGCB.INC
    INCLUDE SMRRDATA.INC
    INCLUDE INFOSEG.INC                 ; needed by smmmpha.inc         ;MHW
    INCLUDE SMMMPHA.INC                 ; Performance hook macros       ;MHW
.xcref
    INCLUDE STRUC.INC
    INCLUDE ERROR2.INC
.cref
.list

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

    PUBLIC DOSSMCHILDEXIT
    PUBLIC DOSSMCHILDEXIT_POSTDT
DOSSMCHILDEXIT 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
    PUSH DS
    PUSH ES
    PUSH FS
    PUSH GS

    MMPHPreDOSSMChildExit               ; Performance Hook (8109h)      ;MHW

;   ************************************
;   *  Boost priority by a delta of 1  *
;   ************************************
;   PUSH 2                              ; Only this thread              ;CJ10
    PUSH DWORD PTR 20000H               ; Don't change class            ;CJ10
;   PUSH 1                              ; Delta of 1                    ;CJ10
    PUSH DWORD PTR 10000H               ; Current thread only           ;CJ10
    CALL DOSSETPRTY

;   ***************************************************************
;   *  Notify shell or application a screen group has terminated  *
;   ***************************************************************
    MOV  CX, ES:[DI].SGCB_Flags         ; Exec failure?
    AND  CX, 2
    PUSH CX
    .IF  < nz >                         ; Yes
      PUSH 1                            ; Exec. failure, skip parent notify
    .ELSE

;     ******************************************************************** AVCO
;     * Only block on popup sem if no popup currently in the foreground  * AVCO
;     * or if there is a popup then block on popup sem only when the     * AVCO
;     * dying session was the topmost before the popup.  This fixes      * AVCO
;     * a problem where a .cmd file starts sessions synchronously but    * AVCO
;     * gets blocked when waiting to be notified a session died but      * AVCO
;     * sesmgr is blocked here waiting for the popup to go away before   * AVCO
;     * cmd.exe can be notified.                                         * AVCO
;     ******************************************************************** AVCO
      POP  CX                                                             ;AVCO
      LFS  SI, TopMost                          ; TopMost screen grp addr ;AVCO
      .IF <PopUpScrnGrp2 eq 0FFFFH>  OR         ; No popup in progress    ;AVCO
      .IF <DX eq FS:[SI].SGCB_ID>               ; dying sgid = topmost    ;AVCO
        MOV CH, 0FFH                                                      ;AVCO
        .repeat                                                           ;@GDW
        PUSH RDATA                      ; Popup semaphore
        PUSH OFFSET PopUpBlockSem
        PUSH DWORD PTR -1                                                 ;@CJ10
        CALL DOSFSRAMSEMREQUEST
      .until  <ax ne ERROR_INTERRUPT>                                     ;@GDW
      .ENDIF                                                              ;AVCO
      PUSH CX                                                             ;AVCO
      .repeat                                                           ;@GDW
        PUSH RDATA                      ; Block router
        PUSH OFFSET SMRoutSem
        PUSH DWORD PTR -1                                               ;@CJ10
        CALL DOSFSRAMSEMREQUEST
        PUSH 0                          ; Normal termination
      .until  <ax ne ERROR_INTERRUPT>                                   ;@GDW
    .ENDIF

    PUSH DX                             ; Terminated session ID
    PUSH BX                             ; Terminated session return code
    CALL DOSSMAPPNOTIFY                 ; Notify parent or shell

;   ************************************
;   *  Lower priority by a delta of 1  *
;   ************************************
;   PUSH 2                              ; Only this thread              ;CJ10
    PUSH DWORD PTR 20000H               ; Don't change class            ;CJ10
;   PUSH -1                             ; Delta of -1                   ;CJ10
    PUSH DWORD PTR 0FFFF0000H           ; Current thread only           ;CJ10
    CALL DOSSETPRTY

;   **********************************************************************
;   *  If parent cwait notification received before children, change     *
;   *  session type for parent and all of its children.                  *
;   *  When this occurs parentexitlist has already killed all children.  *
;   **********************************************************************
    BTR  ES:[DI].SGCB_FamilyType, 0     ; If Parent, make non-parent (Bit 0)
    .IF  < c >                          ; Yes,
      LEA  SI, Local_Var2               ; @ return @ of SGCB
      PUSH SS
      PUSH SI
      PUSH ES:[DI].SGCB_FirstChild      ; Get first child
      PUSH SGID_Lookup + 8000H          ; Look up SGID not PID and      ;CJ10
      CALL DOSSMGETSGCB                 ;   don't serialize QueueRamSem

      LFS  SI, Local_Var2               ; FS:[SI] --> First Child's SGCB
      .REPEAT
        AND  FS:[SI].SGCB_FamilyType, NOT Child ; Make non-child
        LEA  AX, Local_Var2             ; @ return @ of SGCB
        PUSH SS
        PUSH AX
        PUSH FS:[SI].SGCB_Relative      ; Get next relative
        PUSH SGID_Lookup + 8000H        ; Look up SGID not PID and      ;CJ10
        CALL DOSSMGETSGCB               ;   don't serialize QueueRamSem

        LFS  SI, Local_Var2             ; FS:[SI] --> Next family member
      .UNTIL < FS:[SI].SGCB_ID eq DX >  ; Until we're back at terminating session
    .ENDIF

;   *****************************************************************
;   *  WINENDSESSION MUST be called AFTER PARENTNOTIFY (in          *
;   *  DOSSMAPPNOTIFY), since it will invalidate                    *
;   *  the session ID in the SwitchList.  The                       *
;   *  SwitchList is referenced when PARENTNOTIFY calls             *
;   *  WinQueryExtIDFocus.                                          *
;   *  WINENDSESSION must also called after the SGCB_switchramsem   *
;   *  semaphore has been gotten, because it may be held by the     *
;   *  harderr thread (held during an error condition is in         *
;   *  effect, such as starting a session in low memory).           *
;   *  Winthorn would then perceive that                            *
;   *  the SHELL was in the foreground, instead of the dying SG,    *
;   *  (and decide not to switch back to the Program manager).      *
;   *****************************************************************
    .IF  < PM_Present e Yes >
;     ************************************************************
;     * SGCB_queueramsem semaphore MUST be CLEAR before calling  *
;     * WinEndSession to prevent the following deadlock:         *
;     * The Shell Switch thread was blocked on SGCB_queueramsem, *
;     * and owned the Shell SwitchList semaphore. While the      *
;     * Shell Terminate (WinEndSession) which owned              *
;     * SGCB_queueramsem was blocked on the Shell SwitchList     *
;     * semaphore.                                               *
;     * @DB59790 - a detached PM process will have the same sid  *
;     *            so we must pass the pid as well to insure the *
;     *            right session gets ended.                     *
;     ************************************************************
      PUSH DX                           ; Dead Session's ID
      PUSH ES:[DI].SGCB_PID             ; Dead Session's PID                    @DB59790
      PUSH BX                           ; Dead Session's Return Code
      CALL WINENDSESSION                ; Tell PM session died
    .ENDIF                              ; PM existence test

;   ******************************
;   *  Notify Registered Device  *
;   *  Drivers of SG switch.     *
;   ******************************

;   **************************************************************************
;   * This DosSMNotifyDD call had to be moved above the VioFree so if a DBCS *
;   * monitor is installed, it can be de-installed before the VioFree. The   *
;   * DBCS notification dll gets notified during this call & de-installs     *
;   * the monitor.                                                      CJ28 *
;   **************************************************************************

    MOV  NotDD_DosDev_Data_Len, Version_1_2_Len            ;data length ;@D1088,CJ28
    MOV  NotDD_Notification_Type, Termination_Notification ;notify type ;@D1088,CJ28
    MOV  AX, ES:[DI].SGCB_type          ; Outgoing SG type              ;@D1088,CJ28
    MOV  NotDD_InSG_or_OutType, AX                                      ;@D1088,CJ28
    MOV  AX,DX                          ; Outgoing SG                   ;@D1088,CJ28
    XOR  AH, AH                         ; Zero out type byte            ;@D1088,CJ28,VR1
    MOV  NotDD_InType_or_OutSG, AX                                      ;@D1088,CJ28
    PUSH DS                             ; Address of NotifyDD data      ;@D1088,CJ28
    PUSH OFFSET NotDD_DosDev_Data_Len                                   ;@D1088,CJ28
    CALL DosSMNotifyDD                                                  ;CJ28

;   *****************************************
;   *  Notify screen switcher, etc... that  *
;   *  a screen group has terminated        *
;   *****************************************
    .IF  < DH ne Window_Type > AND      ; If NOT windowed AND
    .IF  < DH ne PM_Type >              ; NOT PM
      .IF  < DH e FS_Type >             ; FS session (not a VDM)
        PUSH DX                         ; Terminated screen group ID
        CALL DOSSGFREE                  ; Let screen switcher know

;CJ42;;;PUSH DX                         ; Screen group number
;CJ42;;;CALL VIOFREE                    ; Let VIO know of termination

      .ELSEIF < DH e VDM_Type > OR      ; VDM case
      .IF  < DH e Windowed_VDM_Type >
        MOV  AX, WORD PTR WinDestroyConsole
        OR   AX, WORD PTR WinDestroyConsole[2]
        .IF  < nz >                     ; Call WinDestroyConsole if it's there
          PUSH ES                       ; Trashed by WinDestroyConsole
          PUSH DX                       ; Trashed by WinDestroyConsole

          PUSH DX                       ; SGID
          CALL WinDestroyConsole        ; Destroys Most Registers (like BX)

          POP  DX                       ; Restore DX
          POP  ES                       ; Restore ES
        .ENDIF
      .ENDIF
    .ELSE                               ; VIO or PM Screen Group
      PUSH DX                           ; Screen group number
      CALL VIOFREE                      ; Let VIO know of termination
    .ENDIF                              ; Screen Group Type tests

;   ***********************************************
;   *  Remove terminated screen group from the    *
;   *  active queue and free screen group number  *
;   ***********************************************
    CALL DOSSMDELSGCB                   ; Delete it from the SGCB queue
    POP  CX                             ; Exec failure type
;AVCO.IF  < CXZ >                                                        ;@CJ10
    .IF  < zero CL >                                                      ;AVCO
      .IF  < CH eq 0FFH >                                                 ;AVCO
      PUSH RDATA                        ; Release router
      PUSH OFFSET PopUpBlockSem
      CALL DOSFSRAMSEMCLEAR
      .ENDIF                                                              ;AVCO

      PUSH RDATA                        ; Release router
      PUSH OFFSET SMRoutSem
      CALL DOSFSRAMSEMCLEAR
    .ENDIF


    POP  GS                             ; Restore registers
    POP  FS
    POP  ES
    POP  DS
    POPA

    MMPHPostDOSSMChildExit              ; Performance Hook (8189h)      ;MHW

    LEAVE
    DOSSMCHILDEXIT_POSTDT LABEL FAR
    RET

DOSSMCHILDEXIT ENDP

CODE ENDS
endif
    END
