;       SCCSID = @(#)demctrlc.asm	6.1 91/07/12
;       SCCSID = @(#)demctrlc.asm       6.1 90/11/17
;       SCCSID = @(#)ctrlc.asm  13.15   90/09/18
; Low level routines for detecting special characters on CON input,
;       the ^C exit/int code, the Hard error INT 24 code, the
;       process termination code, and the INT 0 divide overflow handler.
;
;   FATAL
;   FATAL1
;   reset_environment
;   DSKSTATCHK
;   SPOOLINT
;   STATCHK
;   CNTCHAND
;   DIVOV
;   CHARHARD
;   HardErr
;
;   Revision history:
;
;       AN000   version 4.0   Jan 1988
;       A002    PTM    -- dir >lpt3 hangs
;       A003    PTM 3957- fake version for IBMCAHE.COM

;
; get the appropriate segment definitions
;
.xlist
include v86seg.inc

.xcref
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include demmac.inc
include dossymc.inc
include devsym.inc
include demver.inc
include demdbcs.inc
include sft.inc
include demdev.inc
include mi.inc
include syscalls.inc
include error.inc
include vector.inc
include pdb.inc
include exe.inc
include mvdmexp.inc
include demsvc.inc
include demmult.inc
include harderr.inc
include basemid.inc
include utilmid2.inc
.cref
.list

; from 4.0 filemode.inc
ext_open_I24_off        EQU 02H

        CpuMode 286

        I_Need  SFN,WORD
        I_Need  pJFN,DWORD
        I_Need  DevIOBuf,BYTE
        I_Need  DidCTRLC,BYTE
        I_Need  INDOS,BYTE
        I_Need  DSKSTCOM,BYTE
        I_Need  DSKSTCALL,BYTE
        I_Need  DSKSTST,WORD
        I_Need  BCON,DWORD
        I_Need  DSKCHRET,BYTE
        I_Need  DSKSTCNT,WORD
        I_Need  IDLEINT,BYTE
        I_Need  CONSWAP,BYTE
        I_Need  user_SS,WORD
        I_Need  user_SP,WORD
        I_Need  User_In_AX,WORD
        I_Need  ERRORMODE,BYTE
        I_Need  ConC_spsave,WORD
        I_Need  Exit_type,BYTE
        I_Need  PFLAG,BYTE
        I_Need  ExitHold,DWORD
        I_Need  WPErr,BYTE
        I_Need  CONTSTK,WORD
        I_Need  Exit_Code,WORD
        I_Need  CurrentPDB,WORD
        I_Need  ALLOWED,BYTE
        I_Need  FAILERR,BYTE
        I_Need  EXTERR,WORD
        I_Need  fAborting,BYTE
        I_Need  AUXStack,BYTE
        I_Need  SCAN_FLAG,BYTE
        I_Need  EXTOPEN_ON,BYTE               ;AN000; DOS 4.0
        I_Need  InterCon,BYTE                 ;AN000; DOS 4.0
        I_Need  DOS34_FLAG,WORD               ;AN000; DOS 4.0
        I_Need  Special_Version,WORD          ;AN007; DOS 4.0
        I_Need  SaveDS,WORD
        I_Need  SaveBX,WORD
        I_Need  Message_Buffer,BYTE
if debug
        I_Need  BugLev,WORD
        I_Need  BugTyp,WORD
;       include bugtyp.asm
endif
        I_Need  vheVDM,BYTE


V86CODE    SEGMENT
        ASSUME  CS:V86GROUP
IF      BUFFERFLAG
        extrn   restore_user_map:near
ENDIF
        EXTRN   $Get_Interrupt_Vector:NEAR
        EXTRN   BUFOUT:NEAR
        EXTRN   CAL_LK:NEAR
;m        EXTRN   CRLF:NEAR
        EXTRN   DEVIOCALL2:NEAR
        EXTRN   DOS_ABORT:NEAR
        EXTRN   GET_IO_SFT:NEAR
        EXTRN   IOFUNC:NEAR
        EXTRN   Reset_Version:NEAR
        EXTRN   SWAPBACK:NEAR
        EXTRN   arena_free_process:NEAR
        EXTRN   restore_world:NEAR
        EXTRN   ECritDisk:NEAR
        EXTRN   LCritDisk:NEAR
        EXTRN   get_user_stack:NEAR
        EXTRN   RMDevOpen:NEAR
        EXTRN   RMDevClose:NEAR

IF NOT_FILTER

Break   <Checks for ^C in CON I/O>

ASSUME  DS:NOTHING,ES:NOTHING

        procedure   DSKSTATCHK,NEAR     ; Check for ^C if only one level in
        CMP     BYTE PTR [INDOS],1
        retnz                           ; Do NOTHING
        PUSH    CX
        PUSH    ES
        PUSH    BX
        PUSH    DS
        PUSH    SI
        PUSH    CS
        POP     ES
        Context DS
        DOSAssume   CS,<DS>,"DskStatChk"
        MOV     BYTE PTR [DSKSTCOM],CMDNDR
        MOV     BYTE PTR [DSKSTCALL],LENNDR
        MOV     [DSKSTST],0
 IF  DBCS                               ;AN000;
        MOV     AL, [InterCon]          ;AN000;get type of status read 2/13/KK
        MOV     BYTE PTR [DSKCHRET],AL  ;AN000; load interim flag into packet
 ENDIF                                  ;AN000;
        MOV     BX,OFFSET V86GROUP:DSKSTCALL
        LDS     SI,[BCON]
ASSUME  DS:NOTHING
        invoke  DEVIOCALL2
        TEST    [DSKSTST],STBUI
        JZ      GotCh                   ; No characters available
        XOR     AL,AL                   ; Set zero
RET36:
        POP     SI
        POP     DS
        POP     BX
        POP     ES
        POP     CX
        return

GotCh:
        MOV     AL,BYTE PTR [DSKCHRET]
DSK1:
        CMP     AL,"C"-"@"
        JNZ     RET36
        MOV     BYTE PTR [DSKSTCOM],CMDINPUT
        MOV     BYTE PTR [DSKSTCALL],LENIO
        MOV     BYTE PTR [DSKCHRET],CL
        MOV     [DSKSTST],0
        MOV     [DSKSTCNT],1
        invoke  DEVIOCALL2              ; Eat the ^C
        POP     SI
        POP     DS
        POP     BX                      ; Clean stack
        POP     ES
        POP     CX
        JMP     CNTCHAND

NOSTOP:
        CMP     AL,"P"-"@"
        JNZ     check_next
        CMP     BYTE PTR [SCAN_FLAG],0        ; ALT_Q ?
        JZ      INCHKJ                        ; no
        return
check_next:
        IF      NOT TOGLPRN
        CMP     AL,"N"-"@"
        JZ      INCHKJ
        ENDIF

        CMP     AL,"C"-"@"
        JZ      INCHKJ
check_end:
        return

INCHKJ:
        JMP     INCHK

EndProc DSKSTATCHK

;
; SpoolInt - signal processes that the DOS is truly idle.  We are allowed to
; do this ONLY if we are working on a 1-12 system call AND if we are not in
; the middle of an INT 24.
;
procedure   SPOOLINT,NEAR
        PUSHF
        test    IdleInt,-1
        jz      POPFRet

;*************************************************************************
;**     WARNING WARNING                                                  *
;                                                                        *
;       Sidekick (and possibly others) looks for this specific code      *
;       sequence relative to the INT 28 to determine the location        *
;       of the ErrorMode variable.  Sidekick inspects this variable      *
;       to determine if it is running at INT 24h time (in which case     *
;       it cannot come up because it cannot issue any system calls).     *
sint1:                                  ;                                *
        test    ErrorMode,-1            ;                                *
        jnz     POPFRet                 ;                                *
;                                                                        *
; Note that we are going to allow an external program to issue system calls
; at this time.  We MUST preserve IdleInt across this.                   *
;                                                                        *
        PUSH    WORD PTR IdleInt        ;                                *
        INT     int_spooler             ;                                *
    .errnz      (($-0fh)-sint1)         ; special Sidekick support       *
;*************************************************************************

        POP     WORD PTR IdleInt
POPFRET:
        POPF
        return
EndProc SPOOLINT

        procedure   STATCHK,NEAR

        invoke  DSKSTATCHK              ; Allows ^C to be detected under
                                        ; input redirection
        PUSH    BX
        XOR     BX,BX
        invoke  GET_IO_SFT
        POP     BX
        retc
        MOV     AH,1
        invoke  IOFUNC
        JZ      SPOOLINT
        CMP     AL,"S"-"@"
        JNZ     NOSTOP

        CMP     BYTE PTR [SCAN_FLAG],0        ;AN000; ALT_R ?
        JNZ     check_end                     ;AN000; yes
        XOR     AH,AH
        invoke  IOFUNC                  ; Eat Cntrl-S
        JMP     SHORT PAUSOSTRT


PRINTOFF:
PRINTON:
        NOT     BYTE PTR [PFLAG]
        PUSH    BX
        MOV     BX,4
        invoke  GET_IO_SFT
        POP     BX
        jc      short RETP6

IFDEF NOT_MVDM  ; BUGBUG sudeepb 19-Mar-1990 defed out for network support

        TEST    ES:[DI.sf_flags],sf_net_spool
        JZ      NORM_PR                 ; Not redirected, echo is OK
        Callinstall NetSpoolEchoCheck,MultNet,38,<AX>,<AX> ; See if allowed
        JNC     NORM_PR                 ; Echo is OK
        MOV     BYTE PTR [PFLAG],0      ; If not allowed, disable echo
        Callinstall NetSpoolClose,MultNet,36,<AX>,<AX> ; and close
        JMP     SHORT RETP6

ENDIF

NORM_PR:
        CMP     BYTE PTR [PFLAG],0
        JNZ     PRNOPN
        call    RMDevClose
        JMP     SHORT RETP6

PRNOPN:
        call    RMDevOpen

RETP6:  return



PAUSOLP:
        CALL    SPOOLINT
PAUSOSTRT:
        MOV     AH,1
        invoke  IOFUNC
        JZ      PAUSOLP
INCHK:
        PUSH    BX
        XOR     BX,BX
        invoke  GET_IO_SFT
        POP     BX
        retc
        XOR     AH,AH
        invoke  IOFUNC
        CMP     AL,"P"-"@"
;;;;;  7/14/86  ALT_Q key fix

        JZ      PRINTON                       ; no! must be CTRL_P

;;;;;  7/14/86  ALT_Q key fix
        IF      NOT TOGLPRN
        CMP     AL,"N"-"@"
        JZ      PRINTOFF
        ENDIF
        CMP     AL,"C"-"@"
        retnz
EndProc STATCHK

        procedure   CNTCHAND,NEAR
; Ctrl-C handler.
; "^C" and CR/LF is printed.  Then the user registers are restored and the
; user CTRL-C handler is executed.  At this point the top of the stack has 1)
; the interrupt return address should the user CTRL-C handler wish to allow
; processing to continue; 2) the original interrupt return address to the code
; that performed the function call in the first place.  If the user CTRL-C
; handler wishes to continue, it must leave all registers unchanged and RET
; (not IRET) with carry CLEAR.  If carry is SET then an terminate system call
; is simulated.
        TEST    [DOS34_FLAG],CTRL_BREAK_FLAG  ;AN002; from RAWOUT
        JNZ     around_deadlock               ;AN002;
        MOV     AL,3                    ; Display "^C"
        invoke  BUFOUT
        invoke  CRLF
around_deadlock:                              ;AN002;
        push    cs
        pop     ds
        ASSUME  DS:V86GROUP
        CMP     BYTE PTR [CONSWAP],0
        JZ      NOSWAP
        invoke  SWAPBACK
NOSWAP:
        CLI                             ; Prepare to play with stack
        MOV     SS,[user_SS]            ; User stack now restored
        MOV     SP,[user_SP]
        invoke  restore_world           ; User registers now restored
ASSUME  DS:NOTHING
        MOV     BYTE PTR [INDOS],0      ; Go to known state
        MOV     BYTE PTR [ERRORMODE],0
        MOV     [ConC_spsave],SP        ; save his SP
        CLC
        INT     int_ctrl_c              ; Execute user Ctrl-C handler
;
; The user has returned to us.  The circumstances we allow are:
;
;   IRET        We retry the operation by redispatching the system call
;   CLC/RETF    POP the stack and retry
;   ...         Exit the current process with ^C exit
;
; User's may RETURN to us and leave interrupts on.  Turn 'em off just to be
; sure
;
        CLI
        MOV     [user_IN_AX],ax         ; save the AX
        PUSHF                           ; and the flags (maybe new call)
        POP     AX
;
; See if the input stack is identical to the output stack
;
        CMP     SP,[ConC_spsave]
        JNZ     ctrlc_try_new           ; current SP not the same as saved SP
;
; Repeat the operation by redispatching the system call.
;
ctrlc_repeat:
        MOV     AX,User_In_AX
        transfer    COMMAND
;
; The current SP is NOT the same as the input SP.  Presume that he RETF'd
; leaving some flags on the stack and examine the input
;
ctrlc_try_new:
        ADD     SP,2                    ; pop those flags
        TEST    AX,f_carry              ; did he return with carry?
        JZ      Ctrlc_Repeat            ; no carry set, just retry
;
; Well...  time to abort the user.  Signal a ^C exit and use the EXIT system
; call..
;
ctrlc_abort:
        MOV     AX,(EXIT SHL 8) + 0
        MOV     DidCTRLC,-1
        transfer    COMMAND             ; give up by faking $EXIT

EndProc CNTCHAND


Break   <DIVISION OVERFLOW INTERRUPT>

; Default handler for division overflow trap
        procedure   DIVOV,NEAR
ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
        mov     ax, MSG_CMD_DIV_0
        mov     di, offset Message_Buffer
        push    cs
        pop     es                      ; (es:di) = message buffer
        svc     SVC_DEMGETMESSAGE
        MOV     SI,DI
        LODS    WORD PTR CS:[SI]        ; (AX) = length
        MOV     BX,AX                   ; (BX) = length
        MOV     AX,CS
        MOV     SS,AX
        MOV     SP,OFFSET V86GROUP:AUXSTACK ; Enough stack for interrupts
        CALL    OutMes
        JMP     ctrlc_abort             ; Use Ctrl-C abort on divide overflow
EndProc DIVOV

;filter
ENDIF

;
; OutMes: perform message output
; Inputs:   SS:SI points to message
;           BX has message length
; Outputs:  message to BCON
;
procedure   OutMes,NEAR

        Context ES                      ; get ES addressability
        Context DS                      ; get DS addressability

        MOV     BYTE PTR [DskStCom],CMDOUTPUT
        MOV     BYTE PTR [DskStCall],LENIO
        MOV     [DskSTST],0
        MOV     [DskStCnt],BX
        MOV     BX,OFFSET V86GROUP:DskStCall
        MOV     WORD PTR [DskChRet+1],SI    ; transfer address (need an EQU)
        LDS     SI,[BCON]
ASSUME  DS:NOTHING
        invoke  DEVIOCALL2
        MOV     WORD PTR [DskChRet+1],OFFSET V86GROUP:DevIOBuf
        MOV     [DskStCnt],1
        return
EndProc OutMes

Break   <CHARHRD,HARDERR,ERROR -- HANDLE DISK ERRORS AND RETURN TO USER>

        procedure   CHARHARD,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Character device error handler
; Same function as HARDERR

        SaveReg <bx,cx,dx,bp,si,di,ds,es>
        OR      AH,allowed_FAIL + allowed_IGNORE + allowed_RETRY
        MOV     Allowed,AH
        MOV     WORD PTR [EXITHOLD+2],ES
        MOV     WORD PTR [EXITHOLD],BP
        AND     DI,STECODE
        MOV     BP,DS                   ; Device pointer is BP:SI
;m        CALL    FATALC
        RestoreReg <es,ds,di,si,bp,dx,cx,bx>
        return
EndProc CHARHARD

;***    CheckHardError - check for hard error
;
;       This routine checks for hard error that might have happened
;       in a SVC call.  It dispatches to the int 24 handler if a hard
;       error occured.
;
;       ENTRY   NONE
;
;       EXIT    if carry set, fail
;               if carry clear, ignore
;
;       USES    Flags
;
;       Retry and Abort responses are automaticly taken care of.
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

Procedure CheckHardError,near
        test    cs:[vheVDM.vhe_fbMisc],VHE_FLAG_ACTIVE ; pending hard errors?
        jne     short che10             ;  yes, jump to dispatch code
        stc                             ;  no, return fail
        ret

che10:  push    ds
        push    es
        pusha
        context ds
        mov     bp,ds                   ; (BP:SI) = device driver header
        mov     si,offset V86GROUP:vheVDM.vhe_abDeviceHeader
        and     [vheVDM.vhe_fbMisc],not VHE_FLAG_ACTIVE
        mov     di,[vheVDM.vhe_usPacketErr]
        mov     ah,[vheVDM.vhe_fbInt24]
        mov     al,[vheVDM.vhe_fbAllowed]
        mov     [ALLOWED],al
        mov     al,[vheVDM.vhe_bDriveNum]

;       Set the extended error fields with the OS2 kernel error
;       code.  We lose info if the error code returned by
;       SET_I24_EXTENDED_ERROR is used.

        push    si
        mov     si,[vheVDM.vhe_usFailErr]
        mov     [EXTERR],si
;mdr        mov     si,offset V86GROUP:ERR_TABLE_24
        invoke  CAL_LK                  ; set other extended error fields
        pop     si

;       (AX) = drive number and flags
;       (DI) = packet error code
;       (BP:SI) = device driver address
;       [ALLOWED] = allowed flags

;m        call    NET_I24_ENTRY           ; (AL) = response
    ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING
        cmp     al,HDERR_RETRY
        jne     che20                   ; jmp if ignore or fail
        invoke  get_user_stack          ; (DS:SI) = user stack frame
        mov     ax,[si].user_AX
        mov     bx,[si].user_BX
        mov     cx,[si].user_CX
        mov     dx,[si].user_DX
        mov     di,[si].user_DI
        mov     bp,[si].user_BP
        mov     es,[si].user_ES
        push    [si].user_SI
        push    [si].user_DS
        pop     ds
        pop     si
        MOV     [SaveDS],DS             ; PTR B787305
        MOV     [SaveBX],BX
        transfer REDISP                 ; retry system call

che20:  popa
        pop     es
        pop     ds
        cmc                             ; make fail carry set/ignore carry clear
        ret
EndProc   CheckHardError

IF NOT_FILTER

; DI has the INT-24-style extended error.  We now map the error code for this
; into the normalized get extended error set by using the ErrMap24 table as an
; translate table.  Note that we translate ONLY the device returned codes and
; leave all others beyond the look up table alone.
;
        ASSUME  DS:NOTHING, ES:NOTHING
Entry   FATALC
        call    SET_I24_EXTENDED_ERROR
        CMP     DI,error_I24_gen_failure
        JBE     GOT_RIGHT_CODE          ; Error codes above gen_failure get
        MOV     DI,error_I24_gen_failure ; mapped to gen_failure. Real codes
                                        ;  Only come via GetExtendedError

        entry   NET_I24_ENTRY
; Entry point used by REDIRector on Network I 24 errors.
;
;       ASSUME  DS:NOTHING,ES:NOTHING
;
; ALL I 24 regs set up. ALL Extended error info SET. ALLOWED Set.
;     EXITHOLD set for restore of ES:BP.

GOT_RIGHT_CODE:
        CMP     BYTE PTR [ERRORMODE],0  ; No INT 24s if already INT 24
        JZ      NoSetFail
        MOV     AL,3
        JMP     FailRet
NoSetFail:
IF      BUFFERFLAG
;       invoke  RESTORE_USER_MAP                ;AN000;LB. restore user's EMS map
ENDIF
        MOV     [CONTSTK],SP
        Context ES
;        fmt TypINT24,LevLog,<"INT 24: AX = $x DI = $x\n">,<AX,DI>
;
; Wango!!!  We may need to free some user state info...  In particular, we
; may have locked down a JFN for a user and he may NEVER return to us.  Thus,
; we need to free it here and then reallocate it when we come back.
;
        CMP     SFN,-1
        JZ      NoFree
        SaveReg <DS,SI>
        LDS     SI,pJFN
        MOV     BYTE PTR [SI],0FFH
        RestoreReg  <SI,DS>
NoFree:
        CLI                             ; Prepare to play with stack
        INC     BYTE PTR [ERRORMODE]    ; Flag INT 24 in progress
        DEC     BYTE PTR [INDOS]        ; INT 24 handler might not return
;; Extneded Open hooks
        TEST    [DOS34_FLAG],Force_I24_Fail   ;AN000;IFS. form IFS Call Back          ;AN000;
        JNZ     faili24                       ;AN000;IFS.                             ;AN000;
        TEST    [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;IFS.I24 error disabled           ;AN000;
        JZ      i24yes                        ;AN000;IFS.no                           ;AN000;
faili24:                                      ;AN000;
        MOV     AL,3                          ;AN000;IFS.fake fail                    ;AN000;
        JMP     passi24                       ;AN000;IFS.exit                         ;AN000;
i24yes:                                       ;AN000;

;; Extended Open hooks
        MOV     SS,[user_SS]
        MOV     SP,ES:[user_SP]         ; User stack pointer restored
        INT     int_fatal_abort         ; Fatal error interrupt vector, must preserve ES
        MOV     ES:[user_SP],SP         ; restore our stack
        MOV     ES:[user_SS],SS
        MOV     BP,ES
        MOV     SS,BP
passi24:                                ;AN000;
        MOV     SP,[CONTSTK]
        INC     BYTE PTR [INDOS]        ; Back in the DOS
        MOV     BYTE PTR [ERRORMODE],0  ; Back from INT 24
        STI
;;      MOV     [ACT_PAGE],-1           ;LB. invalidate DOS active page         ;AN000;
;;      invoke  SAVE_MAP                ;LB. save user's EMS map                ;AN000;
;        fmt TypINT24,LevLog,<"INT 24: User reply = $x\n">,<AX>
FAILRET:
        LES     BP,[EXITHOLD]
ASSUME  ES:NOTHING
;
; Triage the user's reply.
;
        CMP     AL,1
        JB      CheckIgnore             ; 0 => ignore
        JZ      CheckRetry              ; 1 => retry
        CMP     AL,3                    ; 3 => fail
        JNZ     DoAbort                 ; 2, invalid => abort
;
; The reply was fail.  See if we are allowed to fail.
;
        TEST    [ALLOWED],allowed_FAIL  ; Can we?
        JZ      DoAbort                 ; No, do abort

DoFail:
        MOV     AL,3                    ; just in case...
        TEST    [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO. I24 error disabled
        JNZ     cleanup                       ;AN000;EO. no
        INC     [FAILERR]               ; Tell everybody
CleanUp:
        MOV     WpErr,-1
        CMP     SFN,-1
        retz
        SaveReg <DS,SI,AX>
        MOV     AX,SFN
        LDS     SI,pJFN
        MOV     [SI],AL
        RestoreReg  <AX,SI,DS>
        return
;
; The reply was IGNORE.  See if we are allowed to ignore.
;
CheckIgnore:
        TEST    [ALLOWED],allowed_IGNORE ; Can we?
        JZ      DoFail                  ; No, do fail
        JMP     CleanUp
;
; The reply was RETRY.  See if we are allowed to retry.
;
CheckRetry:
        TEST    [ALLOWED],allowed_RETRY ; Can we?
        JZ      DoFail                  ; No, do fail
        JMP     CleanUp
;
; The reply was ABORT.
;
DoAbort:
        Context DS
        CMP     BYTE PTR [CONSWAP],0
        JZ      NOSWAP2
        invoke  SWAPBACK
NOSWAP2:
;
; See if we are to truly abort.  If we are in the process of aborting, turn
; this abort into a fail.
;
        TEST    fAborting,-1
        JNZ     DoFail
;
; Set return code
;
        MOV     BYTE PTR [exit_Type],Exit_hard_error
        XOR     AL,AL
;
; we are truly aborting the process.  Go restore information from the PDB as
; necessary.
;
        Transfer    exit_inner

;
; reset_environment checks the DS value against the CurrentPDB.  If they are
; different, then an old-style return is performed.  If they are the same,
; then we release jfns and restore to parent.  We still use the PDB at DS:0 as
; the source of the terminate addresses.
;
; Some subtlety:  We are about to issue a bunch of calls that *may* generate
; INT 24s.  We *cannot* allow the user to restart the abort process; we may
; end up aborting the wrong process or turn a terminate/stay/resident into a
; normal abort and leave interrupt handlers around.  What we do is to set a
; flag that will indicate that if any abort code is seen, we just continue the
; operation.  In essence, we dis-allow the abort response.
;
; output:   none.
;
        entry   reset_environment
        ASSUME  DS:NOTHING,ES:NOTHING

        invoke  Reset_Version           ;AN007;MS. reset version number
        PUSH    DS                      ; save PDB of process

;
; There are no critical sections in force.  Although we may enter here with
; critical sections locked down, they are no longer relevant.  We may safely
; free all allocated resources.
;
        MOV     AH,82h
        INT     int_IBM

        MOV     fAborting,-1            ; signal abort in progress

        CallInstall NetResetEnvironment, multNet, 34  ;DOS 4.00 doesn't need it
                                        ; Allow REDIR to clear some stuff
                                        ;   On process exit.
        MOV     AL,int_Terminate
        invoke  $Get_interrupt_vector   ; and who to go to

        POP     CX                      ; get ThisPDB
        push    es
        push    bx                      ; save return address

        MOV     BX,[CurrentPDB]         ; get currentPDB
        MOV     DS,BX
        MOV     AX,DS:[PDB_Parent_PID]  ; get parentPDB

;
; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB
; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not
; Exit_keep_process
;
        CMP     AX,BX
        JZ      reset_return            ; parentPDB = CurrentPDB
        CMP     BX,CX
        JNZ     reset_return            ; CurrentPDB <> ThisPDB
        PUSH    AX                      ; save parent
        CMP     BYTE PTR [exit_type],Exit_keep_process
        JZ      reset_to_parent         ; keeping this process
;
; We are truly removing a process.  Free all allocation blocks belonging to
; this PDB
;
        invoke  arena_free_process
;
; Kill off remainder of this process.  Close file handles and signal to
; relevant network folks that this process is dead.  Remember that CurrentPDB
; is STILL the current process!
;
        invoke  DOS_ABORT

reset_to_parent:
        POP     ES
        SVC     SVC_DEMSETCURRENTPDB    ; Tell OS/2 of the change
        MOV     CurrentPDB,ES           ; set up process as parent

reset_return:                           ; come here for normal return
        PUSH    CS
        POP     DS
        ASSUME  DS:V86GROUP
        MOV     AL,-1
;
; make sure that everything is clean In this case ignore any errors, we cannot
; "FAIL" the abort, the program being aborted is dead.
;
;       EnterCrit   critDisk
;       invoke  FLUSHBUF
;       LeaveCrit   critDisk
;
; Decrement open ref. count if we had done a virtual open earlier.
;
;       invoke  CHECK_VIRT_OPEN

IF      BUFFERFLAG
        invoke  RESTORE_USER_MAP                ;AN000;LB. restore user's EMS map
ENDIF
        CLI
        MOV     BYTE PTR [INDOS],0      ; Go to known state
        MOV     BYTE PTR [WPERR],-1     ; Forget about WP error
        MOV     fAborting,0             ; let aborts occur
        POP     WORD PTR ExitHold
        POP     WORD PTR ExitHold+2
;
; Snake into multitasking... Get stack from CurrentPDB person
;
        MOV     DS,[CurrentPDB]
        ASSUME  DS:NOTHING
        MOV     SS,WORD PTR DS:[PDB_user_stack+2]
        MOV     SP,WORD PTR DS:[PDB_user_stack]

        invoke  restore_world
        ASSUME  ES:NOTHING
        MOV     User_SP,AX
        POP     AX                      ; suck off CS:IP of interrupt...
        POP     AX
        POP     AX
        MOV     AX,0F202h               ; STI
        PUSH    AX
        PUSH    WORD PTR [EXITHOLD+2]
        PUSH    WORD PTR [EXITHOLD]
        MOV     AX,User_SP
        IRET                            ; Long return back to user terminate address


;
; This routine handles extended error codes.
; Input : DI = error code from device
; Output: All EXTERR fields are set
;
Procedure SET_I24_EXTENDED_ERROR,NEAR
        PUSH    AX
;mdr        MOV     AX,OFFSET V86GROUP:ErrMap24End
;mdr        SUB     AX,OFFSET V86GROUP:ErrMap24
;
; AX is the index of the first unavailable error.  Do not translate if
; greater or equal to AX.
;
        CMP     DI,AX
        MOV     AX,DI
        JAE     NoTrans
;mdr        MOV     AL,ErrMap24[DI]
        XOR     AH,AH
NoTrans:
        MOV     [EXTERR],AX
        POP     AX
;
; Now Extended error is set correctly.  Translate it to get correct error
; locus class and recommended action.
;
        PUSH    SI
;mdr        MOV     SI,OFFSET V86GROUP:ERR_TABLE_24
        invoke  CAL_LK                  ; Set other extended error fields
        POP     SI
        ret
EndProc SET_I24_EXTENDED_ERROR

BREAK <IntCharIO - interrupt char I/O for SPOOLINT and possible freeze/resched>
;***    IntCharIO - interrupt char I/O for SPOOLINT and possible freeze/resched
;
;   This function is called by at least once during the execution of all
;   character I/O system calls.  The DOS is polling to do character I/O
;   instead of having interrupt driven I/O.  This is done so that tasks
;   which are doing character I/O can be "quickly" frozen if need be and
;   so that SPOOLINTs can be issued.
;
;   Int_spooler (usually Int 28h) handlers are invoked if IdleInt is set and
;   the foreground task is running.  The handlers are allowed to issue ALL
;   system calls except $Std_Con_String_Input.
;
;
;       ENTRY   none
;
;       EXIT    none
;
;       USES    none

        ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure IntCharIO,NEAR

        PUSHF
        .286p
        PUSHA
        CpuMode reset
        SaveReg <DS,ES>

;*  Issue INT 28, if it is okay to do so

        CMP     IdleInt,0               ; Are spoolints ok?
        JZ      icio3                   ; No, skip the int

        call    SPOOLINT

icio3:  RestoreReg <ES,DS>
    ASSUME  DS:NOTHING,ES:NOTHING
        .286p
        POPA
        CpuMode reset
        POPF
        RET

EndProc IntCharIO

;filter
ENDIF

V86CODE ENDS

        END
