;       SCCSID = @(#)smrsmswt.asm       6.2 91/08/28
PAGE 60,132                             ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SMRSMSWT.ASM
;
; Subroutine Name:      DOSSMSWITCH
;
; Descriptive Name:     Session Switch
;
; Function:     Synchronize Shell session switch with application
;               session calls, detect session bonds, and call the
;               Session Manager to switch to a new foreground session.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   Only the Shell can call this procedure.
;
; Change History:
;  @GDW   08/26/91   PTR B725436 Fix to allow semaphore loop on INTERUPT
;  57015  11/21/91   Bound sg not registed with TaskList so can'be be selected.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMSWITCH : FAR
;                       PUSH    WORD   Action     ; Switch Options
;                       PUSH    WORD   SessionID  ; Session Number
;                       PUSH    DWORD  Reserved   ; Reserved
;                       CALL    DOSSMSWITCH
; Inputs:
;       WORD    Action     Value = 0, Standard switch
;                          Value = 1, Switch to next session
;                                     in the queue
;                          Value = 2, Skip current session
;                                     save
;                          Value = 3, Skip current session
;                                     restore
;                          Value = 4, Extended session switch
;                          Value = 5, Extended session switch but
;                                     don't get bound session.
;       WORD    SessionID  Session Number
;       DWORD   Reserved   Reserved double word of zeros or
;                          Switch list handle if Action = 4
;
; Exit Normal:
;       AX      ReturnCode Value = 0, Session switch successful
;
; Exit Errors:
;       AX      ReturnCode error_scs_not_session_mgr
;                          error_smg_bad_reserve
;                          error_smg_bad_statusreq
;                          error_smg_not_baseshell
;                          error_smg_not_bound
;                          error_smg_session_non_select
;                          error_smg_session_not_found
;                          error_smg_session_not_parent
;
;                          DOSSEMREQUEST    errors
;                          WINSETEXTIDFOCUS errors
;                          DOSSMSGSWITCH    errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:        RDATA - Common data segment
;                               smroutsem - Shell/Application synchronization
;                       SESDATA - Commom segment with active session data
;                                 returned from DOSSMGETSTATUS (GETQSTATUS)
;                                 nextactiveses - next active session
;
;          Routines:    GETQSTATUS
;                       GETBOUNDSESSION
;
; External References:
;          Routines:    DOSSEMREQUEST
;                       DOSSMSGSWITCH
;                       DOSSEMCLEAR
;
;************************************************************************
ifdef I1
;
;   DOSSEMREQUEST (Wait for popup semaphore)
;   DOSSEMREQUEST (Wait for SMG router semaphore)
;
;   If (No_Error)
;     *********************************
;     *  If switch next request, get  *
;     *  next topmost session ID      *
;     *********************************
;     Get request session
;     If Switch Action == 1
;       Get Next Active SG
;       Set Swtich Action = 0
;     EndIf
;
;     DOSSMGETSGCB                      ; Get SGCB of session to switch to
;     If No Error
;       Get Pointer to Parent's SGCB
;       If Select Status = Selectable
;         Repeat
;           GETBOUNDSESSION             ; See if parent is bound
;         Until RC = Error
;
;         If PM Present
;           WINSETEXTIDFOCUS
;         EndIf
;
;       If not OS/2 or VDM Full Screen
;         Use Shell's SGID
;       EndIf
;
;       DOSSMSGSWITCH
;
;     Else
;       RC = Error_SMG_Session_Non_Select
;     EndIf
;   EndIf
;
;   DOSSEMCLEAR (Release SMG router semaphore)
;   DOSSEMCLEAR (Release popup semaphore)
;
;************************************************************************
else

.386C
    EXTRN PM_Present         : BYTE     ; PM existence flag
    EXTRN PopUpBlockSem      : BYTE     ; Popup semaphore
    EXTRN SMRoutSem          : BYTE     ; Shell/application synchronization sem
    EXTRN WinSetExtIDFocus   : DWORD    ; Session Switch
    EXTRN TopMost            : DWORD    ; Topmost Queue Address

    EXTRN GETBOUNDSESSION    : NEAR     ; Get session bound to parent
    EXTRN DOSFSRAMSEMCLEAR   : FAR      ; Release semaphore ownership
    EXTRN DOSFSRAMSEMREQUEST : FAR      ; Synchronize Shell/App. calls
    EXTRN DOSSMSGSWITCH      : FAR      ; Session Switch
    EXTRN DOSSMGETSGCB       : FAR
.xlist
    INCLUDE SMRSMSWT.INC                ; Switch stack frame
.xcref
    INCLUDE SMRSGCB.INC
    INCLUDE SMRRDATA.INC                ; Router shared segment definition
    INCLUDE STRUC.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 DOSSMSWITCH
DOSSMSWITCH PROC FAR

    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
    PUSH DS                             ; Save registers
    PUSH ES
    PUSH SI
    PUSH DI
    PUSH BX

    MOV  AX, RDATA                      ; Addressability to common data
    MOV  DS, AX

;   **********************************
;   *  Sychronize Shell/Application  *
;   *  Session Manager API calls     *
;   **********************************
    .repeat                                                             ;@GDW
      PUSH DS                           ; Popup semaphore
      PUSH OFFSET PopUpBlockSem
      PUSH DWORD PTR -1                                                 ;CJ10
;     PUSH -1                                                           ;CJ10
      CALL DOSFSRAMSEMREQUEST
    .until  <ax ne ERROR_INTERRUPT>                                     ;@GDW

    .repeat                                                             ;@GDW
      PUSH DS                           ; SMG router RAM semaphore
      PUSH OFFSET SMRoutSem
      PUSH DWORD PTR -1                                                 ;CJ10
;     PUSH -1                                                           ;CJ10
      CALL DOSFSRAMSEMREQUEST
    .until  <ax ne ERROR_INTERRUPT>                                     ;@GDW

;   *********************************
;   *  If switch next request, get  *
;   *  next topmost session ID      *
;   *********************************
    MOV  BX, SS:[BP].SMSwtSessionID     ; Get request session
    .IF  < SS:[BP].SMSwtAction eq 1 >
      LES  DI, TopMost
      LFS  SI, ES:[DI].SGCB_Next
      MOV  SS:[BP].SMSwtAction, 0
    .ENDIF

;   **************************************
;   *  Get SGCB of session to switch to  *
;   **************************************
    LEA  SI, Local_Var2                 ; @ return @ of SGCB
    PUSH SS
    PUSH SI
    PUSH BX                             ; SGID
    PUSH SGID_Lookup + 8000H            ; Look up SGID not PID          ;CJ10
    CALL DOSSMGETSGCB

    .IF  < zero AX >                    ; If we found the SGCB          ;CJ10
      LFS  SI, Local_Var2               ; FS:[SI] --> Parent's SGCB
;     *********************************
;     *  Verify requested session ID  *
;     *  exists and is selectable.    *
;     *********************************
      .IF  < FS:[SI].SGCB_SelectStatus e Selectable >

;       ********************************************************        ;57015
;       *  PM session manager can't switch to this session's   *        ;57015
;       *  bound session so don't get bound session.           *        ;57015
;       ********************************************************        ;57015
        .IF  < SS:[BP].SMSwtAction eq 5 >                               ;57015
          MOV  SS:[BP].SMSwtAction, 4                                   ;57015

;       ******************************************
;       *  If parent is bound to child session,  *
;       *  replace switch session ID with child  *
;       ******************************************
        .ELSE                                                           ;57015
          .REPEAT
            CALL GETBOUNDSESSION
          .UNTIL < nonzero AX >                                         ;CJ10
        .ENDIF                                                          ;57015

;       ***************************************************
;       *  Call WINSETEXTIDFOCUS on EVERY screen switch.  *
;       ***************************************************
        .IF  < PM_Present eq Yes >      ; Make sure PM is there
          PUSH BX                       ; Set window focus
;CJ10     PUSH SS:[BP].SMSwtReserved+2  ; Switch handle if
          PUSH DWORD PTR SS:[BP].SMSwtReserved  ; action = 4, or 0's.   ;CJ10
          CALL WINSETEXTIDFOCUS
        .ENDIF                          ; PM existence test

        .IF  < FS:[SI].SGCB_Type ne FS_Type > AND   ; Switch to shell if
        .IF  < FS:[SI].SGCB_Type ne VDM_Type >      ; not a FS (OS/2 or VDM)
          MOV  BX, Shell_SG             ; Switch to PM SG
        .ENDIF                          ; Test for full screen

;       ************************************************************
;       *  Call Session Manager to change the foreground session.  *
;       ************************************************************
        PUSH SS:[BP].SMSwtAction        ; Switch options
        PUSH BX                         ; Requested or bound session

        .IF  < SS:[BP].SMSwtAction eq 4 > ; Extended Session Switch
          MOV  DI, SP                   ; Use DI to point back into stack
          MOV  BYTE PTR SS:[DI][2], 0   ; SMSwtAction = 0
          PUSH FS:[SI].SGCB_DebuggerSID ; Debugger SID (or 0)
          PUSH DWORD PTR 0              ; Don't pass the switch         ;CJ10
;CJ10     PUSH 0                        ; handle to DOSSMSGSWITCH
        .ELSE                           ; Action <> 4
          PUSH FS:[SI].SGCB_DebuggerSID ; Debugger SID (or 0)
;CJ10     PUSH SS:[BP].SMSwtReserved+2  ; Reserved parm
          PUSH DWORD PTR SS:[BP].SMSwtReserved                          ;CJ10
        .ENDIF                          ; Action = 4 Test
        CALL DOSSMSGSWITCH

      .ELSE                             ; Not Selectable
        MOV  AX, Error_SMG_Session_Non_Select
      .ENDIF                            ; Selectability test
    .ENDIF                              ; Failure from DosSMGetSGCB test

;   *************************************
;   *  Preserve switch return code and  *
;   *  clear synchronization semaphore  *
;   *************************************
    PUSH AX                             ; Save return code

    PUSH DS                             ; Clear synchronization semaphore
    PUSH OFFSET SMRoutSem
    CALL DOSFSRAMSEMCLEAR

    PUSH DS                             ; Clear popup semaphore
    PUSH OFFSET PopUpBlockSem
    CALL DOSFSRAMSEMCLEAR

    POP  AX                             ; Restore Session Manager return code
    POP  BX                             ; Restore registers
    POP  DI
    POP  SI
    POP  ES
    POP  DS

    LEAVE                               ; Restore old BP
    RET  8

DOSSMSWITCH ENDP

CODE ENDS
endif
    END
