;       SCCSID = @(#)smgsgswt.asm       6.6 92/02/21
;       SCCSID @(#)smgsgswt.asm 6.6 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:     SMGSGSWT.ASM
;
; Subroutine Name:      DOSSMSGSWITCH
;
; Descriptive Name:     Session Manager Screen Group Switch
;
; Function:     Process a request to change a foreground screen group.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   May only be called internally by one
;                       of the Session Manager threads. This internal
;                       procedure illiminates the Base Shell check and
;                       queue access semaphore processing.
;
; Change History:
;  @@A1 - 02/10/90 PTR B711522 - Problem with DosSMStart
;  @TL7 - 04/05/90 PTR B712376 - Enable for MMIO
;  @D998  06/21/90 DCR 998 - Swaptuning, moved DosSMBaseShell from
;                  smrapdor.asm to smgsgswt.asm.
;  @D1088 07/07/90 DCR 1088 Add support for special needs.
;  @MHW - 09/13/90 PTR B715818 - In-line performance (MMIO) hooks
;  CJ45   11/03/91 PTR B729230 Don't switch if session already foreground.
;  CJ46   11/08/91 PTR SM07088 Always switch if foreground by termination.
;  @lvp65044 4/17/93 Defects 65044,61296 Check DosSMGetSGCB return code.
;   MDLL  01/10/94  BJN Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMSGSWITCH:FAR
;                       PUSH    WORD   Action     ; Switch Options
;                       PUSH    WORD   SGID       ; Screen Group Number
;                       PUSH    WORD   DebugSID   ; Debugger's SID
;                       PUSH    DWORD  Reserved   ; Reserved
;                       CALL    DOSSMSGSWITCH
;
; Inputs:
;       WORD    Action     Value = 0, Switch to specified screen
;                                     group
;                          Value = 1, Switch to next screen group
;                          Value = 2, Skip screen group save for
;                                     for foreground screen group
;                          Value = 3, Skip screen group restore
;                                     for new foreground screen
;                                     group
;       WORD    SGID       Screen group number
;       DWORD   Reserved   Reserved double word of zeros
;
; Exit Normal:
;       AX      ReturnCode Value = 0, successful screen group
;                                     switch
; Exit Errors:
;       AX      ReturnCode error_scs_not_session_mgr
;                          error_smg_not_baseshell
;                          error_smg_session_not_found
;                          error_smg_bad_reserve
;
;                          DOSSMBASESHELL  errors
;                          DOSSMGSWITCH    errors
;
; Effects:      All other registers preserved.
;
; Entry Points: DOSSMSGSWITCH
;               DOSSMGSWITCH
;               DOSSMBASESHELL
;
;**************************************************************************
ifdef I1
;
;   IF (Reserved e 0) AND
;   IF (Switch action is valid)
;      DOSSMBASESHELL (Verify caller is base shell)
;      IF (No_Error)
;         Get topmost sg address
;         IF (Action e switch to next sg)
;            Get the next sgid
;         ELSE (Switch to specified sg)
;            DOSSMGETSGCB (Get sgcb of specified sg)
;         ENDIF
;
;         IF (No error)
;            IF (Foreground by termination)
;                Don't save
;            ENDIF
;            DOSSMGSWITCH (Process switch request)
;         ENDIF
;      ELSE (Not the shell calling)
;         RC = Error_SMG_Not_Baseshell
;      ENDIF
;   ELSE
;      RC = Error_SMG_Bad_reserve
;   ENDIF

;**************************************************************************
else

.386C
    EXTRN PM_Present              : BYTE     ; PM Present Flag
    EXTRN GlobalSelector          : WORD     ; Global info segment sel.
    EXTRN PopUpPID                : WORD     ; Popup process ID
    EXTRN PopUpSGID               : WORD     ; Popup screen group ID
    EXTRN PopUpPrType             : WORD     ; Process Window Type
    EXTRN QHMOUSEHANDLE           : WORD     ; Handle to the mouse
    EXTRN QHKEYBDHANDLE           : WORD     ; Handle to the keyboard
    EXTRN SwtMseParm1             : WORD     ; mouse parm., screen group ID
    EXTRN SwtMseParm2             : WORD     ; mouse parm., switch func.
    EXTRN SwitchActionPacket      : WORD     ; Freeze/Thaw action packet
    EXTRN TopMost                 : DWORD
    EXTRN PopUpScrnGrp2           : WORD
    EXTRN QueueFlags              : WORD
    EXTRN IncomingDebugger        : WORD
    EXTRN BaseShell               : DWORD
    EXTRN SwitchRamSem            : DWORD
    EXTRN ShellPID                : WORD ; Shell ID                     ;@D998
    EXTRN LocalSelector           : WORD ; Selector to LDT              ;@D998
    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 WinQueryExtIDFocus : DWORD    ; PM routine

    EXTRN DOSSGSWITCHBACKGROUND : NEAR  ; Switch to background
    EXTRN DOSSGSWITCHFOREGROUND : NEAR  ; Switch to foreground
    EXTRN DOSSGSWITCHPOPUP      : NEAR  ; Remove popup

    EXTRN DOSDEVIOCTL           : FAR   ; Mouse notification
    EXTRN DOSSEMCLEAR           : FAR   ; Release semaphore ownership
    EXTRN DOSSEMREQUEST         : FAR   ; Request semaphore ownership
    EXTRN DOSSETFGND            : FAR   ; Give 3xb foregrnd priority
    EXTRN VIOSRFBLOCK           : FAR   ; Save/Restore block
    EXTRN VIOSRFUNBLOCK         : FAR   ; Save/Restore unblock
    EXTRN DOSSMGETSGCB          : FAR
    EXTRN DOSSMNOTIFYDD         : FAR

.xlist
    INCLUDE SMRSGCB.INC
    INCLUDE SMGSGSWT.INC
    INCLUDE SMRRDATA.INC                ; Router shared segment definition
.xcref
    INCLUDE ERROR2.INC
    INCLUDE INFOSEG.INC                 ; Information segment definitions
    INCLUDE SMMMPHA.INC                 ; Performance hook macros       ;MHW
    INCLUDE STRUC.INC
.cref
    INCLUDE DC1SEGS.INC                                                 ;MDLL
.list



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

    PUBLIC DOSSMSGSWITCH
    PUBLIC DOSSMSGSWITCH_POSTDT
DOSSMSGSWITCH PROC FAR

    Local_Bytes   EQU 10
    Local_Var1    EQU SS:[BP][-2]          ; Local variable on stack
    Local_Var2    EQU SS:[BP][-4]          ; Local variable on stack
    Local_Var3    EQU SS:[BP][-6]
    Local_InSGID  EQU SS:[BP][-8]          ; Local variable on stack
    Local_OutSGID EQU SS:[BP][-10]

    ENTER Local_Bytes,0
    PUSHA
    PUSH DS                             ; Save registers
    PUSH ES
    PUSH FS
    PUSH GS

    MOV  AX, RDATA                      ; Addressability to global data
    MOV  DS, AX                         ; DS ---> RDATA

    MMPHPreDOSSMSGSwitch                ; Performance Hook (8003h)      ;MHW

    MOV  BX, SS:[BP].SGSwtAction        ; Place action in a register
    MOV  DX, SS:[BP].SGSwtSGID          ; Screen group ID
;   LES  DI, SS:[BP].SGSwtReserved      ; Reserved words of zero        ;CJ10
;   MOV  SI, ES                                                         ;CJ10
;   OR   DI, SI                                                         ;CJ10

    .IF  < [BP].SGSwtReserved e 0 > AND ; Make sure reserved DWORD is 0 ;CJ10
    .IF  < BL be Skip_SG_Restore >      ; Check for illegal Switch Action
;     *****************************************
;     *  Verify the caller is the Base Shell  *
;     *****************************************
      CALL DOSSMBASESHELL               ; SMGSGSTRM MODULE

      .IF < zero AX >                                                   ;@CJ10
;       ***********************************
;       *  Valid screen group requested?  *
;       ***********************************
        LES  SI, TopMost                ; Topmost screen group addr
        .IF  < BL e Switch_To_Next_SG > ; BX = action, not switch next?
          LFS  DI, ES:[SI].SGCB_Next    ; Get the next SG
          MOV  DX, FS:[DI].SGCB_ID      ; Next foreground SGID

        .ELSE                           ; Switch to specified SG
          CWDE                          ;                               ;CJ10
          MOV  DWORD PTR Local_Var2, EAX; Clear it in case of error     ;CJ10
          LEA  DI, Local_Var2           ; @ return @ of SGCB
          PUSH SS
          PUSH DI
          PUSH DX                       ; Parent's SGID
          PUSH SGID_Lookup + 8000H      ; Look up SGID not PID and      ;CJ10
          CALL DOSSMGETSGCB             ;   don't serialize QueueRamSem
          LFS  DI, Local_Var2           ; FS:DI -> NULL on error return ;CJ10

        .ENDIF

        .IF  < zero AX >                                                ;@CJ10
;CJ10     LFS  DI, Local_Var2
;         ****************************
;         *  ES:SI --> TopMost SGCB  *
;         *  FS:DI --> Next SGCB     *
;         ****************************
          PUSH SS:[BP].SGSwtDebugSID    ; Get Debugger SID
          POP  IncomingDebugger         ; Save in SGCB header

          TEST ES:[SI].SGCB_Flags, 4    ; Fgnd by
          .IF  < nz >                   ; termination?
            AND  ES:[SI].SGCB_Flags, NOT 4 ; Turn off indicator bit
            MOV  BH, Skip_Save          ; Don't save
;CJ46;;;;;.ENDIF

;         ***************************************                       ;CJ45
;         *  Check if session to switch to is   *                       ;CJ45
;         *  already foreground - if so set AX. *                       ;CJ45
;         ***************************************                       ;CJ45
          .ELSEIF < <ES:BYTE PTR [SI].SGCB_ID> eq DL >             ;CJ45;CJ46
            MOV  AX, error_smg_already_top                              ;CJ45
          .ENDIF                                                        ;CJ45

          CALL DOSSMGSWITCH             ; Process switch request
        .ENDIF
      .ELSE                             ; Not the shell calling
        MOV  AX, Error_SMG_Not_BaseShell
      .ENDIF
    .ELSE
      MOV  AX, Error_SMG_Bad_Reserve
    .ENDIF

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

    MMPHPostDOSSMSGSwitch               ; Performance Hook (8083h)      ;MHW

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

    LEAVE
    DOSSMSGSWITCH_POSTDT LABEL FAR
    RET  sgswtfrmlen                    ; Return to caller

DOSSMSGSWITCH ENDP

endif                                   ; I1 package check
CODE ENDS                                                               ;MDLL

PAGE
;**************************************************************************
;
; Source File Name:     SMGSGSWT.ASM
;
; Subroutine Name:      DOSSMGSWITCH
;
; Descriptive Name:     Switch to a new screen group
;
; Function:     Saves the state of the foreground screen group and
;               makes the specified screen group the foreground
;               screen group.
;
; Notes:
;       Dependencies:   The queue must be protected by a RAM
;                       semaphore from the calling subroutine.
;
;       Restrictions:   None
;
; Entry Point:
;       Linkage:  EXTRN DOSSMGSWITCH:NEAR
;                       CALL    DOSSMGSWITCH
;
; Inputs:
;       BL      Action     Value = 0, Switch to specified screen
;                                     group
;                          Value = 1, Switch to next screen group
;                          Value = 2, Skip screen group save for
;                                     for foreground screen group
;                          Value = 3, Skip screen group restore
;                                     for new foreground screen
;                                     group
;                          Value = 4, Do popup switch
;                          Value = 5, End popup switch
;                          Value = 6, Screen group start switch
;       BH      StartAct   Value = 0, Save foreground screen group
;                          Value = 1, Skip save of foreground
;                                     screen
;                          Value = 80H, transparent popup
;       DX      SGID       Screen group number
;       DS      RDATA
;
; Exit Normal:
;       AX      ReturnCode Value = 0, successful screen group
;                                     switch
; Exit Errors:
;       AX      ReturnCode error_scs_not_session_mgr
;                          error_smg_session_not_found
;
;                          DOSSGDDNOTIFY    errors
;                          DOSSGSWITCHPROC2 errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;
;          Routines:    DOSSMBASESHELL
;
; External References:
;          Routines:    DOSSEMREQUEST
;                       DOSDEVIOCTL
;                       DOSSGSAVE
;                       DOSSYSTEMSERVICE
;                       DOSSGDDNOTIFY
;                       DOSSGSWITCHPROC2
;                       DOSSGRESTORE
;                       DOSSETFGND
;                       DOSSEMCLEAR
;
;**************************************************************************
ifdef I1
;
;
;   IF (Not hard error popup) AND
;   IF (Do popup switch)
;      Do nothing
;   ELSEIF (Popup screen group e 0) AND
;   IF (End popup switch)
;      Do nothing
;   ELSE
;      REPEAT
;         DOSSEMREQUEST (Access switch ram sem)
;      UNTIL (No_Error)
;      Indicate not hard error popup
;   ENDIF
;
;   IF NOT VDM in foreground
;     VIOSRFBLOCK (Block old or skip new foreground screen groups)
;   ENDIF
;
;   IF (Mouse handle ne 0)
;      DOSDEVIOCTL (Tell mouse that sg is about to be switched)
;   ENDIF
;
;   DOSDEVIOCTL (Tell kbd that sg is about to be switched)
;   IF (Popup sg exists ie. not -1) AND
;   IF (End popup request)
;     DOSSGSWITCHPOPUP
;   ENDIF
;
;   IF (Do popup request) OR
;   IF (NOT Error_SMG_Already_Top)
;      DOSSGSWITCHBACKGROUND
;      IF (no error)
;        DOSSGSWITCHFOREGROUND
;      ENDIF
;   ELSEIF (requested sg already foreground)
;      RC = No_Error
;   ENDIF
;
;   IF (End popup) AND
;   IF (Not hard error end popup)
;      IF (Popup pid going background)
;         BL = 6 (Skip foreground boost)
;      ENDIF
;
;      IF (Not a SG Start) AND
;      IF (Not End PopUp) OR
;      IF (Hard error popup) OR
;      IF (Popup PID going background)
;         IF (SGID = SHELL) AND
;         IF (PM is in system)
;            WINQUERYEXTIDFOCUS (Get extended SGID)
;         ENDIF
;         DOSSETFGND (Give foreground priority boost)
;      ENDIF
;   ENDIF
;
;   IF Non-VDM coming foreground
;     VIOSRFUNBLOCK (Unblock appropriate screen groups)
;   ENDIF
;
;   IF (Mouse handle ne 0) AND
;   IF (Not hard error daemon)
;      DOSDEVIOCTL (Tell mouse switch is complete)
;   ENDIF
;
;   IF (Do popup switch)
;      Set popup sg to sgid
;   ENDIF
;
;   IF (Mouse is installed) AND
;   IF (Not hard error daemon)
;      DOSDEVIOCTL (Tell mouse switch is complete)
;   ENDIF
;
;   IF (Not hard error do/end popup)
;      DOSSEMCLEAR (Switch ram sem)
;   ENDIF
;**************************************************************************
else

CODE_TUNE4 SEGMENT WORD PUBLIC 'CODE' USE16                             ;MDLL
    ASSUME CS:CONFORM16,DS:RDATA,SS:NOTHING,ES:NOTHING                  ;MDLL

    PUBLIC DOSSMGSWITCH
DOSSMGSWITCH PROC NEAR

    ENTER Local_Bytes,0                 ; Get a word for a local variable

    MOV  Local_Var3, AX                 ; Possible SMG_Already_Top RC

    PUSH DI
    PUSH CX                             ; Save CX
    MOV  CL, 0FFH                       ; Indicate hard error do/end popup
    .IF  < DX eq Hard_Error_SG > AND    ; Not hard error do/end popup
    .IF  < BL eq Do_PopUp >
    .ELSEIF < PopUpScrnGrp2 eq Hard_Error_SG > AND
    .IF  < BL eq End_PopUp >
    .ELSE
      .REPEAT
        PUSH DS                         ; Queue Access Semaphore
        PUSH OFFSET SwitchRamSem
        PUSH DWORD PTR -1               ; No wait                       ;@CJ10
        CALL DOSSEMREQUEST
      .UNTIL < zero AX >                                                ;@CJ10
      XOR  CX, CX                       ; Indicate not hard error popup
    .ENDIF

;   *****************************************************************
;   *  Block, and keep blocked, the Screen Group that is foreground *
;   *  when a PopUp occurs, untils the popup ends.                  *
;   *                                                               *
;   *  Do PopUp                        End PopUp                    *
;   *  ----------------------------    ---------------------------  *
;   *  1) Block Outgoing SG            1) Block Outgoing SG         *
;   *  2) Block Incoming SG            2) Do NOT Block Incoming SG  *
;   *  3) UnBlock Incoming SG          3) UnBlock Incoming SG       *
;   *  4) Do NOT UnBlock Outgoing SG   4) UnBlock Outgoing SG       *
;   *****************************************************************

    MOV  AX, GlobalSelector
    MOV  GS, AX
    XOR  AH, AH                         ; Clear upper byte of AX
    MOV  AL, GS:SIS_CurScrnGrp          ; Current foreground scrn grp
    MOV  Local_OutSGID, AX              ; Truncated SGCB ID

    .IF < BH ne Skip_Save >             ; Is there a SG to save?
