community.borland.com

Article #15026: MS-DOS interrupt 24 trap routine

 Technical Information Database

TI26D.txt - MS-DOS interrupt 24 trap routine

Category   :Turbo Pascal
Platform   :DOS
Product    :

Description:

The following example routines are public domain programs
that have been uploaded to our Forum on CompuServe. As a
courtesy to our users that do not have immediate access to
CompuServe, Technical Support distributes these routines free
of charge.

However, because these routines are public domain programs,
not developed by Borland International, we are unable to provide 
any technical support or assistance using these routines. If you
need assistance using these routines, or are experiencing
difficu

Thanks to Marshall Brain for the original code for this routine.

These routines provide a method for Turbo Pascal programs to trap
MS-DOS interrupt 24. INT 24 is called by DOS when a "critical error"
occurs, and it normally prints the familiar "Abort, Retry, Ignore?"
message.

With the INT 24 handler installed, errors of this type will be passed
on to Turbo Pascal as an error. If I/O checking is on, this will cause
 a program crash. If I/O checking is off, IOResult will return an error
code. The global variable INT24Err will b

In most cases, INT24Result should be used, because INT24Err must
be set back to false, and DOS sometimes restores its normal INT 24
handler after an error.
-------------------------------------------------------------------
**Note: Turbo's normal IOResult codes (and Turbo Access error codes)
for MS-DOS DO NOT correspond to I/O error numbers given in Appendix I
of the Turbo Pascal manual, or error codes given in the I/O error nn,
PC=aaaa/Program aborted message. Here is

  IOResult     Turbo error
 ----------    -----------------------------------------------
   00 (0)      00 (0)     none
   01 (1)      90 (144)   record length mismatch
   02 (2)      01 (1)     file does not exist
   03 (3)      F1 (241)   directory is full
   04 (4)      FF (255)   file disappeared
   05 (5)      02 (2)     file not open for input
   06 (6)      03 (3)     file not open for output
   07 (7)      99 (153)   unexpected end of file
   08 (8)      F0 (240)   disk write error
   09 (9)      10 (16)    error in numeric format
   0A (10)     99 (153)   unexpected end of file
   0B (11)     F2 (242)   file size overflow
   0C (12)     99 (153)   unexpected end of file
   0D (13)     F0 (240)   disk write error
   0E (14)     91 (145)   seek beyond end of file
   0F (15)     04 (4)     file not open
   10 (16)     20 (32)    operation not allowed on a logical device
   11 (17)     21 (33)    not allowed in direct mode
   12 (18)     22 (34)    assign to standard files is not allowed
   90 (144)    90 (144)   record length mismatch


program CriticalError;

Const INT24Err     : Boolean=False;
      INT24ErrCode : Byte=0;
      OldINT24     : Array [1..2] Of Integer=(0,0);

Var RegisterSet    : Record Case Integer Of
                       1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: Integer);
                       2: (AL,AH,BL,BH,CL,CH,DL,DH: Byte);
                     End;

Procedure INT24;
  Const FCBFuncs: Array [1..6] Of Byte=(14,15,21,22,27,28);
  Begin
    { To understand this routine, you will need to read the description of
      Interrupt 24h in the DOS manual.  It also helps to examine and
         trace the
      generated code under DEBUG. }
    Inline($0E/$0E/$1F/$07/$C6/$06/ INT24Err /$01/$89/$EC/$83/$C4/$08/
           $89/$F8/$A2/ INT24ErrCode /$58/$B9/$06/$00/$BF/ FCBFuncs /$F2/
           $AE/$75/$04/$B0/$01/$EB/$08/$3C/$39/$B0/$FF/$72/$02/$B0/$83/
           $5B/$59/$5A/$5E/$5F/$89/$E5/$80/$4E/$0A/$01/$5D/$1F/$07/$CF);
{   Turbo:  PUSH BP                    (Save caller's stack frame
            MOV  BP,SP                   Set up this procedure's stack
            PUSH BP                     ?)                        frame
    Inline: PUSH CS
            PUSH CS
            POP  DS                    Set DS and ES temporarily to CS
            POP  ES
            MOV  BYTE [INT24Err],1     Set INT24Err to True  (CS:)
            MOV  SP,BP                 Get correct SP;  ADD: Discard saved
            ADD  SP,8                    BP, INT 24h return address & flags
            MOV  AX,DI                 Get INT 24h error code
            MOV  [INT24ErrCode],AL     Save it in INT24ErrCode
            POP  AX                    Get initial DOS call number
            MOV  CX,6                  Search for it in FCBFuncs: is this
                                                  one
            MOV  DI,Offset FCBFuncs      of the FCB functions that
                                             requires an
            REPNZ SCASB                  error code of 01 in AL?
            JNZ  .1
            MOV  AL,1                  Yes: set it
            JMP  .2

 .1      CMP  AL,39h                No: is it an FCB function that requires
         MOV  AL,0FFh                 AL=FFh (function <39h)?  Yes: set it.
         JB   .2
         MOV  AL,83h                No: handle call, return error 83h, call
                                      failed via INT 24h.
                                    The error code (1, FFh or 83h) is
                                      returned to the Turbo runtime routine
                                      that called DOS, making it look like
                                      a simple DOS error.  Turbo handles
                                      the I/O error.
 .2      POP  BX                    Pop the rest of the registers saved by
         POP  CX                      the initial INT 21h.
         POP  DX
         POP  SI
         POP  DI
         MOV  BP,SP
         OR   Byte Ptr [BP+0Ah],1   Set the carry flag in the saved Flags
                                         reg.
         POP  BP
         POP  DS
         POP  ES
         IRET                       Return to next instruction: all regs.
                                      restored, AL=error code, carry set. }
