home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************/
- /* File Id. Int24c.C. */
- /* Author. Stan Milam. */
- /* Date Written. 11/05/89. */
- /* */
- /* (c) Copyright 1989-90 by Stan Milam */
- /* */
- /* Comments: This code will be responsible for installing */
- /* a Critical Interrupt Handler and handling of the crit- */
- /* ical interrupt. The Interrupt code should check to see*/
- /* if a window can be displayed, set the window colors, */
- /* check the error to see if disk or device error. If disk*/
- /* error display error message using subscript. If device*/
- /* error try to determine device name and display in menu */
- /* title. */
- /* Research Material: */
- /* PC Tech Magazine,April 1987,Exception Handling */
- /* The MS-DOS Encycolpedia. */
- /**********************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include "pcw.i"
- #include "pcwproto.h"
-
- /* Function Declarations */
-
- #if __ZTC__
- #define interrupt
-
- void far *getvect( int nbr ) {
-
- union REGS regs;
- struct SREGS sregs;
-
- regs.h.ah = (char) 0x35;
- regs.h.al = (char) nbr;
- int86x(0x21,®s,®s,&sregs);
- return ( MK_FP(sregs.es, regs.x.bx) );
- }
-
- void setvect( int nbr, void far *isr ) {
-
- union REGS regs;
- struct SREGS sregs;
-
- regs.h.ah = 0x25;
- regs.h.al = (char) nbr;
- regs.x.dx = FP_OFF(isr);
- sregs.ds = FP_SEG(isr);
- int86x(0x21,®s,®s,&sregs);
- }
-
- void (far *old_int24)(void);
- #endif
-
- #ifdef MSC
- void (interrupt far *old_int24)(void);
- #endif
- #ifdef __TURBOC__
- void interrupt (far *old_int24)(void);
- #endif
- #ifdef __POWERC
- void interrupt (far *old_int24)(void);
- #endif
- extern void far interrupt Int24(void);
- int far Critical_Interrupt(int ax, int di, char far *device);
- void far _Save_ES_DS_(void);
-
- /* Local Fucntion Declarations */
-
- static void open_window(int ur, int uc, int lr, int lc);
- static void close_window(int ur, int uc,int lr, int lc);
-
- typedef struct { /* Device Driver Header */
- int next_driver_offset;
- int next_driver_segment;
- int attribute;
- int strategy_offset;
- int interrupt_offset;
- char device_name[8]; /* Only if character device */
- }DEVHDR;
-
- /* For Disk Block Device Errors */
-
- static char *err_titles[] = {
- " Diskette is Write Protected ",
- " Invalid Disk Drive Number ",
- " Disk Drive is Not Ready ",
- " Unknown Device Command ",
- " CRC Error ",
- " Bad Request Structure Length ",
- " Disk Seek Error ",
- " Unknown Disk Media ",
- " Disk Sector Not Found ",
- " Printer Out of Paper ",
- " Device Write Error ",
- " Device Read Error ",
- " General Error "," "," ",
- " Invalid Disk Changing "
- };
-
- static char *disk_err_msg[] = {
- "A critical interrupt has occured and",
- "DOS has indicated the above problem",
- "with a disk drive. Please choose",
- "from the menu actions listed. ",
- NULL
- };
-
- static char *non_disk_err[] = {
- "A critical interrupt has occured and",
- "DOS has indicated the above problem.",
- "Please refer to the error message and",
- "choose from the menu actions listed. ",
- NULL
- };
-
- static char *err_menu[] = {
- "1. Ignore the Error (Not Recommended)",
- "2. Retry the Operation (Try Twice) ",
- "3. Abort the Program (Last Resort) ",
- "4. Fail the Operation (Better than 3)",
- (char *) NULL
- };
-
- char far *_int24buf_; /* To hold screen contents */
-
- /**********************************************************/
- /* set_int24() */
- /* */
- /* Set INT 24 to point to our assembler routine, but first*/
- /* save the address of the old interrupt handler to call */
- /* it if we need to. */
- /**********************************************************/
-
- int set_int24(void) {
-
- _int24buf_ = (char far *) malloc(1148); /* Malloc memory for window */
- if (_int24buf_ == (char far *) NULL) return(0); /* Return if no memory */
- #ifdef MSC
- old_int24 = _dos_getvect(0x24); /* Get old int24 address */
- _dos_setvect(0x24,Int24); /* Set Int 24 to point to */
- #else /* Our code */
- old_int24 = getvect(0x24);
- setvect(0x24, Int24);
- #endif
- #ifdef __POWERC
- _Save_ES_DS_(); /* Save Data & Extra Seg */
- #endif
- return(1);
- }
-
- /**********************************************************/
- /* Critical_Interrupt */
- /* */
- /* This routine is called by the Assembler routine Int24. */
- /* It will use the information passed to it to determine */
- /* if the error was a disk error or a device error. If a */
- /* device error we must determine if the device was a */
- /* character device and display its name otherwise if it */
- /* was a block device (has no name) we simply display a */
- /* message stating " Block Device Error ". If the error */
- /* was a disk error we display the message subscripted */
- /* the value in Di and display the drive passed in the */
- /* 8 lower bits of Ax. Pop up a menu and wait for user */
- /* response in all cases. Return value in AX. */
- /* If the return value in Ax is -1 the Assembler routine */
- /* will restore the registers and call the original INT 24*/
- /* handler. */
- /**********************************************************/
-
- int far Critical_Interrupt(int ax, int di, char far *device) {
-
- char **msg;
- char *wrkptr;
- int mxr, mxc;
- DEVHDR devhdr;
- int uc = 20, lc = 60;
- int tfclr = BLACK, mfclr = BLACK;
- static char tmsg[38], dskmsg[31];
- int choice, err_code, drive;
-
- if (chk_video_state(&mxr, &mxc)) {
- if (_int24buf_ == (char far *) NULL) return(-1);
- if ( ax < 0) {
- farcopy((void far *) &devhdr, device,sizeof(devhdr));
- if (devhdr.attribute < 0) {
- wrkptr = strchr(devhdr.device_name,32);
- if (wrkptr != NULL) {
- wrkptr++;
- *wrkptr = 0;
- }
- strcpy(tmsg," Error In Device: ");
- strncat(tmsg,devhdr.device_name,8);
- }
- else {
- if (ax & 0x0200) strcpy(tmsg," Bad Memory Image of F.A.T. ");
- else strcpy(tmsg, " Block Device Error ");
- }
- msg = non_disk_err; /* Use non disk message */
- memset(dskmsg, '\0', 31); /* Clear & set disk message */
- memset(dskmsg, 196, 30);
- }
- else { /* Disk Error */
- err_code = di & 0x00ff;
- drive = (ax & 0x00ff) + 65;
- msg = disk_err_msg; /* Use disk error message */
- strcpy(tmsg, err_titles[err_code]); /* Use table of error msgs */
- strcpy(dskmsg,"Error in Drive %c:"); /* Use disk message */
- }
-
- /* Build the window, sound the alarm, and wait for user response */
-
- if (mxc == 40) { /* Check max rows and adjust */
- uc = 1;
- lc = 40;
- }
- if (_monitor == COLOR) { /* Check for Color video */
- tfclr = BLUE; /* And adjust if it is */
- mfclr = RED;
- }
- open_window(6,uc,19,lc);
- qputs(6,(mxc/2)-(strlen(tmsg)/2),tfclr,LIGHTGRAY,tmsg);
- q_block_write(7,uc+2,BLACK,LIGHTGRAY,err_menu);
- qprintf(12,CENTER,mfclr,LIGHTGRAY,dskmsg,drive);
- q_block_write(14,uc+2,BLACK,LIGHTGRAY,msg);
- _sound(880); rest(9); _nosound();
- do {
- choice = readkey();
- /* if (choice == 0) choice = readkey() + 128; */
- choice -= 49;
- } while (choice < 0 || choice > 3);
- close_window(6,uc,19,lc);
- return(choice);
- }
- else return(-1); /* Call Original Int 24 */
- }
-
- /**********************************************************/
- /* open_window */
- /* */
- /* Code to save screen image, color the window, draw the */
- /* the border. */
- /**********************************************************/
-
- static void open_window(int ur, int uc, int lr, int lc) {
-
- int far *scrnptr;
- unsigned offset, scrnseg;
- int rows, cols, page, pagesize;
- int bfclr;
-
- rows = (lr - ur) + 1;
- cols = (lc - uc) + 1;
- page = getpage();
- pagesize = getpagesize();
- scrnseg = getscrnseg();
- offset = MK_SCRNOFF(ur,uc);
- scrnptr = (int far *) MK_FP(scrnseg,offset);
- SaveScrn(rows, cols, scrnptr, _int24buf_);
- qfill(ur, uc, lr, lc,LIGHTGRAY, LIGHTGRAY, 32);
- bfclr = (_monitor == COLOR) ? BROWN : BLACK;
- bordercolor(bfclr,LIGHTGRAY);
- setborder(DOUBLESIDES);
- qbox(ur,uc,lr,lc);
- }
-
- /**********************************************************/
- /* close_window */
- /* */
- /* Logic to remove the window. Uses PCW primatives. */
- /**********************************************************/
-
- static void close_window(int ur,int uc, int lr, int lc) {
-
- int far *scrnptr;
- unsigned offset, scrnseg;
- int rows,cols,page,pagesize;
-
- rows = (lr - ur) + 1;
- cols = (lc - uc) + 1;
- page = getpage();
- pagesize = getpagesize();
- scrnseg = getscrnseg();
- offset = MK_SCRNOFF(ur,uc);
- scrnptr = (int far *) MK_FP(scrnseg,offset);
- RestoreScrn(rows, cols, scrnptr, _int24buf_);
- }
-