;     ***********************
;     *  Get OutGoing SGCB  *
;     ***********************
      LEA  SI, Local_Var2               ; @ return @ of SGCB
      PUSH SS
      PUSH SI
      PUSH AX                           ; SGID
      PUSH SGID_Lookup + 8000H          ; Look up SGID not PID          ;CJ10
      CALL DOSSMGETSGCB                 ;   don't serialize QueueRamSem

      .IF <nonzero ax>                  ; If error, SG must have failed  @lvp65044
        OR BH, Skip_Save                ;   so don't save the 'dead' SG. @lvp65044
      .ELSE                                                              @lvp65044
        LES  SI, Local_Var2
      .ENDIF                                                             @lvp65044
    .ENDIF                              ; Check on saving foreground SG

;   ***********************
;   *  Get InComing SGCB  *
;   ***********************
    LEA  DI, Local_Var2                 ; @ return @ of SGCB
    PUSH SS
    PUSH DI
    PUSH DX                             ; SGID
    PUSH SGID_Lookup + 8000H            ; Look up SGID not PID and      ;CJ10
    CALL DOSSMGETSGCB                   ;   don't serialize QueueRamSem

    LFS  DI, Local_Var2
    MOV  Local_InSGID, AX               ; Initialize storage variable to 0
    MOV  DX, FS:[DI].SGCB_ID            ; Get full SGCB ID
    MOV  Local_InSGID, DL               ; Truncate SGCB ID

