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

 page 60,132


;*********************** START OF SPECIFICATIONS ***********************/
;                                                                      */
;  SOURCE FILE NAME: SSWSVRD                                           */
;                                                                      */
;  SUBROUTINE NAME:  DOSSAVREDRAWWAIT                                  */
;                                                                      */
;  DESCRIPTIVE NAME:  Thread to perform save/restore functions         */
;                                                                      */
;  FUNCTION: Allows thread to perform save/restore or restore function.*/
;            Thread will be notified at save or restore time as to     */
;            which action needs to be performed.                       */
;                                                                      */
;  NOTES:  Executes on Level 3                                         */
;                                                                      */
;  ENTRY POINT:  DosSavRedrawWait                                      */
;    LINKAGE:                                                          */
;                                                                      */
;  INPUT: - INDICATOR  (0 = save and restore, 1 = restore only)        */
;         - NOTIFYTYPE action flag (Screen Switcher tells thread which */
;           function <save or restore> needs to be performed.)  This   */
;           is an address                                              */
;         - VIOHandle                                                  */
;                                                                      */
;  EXIT-NORMAL:  AX = 0                                                */
;                                                                      */
;  EXIT-ERROR:   AX = error_scs_invalid_parms     (function is other   */
;                      than save/restore or restore)                   */
;                                                                      */
;  EFFECTS:  Contents of AX destroyed by return code                   */
;            Action flag is updated with function to be performed      */
;                                                                      */
;                                                                      */
;  INTERNAL REFERENCES:                                                */
;    ROUTINES:  SSCBUpdate, SSOpenSySem                                */
;                                                                      */
;  EXTERNAL REFERENCES:                                                */
;    ROUTINES:  DosSemClear, DosSemWait, DosExit                       */
;               DosGetShrSeg, DosGetInfoSeg, DosSemRequest             */
;               DosSemSet, DosOpenSem, DosCloseSem                     */
;                                                                      */
;       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.       */
;                                                                      */
;************************ END OF SPECIFICATIONS ************************/

; IF <passed in parameter greater than 1>
;  AX = error_vio_invalid_parms
; ELSEIF <viohandle ne 0>
;  AX = error_vio_invalid_handle
; ELSE
;  Request synch semaphore
;  IF <this is the first call of this function>
;   Call DOSEXITLIST (set up exit list)
;   Call DOSGETINFOSEG
;   Store pid# and sg# in instanced data segment
;   Call SSGETSGCB      (allocate an sgcb)
;  ENDIF
;  Store current pid# (to register ownership)
;  IF <undoflag not set>
;   IF <save/restore thread not owned> AND
;   IF <save/restore pid not owned> OR
;   IF <save/restore pid is owned by the current process>
;    Set appropriate variables to indicate ownership
;   ENDIF
;   IF <save/restore thread is not the current thread> OR
;   IF <save/restore pid is not the current pid>
;    Clear the synch semaphore
;    AX = error_vio_function_owned
;   ELSE
;    IF <a save/restore is in progress and we are to do it>
;     Set up parameters for next run through
;     Clear saveredrawsem to alert system that we've done our job
;     Set saveresthreadsem (to block us)
;     Clear synch semaphore
;     Wait on saveresthreadsem (until system awakens us)
;     IF <undoflag is not on>
;      Store required screen action into allocated memory word
;     ENDIF
;   ENDIF
;  ENDIF
;  IF <undoflag is on>
;   IF <kill flag is on>
;    Clear synch semaphore
;    Call DOSEXIT
;   ELSEIF <kill flag is off>
;    AX = error_vio_return (this is the requested notification for the app)
;    Clear the synch semaphore
;   ENDIF
;  ENDIF
; ENDIF


EXTRN DOSCLEANUP:FAR
EXTRN DOSEXITLIST:FAR
EXTRN SSOPENSYSEM:NEAR
EXTRN savelocksem:byte, savelockflag:byte, savelockowner:word
EXTRN scrnaction:word
EXTRN saveundoflag:word
EXTRN DOSFSRAMSEMREQUEST:FAR            ; 12-12-88 @GA1
EXTRN DOSFSRAMSEMCLEAR:FAR              ; 12-12-88 @GA1
EXTRN SMG_INSTANCE:DWORD                ; SMG/SSW instance data         ;@TL6

.xlist
INCLUDE SSWINC.INC
INCLUDE INFOSEG.INC
INCLUDE SSWEXTR3.INC
INCLUDE OS2INST.INC                     ; SMG/SSW instance data equates ;@TL6
.list

.386P

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

 PUBLIC  DOSSAVREDRAWWAIT

