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



;*********************** START OF SPECIFICATIONS ***********************/
;                                                                      */
;  SOURCE FILE NAME: SSWRESTR                                          */
;                                                                      */
;  SUBROUTINE NAME:  DOSSGRESTORE                                      */
;                                                                      */
;  DESCRIPTIVE NAME:  Screen Switcher restore function                 */
;                                                                      */
;  FUNCTION:  Causes the specified screen group to be restored         */
;             to the screen along with its associated hardware state   */
;                                                                      */
;  NOTES:  Executes on Level 3                                         */
;                                                                      */
;  ENTRY POINT: DosSGRestore                                           */
;    LINKAGE:           EXTRN DOSSGRESTORE : FAR                       */
;                       PUSH    WORD   ACTION                          */
;                       PUSH    WORD   SGID        ; In coming SG #    */
;                       CALL    DOSSGRESTORE                           */
;                                                                      */
;  INPUT: Screen Group #                                               */
;                                                                      */
;  EXIT-NORMAL:  AX = 0                                                */
;                                                                      */
;  EXIT-ERROR:   AX = 1 for invalid function call (call issued by      */
;                      other than Session Manager)                     */
;                                                                      */
;  EFFECTS:  Contents of AX destroyed by return code                   */
;                                                                      */
;  INTERNAL REFERENCES:                                                */
;    ROUTINES:  SSThawPids                                             */
;                                                                      */
;  EXTERNAL REFERENCES:                                                */
;    ROUTINES:  VIORestore, DosGetShrSeg, DosSemClear                  */
;               DosSemSet, DosSemWait, DosSystemService                */
;               DosTimerStart, DosTimerStop, DosGetInfoSeg             */
;                                                                      */
;       Change History:                                                */
;                                                                      */
;       @TL6 - 03/01/90 - DCR 704 - Merge SMG/SSW instance data into   */
;                         OS2CHAR                                      */
;       @TV1 - 08/19/93 - Defect 69932                                 */
;                         Restoration after VioPopUp corrupts Video    */
;                         for Full Screen Palette Aware applications   */
;                                                                      */
;************************ END OF SPECIFICATIONS ************************/

; Get current pid#
; IF <pid# ne sesmgr pid#>
;  AX=error_scs_not_session_mgr
; ELSE
;  Call SSFINDSG (get pointer to sgcb)
;  IF <normal restore>
;   IF <sg will perform its own restore>
;    IF <we froze a process within the screen group>
;     IF <frozen process owns the restore thread>
;      Call VIORESTORE (Vio will have to perform the restore)
;      Call SSTHAWPIDS (to thaw the process)
;     ELSE (if restore pid not the frozen pid)
;      Release the screen restore thread
;      Call SSTHAWPIDS
;     ENDIF
;    ELSE (there is no frozen pid)
;     Release the screen restore thread
;    ENDIF
;    Clear the semaphore blocking threads waiting on screen locks
;   ELSE (if we do the restore)
;    Call VIORESTORE
;    IF <there is a frozen pid>
;     Call SSTHAWPIDS
;    ELSE
;    ENDIF
;    Clear the semaphore blocking threads waiting on screen locks
;   ENDIF
;  ELSE (If popup restore)
;   IF <sg will do mode restore>
;    IF <we froze a process within the screen group>
;     IF <frozen process owns the mode restore thread>
;      IF <frozen process owns the mode save thread as well>
;       Call VIORESTORE
;       Call SSTHAWPIDS
;      ELSEIF (if it only restores mode)
;       Call SSTHAWPIDS
;       Release the mode restore thread
;      ENDIF
;      Clear the semaphore blocking threads waiting on screen locks
;     ELSE (the frozen process does not own the restore mode thread)
;      Release the mode restore thread
;      Call SSTHAWPIDS
;      Clear the semaphore blocking threads waiting on screen locks
;     ENDIF
;    ELSE (there is no frozen pid)
;     Release the mode restore thread
;     Clear the semaphore blocking threads waiting on screen locks
;    ENDIF
;   ELSE (there is no restore mode thread within the screen group)
;    Call VIORESTORE
;    IF <there is a frozen pid within the screen group>
;     Call SSTHAWPIDS
;     Clear the semaphore blocking threads waiting on screen locks
;    ELSE (there is no frozen pid)
;     Clear the semaphore blocking threads waiting on screen locks
;    ENDIF
;   ENDIF
;  ENDIF
; ENDIF


