home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / EXCEPT.DOC < prev    next >
Text File  |  1997-07-05  |  9KB  |  187 lines

  1. +++Date last modified: 05-Jul-1997
  2.  
  3. USER-GENERATED EXCEPTIONS IN GENERAL
  4. ------------------------------------
  5.  
  6. MS-DOS users can generate exceptions by means of two separate
  7. mechanisms, Ctrl-C and Ctrl-Break. Although these are often treated
  8. the same, they are actually handled in subtly different manners. The
  9. difference in the way these are processed allows a great deal of
  10. flexibility in allowing users to interrupt an executing program.
  11.  
  12. When a program is executed, the Ctrl-C Interrupt 23h is set up to
  13. point to a default error handler. This handler is called whenever a
  14. Ctrl-C character is detected in the keyboard input buffer. When a
  15. program terminates in any way, MS-DOS resets the Interrupt 23h vector
  16. to its default state. Note that the Ctrl-C character in the input
  17. buffer is only recognized - and an Interrupt 23h generated - when
  18. retrieving characters from the buffer and if BREAK ON is set.
  19.  
  20. The Ctrl-Break Interrupt 1Bh works somewhat differently, though
  21. usually in concert with Interrupt 23h. Whenever the ROM BIOS detects
  22. the Ctrl-Break key combination, the keyboard buffer is flushed and a
  23. Ctrl-C key combination is stuffed in place of the previous contents.
  24. This Ctrl-C will later be detected and processed by Interrupt 23h.
  25. Ctrl-Break processing therefore offers more immediate response than
  26. Ctrl-C processing if the default action is overridden.
  27.  
  28. Several caveats are in order here, however. First is the fact that,
  29. unlike Interrupt 23h, MS-DOS does not restore the default state of
  30. Interrupt 1Bh upon program termination. Second is that while Ctrl-C
  31. processing is standardized among the various machines utilizing both
  32. MS-DOS and PC-DOS, Ctrl-Break processing is much less standardized.
  33. Finally, since processing either ultimately relies on trapping
  34. Ctrl-C, either may be ignored for a long period because of the way
  35. that Ctrl-C is detected.
  36.  
  37.  
  38. HANDLING USER-GENERATED EXCEPTIONS
  39. ----------------------------------
  40.  
  41. DOS's default Ctrl-C handler is triggered whenever the Ctrl-C
  42. character is detected in the input buffer. DOS's response is to
  43. simply close all files which were opened using handle functions and
  44. to terminate the program. The limitations of this approach and the
  45. desirability of providing your own exception processing is obvious.
  46.  
  47. An equally obvious solution to the default Ctrl-C handler's problems
  48. is to explicitly do your own Ctrl-C exception processing. CCTRAP.ASM
  49. installs and de-installs you own customized exception handler. Note
  50. that the code is written to accept the address of a function specified
  51. with an explicit segment and offset.
  52.  
  53. Also note that an explicit de-installation function is provided
  54. despite the fact that DOS restores the default Int 23h vector upon
  55. program termination. The reason this is provided is that you should
  56. always de-install a Ctrl-C interrupt trap before you spawn a child
  57. process. Within your program, if you need to spawn such a process
  58. through any mechanism other than spawning a subordinate shell (more
  59. on this in a second), you should explicitly de-install your interrupt
  60. handlers and re-install them when the subordinate process returns. As
  61. noted, this is unnecessary when the subordinate process is a DOS
  62. shell such as COMMAND.COM, since the shell will reset the interrupts
  63. to their defaults during execution.
  64.  
  65. Ctrl-Break processing is much more problematical, though potentially
  66. more powerful. The first problem to deal with is how to assure that
  67. the default Int 1Bh Ctrl-Break handler will be restored upon program
  68. termination. The de-installation function therefore becomes mandatory
  69. in this context rather than optional as in the case of the Int 23h
  70. handler. CBTRAP.ASM shows a sample Ctrl-Break handler. Since Ctrl-Break
  71. processing is much less standardized than Ctrl-C processing, the
  72. safest way to deal with it is to simply set a flag, "cbrcvd", which
  73. informs your program that a Ctrl-Break has been received. Your
  74. program may then poll this flag and take appropriate actions at
  75. "safe" times within your program.
  76.  
  77.  
  78. WHERE THE CARET-C COMES FROM
  79. ----------------------------
  80.  
  81. There's still nothing new here and nothing to prevent the ugly "^C"
  82. being printed to the screen. This is because it is actually printed
  83. by the BIOS during Int 9 processing, long before DOS ever sees it.
  84. What this means is that even though the code in CCTRAP.ASM and
  85. CBTRAP.ASM is fine, it still only provides a framework for solving
  86. our problem.
  87.  
  88. TRAPFLAG.ASM is the final trick to banish the "^C". The actual ISR
  89. has to muck around quite a bit with the keyboard hardware, as is to
  90. be expected of an Int 09h replacement. Whenever a Ctrl-C or Ctrl-
  91. Break is detected, it is trapped, and our exception handler called in
  92. place of the original Int 09h handler, after discarding the trapped
  93. key codes.
  94.  
  95. Referring to TRAPFLAG.ASM, note that since I need to trap both Ctrl-C
  96. and Ctrl-Break, I adopt the flag approach introduced in CBTRAP.ASM
  97. for dealing with both Ctrl-C and Ctrl-Break processing. Now, rather
  98. than supplying an explicit exception vector, I merely set a global
  99. flag to inform me if either exception has occurred and accept the
  100. responsibility of processing the exceptions within the body of my
  101. program. I've added an extra bit of versatility here by posting
  102. different non-zero values to the flag, "ccrcvd" depending on whether
  103. the exception was a Ctrl-C or Ctrl-Break.
  104.  
  105. TRAPDEMO.C is a short C program demonstrating the use of the combined
  106. Ctrl-C/Ctrl-Break handler. Using this approach, your carefully
  107. crafted screens need never more be cluttered with the "^C" uglies.
  108.  
  109.  
  110. SYSTEM-GENERATED EXCEPTIONS
  111. ---------------------------
  112.  
  113. It's usually desirable, in any professional-looking program, to
  114. explicitly trap the Int 24h critical error interrupt to process
  115. system-generated exceptions. CERRINST.ASM is a portable critical
  116. error handler installation program functionally equivalent to the
  117. [_]hardxxx() package in Borland C++ and Microsoft C++ compilers, and
  118. the ceror_xxx() package in Zortech C++.
  119.  
  120. It's obvious that writing code to intercept DOS critical error
  121. exceptions is just as simple as intercepting Ctrl-C or Ctrl-Break
  122. exceptions. The real challenge in writing critical error handlers is
  123. in interpretation of the nature of the exception.
  124.  
  125. The critical error handler requires more information in order to
  126. decide what action to take than does a Ctrl-C handler. All of this
  127. information is passed in the CPU's registers. Just like a typical
  128. compiler vendor's critical error handler, CERRINST.ASM will simply
  129. pass these registers and leave their interpretation to you. In
  130. CERRINST.ASM, the information required for intelligent critical error
  131. processing is posted in 4 global variables, cedevdvr, cetype,
  132. ceerror, and cereturn.
  133.  
  134. Next you need to determine what your program requires of a critical
  135. error handler. CERRTRAP.ASM is a skeletal, yet robust critical error
  136. function which may be called from the handler in CERRINST.ASM.
  137. CERRTRAP.ASM assumes you have set up the following specific error
  138. handlers in the global variables provided:
  139.  
  140. FAT error               (*FAT_err)();
  141. Disk read error         (*read_err)()
  142. Disk write error        (*write_err)()
  143. Terminal error          (*term_err)(),
  144. Printer out of paper    (*no_paper)(),
  145. All other errors        (*fixup_ret)(),
  146.  
  147. In the case of an unrecognized error, fixup_ret() is called. A simple
  148. skeleton for this function would be:
  149.  
  150. #include <dos.h>        /* for _osmajor                                 */
  151. extern int exerr;       /* DOS extended error posted by CERRTRAP.ASM    */
  152. extern int rmvbl;       /* removable media flag posted by CERRTRAP.ASM  */
  153. extern int locus;       /* extended error locus posted by CERRTRAP.ASM   */
  154. extern int class;       /* extended error class posted by CERRTRAP.ASM   */
  155. extern int suggest;     /* suggested action posted by CERRTRAP.ASM      */
  156.  
  157. int fixup_ret(void)
  158. {
  159.         if (2 < _osmajor)
  160.         {
  161.                 /* analyze DOS extended error information */
  162.  
  163.                 return appropriate_error_code;
  164.         }
  165.  
  166.         /* cleanup */
  167.  
  168.         return 2;       /* abort */
  169. }
  170.  
  171. In customizing your specific critical error handler functions, there
  172. are several important restrictions to keep in mind. The first is that
  173. no DOS system services may be requested other than Interrupt 21h
  174. functions 01h-0Ch (character I/O), 30h (get DOS version number), and
  175. 59h (get extended error information). All registers except AL must be
  176. preserved since DOS sets them up for processing Retry returns prior
  177. to invoking the critical error interrupt.
  178.  
  179. Finally, the handler must return with an IRET instruction, passing a
  180. return code in AL to tell DOS what to do next. The available codes
  181. and their actions under various DOS versions are:
  182.  
  183.         0 - Ignore
  184.         1 - Retry
  185.         2 - Abort
  186.         3 - Fail (DOS 3.3 and later)
  187.