[Back to DOS SWAG index] [Back to Main SWAG index] [Original]
{$I- $F+}
UNIT Errtrp;
INTERFACE
USES
crt,
dos;
CONST
ScrSeg : WORD = $B800;
FGNorm = lightgray;
BGNorm = blue;
FGErr = white;
BGErr = red;
VAR
SaveInt24 : POINTER;
ErrorRetry : BOOLEAN;
IOCode : INTEGER;
version : INTEGER;
PROCEDURE DisplayError (ErrNo : INTEGER);
PROCEDURE RuntimeError;
PROCEDURE DisableErrorHandler;
PROCEDURE ErrTrap (ErrNo : INTEGER);
IMPLEMENTATION
VAR
ExitSave : POINTER;
regs : REGISTERS;
(**************************************************************************)
CONST
INT59ERROR : INTEGER = 0;
ERRORACTION : BYTE = 0;
ERRORTYPE : BYTE = 0;
ERRORAREA : BYTE = 0;
ERRORRESP : BYTE = 0;
ERRORRESULT : INTEGER = 0;
TYPE
errmsg = ARRAY [0..89] OF STRING;
ermsgPtr = ^errmsg;
VAR
Errs : ermsgPTR;
PROCEDURE HideCursor; Assembler;
Asm
MOV ax, $0100
MOV cx, $2607
INT $10
END;
PROCEDURE ShowCursor; Assembler;
Asm
MOV ax, $0100
MOV cx, $0506
INT $10
END;
PROCEDURE box;
VAR
i : INTEGER;
BEGIN
TEXTCOLOR (FGErr);
TEXTBACKGROUND (BGErr);
GOTOXY (1, 1);
WRITELN ('ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Critical Error ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿');
FOR i := 1 TO 5 DO
WRITELN ('³ ³');
WRITE ('ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ');
END;{box}
FUNCTION DosVer : INTEGER;
VAR
Maj : shortint;
Min : shortint;
regs : REGISTERS;
BEGIN
regs.ah := $30;
MSDOS (Regs);
Maj := regs.al;
Min := regs.ah;
DosVer := Maj;
END;
PROCEDURE InitErrs;
BEGIN
NEW (Errs);
Errs^ [0] := ' No error occured ';
Errs^ [1] := ' Invalid function number ';
Errs^ [2] := ' File not found ';
Errs^ [3] := ' Path not found ';
Errs^ [4] := ' No handle available ';
Errs^ [5] := ' Access denied ';
Errs^ [6] := ' Invalid handle ';
Errs^ [7] := ' Memory control blocks destroyed ';
Errs^ [8] := ' Insufficient memory ';
Errs^ [9] := ' Invalid memory block address ';
Errs^ [10] := ' Invalid SET command string ';
Errs^ [11] := ' Invalid format ';
Errs^ [12] := ' Invalid access code ';
Errs^ [13] := ' Invalid data ';
Errs^ [14] := ' Reserved ';
Errs^ [15] := ' Invalid drive specification ';
Errs^ [16] := ' Attempt to remove current directory ';
Errs^ [17] := ' Not same device ';
Errs^ [18] := ' No more files to be found ';
Errs^ [19] := ' Disk write protected ';
Errs^ [20] := ' Unknown unit ID ';
Errs^ [21] := ' Disk drive not ready ';
Errs^ [22] := ' Command not defined ';
Errs^ [23] := ' Disk data error ';
Errs^ [24] := ' Bad request structure length ';
Errs^ [25] := ' Disk seek error ';
Errs^ [26] := ' Unknown disk media type ';
Errs^ [27] := ' Disk sector not found ';
Errs^ [28] := ' Printer out of paper ';
Errs^ [29] := ' Write error - Printer Error? ';
Errs^ [30] := ' Read error ';
Errs^ [31] := ' General failure ';
Errs^ [32] := ' File sharing violation ';
Errs^ [33] := ' File locking violation ';
Errs^ [34] := ' Improper disk change ';
Errs^ [35] := ' No FCB available ';
Errs^ [36] := ' Sharing buffer overflow ';
Errs^ [37] := ' Reserved ';
Errs^ [38] := ' Reserved ';
Errs^ [39] := ' Reserved ';
Errs^ [40] := ' Reserved ';
Errs^ [41] := ' Reserved ';
Errs^ [42] := ' Reserved ';
Errs^ [43] := ' Reserved ';
Errs^ [44] := ' Reserved ';
Errs^ [45] := ' Reserved ';
Errs^ [46] := ' Reserved ';
Errs^ [47] := ' Reserved ';
Errs^ [48] := ' Reserved ';
Errs^ [49] := ' Reserved ';
Errs^ [50] := ' Network request not supported ';
Errs^ [51] := ' Remote computer not listening ';
Errs^ [52] := ' Duplicate name on network ';
Errs^ [53] := ' Network name not found ';
Errs^ [54] := ' Network busy ';
Errs^ [55] := ' Network device no longer exists ';
Errs^ [56] := ' NetBIOS command limit exceeded ';
Errs^ [57] := ' Network adapter hardware error ';
Errs^ [58] := ' Incorrect response from network ';
Errs^ [59] := ' Unexpected network error ';
Errs^ [60] := ' Incompatible remote adapter ';
Errs^ [61] := ' Print queue full ';
Errs^ [62] := ' Not enough space for print file ';
Errs^ [63] := ' Print file was deleted ';
Errs^ [64] := ' Network name was deleted ';
Errs^ [65] := ' Access denied ';
Errs^ [66] := ' Network device type incorrect ';
Errs^ [67] := ' Network name not found ';
Errs^ [68] := ' Network name limit exceeded ';
Errs^ [69] := ' NetBIOS session limit exceeded ';
Errs^ [70] := ' Temporarily paused ';
Errs^ [71] := ' Network request not accepted ';
Errs^ [72] := ' Print or disk re-direction is paused ';
Errs^ [73] := ' Reserved ';
Errs^ [74] := ' Reserved ';
Errs^ [75] := ' Reserved ';
Errs^ [76] := ' Reserved ';
Errs^ [77] := ' Reserved ';
Errs^ [78] := ' Reserved ';
Errs^ [79] := ' Reserved ';
Errs^ [80] := ' File already exists ';
Errs^ [81] := ' Reserved ';
Errs^ [82] := ' Cannot make ';
Errs^ [83] := ' Critical-error interrupt failure ';
Errs^ [84] := ' Too many redirections ';
Errs^ [85] := ' Duplicate redirection ';
Errs^ [86] := ' Duplicate password ';
Errs^ [87] := ' Invalid parameter ';
Errs^ [88] := ' Network data fault ';
Errs^ [89] := ' Undefined Error ';
END;
PROCEDURE CritError (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : WORD);
INTERRUPT;
TYPE
ScrPtr = ^ScrBuff;
ScrBuff = ARRAY [1..4096] OF BYTE;
VAR
Display,
SaveScr : ScrPtr;
c : CHAR;
ErrorPrompt,
msg : STRING;
ErrNum : BYTE;
drive,
area,
al, ah : BYTE;
deviceattr : ^WORD;
devicename : ^CHAR;
ch,
i : shortint;
actmsg,
tmsg,
amsg,
dname : STRING;
BEGIN
ah := HI (ax);
al := LO (ax); { in case DOS version < 3 }
ErrNum := LO (DI) + 19; { save the error and add }
msg := Errs^ [ErrNum]; { add 19 to convert to }
{ standard DOS error }
tmsg := '';
actmsg := ''; { we can't suggest a response }
IF (ah AND $80) = 0 THEN { if a disk error then }
BEGIN { get the drive and area }
amsg := ' drive ' + CHR (al + 65) + ':';
area := (ah AND 6) SHR 1;
CASE area OF
0 : amsg := amsg + ' dos communications area ';
1 : amsg := amsg + ' disk directory area ';
2 : amsg := amsg + ' files area ';
END;
END
ELSE { else if a device error }
BEGIN { get type of device }
deviceattr := PTR (bp, si + 4);
i := 0;
IF (deviceattr^ AND $8000) <> 0 THEN { if a character device }
BEGIN { like a printer }
amsg := 'character device';
ch := 0;
REPEAT
i := i + 1;
devicename := PTR (bp, si + $0a + ch); { get the device name }
dname [i] := devicename^;
dname [0] := CHR (i);
INC (ch);
UNTIL (devicename^ = CHR (0) ) OR (ch > 7);
END
ELSE { else }
BEGIN { just inform of the error }
dname := 'disk in ' + CHR (al) + ':';
msg := ' general failure ' ;
END;
amsg := amsg + ' ' + dname;
END;
INLINE ($FA); { Enable interrupts }
Display := PTR (ScrSeg, $0000); { save the current screen }
NEW (SaveScr);
SaveScr^ := Display^;
WINDOW (15, 10, 65, 16); { make a box to display the}
TEXTCOLOR (FGErr); { error message }
TEXTBACKGROUND (BGErr);
CLRSCR;
box;
IF Version >= 3 THEN { check the DOS version }
BEGIN { major component }
regs.ah := $59; { and use DosExtErr since }
regs.bx := $00; { it is available }
MSDOS (Regs);
INT59ERROR := regs.ax;
ERRORTYPE := regs.bh;
ERRORACTION := regs.bl;
ERRORAREA := regs.ch;
msg := Errs^ [INT59ERROR]; { get the error information}
(*
case ERRORAREA of
1: amsg:='Unknown';
2: amsg:='Block Device'; { usually disk access error}
3: amsg:='Network Problem';
4: amsg:='Serial Device'; { printer or COM problem }
5: amsg:='Memory'; { corrupted memory }
end;
*)
CASE ERRORTYPE OF
1 : tmsg := 'Out of Resource'; { no channels, space }
2 : tmsg := 'Temporary situation'; { file locked for instance;}
{ not an error and will }
{ clear eventually }
3 : tmsg := 'Authorization Violation'; { permission problem e.g. }
{ write to read only file }
4 : tmsg := 'Internal Software Error'; { system software bug }
5 : tmsg := 'Hardware Error'; { serious trouble -- fix }
{ the machine }
6 : tmsg := 'System Error'; { serious trouble software }
{ at fault -- e.g. missing }
{ CONFIG file }
7 : tmsg := 'Program Error'; { inconsistent request }
{ from your program }
8 : tmsg := 'Not found'; { as stated }
9 : tmsg := 'Bad Format'; { as stated }
10 : tmsg := 'Locked'; { interlock situation }
11 : tmsg := 'Media Error'; { CRC error, wrong disk in }
{ drive, bad disk cluster }
12 : tmsg := 'Exists'; { collision with existing }
{ item, e.g. duplicate }
{ device name }
13 : tmsg := 'Unknown Error';
END;
CASE ERRORACTION OF
1 : actmsg := 'Retry'; { retry a few times then }
{ give user abort option }
{ if not fixed }
2 : actmsg := 'Delay Retry'; { pause, retry, then give }
{ user abort option }
3 : actmsg := 'User Action'; { ask user to reenter item }
{ e.g. bad drive letter or }
{ filename used }
4 : actmsg := 'Abort'; { invoke an orderly shut }
{ down -- close files, etc }
5 : actmsg := 'Immediate Exit'; { don't clean up, you may }
{ really screw something up}
6 : actmsg := 'Ignore';
7 : actmsg := 'Retry'; { after user intervention: }
END; { let the user fix it first}
END;
amsg := tmsg + amsg;
actmsg := 'Suggested Action: ' + actmsg;
GOTOXY ( (54 - LENGTH (msg) ) DIV 2, 3);
WRITE (msg);
GOTOXY ( (54 - LENGTH (amsg) ) DIV 2, 4);
WRITE (amsg);
GOTOXY ( (54 - LENGTH (actmsg) ) DIV 2, 6);
WRITE (actmsg);
{ display it }
ErrorPrompt := ' I)gnore R)etry A)bort F)ail ? ';
GOTOXY ( (54 - LENGTH (ErrorPrompt) ) DIV 2, 5);
WRITE (ErrorPrompt);
REPEAT { get the user response }
c := READKEY;
c := UPCASE (c);
UNTIL c IN ['A', 'R', 'I', 'F'];
WINDOW (1, 1, 80, 25); { restore the screen }
TEXTCOLOR (FGNorm);
TEXTBACKGROUND (BGNorm);
Display^ := SaveScr^;
DISPOSE (SaveScr);
CASE c OF
'I' : BEGIN
AX := 0;
ERRORRETRY := FALSE;
END;
'R' : BEGIN
AX := 1;
ERRORRETRY := TRUE;
END;
'A' : BEGIN
Ax := 2;
ERRORRETRY := FALSE;
Showcursor;
END;
'F' : BEGIN
Ax := 3;
ERRORRETRY := FALSE;
Showcursor;
END;
END;
END;{procedure CritError}
(**************************************************************************)
PROCEDURE DisplayError (ErrNo : INTEGER);
VAR
msg,
exitmsg : STRING;
BEGIN
CASE ErrNo OF
2 : exitmsg := 'File not found';
3 : exitmsg := 'Path not found';
4 : exitmsg := 'Too many open files';
5 : exitmsg := 'Access denied';
6 : exitmsg := 'Invalid file handle';
12 : exitmsg := 'Invalid file access code';
15 : exitmsg := 'Invalid drive';
16 : exitmsg := 'Cannot remove current directory';
17 : exitmsg := 'Cannot rename across drives';
100 : exitmsg := 'Disk read error';
101 : exitmsg := 'Disk write error - Disk Full ?';
102 : exitmsg := 'File not assigned';
103 : exitmsg := 'File not opened';
104 : exitmsg := 'File not open for input';
105 : exitmsg := 'File not open for output';
106 : exitmsg := 'Invalid numeric format';
150 : exitmsg := 'Disk is write protected';
151 : exitmsg := 'Unknown unit';
152 : exitmsg := 'Drive not ready';
153 : exitmsg := 'Unkown command';
154 : exitmsg := 'CRC error in data';
155 : exitmsg := 'Bad drive request structure length';
156 : exitmsg := 'Disk seek error';
157 : exitmsg := 'Unknown media type';
158 : exitmsg := 'Sector not found';
159 : exitmsg := 'Printer out of paper';
160 : exitmsg := 'Device write fault';
161 : exitmsg := 'Device read fault';
162 : exitmsg := 'Hardware failure';
200 : exitmsg := 'Division by zero';
201 : exitmsg := 'Range check error';
202 : exitmsg := 'Stack overflow';
203 : exitmsg := 'Heap overflow';
204 : exitmsg := 'Invalid pointer operation';
205 : exitmsg := 'Floating point overflow';
206 : exitmsg := 'Floating point underflow';
207 : exitmsg := 'Invalid floating point operation'
ELSE exitmsg := 'Unknown Error # ';
END;
msg := exitmsg;
TEXTCOLOR (FGErr);
TEXTBACKGROUND (BGErr);
GOTOXY ( (50 - LENGTH (msg) ) DIV 2, 3);
WRITE (msg);
END;
PROCEDURE ErrTrap (ErrNo : INTEGER);
TYPE
ScrPtr = ^ScrBuff;
ScrBuff = ARRAY [1..4096] OF BYTE;
VAR
Display,
SaveScr : ScrPtr;
c : CHAR;
ErrorPrompt,
msg : STRING;
BEGIN
Display := PTR (ScrSeg, $0000); { save the current screen }
NEW (SaveScr);
SaveScr^ := Display^;
WINDOW (15, 10, 65, 16); { make a box to display the}
TEXTCOLOR (FGErr); { error message }
TEXTBACKGROUND (BGErr);
CLRSCR;
box;
ErrorRetry := TRUE;
DisplayError (ErrNo);
{ display it }
ErrorPrompt := ' I)gnore R)etry A)bort F)ail ? ';
GOTOXY ( (54 - LENGTH (ErrorPrompt) ) DIV 2, 5);
WRITE (ErrorPrompt);
REPEAT { get the user response }
c := READKEY;
c := UPCASE (c);
UNTIL c IN ['A', 'R', 'I', 'F'];
CASE c OF
'I' : ErrorRetry := FALSE;
'R' : ErrorRetry := TRUE;
'A' : BEGIN
ErrorRetry := FALSE;
Showcursor;
END;
'F' : BEGIN
ErrorRetry := FALSE;
Showcursor;
END;
END;
IF ErrorRetry = FALSE THEN
BEGIN
GOTOXY (4, 4);
WRITE ('If you are unable to correct the error');
GOTOXY (4, 5);
WRITE ('please report the error ', #40, Errno, #41, ' and ');
GOTOXY (4, 6);
WRITE ('exact circumstances when it occurred to us.');
WINDOW (1, 1, 80, 25); { restore the screen }
TEXTCOLOR (FGNorm);
TEXTBACKGROUND (BGNorm);
Display^ := SaveScr^;
DISPOSE (SaveScr);
ErrorAddr := NIL;
GOTOXY (1, 1);
Showcursor;
HALT;
END;
WINDOW (1, 1, 80, 25); { restore the screen }
TEXTCOLOR (FGNorm);
TEXTBACKGROUND (BGNorm);
Display^ := SaveScr^;
DISPOSE (SaveScr);
END;
PROCEDURE RuntimeError;
TYPE
ScrPtr = ^ScrBuff;
ScrBuff = ARRAY [1..4096] OF BYTE;
VAR
Display,
SaveScr : ScrPtr;
c : CHAR;
ErrorPrompt,
msg : STRING;
BEGIN
IF ErrorAddr <> NIL THEN
BEGIN
Display := PTR (ScrSeg, $0000); { save the current screen }
NEW (SaveScr);
SaveScr^ := Display^;
WINDOW (15, 10, 65, 16); { make a box to display the}
TEXTCOLOR (FGErr); { error message }
TEXTBACKGROUND (BGErr);
CLRSCR;
box;
GOTOXY (15, 1);
WRITE (' Fatal Error ');
DisplayError (ExitCode);
GOTOXY (20, 2);
WRITE ('Run time error ', ExitCode);
GOTOXY (4, 4);
WRITE ('If you are unable to correct the error');
GOTOXY (4, 5);
WRITE ('Please report the error and exact');
GOTOXY (4, 6);
WRITE ('circumstances when it occurred to us.');
GOTOXY (4, 7);
WRITE ( ' Press a key to continue ');
ErrorAddr := NIL;
ExitProc := ExitSave;
c := READKEY;
END;
WINDOW (1, 1, 80, 25); { restore the screen }
TEXTCOLOR (FGNorm);
TEXTBACKGROUND (BGNorm);
Display^ := SaveScr^;
DISPOSE (SaveScr);
ShowCursor;
TEXTCOLOR (lightgray);
TEXTBACKGROUND (black);
SETINTVEC ($24, SaveInt24);
END;
PROCEDURE DisableErrorHandler;
BEGIN
SETINTVEC ($24, SaveInt24);
ExitProc := ExitSave;
END;
(**************************************************************************)
BEGIN
InitErrs;
Version := DosVer;
Hidecursor;
IF mem [$0000 : $0449] <> 7 THEN ScrSeg := $B800 ELSE ScrSeg := $B000;
GETINTVEC ($24, SaveInt24);
SETINTVEC ($24, @CritError);
ExitSave := ExitProc;
ExitProc := @RuntimeError;
END.
{ --------------------- DEMO PROGRAM -------------------------- }
{$I-} { THIS MUST BE HERE FOR THE ERROR TRAP TO WORK !! }
PROGRAM testerr;
USES dos, crt, printer, errtrp;
VAR
regs : REGISTERS;
fil : FILE;
Pchar : STRING;
BEGIN
CLRSCR;
(*COMMENT OUT THE FUNCTIONS NOT BEING TESTED*)
(* USING THE CRITICAL ERROR HANDLER PROCEDURE CRITERR *)
(* remove disc from A: drive to test this *)
(******************************************)
WRITE ('trying to write to drive a: ');
ASSIGN (fil, 'A:filename.ext');
REWRITE (fil);
DisableErrorHandler;
(* USING THE ERRTRAP PROCEDURE *)
WRITE ('trying to write to drive a: using ERRTRAP');
REPEAT
ASSIGN (fil, 'A:filename.ext');
REWRITE (fil);
iocode := IORESULT;
IF IOCode <> 0 THEN ErrTrap (IOCode);
UNTIL ERRORRETRY = FALSE;
END.
[Back to DOS SWAG index] [Back to Main SWAG index] [Original]