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

;************************************************************************
;
; Source File Name:     SMRSELEV.ASM
;
; Subroutine Name:      APPSELECTSESSION
;
; Descriptive Name:     Process an Application Select Session Request
;
; Function:     This will use the request block and queue status table
;               to determine if a session in the requestor's family is
;               the current foreground session. If a family member is
;               in the foreground, process the switch request.
;
;               WINSetExtIdFocus may be called to set the foreground
;               window focus if the requested session is running
;               windowed.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
; Change History:
;   @CJ16 02/05/91 PTR B715577 Fix for ptr B714812. (2.0 B719611)
;   CJ37  07/09/91 PTR B724566 Block instead of looping for Popup semaphore.
;   @GDW  08/26/91 PTR B725436 Fix to allow semaphore loop on INTERUPT
;   @VR1  02/25/92 PTR B725635 Save the RqSwtSessionID for later use
;
; Entry Point:
;       Linkage:  EXTRN APPSELECTSESSION:NEAR
;                       CALL    APPSELECTSESSION
; Inputs:
;       DS      RDATA
;       ES:DI   ReqBlock   Address to an application select request
;                          block.
;
; 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_bound
;                          error_smg_session_not_foregrnd
;                          error_smg_session_not_found
;                          error_smg_session_not_parent
;                          error_smg_no_target_window                   ;@CJ16
;
;                          FOREGROUNDFAMILY errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:        QDATA - Common data segment
;                               reqblock (SMRREQB.INC)
;                                  reqsessionid   - Parent session ID
;                                  reqreturncode  - Return code
;                                  rqswtsessionid - Child session ID
;
;          Routines:    FOREGROUNDFAMILY
;                       GETBOUNDSESSION
;                       DOSSEMCLEAR
;                       DOSSEMREQUEST
;
; External References:
;          Routines:    DOSSMSGSWITCH
;
;************************************************************************
ifdef I1
;
;   FOREGROUNDFAMILY (Parent or child session in the foreground)
;   IF (No_Error)
;     DOSFSRAMSEMREQUEST (Popup Switch semaphore - no wait)
;     IF (no popup in progress)
;        IF (parent not specifying itself)
;           Repeat
;              GETBOUNDSESSION
;           Until (Error)
;        ENDIF
;
;        IF (PM is present)
;           WINSETEXTIDFOCUS (Set input focus)
;        ENDIF
;
;        IF (NOT Full Screen app) AND
;        IF (NOT VDM Type)
;          Set variable to specify a switch to Shell's sg
;        ENDIF
;
;        IF (No_Error)
;           DOSSMSGSWITCH (Switch to specified child session)
;        ENDIF
;        DOSFSRAMSEMCLEAR (Clear popup switch semaphore)
;     ELSE
;       RC = Try_Again
;     ENDIF
;   ENDIF
;
;************************************************************************
else

.386C
    EXTRN PM_Present         : BYTE     ; PM existence flag
    EXTRN PopUpBlockSem      : BYTE     ; Popup semaphore
    EXTRN WinSetExtIDFocus   : DWORD    ; Set ext. SGID for window focus

    EXTRN FOREGROUNDFAMILY   : NEAR     ; Parent or child foreground
    EXTRN GETBOUNDSESSION    : NEAR     ; Get session bound to parent
    EXTRN DOSSMSGSWITCH      : FAR      ; Switch to requested child
    EXTRN DOSFSRAMSEMCLEAR   : FAR      ; Release semaphore ownership
    EXTRN DOSFSRAMSEMREQUEST : FAR
    EXTRN DOSSMGETSGCB       : FAR
.xlist
    INCLUDE SMRREQB.INC                 ; Request block data definitions
.xcref
    INCLUDE SMRRDATA.INC                ; Router data declarations
    INCLUDE STRUC.INC
    INCLUDE SMRSGCB.INC
    INCLUDE ERROR2.INC                  ; Error code equates
.cref
.list

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

    PUBLIC APPSELECTSESSION
APPSELECTSESSION 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 all registers

