home *** CD-ROM | disk | FTP | other *** search
- ;------------------------------------------------------------------------------
- ;
- ; So I have to have this clipper-compiled application ready to
- ; distribute in a week. It's bad enough that all these new reports
- ; have to be written and a bunch of other things changed, but there is
- ; still the problem of the critical error handler to be resolved.
- ;
- ; Clipper programs that manipulate devices end up using the dos
- ; critical error handler -- the one that asks "abort, retry or ignore?"
- ; The worst thing about this for the clipper user is that if their user
- ; takes the printer offline for just a second, the dos function that
- ; clipper uses to print freaks and passes control to the critical error
- ; handler, which at best annoys the user and at worst ends up aborting
- ; the application. Same goes for accessing floppies that have no disk
- ; in them or an unformatted disk.
- ;
- ; Well, it's actually fairly easy to replace the address of the default
- ; critical error handler with the address of one of your own (dos
- ; cleans up after you when your program terminates, so that's no
- ; problem) but, what should it do?
- ;
- ; Well, all I wanted was two things: ignore printer errors, and report
- ; disk errors as failed.
- ;
- ; this routine does that. it doesn't do much else, and doesn't do it
- ; too well, but it works and it's better than nothing.
- ;
- ; if you're printing, and the user turns off the printer or takes it
- ; offline, the program just keeps on trying to print (forever!)
- ;
- ; if you use the file() function, it will fail if done against a floppy
- ; drive that has no disk or an unformatted disk.
- ;
- ; the dbase/clipper dir command seems to pass control to another copy
- ; of dos to do its work, and so it picks up on another copy of the
- ; default critical error handler. However, with this routine in place,
- ; if the user responds to the a/r/e message with A for abort, the
- ; application program will not be aborted (it would otherwise..)
- ;
- ; how to use: link CRITINST.OBJ in with your clipper application, and
- ; somewhere, preferably at the start of everything, install it with a
- ; line like CRITINST()
- ; that's it.
- ;
- ; if you don't have the obj, just compile this with: MASM CRITINST;
- ;
- ; if you want to expand upon it to do other wonderful things, go right ahead.
- ;
- ; Unreservedly fosted off into the public domain by David Michmerhuizen,
- ; Fremont CA 1987.
- ;
- ;------------------------------------------------------------------------------
-
- EXTRN _PARNI:FAR ; use to get int arguments.
- EXTRN _RET:FAR ; how clipper wants us to return
-
- _PROG SEGMENT ; Clippers segment name
- ASSUME CS:_PROG
-
- PUBLIC CRITINST ; Make our name available
-
- CRITINST PROC FAR
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- mov ah,25h
- mov al,23h
- push ds
- mov dx,seg BRKHAND
- mov ds,dx
- mov dx,offset BRKHAND
- int 21H ;local error handler is in place
- POP ds
- mov ah,25H ;function to replace an int vector
- mov al,24H ;DOS critical error interrupt number
- push ds
- mov dx,seg CRITHAND
- mov ds,dx
- mov dx,offset CRITHAND
- int 21H ;local error handler is in place
- POP ds
- POP DX
- POP CX
- POP BX
- POP AX
-
- CALL _RET ;Clipper housekeeping
- RET ;'real' return
-
- CRITINST ENDP
-
-
- devhdr_addr label dword ;these values are saved upon entry
- devhdr_off dw ? ;its stuff dos makes available so we
- devhdr_seg dw ? ;can figure out what's goin' on.
- save_ax dw ? ;
- save_di dw ? ;
-
- save_sp dw ? ;these are used in a CANCEL request
- app_err dw ?
-
-
- CRITHAND PROC FAR
- mov cs:save_sp,sp ;save the stack position at start
- push ax ;save DOS's registers
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push es
- push ds
- push cs
- pop ds
- mov devhdr_off,si ;save address of the device header
- mov devhdr_seg,bp
- mov save_ax,ax ;save err type & read/write bit flags
- mov save_di,di ;save error code
- and di,00ffH ;get critical error code
- add di,19 ;convert to DOS error code
- mov app_err,di ;save in case we return directly to
- ; the interrupted application
- mov ax,save_ax
- test ah,80H ;disk error ?
- jnz ce_40 ; no, process character device error
- jmp ce_50 ; yes, process disk error
-
-
- ce_40: ;-------------------- action taken on RETRY request
-
- pop ds ;restore DOS registers
- pop es
- pop bp
- pop si
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- mov al,1 ;set "Retry" return code
- iret ;and exit to DOS
-
- ce_50: ;--------------------- action taken on CANCEL request
- mov sp,cs:save_sp ;locally-saved regs are irrelevant
- pop ax ;and discard DOS IP
- pop ax ; DOS CS
- pop ax ; DOS flags
-
- pop ax ;restore application's registers
- pop bx
- pop cx
- pop dx
- pop si
- pop di
- pop bp
- pop ds
- pop es
-
- push bp ;set the carry flag (on the stack)
- mov bp,sp ; so the application will
- or word ptr [bp+6],1 ; notice that an error occurred
- pop bp
- ; mov ax,cs:app_err ;and pass back a DOS error code
- mov al,2 ;cancel thru the ^c handler we installed
- iret
-
- CRITHAND ENDP
-
- BRKHAND PROC FAR
- IRET
- BRKHAND ENDP
-
- _PROG ENDS
- END