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