;   ***************************************
;   *  Verify requestor's family member   *
;   *  is the current foreground session  *
;   ***************************************
    MOV  BX, ES:[DI].ReqSessionID
    CALL FOREGROUNDFAMILY

    .IF  < zero AX >    NEAR                                            ;CJ10
;     ******************************************
;     *  See if there is a popup in progress.  *
;     ******************************************
      .repeat                                                           ;@GDW
        PUSH DS                         ; See if there is a popup in progress
        PUSH OFFSET PopUpBlockSem       ; Use new semaphore
        PUSH DWORD PTR 5000             ; Wait for 5 seconds            ;CJ37
        CALL DOSFSRAMSEMREQUEST
      .until  <ax ne ERROR_INTERRUPT>                                   ;@GDW

;     ***********************************************************
;     *  Call Session Manager to change the foreground session  *
;     ***********************************************************
      .IF  < zero AX > NEAR             ; got the semaphore - no popup  ;@CJ16

;       ******************************************
;       *  If parent is bound to child session,  *
;       *  replace switch session ID with child  *
;       ******************************************
        MOV  BX, ES:[DI].RqSwtSessionID
        .IF  < BX ne ES:[DI].ReqSessionID > ; If parent not specifing self
          .REPEAT
            CALL GETBOUNDSESSION        ; FS:[SI] --> Parent or bonded SGCB
          .UNTIL < nonzero AX >                                         ;CJ10
        .ELSE                           ; Parent specifing itself
          LEA  SI, Local_Var2
          PUSH SS
          PUSH SI
          PUSH BX                       ; Requestor'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] --> Requestor's SGCB
        .ENDIF

        XOR  AX, AX                     ; Preset to good return code
        .IF  < PM_Present eq Yes >      ; Make sure PM is really there
          MOV  CX, BX                   ; Save the RqSwtSessionID in CX;VR1
          PUSH BX                       ; Set window focus
          PUSH DWORD PTR 0              ; Switch handle not needed here ;CJ10
;CJ10     PUSH 0                        ; Switch handle not needed here
          CALL WINSETEXTIDFOCUS
        .ENDIF                          ; Check for PM

        .IF  < FS:[SI].SGCB_Type ne FS_Type > AND ; Not FS application
        .IF  < FS:[SI].SGCB_Type ne VDM_Type >    ; Not VDM application
          MOV  BX, Shell_SG                       ; Switch to Shell's SG
        .ENDIF

        .IF  < zero AX >                                                ;CJ10
          PUSH AX                       ; Switch to specified session   ;CJ10
          PUSH BX                       ; Req child session
          PUSH FS:[SI].SGCB_DebuggerSID ; Debugger SID
          PUSH DWORD PTR 0              ; Double word reserved          ;CJ10
;CJ10     PUSH 0
          CALL DOSSMSGSWITCH

          .IF  <zero AX> AND                                            ;@CJ16
          .IF  < PM_Present eq Yes >    ; Make sure PM is really there  ;@CJ16
            PUSH CX                     ; Session to switch to          ;@CJ16,VR1
            PUSH DWORD PTR 0FFFFFFFFh   ; -1 special flag to check if   ;@CJ16,VR1
;VR1        PUSH 0FFFFh                 ; window can be switched to     ;@CJ16
            CALL WINSETEXTIDFOCUS                                       ;@CJ16
          .ENDIF                                                        ;@CJ16
        .ENDIF

        PUSH AX                         ; Save return code              ;@CJ16
        PUSH DS                         ; Allow popups
        PUSH OFFSET PopUpBlockSem
        CALL DOSFSRAMSEMCLEAR
        POP  AX                         ; Restore return code           ;@CJ16
      .ELSE                             ; Semaphore owned - ie popup in progress
        MOV  AX, Try_Again              ; Tell app side to keep trying request
      .ENDIF                            ; Test to see if there is a popup
    .ENDIF

    MOV  AX_Reg[-Local_Bytes], AX
    POPA                                ; Restore registers

    LEAVE
    RET

APPSELECTSESSION ENDP

CODE ENDS
endif
    END
