INT 24H: Critical Error Handler

 The INT 24H vector (0000:0090) is set to the address that will gain
 control when a DOS device driver encounters a so-called critical error.

 On program startup, the address at this vector is copied into the
 pfCritErr field of the PSP.  This PSP-local copy of the address is
 restored into the interrupt table upon program exit.  Therefore, changing
 the INT 24H vector will affect handling of your own program as well as any
 child programs you EXEC.

 The normal DOS INT 24H handler is the code that displays the message...

       Abort, Retry, Fail, Ignore? _

 ...which you see when a diskette drive door is open or the printer is off-
 line.  Note: the "Fail" was added in DOS version 3.0.

 Most sophisticated programs supply their critical error handler to avoid
 having DOS screw up a carefully-maintained screen display.  To supply a
 custom Critical Error handler, use fn 25H to replace interrupt vector 24H.

  Upon entry to the INT 24H handler, the registers are as follows:

 BP:SI = addr of a Device Header to help identify the failing device
    DI = bits 0-7 contain an error code (bits 8-15 are undefined)
    AL = if AH bit 7=0, AL is the drive number (0=A, 1=B, etc.)
    AH = error information as follows:
         ╙╥┴─┴╥┴╥┴╥┴─┴─┴╥╜ bits mask
          ║   ║ ║ ║ ╚╦╝ ╚═►  0: 01H operation type: 0=read, 1=write
          ║   ║ ║ ║  ╚════►1-2: 06H affected disk area:
          ║   ║ ║ ║                 00=system files, 01=FAT
          ║   ║ ║ ║                 10=directory,    11=data area
          ║   ║ ║ ╚═══════►  3: 08H 1=FAIL exit is allowed ───┐
          ║   ║ ╚═════════►  4: 10H 1=RETRY exit is allowed   ╞═►3.0+ only
          ║   ╚═══════════►  5: 20H 1=IGNORE exit is allowed ─┘
          ╚═══════════════►  7: 80H device type: 0=disk, 1=other

           * When bit 7=1 (non-disk error), bits 0-6 are not defined.

  You can handle the error by prompting the user to take action (e.g., close
  the drive door or turn on the printer).

  You can obtain additional information from DOS Fn 59H and/or the device
  driver header block pointed to by BP:SI.

 Warning! Be careful about using DOS fns in your Critical Error handler.
          With DOS 5.0+, ONLY the following fns can be called safely:

            01H-0CH (DOS character I/O)
            33H (all subfns are OK, including 3306H get DOS version)
            50H (set PSP address)
            51H and 62H (query PSP address)
            59H (get extended error information)

          With DOS 2.0-3.0, you are even more limited: only 01H-0cH and
          59H are allowed, unless you set the DOS ErrorMode flag before
          invoking INT 21H (in that case, you must avoid 01H-0cH!).

  After handling or trying to correct the error, you can set AL with an
  action code and get back to DOS indicating one of these actions:

     AL=0: ignore the error
     AL=1: retry the operation
     AL=2: abort. Terminate via the INT 23H address (as on Ctrl-Break)
     AL=3: return to application indicating a failed DOS function

     DOS 3.0+  Examine AH on entry to see which actions are not allowed.

  The AL=3 option seems ideal.  For instance, if an "Open File" operation
  caused the error because of no disk in the drive, you could let your
  application take care of it with its normal error handling.  However, it
  has DISadvantages:

   ■ The AL=3 option is NOT available with DOS version prior to DOS 3.0.
   ■ DOS always returns error code 53H which is not too informative.

    Note: The DOS 4.0+ fn 6cH lets you avoid problems relating to critical
          errors on a file-by-file basis.  I only wish this had existed
          since 2.1!

█▌The Stack▐█
  Upon entry into the INT 24H error handler, the stack is in a known state
  as described here:

   IP, CS, Flags               To get back to DOS via IRET
   AX,BX,CX,DX,SI,DI,BP,DS,ES  Application program registers before INT 21H
   IP, CS, Flags               To get back to application via IRET

  This information can be used to determine which DOS function failed (it's
  in AH as saved on the stack) and any parameters in other registers.  But
  its primary value is that it lets your INT 24H handler restore the
  registers and exit directly to the application program.

  You will typically want to pretend to be DOS and set AX with a DOS error
  code and set CF=CY to indicate an error.  If you exit to the application
  this way, the manual says that DOS will be in an "unstable" state until a
  fn higher than 0cH is used.  Just be sure that the application does a
  fn 30H or some such as it handles the error.

  Another handy technique:  Simply set an application-internal error flag,
  exit the handler with AL=0 (ignore).  Then have your application check
  that flag after each DOS I/O fn.  This works for all versions of DOS.

  The INT 24H vector is NOT taken for errors occurring during INT 25H/26H.

See Also: DOS Error Codes
          Program Startup & Exit
          DOS Functions