EXTRN ssmgr_pid      : word
EXTRN scrnaction     : word
EXTRN modeaction     : word
EXTRN screenlocksgid : word
EXTRN savelockowner  : word
EXTRN savelocksem    : dword
EXTRN savelockflag   : byte
EXTRN blank          : byte
EXTRN localsg        : word
EXTRN DOSSETFGND     : FAR           ; Set foreground SG priority
;EXTRN DOSSMNOTIFYDD  : FAR

.xlist
INCLUDE SSWINC.INC
INCLUDE INFOSEG.INC
INCLUDE SSWEXTR3.INC
INCLUDE SMREXTRN.INC                   ; Device Driver Notification EQUs
.list

.386P

CODE    SEGMENT WORD PUBLIC 'CODE' USE16                                ;@TL6

        ASSUME  CS:CODE, DS:NOTHING,SS:NOTHING,ES:NOTHING               ;@TL6

;---------------------------------------------------------------------------

PROC1           PROC    NEAR            ; Saveredraw thread release
 .IF < ss:[bp].sgid ne 1>               ; PM (SG 1) sets its own prioriy   @@AR
   push    3                            ; Give restore thread fgnd priorityCDB2
   mov     ax, ss:[bp].sgid             ; Get rid of process type in high byte
   xor     ah, ah                       ;                               ;@TL6,VR8
   push    ax
   call    DOSSETFGND                   ;                                  CDB2
 .ENDIF                                 ;                                  @@AR

 push    cx
;mov     cx,di                          ; procedure                     ;@TL6
 lea     cx,[di].saveredrawsem                                          ;@TL6
 push    ds                             ; Then set a sem which
 push    cx                             ; we will wait for
 call    DOSSEMSET                      ; restore thd to clear
 .IF <zero ax> OR                                                       ;@TL6
 .IF <ax e error_sem_owner_died>

;  ******************************
;  *  Notify Registered Device  *
;  *  Drivers of SG switch.     *
;  ******************************
;  PUSH   Post_Restore_Notification     ; Not. Type
;  PUSH   SS:[BP].SGID                  ; Incoming SG
;  PUSH   0                             ; Current SG
;  CALL   DosSMNotifyDD

   or      [di].saverestflags,restscrnreq  ; Tell thread to restore
   mov     scrnaction,restscrn
;  mov     cx,di                                                        ;@TL6
   lea     ax,[di].saveresthreadsem                                     ;@TL6
   push    ds                           ; Now release thread to
   push    ax                           ; perform the restore           ;@TL6
   call    DOSSEMCLEAR
   .IF <zero ax> OR                                                     ;@TL6
   .IF <ax e error_sem_owner_died>
;    mov     cx,di                                                      ;@TL6
;    add     cx,saveredrawsem
     push    ds                         ; Now we wait until the
     push    cx                         ; restore thread clears
     push    dword ptr timeout          ; the semaphore                 ;CJ10
;    push    timeout                                                    ;CJ10
     call    DOSSEMWAIT
     .IF <zero ax> OR                                                   ;@TL6
     .IF <ax e error_sem_owner_died>
       test    [di].saverestflags,1     ; check for dosexitlist cleanup
       .IF z
         and     [di].saverestflags,restscrncomp
       .ELSE
         push    DWORD PTR 0            ; 8/14/86                       ;CJ10
;CJ10    push    0                      ; 8/14/86
         push    24                     ; 8/14/86
         push    79                     ; 8/14/86
         push    -1                     ; 8/14/86
         push    ds                     ; 8/14/86
         push    offset blank           ; 8/14/86
         push    0                      ; 8/14/86
         call    VIOSCROLLDN            ; 8/14/86
         .IF <zero ax>                                                  ;@TL6
           mov     [di].saverestflags,ax                                ;@TL6
         .ENDIF
       .ENDIF
     .ENDIF
   .ENDIF
 .ENDIF
 pop    cx
 RET
PROC1           ENDP


;---------------------------------------------------------------------------
PROC3           PROC    NEAR            ; Restore mode thread release
                                        ; procedure