;   ***************************************
;   *  ES:SI --> TopMost SGCB (outgoing)  *
;   *  FS:DI --> Next SGCB (incoming)     *
;   *  GS    --> Global InfoSeg           *
;   ***************************************
;   **********************
;   *  Push Outgoing SG  *
;   **********************
    .IF < BH e Skip_Save > OR            ; Don't block dead Screen Groups
    .IF  <ES:[SI].SGCB_Type e VDM_Type > ; Is outgoing session a FS VDM?
      PUSH -1                            ; Don't Block it
    .ELSE
      PUSH Local_OutSGID                 ; Truncated SGCB_ID
    .ENDIF                               ; Outgoing VDM Test

;   **********************
;   *  Push Incoming SG  *
;   **********************
    .IF  < BL e End_PopUp > OR            ; Don't block for End_PopUp OR
    .IF  < DH e VDM_Type >                ;  for an incoming FS VDM.
      PUSH -1                             ; Don't block VIO
    .ELSE                                 ; Not End popup or FS VDM
      PUSH DX
    .ENDIF                                ; New foreground test

    CALL VIOSRFBLOCK                    ; Block switching screen groups
;   ******************************
;   *  Notify Registered Device  *
;   *  Drivers of SG switch.     *
;   ******************************
;@D1088    PUSH Pre_Switch_Notification        ; Notification Type
;@D1088    PUSH DX                             ; New SG
;@D1088    PUSH ES:[SI].SGCB_ID                ; Old SG

    MOV  NotDD_DosDev_Data_Len, Session_2_0_Len           ;data length  ;@D1088
    MOV  NotDD_Notification_Type, Pre_Switch_Notification ;notify type  ;@D1088
    MOV  AX, DX                         ; Incoming SG                   ;@D1088
    XOR  AH, AH                         ; Zero out type byte            ;@D1088,VR7
    MOV  NotDD_InSG_or_OutType, AX                                      ;@D1088
    MOV  AX, FS:[DI].SGCB_Type          ; Incoming SG type              ;@D1088
    MOV  NotDD_InType_or_OutSG, AX                                      ;@D1088
    MOV  AX, ES:[SI].SGCB_ID            ; Outgoing SG                   ;@D1088
    XOR  AH, AH                         ; Zero out type byte            ;@D1088,VR7
    MOV  NotDD_OutSG,AX                                                 ;@D1088
    MOV  AX, ES:[SI].SGCB_Type          ; Outgoing SG type              ;@D1088
    MOV  NotDD_OutType, AX                                              ;@D1088
    PUSH DS                             ; Address of NotifyDD data      ;@D1088
    PUSH OFFSET NotDD_DosDev_Data_Len                                   ;@D1088
    CALL DOSSMNOTIFYDD

