ERRORPRF.PAS  ·  PAS  ·  4.4 KB  ·  1987-05-02  ·  from Compute-PC-Magazine-Disk_January-1988_Volume-2_No.1_Issue-3
{$I-}
Program Error_proof;
{        Programmer : Doug Burger         1 May 87
         Purpose    : Set up a way for Turbo Pascal programs to
                      detect when a critical error occurs

  The following assembler code works as follows:
  Execution of the code begins when MS-DOS encounters a
  critical error, i.e. when the disk drive door is left open.

  1.  The return address (IP & CS), flags, and AX register are removed from
      the stack.  The address is the return point within the Int 21h code.
  2.  The error code in DI is converted into an MS-DOS System extended
      error code and put in AX.
  3.  The user's registers at the time of the original Int 21h call
      are restored.
  4.  The error code is put into a Turbo variable, whose address is
      added to the code in the initialization procedure.
  5.  FF is put into AL as an error flag similar to the older
      functions.
  6.  The Interrupt Flag is set; the Carry Flag is set as an error
      flag of the newer functions occurred.
  7.  Execution returns to the original caller of Int 21h.  The original
      flags are not returned in order for the Carry Flag to be effective.
}
const int24 : array[1..27] of byte = ($83,$C4,$08,  {   add  SP,8            }
                                     $8B,$C7,       {   mov  AX,DI           }
                                     $05,$13,$00,   {   add  AX,19d          }
                                     $5B,           {   pop  BX              }
                                     $59,           {   pop  CX              }
                                     $5A,           {   pop  DX              }
                                     $5E,           {   pop  SI              }
                                     $5F,           {   pop  DI              }
                                     $5D,           {   pop  BP              }
                                     $1F,           {   pop  DS              }
                                     $07,           {   pop  ES              }
                                     $A3,$00,$00,   {   mov  errcode,AX      }
                                     $B8,$FF,$00,   {   mov  AX,00FFh        }
                                     $FB,           {   sti                  }
                                     $F9,           {   stc                  }
                                     $CA,$02,$00);  {   ret  2               }

type registers = record
                    AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : integer;
                 end;

var errcode : integer;               { The MS-DOS error code will go here }
    old24seg,old24ofs : integer;

    outfile : text;
    errornum : integer;

Procedure Enable24;
var R : registers;
begin
   errcode:=0;
   R.AX:=$3524;                       { Get Interrupt Vector }
   intr($21,R);
   old24seg:=R.ES;                    { save the old vector for later restore }
   old24ofs:=R.BX;
   int24[18]:=ofs(errcode) and $FF;   { put the variable address in the code }
   int24[19]:=(ofs(errcode) and $FF00) shr 8;
   R.AX:=$2524;                       { set the Int 24h vector to new code }
   R.DS:=seg(int24);
   R.DX:=ofs(int24);
   intr($21,R);
end;

Procedure Disable24;
var R : registers;
begin
   R.AX:=$2524;                       { Set Interrupt Vector }
   R.DS:=old24seg;                    { Restore the orignal vectors }
   R.DX:=old24ofs;
   intr($21,R);
end;

Function Extended_Error:integer;
begin
   Extended_Error:=errcode;
   errcode:=0;
end;

begin
   ClrScr;
   Enable24;
   assign(outfile,'b:test');
   writeln('Critical Error Trapping':51);writeln;
   writeln('Open the drive door for failing the Open File call (Press RET)');
   readln;
   rewrite(outfile);
   errornum:=IOResult;
   if errornum<>0  then
   begin
      writeln('Create File failed');
      writeln('"Normal" error is ',errornum);
      writeln('Extended error code is ',Extended_Error);
      Disable24;
      halt;
   end;
   write(outfile,'This is a little something for the buffer.');
   writeln('Open the drive door for failing the Close File call (Press RET)');
   readln;
   close(outfile);
   errornum:=IOResult;
   if errornum<>0  then
   begin
      writeln('Close File failed');
      writeln('"Normal" error is ',errornum);
      writeln('Extended error code is ',Extended_Error);
   end;
   Disable24;
end.