; **************************************************************************
; * @TV1 - Restore the Adapter before letting the VIOMODEWAIT thread loose *
; * since we (SESMGR) saved the adapter state AFTER the app last saved his *
; * state with a VIOSAVEREDRAWWAIT.   Thus, we should restore that known   *
; * state BEFORE he tries to reset the Mode.   His Reset will be virtually *
; * worthless, but at least he will regain control with a known state.     *
; **************************************************************************

 and     [di].savemodeflags,restmodecomp; @TV1 Moved following six lines from
 push    ss:[bp].sgid                   ; after DOSSEMWAIT below
 mov     ax,ss:[bp].action
 add     ax,2                           ; tell VIO to
 push    ax                             ; restore all but the
 call    VIORESTORE                     ; mode

 push    3                              ; Give restore thread fgnd priorityCDB2
 mov     ax, ss:[bp].sgid               ; Get rid of process type in high byte
 xor     ah,ah                          ;
 push    ax
 call    DOSSETFGND                     ;                                  CDB2
 push    cx
;mov     cx,di                                                          ;@TL6
 lea     cx,[di].savemodesem                                            ;@TL6
 push    ds                             ; set a sem which we
 push    cx                             ; will wait on for thd
 call    DOSSEMSET                      ; to clear
 .IF <zero ax> OR                                                       ;@TL6
 .IF <ax e error_sem_owner_died>        ; Tell thread to go
   or      [di].savemodeflags,restmodereq  ; restore the mode
   mov     modeaction,0
;  mov     cx,di                                                        ;@TL6
   lea     ax,[di].savemodethreadsem                                    ;@TL6
   push    ds                           ; Release the thread
   push    ax                           ; to perform the mode           ;@TL6
   call    DOSSEMCLEAR                  ; restore
   .IF <zero ax> OR                                                     ;@TL6
   .IF <ax e error_sem_owner_died>
;    mov     cx,di                                                      ;@TL6
;    add     cx,offset savemodesem                                      ;@TL6
     push    ds                         ; Now wait on the
     push    cx                         ; previously set sem
     push    dword ptr timeout                                          ;CJ10
;    push    timeout                    ; until the thread              ;CJ10
     call    DOSSEMWAIT                 ; clears it one way or
                                        ; the other                     ;@TL6

;    ************************************************************************
;    * @TV1 - moved to top of procedure to allow for restoration of adapter *
;    * state BEFORE the VIOMODEWAIT thread regains control.  If this isn't  *
;    * done first, we will tromp over his saved state and cause Video       *
;    * corruption whenever switching back to that app.                      *
;    ************************************************************************
;
;    .IF <zero ax> OR
;    .IF <ax e error_sem_owner_died>
;      and     [di].savemodeflags,restmodecomp
;      push    ss:[bp].sgid
;      mov     ax,ss:[bp].action        ; Now we tell VIO to
;      add     ax,2                     ; restore all but the
;      push    ax                       ; mode
;      call    VIORESTORE
;    .ENDIF

   .ENDIF
 .ENDIF
 pop    cx
 RET
PROC3           ENDP
;***************************************************************************

PUBLIC  DOSSGRESTORE

DOSSGRESTORE   PROC    FAR

   push    bp
   mov     bp,sp

   push    bx
   push    cx
   push    dx
   push    es
   push    ds
   push    si
   push    di
   mov     ax,stdatasg                  ; We can access our
   mov     ds,ax                        ; static data area
   mov     es,localsg                   ; Point ES to local selector
   mov     bx,es:lis_curprocid          ; Get current pid#
   .IF <bx ne ssmgr_pid>
     mov     ax,error_scs_not_session_mgr  ; Session Manager,
   .ELSE near
     mov     bx,ss:[bp].sgid            ; Get sg# into bx
     xor     bh,bh                      ; Get rid of process type
     call    SSFINDSG                   ; Get pointer to sgcb
                                        ; into DI
     .IF <ax ne error_scs_sg_notfound> near  ; If we find the sg#
       .IF <ss:[bp].action e 0> near    ; If a normal restore
         .IF <[di].scrnactionflag ne null> near  ; If sg will restore
           .IF <[di].sgprocessfrozen ne 0>  ; If there is a frozen
                                        ; process
             mov     ax,[di].saverestpid  ; Check if frozen pid
             .IF <[di].sgprocessfrozen e ax>  ; owns restore thread
               push    ss:[bp].sgid    ; Tell VIO to restore whatever
               push    ss:[bp].action  ; it can
               call    VIORESTORE
              .IF <zero ax>                                             ;@TL6

