/***************************************************************************
 *                                                                         *
 *   PASCRIT.C                                                             *
 *                                                                         *
 *   Copyright (c) 1996-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the GCOMM.LIB routine for setting the critical error vector   *
 *   to a routine that calls for retry 3 times, then fails the I/O         *
 *   operation.                                                            *
 *                                                                         *
 *                                        - T. Stryker 6/24/86             *
 *                    v6.0 enhancements   - C. Robert & S. Brinker 10/1/91 *
 *                    NT version          - I. Minkin 3/08/96              *
 *                                                                         *
 ***************************************************************************/

#define FILREV "$Revision: 5 $"

#ifdef GCDOS
#include "gcomm.h"
#include "brkthu.h"

#pragma inline
#pragma warn -par
                                   /* bits passed by DOS in AX for handler */
#define ALLOWIGNORE 0x2000         /*   handler is allowed to ignore error */
#define ALLOWRETRY  0x1000         /*   handler is allowed to retry I/O    */
#define ALLOWFAIL   0x0800         /*   handler is allowed to fail the I/O */

                                   /* codes returned in AL by handler      */
#define IGNORE           0         /*   ignore the error, continue         */
#define RETRY            1         /*   retry the I/O that produced error  */
#define FAIL             3         /*   fail the I/O, return to caller     */

#ifdef GCDOSP
static VOID _far _interrupt
critic(REGS_BINT r)                /* protmode critical error handler      */
#define ax r.ax
#define bp r.bp
#define si r.si
#else
static VOID interrupt
critic(bp,di,si,ds,es,dx,cx,bx,ax) /* non-protmode critical error handler  */
UINT bp,di,si,ds,es,dx,cx,bx,ax;
#endif // GCDOSP
{
     static UINT oldtik=0,cycount=0;

     enairp();
     if (btuTicker()-oldtik > 5) {
          cycount=0;
     }
     ax&=0xFF00;
     if (++cycount <= 3 && (ax&ALLOWRETRY)) {
          ax+=RETRY;
     }
     else if (ax&ALLOWFAIL) {
          ax+=FAIL;
     }
     else if (ax&ALLOWIGNORE) {
          ax+=IGNORE;
     }
     else {
          catastro("CRIT ERROR: CAN'T FAIL OR IGNORE");
     }
     oldtik=btuTicker();
}

VOID
pascrit(VOID)                 /* set DOS critical error handler vector     */
{
#ifdef GCDOSP
     PIHANDLER protcre;
     REALPTR realcre;

     DosSetPassToProtVec(0x24,critic,&protcre,&realcre);
#else
asm  push ds                  /* in real mode and under Ergo, set it the   */
asm  mov  dx,offset critic    /*   old fashioned way                       */
asm  mov  ax,cs
asm  mov  ds,ax
asm  mov  ah,25H
asm  mov  al,24H
asm  INT  21H
asm  pop  ds
#endif // GCDOSP
}
#else
#include <windows.h>
#include "gcomm.h"

VOID
pascrit(VOID)                      /* crit error handler (passive flavor)  */
{
  UINT errMode=SetErrorMode(0);
  errMode|=SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX;
  SetErrorMode(errMode);
}
#endif // GCDOS
