home *** CD-ROM | disk | FTP | other *** search
-
-
-
- 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
- difficulties, we recommend that you log onto CompuServe and
- request assistance from the Forum members that developed these
- routines.
-
- 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 be true if an INT 24 error has occurred. The variable
- INT24ErrorCode will contain the INT 24 error code as given by
- DOS. These errors can be found in the DOS Technical Reference
- Manual. They correspond to the error codes returned by the
- function INT24Result, with an offset of 256. INT24Result is used
- like IOResult, and calls IOResult. It then checks INT24Err, and
- if it is true, returns INT24ErrorCode+256, instead.
-
- 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 a
- table of correspondence (all numbers are in hexadecimal and
- (decimal)):
-
- ---------- -----------------------------------------------
- 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 frame
- PUSH BP ?)
- 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):
-
- 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.
-
-