;   *********************************************************
;   *  Remove popup if one exists on a screen group switch  *
;   *********************************************************
    MOV  AX, Local_Var3                 ; Restore Possible SMG_Already_Top
    PUSH DX                             ; Save full SGID
    .IF  < <WORD PTR PopUpScrnGrp2> ne 0FFFFH > AND
    .IF  < BL eq End_PopUp >
      CALL DOSSGSWITCHPOPUP
    .ENDIF

;   ***************************************************
;   *  Save the state of the foreground screen group  *
;   ***************************************************
    .IF  < BL eq Do_PopUp > OR           ; BX = action, do popup request
    .IF  < AX ne Error_SMG_Already_Top > ; Found queue and not topmost
      .IF < BH ne Skip_Save >            ; Do we want to save foreground?
        CALL DOSSGSWITCHBACKGROUND       ; Switch old SG to background
      .ELSE                              ;                                 @@A1
        XOR  AX, AX                      ; Make sure AX is No_Error        @@A1
      .ENDIF                             ; Save ForeGround Test

;     ******************************************
;     *  Switch to new foreground screen group *
;     ******************************************
      .IF  < zero AX >                  ; Error occurred during save?   ;@CJ10
        CALL DOSSGSWITCHFOREGROUND      ; Switch new SG to foreground
      .ENDIF