End;




Procedure INT24On;  {Enable INT 24 trapping}
Begin
  INT24Err:=False;
  With RegisterSet Do
  Begin
    AX:=$3524;
    MsDos(RegisterSet);
    If (OldINT24[1] Or OldINT24[2]) = 0 Then
    Begin
      OldINT24[1]:=ES;
      OldINT24[2]:=BX;
    End;
    DS:=CSeg;
    DX:=Ofs(INT24);
    AX:=$2524;
    MsDos(RegisterSet);
  End;
End;

Procedure INT24Off;  {Disable INT 24 trapping.  Should be done at the
                      end of the program, if you plan to be running
                      the program from within the Turbo compiler.}
Begin
  INT24Err:=False;
  If OldINT24[1]<>0 Then
    With RegisterSet Do
    Begin
      DS:=OldINT24[1];
      DX:=OldINT24[2];
      AX:=$2524;
      MsDos(RegisterSet);
    End;
  OldINT24[1]:=0;
  OldINT24[2]:=0;
End;

Function INT24Result: Integer;
Var I : Integer;

Begin
  I:=IOResult;
  If INT24Err Then

  Begin
    I:=I+256*(INT24ErrCode+1);
    INT24On;
  End;


  INT24Result:=I;
End;


{  INT24Result returns all the regular Turbo IOResult codes if no
   critical  error has occurred.   If a critical error,  then the
   following  values are added to the error code from Turbo (each
   is 256 times the INT24ErrorCode value returned by DOS):

    256:  Attempt to write on write protected disk
    512:  Unknown unit                  [internal dos error]
    768:  Drive not ready               [drive door open or bad drive]
   1024:  Unknown command               [internal dos error]
   1280:  Data error (CRC)              [bad sector or drive]
   1536:  Bad request structure length  [internal dos error]
   1792:  Seek error                    [bad disk or drive]
   2048:  Unknown media type            [bad disk or drive]
   2304:  Sector not found              [bad disk or drive]
   2560:  Printer out of paper          [anything that the printer
                                         might signal]
   2816:  Write fault                   [character device not ready]
   3072   Read fault                    [character device not ready]
   3328:  General failure               [several meanings]
  If you need the IOResult part, use
    I:=INT24Result and 255; [masks out the INT 24 code]
  For the INT 24 code, use
    I:=INT24Result Shr8;    [same as Div 256, except faster]
  INT24Result clears both error codes, so you must assign it  to
  a variable if you want to extract both codes:
    J:=INT24Result;
    Writeln('Turbo IOResult  = ',J And 255);
    Writeln('DOS INT 24 code = ',J Shr 8); }


{ Main program }
{ Run this with printer off (or no printer), and nothing in drive A }

Var F : File;
    I : Integer;

Procedure PrinterTest;
Begin
  WriteLn(LST,'test');

  I:=INT24Result;
  If I<>0 Then
    WriteLn('Printer error: ',I)
  Else
    WriteLn('Printer OK');
End;

Procedure FileTest;
Begin
  Assign(F,'A:FILE');
  {$I-}
  Reset(F);
  {$I+}
  I:=INT24Result;
  If I<>0 Then
    WriteLn('Open failure on A:FILE :  INT24Result=',I)
  Else
  begin
    WriteLn('A:FILE exists');
    Close(F);
  end;
End;

Begin
  INT24On;
  PrinterTest;
  FileTest;
  PrinterTest;
  INT24Off;
  FileTest;
  PrinterTest;
End.


Reference:
 

3/30/99 3:11:26 PM
 

Last Modified: 01-SEP-99