;       SCCSID = @(#)sswddntf.asm       6.4 91/11/19
    page 60,132
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SSWDDNTF.ASM
;
; Subroutine Name:      DOSSGDDNOTIFY
;
; Descriptive Name:     Device driver notification of current screen
;                       group
;
; Function:     The call is issued by the Session Manager.  The Screen
;               Switcher will invoke DosSGSwitch call to make the
;               specified screen group foreground.  And then notifies
;               the keyboard device driver and any registered device
;               driver(s) required post-save screen group switch
;               notification.
;
; Notes:
;       Dependencies:   None.
;
;       Restrictions:   Only the Shell may call this routine.
;
;       Change History:
;
;       @TL6 - 03/01/90 - DCR 704 - Merge SMG/SSW instance data into OS2CHAR
;       @GDW   08/26/91   PTR B725436 Fix to allow semaphore loop on INTERUPT
;       MDLL   01/10/94   BJN Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage:  EXTRN DOSSGDDNOTIFY : FAR
;                       PUSH    WORD   Old_SGID      ; Out going SG #
;                       PUSH    WORD   New_SGID      ; In coming SG #
;                       PUSH    WORD   Debugger_SGID ; Debugger's SG # or 0
;                       CALL    DOSSGDDNOTIFY
;
; Input:
;       WORD     Old_SGID       screen group number to be invalidated
;                               Bit 15 = Do validation/invalidation
; |                             Bit 14 = 0 = Non-VDM
; |                                      1 = VDM
;       WORD     New_SGID       screen group number to be validated
;                               Bit 15 = Do validation/invalidation
; |                             Bit 14 = 0 = Non-VDM
; |                                      1 = VDM
;       WORD     Debugger_SGID  debuggers screen group number or 0                          */
;                               Bit 15 = Do validation/invlidation
;                               Bit 14 = 0 = InValidate
;                                        1 = Validate
;
; Exit Normal:
;       AX      ReturnCode   Value = 0
;
; Exit Error:
;       AX      error_sgs_not_session_mgr
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:
;          Routines:    SSFINDSG
;                       SSSEMSU
;                       SSMEMMAP
;
; External References:
;          Routines:    DOSDEVIOCTL
;                       DOSGETINFOSEG
;                       DOSSGSWITCH
;                       DOSSEMREQUEST
;                       DOSSEMCLEAR
;                       DOSSMNOTIFYDD
;
;**************************************************************************
;
;   DOSGETINFOSEG (Determine caller's screen group)
;   IF (No_Error)
;      Get current PID from local infoseg
;      IF (current pid ne ssmgr_pid)
;         RC = ERROR_SCS_NOT_SESSION_MANAGER
;      ELSE
;         DOSSEMREQUEST (Wait for savelocksem)
;         IF (No_Error) OR
;         IF (Error_Sem_Owner_Died)
;            Set savelockowner with current PID
;            Set savelockflag with debug flag
;            Set screenlocksgid with current SGID
;            Get incoming SGID from stack
;
;            IF (Background SG start)
;               Get out going SGID from stack
;            ELSE
;               Mask off high bit (bit 15) of the incoming SGID
;            ENDIF
;
; |          IF New foreground is Not a VDM (Bit 14 is 0)
;               SSGETSGCB (get pointer to the sgcb)
; |          ENDIF
;
;            IF (No_Error)
;               IF (Foreground start)
;                  DOSSGSWITCH (Screen switch)
;                  IF (No_Error)
;                     KBDSWITCHFGND (Notify KBD D/D)
; #                   DOSSMNOTIFYDD (Post save notification)
;                  ENDIF
; |             ELSEIF NOT VDM (No SGCB for VDM sessions)
;                  Set background flag on in SGCB
;               ENDIF
;            ENDIF
;
;            Clear savelockowner
;            Clear savelockflag
;            DOSSEMCLEAR (Release savelocksem)
;
;            IF (No_Error)
;               Clear screenlocksgid
;            ENDIF
;         ENDIF
;      ENDIF
;   ENDIF
;
;************************************************************************

.286C
    EXTRN savelocksem        : BYTE
    EXTRN savelockflag       : BYTE
    EXTRN ssmgr_pid          : WORD
    EXTRN kbd_parm_table     : BYTE
    EXTRN savelockowner      : WORD
    EXTRN screenlocksgid     : WORD
;   EXTRN DOSSMNOTIFYDD      : FAR
    EXTRN DOSFSRAMSEMREQUEST : FAR
    EXTRN DOSFSRAMSEMCLEAR   : FAR

.xlist
    INCLUDE INFOSEG.INC
    INCLUDE SSWEXTR3.INC
    INCLUDE SSWINC.INC
.list

.386p

CODE_TUNE4    SEGMENT WORD PUBLIC 'CODE' USE16                          ;MDLL

    ASSUME CS:CODE_TUNE4, DS:NOTHING,SS:NOTHING,ES:NOTHING              ;MDLL

    PUBLIC DOSSGDDNOTIFY

DOSSGDDNOTIFY PROC FAR

    PUSH BP
    MOV  BP, SP
    PUSH BX
;   PUSH CX                                                             ;@TL6
    PUSH DS
    PUSH ES
    PUSH DI
;   PUSH SI                             ; To optimize VDM path          ;@TL6

;   PUSH AX                             ; Need to store 2 words         ;@TL6
;   MOV  BX, SP                         ; which will be used to         ;@TL6
;   PUSH AX                             ; store the globalsg            ;@TL6
;   MOV  CX, SP                         ; and the localsg               ;@TL6
;   PUSH SS                                                             ;@TL6
;   PUSH BX                                                             ;@TL6
;   PUSH SS                                                             ;@TL6
;   PUSH CX                                                             ;@TL6

;   CALL DOSGETINFOSEG                  ; Determine caller's            ;@TL6
;   .IF  < zero AX >  near              ; screen group                  ;@TL6
;     POP  ES                           ; Get localsg into es           ;@TL6
;     POP  BX                                                           ;@TL6
      MOV  BX, stdatasg                 ; We can access our
      MOV  DS, BX                       ; static data area

      MOV  ES, localsg                  ; Setup local infoseg in ES     ;@TL6
      MOV  BX, ES:Lis_CurProcID         ; Get current pid#
      .IF  < BX ne ssmgr_pid >          ; If this is not the            ;@TL6
        MOV  AX, error_scs_not_session_mgr ; Session Manager,

      .ELSE NEAR
        .repeat                                                         ;@GDW
          PUSH DS
          PUSH OFFSET savelocksem
          PUSH DWORD PTR timeout                                        ;CJ10
;CJ10     PUSH timeout
          call DOSFSRAMSEMREQUEST
        .until  <ax ne ERROR_INTERRUPT>                                 ;@GDW

        .IF  < zero AX > NEAR OR        ; If no error or                ;@TL6
        .IF  < AX e error_sem_owner_died >  NEAR ; if owner died
          MOV  savelockflag, 3          ;  < < < < DEBUG >  >  >  >
          MOV  BX, ES:Lis_CurScrnGrp
          MOV  screenlocksgid, BX
          MOV  BX, SS:[BP].d_sgid       ; SG# into bx

          .IF  < BX eq null >             ; Background SG start
            MOV  BX,  SS:[BP].d_invalsgid ; New (background) SG
          .ELSE                           ; Really a switch
            AND  BX,  7FFFH               ; Do invalidation
          .ENDIF

          TEST BX, 4000H                  ; VDM ? If yes, then skip this call
          .IF  z                          ; No - go look for sgcb
              PUSH SI                     ; Save/restore SI             ;@TL6
              CALL SSGETSGCB              ; Create SGCB if doesn't exist
              POP  SI                     ;                             ;@TL6
          .ENDIF

          PUSH   AX                       ; Save error code

          .IF  < zero AX >                                              ;@TL6
            .IF  < SS:[BP].d_sgid ne null > ; Not background start
              PUSH SS:[BP].d_invalsgid
              PUSH SS:[BP].d_sgid

              PUSH ss:[bp].d_debuggersgid ; Debugger's SGID
              PUSH AX                   ; word of zero                  ;@TL6
              CALL DOSSGSWITCH          ; Switch to d_sgid

              .IF  < zero AX >                                          ;@TL6
                TEST SS:[BP].d_sgid, 4000H ; VDM ?
                .IF  z                  ; No
                  PUSH BX
                  CALL KBDSWITCHFGND    ; Don't call this for VDMs
                .ENDIF

;               ******************************
;               *  Notify Registered Device  *
;               *  Drivers of SG switch.     *
;               ******************************
;               Notification now done in DosSMGSwitch
;               MOV  AX, SS:[BP].d_invalsgid ; Old SG
;               AND  AX, 7FFFH          ; Peel off high bit
;               .IF  < AX ne BX >       ; Not returning from SG termination
;                 PUSH Post_Save_Notification ; Not. Type
;                 PUSH BX               ; New SG
;                 PUSH AX               ; Old SG
;                 CALL DOSSMNOTIFYDD
;               .ENDIF                  ; Hard Error test
              .ENDIF

            .ELSE
              OR   [DI].sgflags, in_backgrnd ; New SG in background
            .ENDIF
          .ENDIF

          PUSH DS                       ; Clear the system-wide
          PUSH OFFSET savelocksem       ; semaphore
          MOV  savelockflag, 0
          CALL DOSFSRAMSEMCLEAR

          .IF  < zero AX >                                              ;CJ10
            MOV  screenlocksgid, AX     ; Clear flag                    ;@TL6
          .ELSE
            XCHG AX, BX
          .ENDIF

          POP  AX                       ; Return the error from SSGETSGCB call

        .ENDIF
      .ENDIF
;   .ENDIF                                                              ;@TL6
;   POP  SI                             ; To optimize VDM path          ;@TL6
    POP  DI
    POP  ES
    POP  DS
;   POP  CX                                                             ;@TL6
    POP  BX
    POP  BP

    RET  6

DOSSGDDNOTIFY ENDP
CODE_TUNE4    ENDS                                                      ;MDLL
    END