;   ********************************************************************
;   *  Is requested screen group already the foreground screen group?  *
;   ********************************************************************
    .ELSEIF < AX eq Error_SMG_Already_Top >
      Clear AX                          ; Successful return code        ;@CJ10
    .ENDIF

    MOV  Local_Var3, AX                 ; Save switch return code
    .IF  < zero AX > AND                                                ;@CJ10
    .IF  < BL ne SG_Start_Switch > AND  ; Not a screen group start
    .IF  < BL ne End_PopUp > OR         ; If not End popup
    .IF  < CX ne Hard_Error_SG > OR     ; or it is a hard error end popup
    .IF  < PopUpSGID ne DX >            ; Popup pid going backgrd

      .IF  < DL e Shell_SG > AND        ; If SGID = Shell
      .IF  < PM_Present e Yes >         ; and if PM is present
        PUSH DX                         ; Place to store extended SGID
        MOV  DX, SP                     ; Address to store extended SGID
        PUSH SS
        PUSH DX
        CALL WinQueryExtIDFocus         ; DS ---> RDATA

        POP  DX                         ; Get extended session id
        XOR  AX, AX                     ; Ignore any errors
      .ENDIF

      PUSH 3                            ; Boost SG priority
      PUSH DX                           ;
      CALL DOSSETFGND

    .ENDIF
    POP  DX                             ; Restore SGID