DOSSAVREDRAWWAIT   PROC    FAR


 push    bp
 mov     bp,sp

 push    bx
 push    cx
 push    dx
 push    ds
 push    es
 push    di
 push    si


 .IF <ss:[bp].indicator a 1>            ; If error in parm
   mov     ax,error_vio_invalid_parms
 .ELSEIF <ss:[bp].viohandle ne 0>       ; ES7/8/87
   mov     ax,error_vio_invalid_handle  ; ES7/8/87
 .ELSE near

;  mov     ax,indatasg                  ; Set up addressability         ;@TL6
;  mov     es,ax                        ; to instanced and              ;@TL6
   mov     ax,stdatasg                  ; common data segments
   mov     ds,ax
   les     si,ds:SMG_INSTANCE           ; Gain access to instance data  ;@TL6

   .repeat                                                              ;@GDW
     push    ds
     push    offset savelocksem
     push    dword ptr timeout                                          ;CJ10
;    push    timeout                                                    ;CJ10
     call    DOSFSRAMSEMREQUEST         ; 12-12-88 @GA1
   .until  <ax ne ERROR_INTERRUPT>                                      ;@GDW
;--------------------------------------------------------------------------
   .IF <zero ax> OR                                                     ;@TL6
   .IF <ax e error_sem_owner_died> near
     .IF <es:[si].in_sgid e 0>          ; First call?                   ;@TL6
       mov     ax,cs                                                    ;@TL6
       or      ax,1                     ; Exitlist must be in Ring 3    ;@TL6
       push    0C001H                   ; For DCR18 7/10/87
       push    ax                                                       ;@TL6
       push    offset doscleanup
       call    DOSEXITLIST
       .IF <zero ax> near                                               ;@TL6
;@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    pop     cx                     ; Get localsg into cx
;@TL6    pop     dx

;@TL6    .IF <zero ax> near                                             ;@TL6
;@TL6      mov     es:[si].in_localsg,cx; save local infoseg selector
           mov     ax,es
           mov     es,localsg           ; Setup local infoseg in ES     ;@TL6
           mov     bx,es:lis_curscrngrp ; Save sg# and
           mov     dx,es:lis_curprocid  ; pid#
           mov     es,ax
           mov     es:[si].in_procid,dx ; Store in instanced            ;@TL6
           mov     es:[si].in_sgid,bx   ; data segment                  ;@TL6
           push    si                   ; Save instance data offset     ;@TL6
           call    ssgetsgcb            ; bx must contain sg#
           pop     si                   ; Restore instance data offset  ;@TL6
           .IF <zero ax> near                                           ;@TL6
             mov     es:[si].in_di_reg,di                               ;@TL6
           .ENDIF
;@TL6    .ENDIF
       .ENDIF
     .ENDIF
     .IF <zero ax> near                 ; If no error or                ;@TL6
       mov     bx,es:[si].in_procid     ; Get current pid#              ;@TL6
;      mov     savelockowner,bx         ; register ownership of ram sem 12-12-88 @GA1
       mov     savelockflag,6           ; unique identifier
       mov     di,es:[si].in_di_reg                                     ;@TL6
       test    [di].saverestflags,svredundoflag
       .IF z near                       ; was not just issued
;@TL6    mov     es,es:[si].in_localsg
         mov     es,localsg
         mov     cx,es:lis_curthrdid    ; and thread
         .IF <[di].saveresthreadid e ax> AND  ; If no thread ID has     ;@TL6
         .IF <[di].saverestpid e ax> OR       ; been assigned and no    ;@TL6
         .IF <[di].saveresthreadid e ax> AND  ; pid has been assigned   ;@TL6
         .IF <[di].saverestpid e bx>    ; or this call follows
                                        ; an undo call which
                                        ; did not relinq ownrshp
           mov     [di].saverestpid,bx
           mov     [di].saveresthreadid,cx
           mov     ax,ss:[bp].indicator  ; Get the save/redraw
           mov     [di].scrnactionflag,ax  ; indicator into sgcb
           mov     eax,dword ptr ss:[bp].notifytype                     ;CJ10
           mov     dword ptr [di].scrnactionflagaddr,eax                ;CJ10
;CJ10      mov     ax,word ptr ss:[bp].notifytype + 2
;CJ10      mov     word ptr [di].scrnactionflagaddr+ 2,ax
           sub     eax,eax              ; c 7/18/86                     ;CJ10
         .ENDIF
         .IF <[di].saveresthreadid ne cx> OR
         .IF <[di].saverestpid ne bx>
           push    ds                   ; c 7/17/86
           push    offset savelocksem   ; c 7/17/86
