home *** CD-ROM | disk | FTP | other *** search
- // CRITERR.C -- Use _seterrormode() to control critical error
- // (INT 24h) processing.
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <conio.h>
- #include <ctype.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <pldos32.h>
- #include <pharlap.h>
-
- //
- // Prot mode segment regs, needed by critical error handler in CRITHAND.ASM
- //
- USHORT CSReg;
- USHORT DSReg;
- USHORT ESReg;
- USHORT FSReg;
- USHORT GSReg;
-
- void CauseCritErr(void);
- int __cdecl ProcessCritErr(FARPTR pIntStackFrame);
- void CritErrHand(); // in CRITHAND.ASM
-
- int main()
- {
- REALPTR RealCritErrVec;
- FARPTR ProtCritErrVec;
- FARPTR OurCritErrHand;
-
- //
- // Get our segment registers, for use by critical error handler
- //
- _asm {
- mov CSReg,cs
- mov DSReg,ds
- mov ESReg,es
- mov ax,fs
- mov FSReg,ax
- mov ax,gs
- mov GSReg,ax
- }
-
- //
- // Tell the user to open the A: floppy door, so this program will be
- // able to cause critical errors.
- //
- printf("Please open the A: floppy disk door, press any key to \
- continue\n");
- _getch();
-
- //
- // Cause a critical error by attempting to read from the open A: floppy
- // disk drive. The DOS Abort/Retry/Fail query should appear.
- //
- printf("\n** DOS should receive this critical error **\n");
- CauseCritErr();
-
- //
- // Save previous critical error (INT 24h) handler, and install our
- // handler to always get control in protected mode.
- //
- _dx_rmiv_get(0x24, &RealCritErrVec);
- _dx_pmiv_get(0x24, &ProtCritErrVec);
- FP_SET(OurCritErrHand, CritErrHand, CSReg);
- _dx_apmiv_set(0x24, OurCritErrHand);
-
- //
- // Cause a critical error again. Our handler should get control.
- //
- printf("\n** Our critical error handler should get this one **\n");
- CauseCritErr();
-
- //
- // Set critical error to always fail, and cause a critical error
- //
- _seterrormode(_CRIT_ERROR_FAIL);
- printf("\n** This call should just be failed immediately **\n");
- CauseCritErr();
-
- //
- // Set critical error to be handled, and cause a critical error
- //
- _seterrormode(_CRIT_ERROR_PROMPT);
- printf("\n** Our handler should get get control again **\n");
- CauseCritErr();
-
- //
- // Restore original critical error vectors
- //
- _dx_rpmiv_set(0x24, ProtCritErrVec, RealCritErrVec);
-
- return 0;
- }
-
- void CauseCritErr(void)
- {
- int handle;
- UINT errv;
-
- printf("Causing critical error by opening file on A: drive\n");
- errv = _dos_open("A:\foo", _O_RDONLY, &handle);
- if (errv == 0)
- printf("Open succeeded!!!\n");
- else
- {
- printf("Open failed, DOS error code = %d\n", errv);
- switch (errno)
- {
- case EACCES:
- printf("Access denied\n");
- break;
- case EINVAL:
- printf("Invalid access mode\n");
- break;
- case EMFILE:
- printf("Too many open file handles\n");
- break;
- case ENOENT:
- printf("Path or file not found\n");
- break;
- default:
- printf("Unknown errno: %d\n", errno);
- break;
- }
- }
- return;
- }
-
- //
- // ProcessCritErr - This routine is called by the assembly language
- // critical error handler routine in CRITHAND.ASM
- //
- // At critical error time, you can only make DOS calls 01h through 0Ch,
- // so we can't use any C library calls that would use any other DOS calls
- // (such as printf(), which uses Write File to write to standard output).
- //
- // Returns action code (0-3) to return to DOS in AL.
- //
- int __cdecl ProcessCritErr(FARPTR pIntStackFrame)
- {
- INT_STACK_FRAME IntFrame; // protected mode interrupt stack frame
- struct {
- USHORT dos_ax;
- USHORT dos_bx;
- USHORT dos_cx;
- USHORT dos_dx;
- USHORT dos_si;
- USHORT dos_di;
- USHORT dos_bp;
- USHORT dos_ds;
- USHORT dos_es;
- USHORT dos_ip;
- USHORT dos_cs;
- USHORT dos_flags;
- } DosCEFrame; // real mode DOS INT 24h stack frame
- REALPTR pRealCEFrame; // Real mode ptr to critical err frame
- UCHAR ch;
- UCHAR buf[25];
-
- //
- // Get the interrupt stack frame, and use that to get the address of the
- // real mode stack frame when DOS issued the INT 24h
- //
- ReadFarMem(&IntFrame, pIntStackFrame, sizeof(IntFrame));
- if (IntFrame.int_inum != 0x24 || !(IntFrame.int_dxfl & IFL_RMODE))
- {
- printf("Not INT 24h, or didn't originate in real mode!!\n");
- return 3;
- }
- RP_SET(pRealCEFrame, IntFrame.int_esp, IntFrame.int_ss);
- ReadRealMem(&DosCEFrame, pRealCEFrame, sizeof(DosCEFrame));
- _dos_str_out("Critical error occurred on INT 21h function $");
- _itoa((int) (DosCEFrame.dos_ax >> 8), buf, 16);
- strcat(buf, "h\r\n$");
- _dos_str_out(buf);
-
- //
- // Ask the user what action to take
- //
- do {
- _dos_str_out("Enter action code (0=ignore, 1=retry, \
- 2=terminate, 3=fail): $");
- _dos_char_ine(&ch);
- _dos_str_out("\r\n$");
- } while (ch < '0' || ch > '3');
-
- return (int) (ch - '0');
- }
-