;   ***************************************
;   *  ES:SI --> TopMost SGCB (outgoing)  *
;   *  FS:DI --> Next SGCB (incoming)     *
;   ***************************************
;   **********************
;   *  Push Incoming SG  *
;   **********************
    .IF  < DH e VDM_Type>               ; Is incoming session a FS VDM?
      PUSH -1                           ; Don't unblock it
    .ELSE
      PUSH Local_InSGID                 ; Block new foreground if not end popup
    .ENDIF

;   **********************
;   *  Push Outgoing SG  *
;   **********************
    .IF  < BL e Do_PopUp > OR           ; Do popup switch OR
    .IF  <ES:[SI].SGCB_Type e VDM_Type> ; Outgoing session a FS VDM?
      PUSH -1                           ; Don't unblock old foreground SG
    .ELSE                               ; Not a do popup or FS VDM switch
      PUSH Local_OutSGID
    .ENDIF

    CALL VIOSRFUNBLOCK                  ; Block switching screen groups

    .IF  < <WORD PTR Local_Var3> e No_Error >
      .IF  < BL eq Do_PopUp >           ; If Do PopUp
        MOV  AX, Local_InSGID           ; Indicate in popup mode
        MOV  PopUpScrnGrp2, AX          ; Indicate in popup mode
      .ENDIF

