home *** CD-ROM | disk | FTP | other *** search
-
- { Thanks to Marshall Brain for the original code for this routine.
- Thanks to John Cooper for pointing out a small flaw in the code.
-
-
- These routines provide a method for Turbo Pascal programs to trap MS-DOS
- interrupt 24 (hex). 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 a
- divisor 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 it does extra cleanup
- (sets INT24Err back to false, and restores the INT 24 handler, since DOS
- seems to sometimes reset the INT 24 vector after an error).
-
-
- These routines are known to work correctly with: Turbo Pascal 2.00B PC-DOS;
- Turbo Pascal 2.00B MS-DOS.
-
-
- Note that Turbo's normal IOResult codes for MS-DOS DO NOT correspond to the
- I/O error numbers given in Appendix I of the Turbo Pascal manual, or to the
- error codes given in the I/O error nn, PC=aaaa/Program aborted message. Here
- is a table of the correspondence (all numbers in hexadecimal):
-
- IOResult Turbo error
- -------- -------------------------------------------------
- 00 00 none
- 01 90 record length mismatch
- 02 01 file does not exist
- 03 F1 directory is full
- 04 FF file disappeared
- 05 02 file not open for input
- 06 03 file not open for output
- 07 99 unexpected end of file
- 08 F0 disk write error
- 09 10 error in numeric format
- 0A 99 unexpected end of file
- 0B F2 file size overflow
- 0C 99 unexpected end of file
- 0D F0 disk write error
- 0E 91 seek beyond end of file
- 0F 04 file not open
- 10 20 operation not allowed on a logical device
- 11 21 not allowed in direct mode
- 12 22 assign to standard files is not allowed
-
- - Bela Lubkin
- Borland International Technical Support
- CompuServe 71016,1573
- }
-
- 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;
- Begin
- { To understand this routine, you will need to read
- the description on Interrupt 24 in the DOS manual.
- It also helps to examine the generated code under DEBUG. }
- Inline
- ($2E/$C6/$06/ INT24Err /$01/$89/$EC/$83/$C4/$08/$89/$F8/$2E/$A2/
- INT24ErrCode /$58/$B0/$FF/$5B/$59/$5A/$5E/$5F/$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: MOV BYTE CS:[INT24Err],1 Set INT24Err to True
- MOV SP,BP Get correct SP; ADD: Discard saved
- ADD SP,8 BP, INT 24 return address & flags
- MOV AX,DI Get INT 24 error code
- MOV CS:[INT24ErrCode],AL Save it in INT24ErrCode
- POP AX Pop all registers
- MOV AL,0FFH Set FCB call error flag:
- POP BX will cause Turbo I/O error on file
- POP CX operations, no error on character
- POP DX operations
- POP SI
- POP DI
- POP BP
- POP DS
- POP ES
- IRET Return to next instruction }
- 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 run the program from
- within the Turbo compiler. If the INT 24 handler is
- left in place, and the compiler gets a critical
- error, the system is likely to crash. }
- 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;
- 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 Shr 8; [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);
-
- Note that in most cases, errors on character devices (LST and AUX) will not
- return an IOResult, only an INT 24 error code. }
-
- { Main program. Delete next line to enable }
- (*
-
- { 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 WriteLn('A:FILE exists');
- Close(F);
- End;
-
- Begin
- INT24On;
- PrinterTest;
- FileTest;
- PrinterTest;
- INT24Off;
- FileTest;
- PrinterTest;
- End.
- (**)
-
-