;          mov     savelockowner,0      ; ES9/3/87 c 7/17/86 12-12-88 @GA1
           mov     savelockflag,0       ; ES9/3/87 c 7/27/86
           call    DOSFSRAMSEMCLEAR          ; c 7/17/86 12-12-88 @GA1
           .IF <zero ax>                ; c 7/17/86                     ;@TL6
             mov     ax,error_vio_function_owned  ; c 7/18/86
           .ENDIF
         .ELSE near
           and     [di].saverestflags,0FFFEH  ; Turn off lsb (may be set
                                              ; by doscleanup routine)
           test    [di].saverestflags,saverestfunct
           .IF ne z
             mov     ax,ss:[bp].indicator  ; Get the save/redraw
             mov     [di].scrnactionflag,ax  ; indicator into sgcb
             mov     eax,dword ptr ss:[bp].notifytype  ; Notify offset  ;CJ10
             mov     dword ptr [di].scrnactionflagaddr,eax              ;CJ10
;CJ10        mov     ax,word ptr ss:[bp].notifytype + 2
;CJ10        mov     word ptr [di].scrnactionflagaddr+ 2,ax
             and     [di].saverestflags,saverestcomplte
;@TL6        mov     cx,di
             lea     cx,[di].saveredrawsem                              ;@TL6
             push    ds
             push    cx
             call    DOSSEMCLEAR
           .ENDIF
           .IF <zero ax> OR                                             ;@TL6
           .IF <ax e error_sem_owner_died> near
;@TL6        mov     cx,di
             lea     cx,[di].saveresthreadsem                           ;@TL6
             push    ds
             push    cx
             call    DOSSEMSET
             .IF <zero ax>                                              ;@TL6
               push    ds
               push    offset savelocksem
;              mov     savelockowner,0          ; 12-12-88 @GA1
               mov     savelockflag,0
               call    DOSFSRAMSEMCLEAR         ; 12-12-88 @GA1
               .IF <zero ax> OR                                         ;@TL6
               .IF <ax e error_sem_owner_died>
                 .REPEAT                                  ; ES10/8/87
                   push    ds
                   push    cx           ; Wait on saveresthreadsem
                   push    dword ptr timeout                            ;CJ10
;CJ10              push    timeout
                   call    DOSSEMWAIT
                 .UNTIL <ax ne error_interrupt>           ; ES10/8/87
                 .IF <zero ax> OR                                       ;@TL6
                 .IF <ax e error_sem_owner_died>
                   test    [di].saverestflags,svredundoflag
                   .IF z
                     les     si,[di].scrnactionflagaddr  ; Get addr
                                      ;to store parm
                     mov     cx,scrnaction
                     mov     word ptr es:[si],cx
                   .ENDIF
                 .ENDIF
               .ENDIF
           .ENDIF
         .ENDIF
       .ENDIF
     .ENDIF
   .ENDIF
   .IF <zero ax>                                                        ;@TL6
     test    [di].saverestflags,svredundoflag
     .IF ne z
       and     [di].saverestflags,svredundoflagoff
       .IF <[di].scrnkillindicator e 1>
         .IF <savelockflag e 6>
           push    ds
           push    offset savelocksem
           mov     savelockflag,al      ; clear flag                    ;@TL6
;          mov     savelockowner,0      ; 12-12-88 @GA1
           call    DOSFSRAMSEMCLEAR     ; 12-12-88 @GA1
         .ENDIF
         mov     [di].scrnkillindicator,null
         pop     si
         pop     di
         pop     es
         pop     ds
         pop     dx
         pop     cx
         pop     bx
         pop     bp

         push    0
         push    0
         call    DOSEXIT
       .ELSEIF <[di].scrnkillindicator e 0>
         mov     [di].scrnkillindicator,null
         mov     ax,error_vio_return
         .IF <savelockflag e 6>
           push    ds
           push    offset savelocksem
           mov     savelockflag,0          ; ES9/3/87
;          mov     savelockowner,0         ; ES9/3/87  12-12-88 @GA1
           call    DOSFSRAMSEMCLEAR        ; 12-12-88 @GA1
         .ENDIF
       .ENDIF
     .ENDIF
   .ENDIF
  .ENDIF
 .ENDIF

 pop     si
 pop     di
 pop     es
 pop     ds
 pop     dx
 pop     cx
 pop     bx

 pop     bp
 ret
DOSSAVREDRAWWAIT   ENDP
CODE_TUNE4    ENDS                                                      ;MDLL
 END