;              ******************************
;              *  Notify Registered Device  *
;              *  Drivers of SG switch.     *
;              ******************************
;              PUSH   Post_Restore_Notification  ; Not. Type
;              PUSH   SS:[BP].SGID            ; Incoming SG
;              PUSH   0                       ; Current SG
;              CALL   DosSMNotifyDD

               and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
               call    SSTHAWPIDS       ; Then thaw the process
              .ENDIF                    ; added on 12/3/86
             .ELSE                      ; If restore pid not the frozen pid
               call    proc1            ; release the scrn restore thread
               .IF <zero ax>                                            ;@TL6
                 and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
                 call    SSTHAWPIDS     ; then thaw out the frozen pid
               .ENDIF
             .ENDIF
           .ELSE                        ; If there is no frozen pid
             call    proc1              ; just release the scrn restore
             .IF <zero ax>              ; thread                        ;@TL6
               and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
             .ENDIF
           .ENDIF
           .IF <zero ax>                                                ;@TL6
;@TL6        push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6        push    word ptr [di].lockneededsem  ; threads waiting for
             push    dword ptr [di].lockneededsem                       ;@TL6
             call    DOSSEMCLEAR        ; screen locks
           .ENDIF
;---------------------------------------------------------------------------
         .ELSE                          ; If we do the restore
;---------------------------------------------------------------------------
           push    ss:[bp].sgid         ; Tell VIO to do a
           push    ss:[bp].action       ; complete restore
           call    VIORESTORE
           .IF <zero ax> OR                                             ;@TL6
           .IF <ax e error_sem_owner_died>

;            ******************************
;            *  Notify Registered Device  *
;            *  Drivers of SG switch.     *
;            ******************************
;            PUSH   Post_Restore_Notification  ; Not. Type
;            PUSH   SS:[BP].SGID            ; Incoming SG
;            PUSH   0                       ; Current SG
;            CALL   DosSMNotifyDD

             and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
             .IF <[di].sgprocessfrozen ne 0>  ; If there is a frozen pid
               call    SSTHAWPIDS       ; thaw it
             .ENDIF
             .IF <zero ax>                                              ;@TL6
;@TL6          push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6          push    word ptr [di].lockneededsem  ; threads waiting for
               push    dword ptr [di].lockneededsem                     ;@TL6
               call    DOSSEMCLEAR      ; screen locks
             .ENDIF
           .ENDIF
         .ENDIF
;---------------------------------------------------------------------------
       .ELSE near                       ; If pop-up restore
;---------------------------------------------------------------------------
         .IF <[di].modeactionflag ne null> near  ; If sg will do mode
                                        ; restore
;---------------------------------------------------------------------------
           .IF <[di].sgprocessfrozen ne 0> near  ; If there is a
                                        ; frozen process
;---------------------------------------------------------------------------
             mov     ax,[di].savemodepid  ; Check if frozen pid
             .IF <[di].sgprocessfrozen e ax>  ; owns mode restore thread
              .IF <[di].modeactionflag e 1>  ; and saves mode as well
               push    ss:[bp].sgid
               push    ss:[bp].action       ; Now we tell VIO to
               call    VIORESTORE           ; restore all
               .IF <zero ax>                                            ;@TL6
                call    SSTHAWPIDS
               .ENDIF
              .ELSEIF <[di].modeactionflag e 0>  ; If it only restores mode
                call    SSTHAWPIDS
               .IF <zero ax>                                            ;@TL6
                 call    proc3          ; ES7/8/87
               .ENDIF
              .ENDIF
              .IF <zero ax>                                             ;@TL6
                and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
;@TL6           push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6           push    word ptr [di].lockneededsem  ; threads waiting
                push    dword ptr [di].lockneededsem                    ;@TL6
                call    DOSSEMCLEAR  ; for screen locks

