home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / progmisc / tde221.zip / INT24.ASM < prev    next >
Assembly Source File  |  1993-04-01  |  13KB  |  297 lines

  1. ;
  2. ; Sometimes, things may go wrong that are outside the control of an application
  3. ; program.  When an application program needs to access system resources, lots
  4. ; of things can go wrong:  hard disk errors, lost network connections, printing
  5. ; a file before turning on the printer, etc....  These types of errors are
  6. ; known as Critical Errors.  The operating system doesn't know what to do in
  7. ; these situations, so it asks the application program for advice.  Ideally,
  8. ; the application program should be prepared to handle these situations.  After
  9. ; a critical error occurs in MSDOS, an application program will be asked to
  10. ; Abort, Retry, or Fail the operation.
  11. ;
  12. ; In this critical error handler (CEH), we never let the user return
  13. ; the Abort choice for the standard Abort, Retry, Fail prompt.  When the
  14. ; user selects Abort, all pending work and the application program are
  15. ; terminated.  Users can get very frustrated when they can't save their work
  16. ; or if they loose everything because an application can't recover from
  17. ; a critical error.
  18. ;
  19. ;------------------------  special case in 2.21  -------------------------
  20. ; A couple of days ago, I tried to edit a file on our network drive
  21. ; running Novell 3.11.  The file was corrupt and there was no way to
  22. ; get out of the TDE critical error handler except by Ctrl-Alt-Del,
  23. ; AKA Vulcan nerve pinch.  I added the Abort choice to the CEH to keep
  24. ; TDE out of an infinite loop.  Don't returning Abort as a critical
  25. ; error leave the workstation in an unstable state or something?
  26. ; I still lose all pending work with Abort, but at least I can exit TDE.
  27. ; Shouldn't Novell recognize the Fail option in addition to Abort and Retry?
  28. ;---------------------------------  end  ---------------------------------
  29. ;
  30. ; The simple critical error handler (CEH) in TDE is designed to be memory
  31. ; model independent.  When we first install this CEH, pass in the FAR address
  32. ; of a CEH structure.  Save the address of CEH structure in the code segment
  33. ; of our assembly CEH replacement.  When a critical error occurs, load in the
  34. ; address of our CEH structure and save the return codes in the structure.
  35. ; Call the prompt functions in criterr.c, then return from interrupt.
  36. ;
  37. ; Let's set the error flag only if a Fail or Ignore condition is input by
  38. ; the user.  The Ignore option is not explicity supported by this algorithm,
  39. ; but it is returned for DOS versions less than 3.0.  The Fail option is
  40. ; not available for DOS versions less than 3.0.  If the user selects the
  41. ; Retry option, set the ceh.flag to OK, because there is no error.  By
  42. ; selecting Retry, the user just wants to retry the DOS operation, which is
  43. ; not necessarily an error condition.
  44. ;
  45. ; See:
  46. ;
  47. ;   Programmer's Reference Manual, Microsoft Corporation, Redmond,
  48. ;     Washington, 1986, Document No. 410630014-320-003-1285, pp. 1-20 thru
  49. ;     1-21, pp. 1-34 thru 1-38, p 1-99, pp. 1-121 thru 1-124, pp. 1-216 thru
  50. ;     1-218, pp. 2-1 thru 2-30.
  51. ;
  52. ;   Ray Duncan, _Advanced MS-DOS_, Microsoft Press, Redmond, Washington,
  53. ;     1986, ISBN 0-914845-77-2, pp 89-97, pp 130-133.
  54. ;
  55. ;
  56. ; Assembler flags:
  57. ;
  58. ;      QuickAssembler:   qcl /c int24.asm
  59. ;            MASM 6.0:   ml /c /Cp /Zm int24.asm
  60. ;
  61. ; Editor name:   TDE, the Thomson-Davis Editor.
  62. ; Author:        Frank Davis
  63. ; Date:          June 5, 1991, version 1.0
  64. ; Date:          July 29, 1991, version 1.1
  65. ; Date:          October 5, 1991, version 1.2
  66. ; Date:          January 20, 1992, version 1.3
  67. ; Date:          February 17, 1992, version 1.4
  68. ; Date:          April 1, 1992, version 1.5
  69. ; Date:          June 5, 1992, version 2.0
  70. ; Date:          October 31, 1992, version 2.1
  71. ;
  72. ; This code is released into the public domain, Frank Davis.  You may
  73. ; distribute it freely.
  74.  
  75. ;typedef struct {         typedef from tdestr.h
  76. ;   int  flag;
  77. ;   int  ecode;
  78. ;   int  rw;
  79. ;   int  drive;
  80. ;   int  extended;
  81. ;   int  class;
  82. ;   int  action;
  83. ;   int  locus;
  84. ;   int  dattr;
  85. ;   char dname[10];
  86. ;} CEH;
  87.  
  88. flag            EQU     0
  89. ecode           EQU     2
  90. rw              EQU     4
  91. drive           EQU     6
  92. extended        EQU     8
  93. class           EQU     10
  94. action          EQU     12
  95. locus           EQU     14
  96. dattr           EQU     16
  97. dname           EQU     18
  98.  
  99. ; see any DOS tech ref manual for the format of device headers.
  100. ;
  101. dev_attr_word   EQU     4
  102. char_dev_name   EQU     10
  103.  
  104. ;
  105. ; external C routine in criterr.c
  106. ;
  107.         EXTRN   _crit_err_handler:FAR
  108.  
  109.  
  110. _TEXT   SEGMENT WORD PUBLIC 'CODE'
  111.         ASSUME  cs:_TEXT, ds:NOTHING, es:NOTHING
  112.         public  _install_ceh
  113.  
  114.  
  115. ;
  116. ; Prototype this function as far in the C header file so it may be used easily
  117. ; with any memory model.  See the last section in tdefunc.h for more info.
  118. ;
  119. _install_ceh    PROC    FAR
  120.         jmp     initialize
  121.  
  122. ceh_pointer     DW      ?,?     ; pointer to critical error handler structure
  123. dos_version     DW      ?       ; what version of DOS are we working with?
  124.  
  125. start:
  126. ;
  127. ;  the first thing we need to do is turn interrupts back on.  interrupts
  128. ;  are disabled when the handler receives control.
  129. ;
  130. ;  segment register strategy:
  131. ;      use ds to access variables in the code segment and the device header
  132. ;      use es to access the ceh structure.
  133. ;
  134.         sti                     ; turn interrupts back on
  135.         push    bx              ; push required registers
  136.         push    cx
  137.         push    dx
  138.         push    ds
  139.         push    es
  140.  
  141.         ASSUME  ds:_TEXT, es:NOTHING    ; put cs in ds and tell assembler
  142.                                         ; ds references code, _TEXT seg
  143.         mov     dx, cs
  144.         mov     ds, dx
  145.  
  146.         mov     dx, di                          ; put error code in dx
  147.         xor     dh, dh                          ; high part of di is undef'ed
  148.         mov     bx, WORD PTR ceh_pointer+2      ; get SEGMENT of ceh struc
  149.         mov     es, bx                          ; put it in es
  150.         mov     di, WORD PTR ceh_pointer        ; get OFFSET of ceh struc
  151.         mov     WORD PTR es:[di].ecode, dx      ; save error code
  152.         mov     dl, ah                          ; move error stuff to dl
  153.         and     dl, 1                           ; 1 == write error
  154.         mov     WORD PTR es:[di].rw, dx         ; save read/write error code
  155.  
  156.         mov     dl, al                          ; put drive letter in dl
  157.         mov     WORD PTR es:[di].drive, dx      ; save drive number
  158.         test    ah, 80h                 ; was this a character or block dev
  159.         jz      drive_err               ; if fail, then block error
  160.         mov     ds, bp                  ; put SEGMENT of device header in ds
  161.         mov     dx, WORD PTR [si].dev_attr_word ; see DOS tech ref, get dev attr
  162.         test    dx, 8000h               ; was there a prob w/ FAT
  163.         jz      drive_err               ; if bit 15 == 0, drive error - FAT prob
  164.         mov     WORD PTR es:[di].dattr, 1       ; 1 == character device
  165.         mov     bx, di                  ; save OFFSET of CEH struct in bx
  166.         add     di, dname               ; load destination of char dev name
  167.         add     si, char_dev_name       ; char dev
  168.         mov     cx, 8                   ; char name is 8 bytes
  169.         rep     movsb                   ; move 8 bytes of driver name
  170.         xor     al, al                  ; zero out al
  171.         stosb                           ; store a terminating NULL
  172.         mov     di, bx                  ; get back the OFFSET of CEH struct
  173.         jmp     SHORT get_extended_error
  174.         ALIGN   2
  175. drive_err:
  176.         mov     WORD PTR es:[di].dattr, 0       ; 0 == disk drive
  177. get_extended_error:
  178.         mov     dx, cs                  ; put cs back into ds
  179.         mov     ds, dx
  180.         mov     ax, WORD PTR ds:dos_version     ; get DOS version
  181.         or      ax, ax                  ; is it 0?
  182.         jz      no_ext_avail            ; skip extended error
  183.  
  184. ;
  185. ; page 1-216, Programmer's Ref Man, 1986, function 59h pretty much wipes
  186. ; out all registers that don't return info.  function 59h is available
  187. ; for DOS >= 3.
  188. ;
  189.         push    di
  190.         push    ds
  191.         push    es
  192.         xor     bx, bx                  ; version indicator, 0 = current
  193.         mov     ah, 59h                 ; function 59h == get extended err
  194.         int     21h                     ; Standard DOS interrupt
  195.         pop     es
  196.         pop     ds
  197.         pop     di
  198.         cmp     ax, 88                          ; check for return code > 88
  199.         ja      no_ext_avail                    ; if ax <= 88, we have info
  200.         mov     WORD PTR es:[di].extended, ax   ; save ext err code
  201.         xor     ax, ax                          ; zero out ax
  202.         mov     al, bh                          ; get error class
  203.         mov     WORD PTR es:[di].class, ax      ; save error class
  204.         mov     al, bl                          ; get suggested action
  205.         mov     WORD PTR es:[di].action, ax     ; save suggested action
  206.         mov     al, ch                          ; get locus
  207.         mov     WORD PTR es:[di].locus, ax      ; save locus
  208.         jmp     SHORT prompt_user               ; now, ask user what to do
  209.         ALIGN   2
  210.  
  211. no_ext_avail:
  212.         xor     ax, ax                          ; zero out ax
  213.         mov     WORD PTR es:[di].extended, ax   ; not avail
  214.         mov     WORD PTR es:[di].class, ax      ; not avail
  215.         mov     WORD PTR es:[di].action, ax     ; not avail
  216.         mov     WORD PTR es:[di].locus, ax      ; not avail
  217.  
  218. prompt_user:
  219.         push    di                      ; save OFFSET of CEH struct
  220.         push    es                      ; save SEGMENT OF CEH struct
  221.         push    ds                      ; save code segment in ds
  222.         mov     ax, ss                  ; put stack segment in ds
  223.         mov     ds, ax                  ; C routine expects stack seg in ds
  224.         call    FAR PTR _crit_err_handler       ; return code is in ax
  225.         pop     ds                      ; get back our registers
  226.         pop     es
  227.         pop     di
  228.  
  229.         mov     bx, WORD PTR ds:dos_version     ; get the DOS version
  230.         or      bx, bx                          ; is bx == 0?
  231.         jne     retry_or_fail                   ; DOS version is >= 3
  232.         cmp     ax, 3                           ; did user try fail?
  233.         jne     retry_or_fail                   ; cannot fail with DOS < 3
  234.         mov     ax, 0                           ; change it to Ignore
  235.         ALIGN   2
  236.  
  237. retry_or_fail:
  238.         mov     dx, -1                          ; if we fail, store a -1
  239.         cmp     ax, 1                           ; did user do a retry?
  240.         jne     end_int_24                      ; if retry, change error code
  241.         xor     dx, dx                          ;   reset error flag on retry
  242.  
  243. end_int_24:
  244.         mov     WORD PTR es:[di].flag, dx       ; save ceh flag
  245.         pop     es
  246.         pop     ds
  247.         pop     dx
  248.         pop     cx
  249.         pop     bx              ; pop registers
  250.         iret                    ; return from interrupt
  251.  
  252. ; ***********************************************************************
  253. ; prototype for _install_ceh in the C header file, tdefunc.h, is
  254. ;
  255. ;               void far install_ceh( void far * )
  256. ;
  257. ; The formal parameters are available on the stack.  Use bp register to
  258. ; access them.
  259. ;
  260. ; ***********************************************************************
  261.  
  262. initialize:
  263.         push    bp              ; setup bp to access formal parameter
  264.         mov     bp, sp
  265.  
  266.         push    ds              ; save ds
  267.  
  268.         ASSUME  ds:_TEXT        ; tell assembler ds references code, _TEXT seg
  269.         mov     ax, cs
  270.         mov     ds, ax          ; put cs in ds - required by function 25h, below
  271.  
  272.         mov     ah, 30h         ; function 30h == get DOS version
  273.         int     21h             ; DOS interrupt
  274.         xor     bx, bx          ; start out with zero for DOS version
  275.         cmp     al, 3           ; compare major version
  276.         jl      store_dos       ; if less than version 3, store 0
  277.         mov     bx, 3           ; else store 3 for DOS >= 3
  278. store_dos:
  279.         mov     WORD PTR dos_version, bx        ; save DOS info for my int 24
  280.  
  281.         mov     ax, WORD PTR [bp+6]             ; load OFFSET of void FAR *
  282.         mov     WORD PTR ceh_pointer, ax        ; save OFFSET of void FAR *
  283.         mov     ax, WORD PTR [bp+8]             ; load SEGMENT of void FAR *
  284.         mov     WORD PTR ceh_pointer+2, ax      ; save SEGMENT of void FAR *
  285.  
  286.         mov     dx, OFFSET start        ; get new offset of int 24
  287.                                         ; we have already set ds above
  288.         mov     ax, 2524h               ; use function 25 so int 24 points
  289.         int     21h                     ;  to my critical error routine
  290.  
  291.         pop     ds              ; clean up
  292.         pop     bp
  293.         retf
  294. _install_ceh            endp
  295. _TEXT   ends
  296.         end
  297.