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.
█▌Entry▐█
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:
╓7┬6┬5┬4┬3┬2┬1┬0╖
║*│0│i│r│f│loc│w║
╙╥┴─┴╥┴╥┴╥┴─┴─┴╥╜ 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!).
█▌Exit▐█
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
-♦-