TITLE CRITERR.ASM SUBTTL TRAP CRITICAL ERRORS FROM W/IN C IFDEF ??version ;TASM %NOCONDS ELSE ;MASM .SFCOND ;DONT SHOW FALSE CONDITIONALS ENDIF ; MODULE CRITERR.ASM ; JANUARY 1991 ; PETER HYMAN (609) 799-2638 ; 148 TENNYSON DRIVE ; PLAINSBORO, NJ 08536 ; MODIFIED 2/16/91 SEE NOTES AT END OF SOURCE FOR DESCRIPTION OF CHANGES ;;;;; TWO FUNCTIONS ;;;;; ; FUNCTION NAME: CRITERR( ONOFF ) ; INPUTS 1 = TRAP CRITICAL ERRORS, 0 TURN OFF TRAP ; RETURNS 0 IF SUCCESSFUL, 1 IF ALREADY INSTALLED ; FUNCTION NAME: CLRCRITERR( ) ; CLEAR CRITICAL ERROR VARIABLES ; ON CRITICAL ERRORS, INT 24H HANDLER WILL RETURN AN IGNORE CODE TO DOS ; IF VERSION < 3, OR A FAIL CODE FOR DOS >= 3 ; IF VERSION >= 3, DOS FUNCTION 59H IS CALLED ALSO, AND EXTENDED ERROR ; INFO IS ALSO PUT INTO STRUCTURE ;;;;; USES SIMPLIFIED SEGMENT DIRECTIVES. ASSEMBLE WITH I8086S, M, C OR L ;;;;; DEFINED ;;;;; ASSEMBLE AS MASM/TASM /mx /dI8086[S|M|C|L] criterr; ;;;;; TURBO ASSEMBLER YIELDS SMALLER CODE WITH /Q OPTION IFDEF I8086S .MODEL SMALL p equ 4 ; p is offset into stack for args SCODE EQU 1 ENDIF IFDEF I8086M .MODEL MEDIUM p equ 6 LCODE equ 1 ENDIF IFDEF I8086C .MODEL COMPACT p equ 4 SCODE EQU 1 LDATA EQU 1 ENDIF IFDEF I8086L .MODEL LARGE p equ 6 LCODE EQU 1 LDATA EQU 1 ENDIF IFNDEF I8086S IFNDEF I8086M IFNDEF I8086C IFNDEF I8086L %OUT NO MEMORY MODEL SPECIFIED END ENDIF ENDIF ENDIF ENDIF ;;;;; FORMAT FOR CRITICAL ERROR HEADER BLOCK ;;;;; ;;;;; CERTAIN CHAR VARIABLES EXPANDED TO INT FOR PROPER ALLIGNMENT ;;;;; CERR STRUC ; critical error structure ceflag db ? ; flag to indicate critical error 1 = yes cerrno db ? ; critical error number ; 2/16/91 changed to byte cerrtype dw ? ; critical error type/action/drive, AX drive db ? ; drive letter as a char read_wr db ? ; read or write error 1 = write disk_area db ? ; area of error, 0 = dos area, 1 = fat, 2 = dir, 3 = data resp_mask db ? ; allowable responses (moot) exterr db ? ; extended error number DOS >= 3 2/16/91 changed to byte eclass db ? ; error class action db ? ; action recommendations locus db ? ; locus nextdev dd ? ; next device pointer attr dw ? ; device attribute nxtfunc dw ? ; pointer to next strategy function intfunc dw ? ; pointer to interrupt function devname db 8 dup(?) ; device name dummy db ? ; terminating null CERR ENDS ; SEE DOS TECHNICAL REFERENCE FOR EXPLANATION OF CODES ;;;;; BEGIN DATA SEGMENT ;;;;; USING SIMPLIFIED SEGMENT DIRECTIVES .DATA ; begin data segment extrn __osmajor:byte ; operating system version _criterrtrap db 0 ; critical error flag 1=trapped, 0 = off ;;;;; GLOBAL ;;;;; public _cerr ; GLOBALS _cerr CERR <> ; CRITICAL ERROR STRUCTURE BLOCK .DATA? ; uninitialized data _oldint24vec label dword _oldint24off dw ? ; static vector to int 24 before trap _oldint24seg dw ? ; ; PROCEDURE CRITERR( ONOFF ) ; SETS ALTERNATE CRITICAL ERROR HANDLER ; USAGE: criterr( 1 ) to set, criterr( 0 ) to turn off .CODE ; begin code segment savds dw 0 ; save proper data segment public _criterr ifdef SCODE _criterr proc else _criterr proc far endif push bp mov bp, sp push si push di mov ax, p[bp] ; see if a 0 or 1 was passed test ax, ax ; non zero? jne settrap ; 1, so set trap removetrap: cmp _criterrtrap, 1 ; see if installed jne done ; not installed, so return push ds lds dx, _oldint24vec ; restore original int 24 vector mov ax, 2524h int 21h ; dos set vector function pop ds mov _criterrtrap, 0 ; reset flag xor ax, ax ; set return code jmp done settrap: cmp _criterrtrap, 1 ; see if installed je done ; yes, so return (AX = 1) mov cs:savds, ds ; move current data segment to savds push es mov ax,03524h ; save old vector to int 24 int 021h mov _oldint24off,bx mov _oldint24seg,es pop es push ds mov dx, offset cs:int_service ; load address of new routine mov ax,cs mov ds,ax mov ax,02524h ; set it int 021h pop ds mov _criterrtrap, 1 ; set flag xor ax, ax ;set return code done: push ax ; save AX ifdef LCODE call far ptr _clrcriterr ; reset values else call _clrcriterr endif pop ax pop di pop si pop bp ret ; return to caller, return code in AX ;;;;; NEW CRITICAL ERROR HANDLER ;;;;; ;;;;; SEE DOS TECHNICAL REFERENCE ;;;;; int_service: ;int 24 trap goes here push bp mov bp,sp ; set to critical stack frame push bx ; all used registers except AX must be push cx ; saved !!!!! push dx push si push di push ds push es pushf mov ds,cs:savds ; reset ds to program's ds mov bx, di ; save DI mov di, offset _cerr ; set di to point to structure cerr mov ceflag[di], 1 ; set ceflag 2/16/91 mov cerrno[di], bl ; move to cerrno -- move byte only 2/16/91 mov cerrtype[di],ax ; save error type/drive number test ax, 8000h ; char or block device mov bx, ax jnz response ; char device, so skip add bl, 'A' ; add letter A mov drive[di], bl ; move drive over and bh, 00000110b ; leave only bits 1 and 2 shr bh,1 ; shift it over 1 mov disk_area[di], bh ; save area of error mov bh, ah response: ; determine response possibilities and bh, 1 ; 2/16/91 this block moved from prev para. mov read_wr[di], bh ; move read write flag mov bh, ah and bh, 00111000b ; leave only bits 3-5 shr bh,1 shr bh,1 shr bh,1 ; shift it over mov resp_mask[di],bh ; save response mask move_dev_header: ; move device header block push ds ; set up data registers pop es mov bx,[bp] ; load bp to get segment for device header mov ds,bx ; si contains offset of device header mov di,offset _cerr.nextdev ; copy device header block cld mov cx,9 rep movsw ; move 18 bytes of device header block push es pop ds ; restore data registers ; now check for DOS version xor ax,ax ; return code ignore for dos < 3 cmp __osmajor,3 ; dos >= 3? jl doneint ; no ; prepare to get extended error mov bx, 0 mov ah, 59h ; get dos extended error int 21h ; call dos mov di, offset _cerr; set di to point to cerr structure mov exterr[di], al ; error code -- move byte only 2/16/91 mov eclass[di], bh ; error class mov action[di], bl ; action mov locus[di], ch ; locus mov al, 3 ; return fail code doneint: popf pop es pop ds pop di pop si pop dx pop cx pop bx pop bp ; restore stack frame iret ; return from interrupt _criterr endp ;;;;; FUNCTION TO CLEAR CRITICAL ERROR STATUS ;;;;; ;;;;; USAGE: clrcriterr() public _clrcriterr ifdef SCODE _clrcriterr proc ; function to clear critical error number else _clrcriterr proc far ; function to clear critical error number endif push bp mov bp,sp push di push ds pop es xor ax,ax ; zero entire structure mov di, offset _cerr mov cx, size _cerr ; get size of entire block rep stosb pop di pop bp ret _clrcriterr endp end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PROGRAM MODIFICATIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MODIFIED 2/16/91 TO INCLUDE THE FOLLOWING ; STRUCTURE MEMBER ceflag ADDED ; THIS WAS REQUIRED TO DETECT CRITICAL ERRORS, SINCE cerrno COULD HAVE ; A VALUE OF 0 WHICH WOULD INDICATE A WRITE PROTECT ERROR. ceflag WILL ; BE SET IT THERE WAS A CRITICAL ERROR ; CALLS TO EXTERNAL FUNCTION _dos_exterr REMOVED ; STUCTURE MEMBERS cerrno AND exterr CHANGED TO BYTE SIZE ; STRUCTURE MEMBER pad REMOVED BECAUSE ABOVE MADE IT UNNECESSARY ; THE CODE WHICH SET THE read_wr STRUCTURE MEMBER WAS MOVED TO JUST ; BELOW THE response: LABEL SINCE IT WAS NOT CORRECTLY LOCATED PREVIOUSLY ; AND WOULD NEVER BE SET FOR NON-DISK ERRORS ; TESTS TO SEE IF HANDLER WAS ALREADY INSTALLED WERE CHANGED. IT WAS ; POSSIBLE TO INSTALL THE HANDLER MULTIPLE TIMES THEREBY REMOVING THE ; ABILITY TO UNINSTALL IT. CODE AFTER removetrap: AND settrap: WAS MODIFIED ; TO COMPARE FLAG. ; cerr STRUCTURE WILL BE RESET WHENEVER THE CRITERR FUNCTION IS CALLED. IF ; IS INSTALLED, REMOVED.