Contributor: JEFF WILSON { Here is a unit that I've played with a bit.. I have no idea who the original author is. What it does is expand the Runtime Errors reported by TP and optionally logs it to a file that you supply the name to.. It works fine for me on MSDOS 3.3 and 5.0. If you make any improvements to it I would appreciate a copy of it.. } {$S-} UNIT Errors ; INTERFACE USES Dos ; VAR ErrorFile : PathStr ; { optional name you include in the } { main program code } PROCEDURE CheckRTError ; IMPLEMENTATION VAR ErrorExitProc : Pointer ; FUNCTION HexStr(w: Word): String ; CONST HexChars : Array [0..$F] of Char = '0123456789ABCDEF' ; BEGIN HexStr := HexChars[Hi(w) shr 4] + HexChars[Hi(w) and $F] + HexChars[Lo(w) shr 4] + HexChars[Lo(w) and $F] ; END ; FUNCTION ExtendedError: String ; { goto DOS to get the last reported error } VAR Regs : Registers ; BEGIN FillChar(Regs,Sizeof(Regs),#0) ; Regs.AH := $59 ; MSDos(Regs) ; CASE Regs.AX OF $20 : ExtendedError := 'Share Violation' ; $21 : ExtendedError := 'Lock Violation' ; $23 : ExtendedError := 'FCB Unavailable' ; $24 : ExtendedError := 'Sharing Buffer Overflow' ; ELSE ExtendedError := 'Extended Error ' + HexStr(Regs.AX) ; END ; { case } END ; FUNCTION ErrorMsg(Err : Integer): String ; BEGIN CASE Err OF 1 : ErrorMsg := 'Invalid Function Number'; 2 : ErrorMsg := 'File Not Found'; 3 : ErrorMsg := 'Path Not Found'; 4 : ErrorMsg := 'Too Many Open Files'; 5 : ErrorMsg := 'File Access Denied'; 6 : ErrorMsg := 'Invalid File Handle'; 12 : ErrorMsg := 'Invalid File Access Code'; 15 : ErrorMsg := 'Invalid Drive Number'; 16 : ErrorMsg := 'Cannot Remove Current Directory'; 17 : ErrorMsg := 'Cannot Rename Across Drives'; 18 : ErrorMsg := 'No More Files'; 100 : ErrorMsg := 'Disk Read Past End Of File'; 101 : ErrorMsg := 'Disk Full'; 102 : ErrorMsg := 'File Not Assigned'; 103 : ErrorMsg := 'File Not Open'; 104 : ErrorMsg := 'File Not Open For Input'; 105 : ErrorMsg := 'File Not Open For Output'; 106 : ErrorMsg := 'Invalid Numeric Format'; 150 : ErrorMsg := 'Disk is write protected'; 151 : ErrorMsg := 'Unknown Unit'; 152 : ErrorMsg := 'Drive Not Ready'; 153 : ErrorMsg := 'Unknown command'; 154 : ErrorMsg := 'CRC Error in data'; 155 : ErrorMsg := 'Bad drive request structure length'; 156 : ErrorMsg := 'Disk seek error'; 157 : ErrorMsg := 'Unknown media type'; 158 : ErrorMsg := 'Sector not found'; 159 : ErrorMsg := 'Printer out of paper'; 160 : ErrorMsg := 'Device write fault'; 161 : ErrorMsg := 'Device read fault'; 162 : ErrorMsg := 'Hardware failure'; 163 : ErrorMsg := ExtendedError ; 200 : ErrorMsg := 'Division by zero'; 201 : ErrorMsg := 'Range check error'; 202 : ErrorMsg := 'Stack overflow error'; 203 : ErrorMsg := 'Heap overflow error'; 204 : ErrorMsg := 'Invalid pointer operation'; 205 : ErrorMsg := 'Floating point overflow'; 206 : ErrorMsg := 'Floating point underflow'; 207 : ErrorMsg := 'Invalid floating point operation'; 208 : ErrorMsg := 'Overlay manager not installed'; 209 : ErrorMsg := 'Overlay file read error'; 210 : ErrorMsg := 'Object not initialized'; 211 : ErrorMsg := 'Call to abstract method'; 212 : ErrorMsg := 'Stream registration error'; 213 : ErrorMsg := 'Collection index out of range'; 214 : ErrorMsg := 'Collection overflow error'; 215 : ErrorMsg := 'Arithmetic overflow error'; 216 : ErrorMsg := 'General protection fault'; END ; END ; FUNCTION LZ(W : Word): String ; VAR s : String ; BEGIN Str(w:0,s) ; IF Length(s) = 1 THEN s := '0' + s ; LZ := s ; END ; FUNCTION TodayDate : String ; VAR Year, Month, Day, Dummy, Hour, Minute, Second : Word ; BEGIN GetDate(Year, Month, Day, Dummy) ; GetTime(Hour, Minute, Second, Dummy) ; TodayDate := LZ(Month) + '/' + LZ(Day) + '/' + LZ(Year-1900) + ' ' + LZ(Hour) + ':' + LZ(Minute) ; END ; {$F+} PROCEDURE CheckRTError ; VAR F : Text ; BEGIN IF ErrorAddr <> Nil THEN BEGIN IF ErrorFile <> '' THEN BEGIN Assign(F,ErrorFile) ; {$I-} Append(F) ; {$I+} IF IOResult <> 0 THEN Rewrite(F) ; Writeln(F,'Date: ' + TodayDate) ; Write(F,'RunTime Error #',ExitCode,' at ') ; Write(F,HexStr(Seg(ErrorAddr^)) + ':') ; WriteLn(F,HexStr(Ofs(ErrorAddr^))) ; Writeln(F,ErrorMsg(ExitCode)) ; Writeln(F,'') ; Close(F) ; END ; Writeln('Date: ' + TodayDate) ; Write('RunTime Error #',ExitCode,' at ') ; Write(HexStr(Seg(ErrorAddr^)) + ':') ; WriteLn(HexStr(Ofs(ErrorAddr^))) ; Writeln(ErrorMsg(ExitCode)) ; Writeln ; ErrorAddr := Nil ; { reset variable so TP doesn't report } ExitProc := ErrorExitProc ; { the error and reset the Exit Pointer } END ; END ; {$F-} BEGIN ErrorFile := '' ; { don't log the error to a file } ErrorExitProc := ExitProc ; ExitProc := @CheckRTError ; END. {============== DEMO ==============} PROGRAM Test ; USES Errors ; VAR TestFile : Text ; BEGIN ErrorFile := 'TESTERR.TXT' ; { log errors to this file } RunError(3) ; { test whatever you want } END.