;               ******************************
;               *  Notify Registered Device  *
;               *  Drivers of SG switch.     *
;               ******************************
;               PUSH   Post_Restore_Notification  ; Not. Type
;               PUSH   SS:[BP].SGID               ; Incoming SG
;               PUSH   0                          ; Current SG
;               CALL   DosSMNotifyDD

              .ENDIF
             .ELSE                      ; If frozen pid does not
               call   proc3             ; ES7/8/87
               .IF <zero ax>                                            ;@TL6
                 and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
                 call   SSTHAWPIDS
                 .IF <zero ax>                                          ;@TL6
;@TL6              push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6              push    word ptr [di].lockneededsem  ; threads waiting
                   push    dword ptr [di].lockneededsem                 ;@TL6
                   call    DOSSEMCLEAR  ; for screen locks

;                  ******************************
;                  *  Notify Registered Device  *
;                  *  Drivers of SG switch.     *
;                  ******************************
;                  PUSH   Post_Restore_Notification  ; Not. Type
;                  PUSH   SS:[BP].SGID            ; Incoming SG
;                  PUSH   0                       ; Current SG
;                  CALL   DosSMNotifyDD

                 .ENDIF
               .ENDIF
             .ENDIF
;---------------------------------------------------------------------------
           .ELSE                        ; If no frozen pid
;---------------------------------------------------------------------------
             call  proc3                ; ES7/8/87
             .IF <zero ax>                                              ;@TL6
                 and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
;@TL6            push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6            push    word ptr [di].lockneededsem  ; threads waiting
                 push    dword ptr [di].lockneededsem                   ;@TL6
                 call    DOSSEMCLEAR    ; for screen locks

;                ******************************
;                *  Notify Registered Device  *
;                *  Drivers of SG switch.     *
;                ******************************
;                PUSH   Post_Restore_Notification  ; Not. Type
;                PUSH   SS:[BP].SGID               ; Incoming SG
;                PUSH   0                          ; Current SG
;                CALL   DosSMNotifyDD

             .ENDIF
           .ENDIF
;---------------------------------------------------------------------------
         .ELSE                          ; If no restore mode thd
;---------------------------------------------------------------------------
           sub     ax,ax                        ; assume no error       ;@TL6
           .IF <ss:[bp].action ne 2>            ; CDB
             push    ss:[bp].sgid
             push    ss:[bp].action             ; Now we tell VIO to
             call    VIORESTORE                 ; restore all

;@TL6        .IF <ax e no_error>
;              ******************************
;              *  Notify Registered Device  *
;              *  Drivers of SG switch.     *
;              ******************************
;              PUSH   Post_Restore_Notification  ; Not. Type
;              PUSH   SS:[BP].SGID            ; Incoming SG
;              PUSH   0                       ; Current SG
;              CALL   DosSMNotifyDD
;@TL6          XOR    AX, AX                  ; Set good return code
;@TL6        .ENDIF

;@TL6      .ELSE                                ; CDB
;@TL6         xor     ax,ax                     ; CDB
           .ENDIF                               ; CDB

           .IF <zero ax>                                                ;@TL6
             .IF <[di].sgprocessfrozen ne 0>  ; If there's a frozen pid
               and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
               call    SSTHAWPIDS       ; thaw it
               .IF <zero ax>                                            ;@TL6
;@TL6            push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6            push    word ptr [di].lockneededsem  ; threads waiting
                 push    dword ptr [di].lockneededsem                   ;@TL6
                 call    DOSSEMCLEAR    ; for screen locks
               .ENDIF
             .ELSE                      ; If no frozen pid
                 and     [di].sgflags,in_foregrnd  ; Turn off backgrnd flg
;@TL6            push    word ptr [di].lockneededsem + 2  ; Now clear all
;@TL6            push    word ptr [di].lockneededsem  ; threads waiting for
                 push    dword ptr [di].lockneededsem                   ;@TL6
                 call    DOSSEMCLEAR    ; screen locks
             .ENDIF
           .ENDIF
         .ENDIF
       .ENDIF
     .ENDIF
   .ENDIF
 pop     di
 pop     si
 pop     ds
 pop     es
 pop     dx
 pop     cx
 pop     bx

 pop     bp
 ret     4

DOSSGRESTORE   ENDP

CODE    ENDS                                                            ;@TL6
 END