;     ******************************
;     *  Notify Registered Device  *
;     *  Drivers of SG switch.     *
;     ******************************
;@D1088      PUSH Post_Switch_Notification     ; Notification Type
;@D1088      PUSH DX                           ; New SG
;@D1088      PUSH ES:[SI].SGCB_ID              ; Old SG

      MOV  NotDD_DosDev_Data_Len, Session_2_0_Len            ;data len  ;@D1088
      MOV  NotDD_Notification_Type, Post_Switch_Notification ;type      ;@D1088
      MOV  AX, DX                       ; Incoming SG                   ;@D1088
      XOR  AH, AH                       ; Zero out type byte            ;@D1088,VR7
      MOV  NotDD_InSG_or_OutType, AX                                    ;@D1088
      MOV  AX, FS:[DI].SGCB_Type        ; Incoming SG type              ;@D1088
      MOV  NotDD_InType_or_OutSG, AX                                    ;@D1088
      MOV  AX, ES:[SI].SGCB_ID          ; Outgoing SG                   ;@D1088
      XOR  AH, AH                       ; Zero out type byte            ;@D1088,VR7
      MOV  NotDD_OutSG, AX                                              ;@D1088
      MOV  AX, ES:[SI].SGCB_Type        ; Outgoing SG type              ;@D1088
      MOV  NotDD_OutType, AX                                            ;@D1088
      PUSH DS                           ; Address of NotifyDD data      ;@D1088
      PUSH OFFSET NotDD_DosDev_Data_Len                                 ;@D1088
      CALL DOSSMNOTIFYDD
    .ENDIF                              ; DosSMFreezeVDM Error

    .IF  < CX eq Hard_Error_SG >        ; Not hard error do/end popup
      PUSH DS                           ; Switch Semaphore
      PUSH OFFSET SwitchRamSem
      CALL DOSSEMCLEAR
    .ENDIF

    MOV  AX, Local_Var3                 ; Save switch return code
    POP  CX                             ; Restore CX
    POP  DI

    LEAVE
    RET

DOSSMGSWITCH ENDP
endif

CODE_TUNE4 ENDS                                                         ;MDLL


PAGE
;**************************************************************************
;
; Source File Name:     SMRAPDOR.ASM                                    ;@D998
;
; Subroutine Name:      DOSSMBASESHELL
;
; Descriptive Name:     Shell Verification
;
; Function:     Compares the current process ID in the local
;               information segment with the process ID in the
;               local information segment at the time of
;               initialization.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   No private Session Manager data may be
;                       accessed until this procedure is called
;                       to verify that the calling procedure is
;                       running under the Shell process ID.
; Change History:
;   MDLL  01/10/94  BJN Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMBASESHELL:NEAR
;                       CALL    DOSSMBASESHELL
;
; Inputs:
;       DS      RDATA      Shared data segment selector
;
; Exit Normal:
;       AX      ReturnCode Value = 0, Shell process
;
; Exit Errors:
;       AX      ReturnCode error_smg_not_baseshell
;
; Effects:      GS --> Local InfoSeg
;               All other registers preserved.
;
; Internal References:
;          Data:        The following data is in a shared data segment(SDATA)
;                               shellproc
;          Routines:
;
; External References:
;          Data:
;          Routines:
;
;**************************************************************************
ifdef I1
;
;   IF (curprocid e shell procid)
;        RC = No_Error
;   ELSE
;        RC = Error_SMG_Not_Baseshell
;   ENDIF
;
;**************************************************************************
else

CODE_TUNE1 SEGMENT WORD PUBLIC 'CODE' USE16                             ;MDLL
    ASSUME CS:CONFORM16,DS:RDATA,SS:NOTHING,ES:NOTHING                  ;MDLL

    PUBLIC DOSSMBASESHELL
DOSSMBASESHELL PROC NEAR

    ENTER 0,0
;   *****************************************************
;   *  Get current process ID and verify Shell process  *
;   *****************************************************
    MOV  AX, ShellPID
    MOV  GS, LocalSelector
    .IF  < GS:LIS_CurProcID eq AX >     ; Base Shell calling?
      SUB  AX, AX                       ; Yes, successful return code   ;CJ10
    .ELSE
      MOV  AX, Error_SMG_Not_Baseshell  ; No, return an error
    .ENDIF

    LEAVE
    RET                                 ; Return to caller

DOSSMBASESHELL ENDP
endif

CODE_TUNE1 ENDS                                                         ;MDLL
    END
