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