;       SCCSID = @(#)sswsvrdu.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 CODE NAME: SSWSVRDU                                          */
;                                                                      */
;  SUBROUTINE NAME:  DOSSAVREDRAWUNDO                                  */
;                                                                      */
;  DESCRIPTIVE NAME:  Pid relinquishes save/restore function           */
;                                                                      */
;  FUNCTION: Allows PID which originally issued a DosSavRedrawWait to  */
;            either relinquish ownership of the sav/rest function or   */
;            replace the existing thread with a different thread.      */
;                                                                      */
;  NOTES:  Executes on Level 3                                         */
;                                                                      */
;  ENTRY POINT:  DosSavRedrawUndo                                      */
;    LINKAGE:                                                          */
;                                                                      */
;  INPUT: - Ownership indicator      (0 = reserve ownership            */
;                                     1 = give up ownership            */
;         - Kill indicator           (0 = return error to thread       */
;                                     1 = terminate thread)            */
;         - VIOHandle                                                  */
;                                                                      */
;                                                                      */
;  EXIT-NORMAL:  AX = 0                                                */
;                                                                      */
;  EXIT-ERROR:   AX = error_vio_function_owned                         */
;                                                                      */
;  EFFECTS:  Contents of AX destroyed by return code                   */
;                                                                      */
;                                                                      */
;  INTERNAL REFERENCES:                                                */
;    ROUTINES:  SSCBUpdate, SSOpenSySem                                */
;                                                                      */
;  EXTERNAL REFERENCES:                                                */
;    ROUTINES:  DosSemRequest, DosGetInfoSeg,                          */
;               DosSemClear, 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                                     */
;                                                                      */
;************************ END OF SPECIFICATIONS ************************/

; IF <kill indicator or owner indicator are greater than 1>
;  AX = error_vio_invalid_parms
; ELSEIF <viohandle ne 0>
;  AX = error_vio_invalid_handle
; ELSE
;  IF <this is the first call>
;   AX = error_vio_no_save_restore_thd
;  ELSE
;   Get local seg
;   Wait on saveundosem  (in case a save is going on using a save mode thread)
;   Request the synch semaphore
;   Call SSGETSGCB (get pointer to sgcb)
;   IF <the current pid owns the save/restore screen function>
;    IF <relinquishing total ownership>
;     Clear ownership parameter
;    ELSE
;     Clear AX
;    END
;    Clear screen action variables
;    Store kill indicator where save/restore screen thread can find it
;    Set undoflag (notifies the thread that its time has come)
;    Release the thread by clearing the blocking semaphore
;    Clear the synch semaphore
;    IF <kill indicator e 1>  - meaning that the thread is to kill itself
;     REPEAT
;      Call DOSGETPRTY
;     UNTIL <the system returns a non-zero value indicating thread is gone>
;    ELSE
;     Clear save screen variable in instanced data segment
;    ENDIF
;     Clear AX
;     Clear the save screen thread variable
;   ELSEIF (if there is no current owner of the save/restore screen function)
;    AX = error_vio_no_save_restore_thread
;   ELSE (the current pid is not the registered owner)
;    AX = error_vio_function_owned
;   ENDIF
;   Clear synch semaphore
;  ENDIF
; ENDIF


EXTRN savelocksem:byte, savelockowner:word, savelockflag:byte
EXTRN SSOPENSYSEM:near
EXTRN saveundosem:dword
EXTRN priority: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    SEGMENT WORD PUBLIC 'CODE' USE16                                ;@TL6

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

 PUBLIC  DOSSAVREDRAWUNDO

DOSSAVREDRAWUNDO   PROC    FAR

 push    bp
 mov     bp,sp

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


 .IF <ss:[bp].s_killindic a 1> OR       ; If error in parm
 .IF <ss:[bp].s_ownerindic a 1>
   mov     ax,error_vio_invalid_parms
 .ELSEIF <ss:[bp].s_viohandle ne 0>     ; ES7/8/87
   mov     ax,error_vio_invalid_handle  ; ES7/8/87
 .ELSE near
;  mov     ax,indatasg                  ; Set addr. to instanced        ;@TL6
;  mov     es,ax                        ; and common data segs          ;@TL6
   mov     ax,stdatasg
   mov     ds,ax
   les     si,ds:SMG_INSTANCE           ; Gain access to instance data  ;@TL6
   .IF <es:[si].in_sgid e 0>            ; If this is first call         ;@TL6
     mov     ax, error_vio_no_save_restore_thd  ; return an error
   .ELSE  near
;    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     es                         ; Get localsg into es           ;@TL6
;    pop     bx                                                         ;@TL6
;   .IF <zero ax> near                                                  ;@TL6
     .REPEAT                            ; ES10/8/87
       push    ds                       ; In case a save is ongoing
       push    offset saveundosem       ; which uses the saverest thread
       push    dword ptr timeout        ; Indefinite wait               ;CJ10
;CJ10  push    timeout
       call    DOSSEMWAIT
     .UNTIL <AX ne error_interrupt>     ; ES10/8/87

     .IF <zero ax> near                                                 ;@TL6
       mov     es,localsg               ; Setup local infoseg in ES     ;@TL6
       mov     bx,es:LIS_curscrngrp     ; Get current pid#

       .repeat                                                          ;@GDW
         push    ds
         push    offset savelocksem
         push    dword ptr timeout      ; Indefinite wait               ;CJ10
;CJ10    push    timeout
         call    DOSFSRAMSEMREQUEST     ; 12-12-88 @GA1
       .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     ax,es:LIS_curprocid    ; 12-12-88 @GA1
;        mov     savelockowner,ax       ; 12-12-88 @GA1
         mov     savelockflag,7
         call    SSGETSGCB              ; Get pointer to sgcb
         .IF <zero ax> near                                             ;@TL6
           mov     cx,es:LIS_curprocid
           .IF <[di].saverestpid e cx> near  ; If pid# matches
             .IF <ss:[bp].s_ownerindic e 1>  ; if relinquishing
                                             ;total
               mov     [di].saverestpid,ax ; ownership, clear           ;@TL6
                                        ;pid#
;@TL6        .ELSE                      ; 9/26/86
;@TL6          mov     ax,indatasg
;@TL6          mov     es,ax
;@TL6          xor     ax,ax            ; 9/26/86
             .ENDIF
               cwde                                                     ;CJ10
               mov     [di].scrnactionflag,null
;CJ10          mov     word ptr [di].scrnactionflagaddr + 2,ax  ; zero  ;@TL6
               mov     dword ptr [di].scrnactionflagaddr, eax   ; zero;@TL6,CJ10

               mov     ax,ss:[bp].s_killindic
               mov     [di].scrnkillindicator,al
               or      [di].saverestflags,svredundoflag
;@TL6          mov     cx,di
               lea     cx,[di].saveresthreadsem                         ;@TL6
               push    ds
               push    cx
               call    DOSSEMCLEAR

             .IF <zero ax>                                              ;@TL6
               push    ds
               push    offset savelocksem
;              mov     savelockowner,0  ; ES9/3/87  12-12-88 @GA1
               mov     savelockflag,al  ; ES9/3/87  clear flag          ;@TL6
               call    DOSFSRAMSEMCLEAR ; 12-12-88 @GA1
             .ENDIF

             .IF <ss:[bp].s_killindic e 1>  ; 9/26/86
               .REPEAT                  ; Code to delay return to
                 push    2              ; caller until other thread
                 push    ds             ; is dead
                 push    offset priority
                 push    [di].saveresthreadid
                 call    DOSGETPRTY
               .UNTIL <nonzero ax>                                      ;@TL6
             .ELSE                      ; 9/26/86
;@TL6          mov     ax,indatasg
;@TL6          mov     es,ax
               les     si,ds:SMG_INSTANCE                               ;@TL6
               mov     es:[si].in_saverestpid,0  ; 9/26/86              ;@TL6
             .ENDIF

             xor     ax,ax              ; clear
             mov     [di].saveresthreadid,ax                            ;@TL6

           .ELSEIF <[di].saverestpid e 0>
             mov     ax,error_vio_no_save_restore_thd
           .ELSE
             mov     ax,error_vio_function_owned
           .ENDIF
          .IF <savelockflag e 7>
           push    ax
           push    ds
           push    offset savelocksem
;          mov     savelockowner,0      ; ES9/3/87 12-12-88 @GA1
           mov     savelockflag,0       ; ES9/3/87
           call    DOSFSRAMSEMCLEAR     ; 12-12-88 @GA1
           pop     cx
           .IF <zero ax>                                                ;@TL6
             xchg    ax,cx              ; save any previous error
           .ENDIF
          .ENDIF
         .ENDIF
       .ENDIF
     .ENDIF
;   .ENDIF                                                              ;@TL6
   .ENDIF
 .ENDIF
 pop     si
 pop     di
 pop     es
 pop     ds
 pop     dx
 pop     cx
 pop     bx
 pop     bp

 ret

DOSSAVREDRAWUNDO   ENDP
CODE    ENDS                                                            ;@TL6
 END

