home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / sysutl / safari2.arc / SAFARI.ASM < prev    next >
Assembly Source File  |  1987-08-19  |  15KB  |  528 lines

  1. ;======================================================================
  2. ;  SAFARI - Staying Away From Abort, Retry, Ignore
  3. ;  A resident interrupt handler for the DOS critical error handler
  4. ;  Tested in PC-DOS 2.0 to 3.31
  5. ;----------------------------------------------------------------------
  6. CSEG    SEGMENT PARA    PUBLIC    'CODE'
  7.  
  8.     ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  9.  
  10.         ORG    100H            ;SKIP TO END OF THE PSP
  11. ENTPT:        JMP    INITIALIZE        ;COM FILE ENTRY    ALWAYS AT 100H
  12.  
  13. COPYRIGHT    DB    "SAFARI 1.0 (c) Ziff Communications Co.$"
  14. PROGRAMMER    DB    "Robert L. Hummel"
  15.  
  16. ;----------------------------------------------------------------------
  17. ;    Program data area.  Bufferes at end of resident code.
  18. ;----------------------------------------------------------------------
  19. BOX_ATTR    EQU    4FH            ;Window color: 70 for b/w
  20. BCOL        EQU    0            ;Window top left column
  21. BROW        EQU    4            ;Window top left row
  22. NCOL        EQU    46            ;Width of window
  23. NROW        EQU    15            ;Length of window
  24.  
  25. DISPLAY_PAGE    DB    0            ;Hold current value
  26. CURSOR_POS    DW    0            ;Hold current value
  27.  
  28. OLD_INT_24    DD    0            ;Address of original Handler
  29. DI_REG        DB    0,0            ;Local storage for error codes
  30. AX_REG        DB    0,0            ; as low-byte, hi-byte
  31. ATTR_BYTE    DB    0            ;From device header
  32.  
  33. ; Strings encoded as col, row, ASCIIZ
  34.  
  35. HEADER        DB    BCOL,BROW,"<< SAFARI Critical Error Handler >>",0
  36. DISK_ERR    DB    BCOL+1,BROW+1,"System Reports A Disk Error",0
  37. CHAR_DEV_ERR    DB    BCOL+1,BROW+1,"System Reports A Character Device Error",0
  38. BAD_FAT_ERR    DB    BCOL+1,BROW+1,"System Reports A Bad FAT",0
  39.  
  40. ERR_TABLE    DW    ERR0,ERR1,ERR2,ERR3,ERR4,ERR5,ERR6,ERR7
  41.         DW    ERR8,ERR9,ERRA,ERRB,ERRC
  42. ERR0        DB    BCOL+1,BROW+2
  43.         DB    "Attempt To Write On Write-Protected Diskette",0
  44. ERR1        DB    BCOL+1,BROW+2,"Unknown Or Bad Unit",0
  45. ERR2        DB    BCOL+1,BROW+2,"Drive Not Ready",0
  46. ERR3        DB    BCOL+1,BROW+2,"Unknown Command",0
  47. ERR4        DB    BCOL+1,BROW+2,"Data Error (CRC)",0
  48. ERR5        DB    BCOL+1,BROW+2,"Bad Request Structure Length",0
  49. ERR6        DB    BCOL+1,BROW+2,"Seek Error",0
  50. ERR7        DB    BCOL+1,BROW+2,"Unknown media type",0
  51. ERR8        DB    BCOL+1,BROW+2,"Sector Not Found",0
  52. ERR9        DB    BCOL+1,BROW+2,"Printer Out Of Paper",0
  53. ERRA        DB    BCOL+1,BROW+2,"Write Fault",0
  54. ERRB        DB    BCOL+1,BROW+2,"Read Fault",0
  55. ERRC        DB    BCOL+1,BROW+2,"General Failure",0
  56.  
  57. DRIVE_MSG    DB    BCOL+1,BROW+3,"On Drive "
  58. DRIVE_NAME    DB    "A:",0
  59.  
  60. READ_OPER    DB    BCOL+1,BROW+4,"During A Read Operation",0
  61. WRITE_OPER    DB    BCOL+1,BROW+4,"During A Write Operation",0
  62.  
  63. AREA_MSG    DB    BCOL+1,BROW+5,"Error Localized In",0
  64. AREA_TABLE    DW    DOS_AREA,FAT_AREA,DIR_AREA,DATA_AREA
  65. DOS_AREA    DB    BCOL+1,BROW+6,"DOS Area",0
  66. FAT_AREA    DB    BCOL+1,BROW+6,"File Allocation Table",0
  67. DIR_AREA    DB    BCOL+1,BROW+6,"Directory Area",0
  68. DATA_AREA    DB    BCOL+1,BROW+6,"Data Area",0
  69.  
  70. REG_BLK1    DB    BCOL+1,BROW+ 8,"AX=0000 BX=0000 CX=0000 DX=0000",0
  71. REG_BLK2    DB    BCOL+1,BROW+ 9,"DS=0000 SI=0000 ES=0000 DI=0000",0
  72. REG_BLK3    DB    BCOL+1,BROW+10,"CS:IP=0000:0000",0
  73.  
  74. ;======================================================================
  75. ; Control is passed here by the jump we inserted into the DOS Int 24 handler
  76. ;----------------------------------------------------------------------
  77. INT_24        PROC    FAR
  78.  
  79.         STI                ;Allow Interrupts
  80.  
  81.         PUSH    AX            ;Save used registers
  82.         PUSH    DS
  83.  
  84.         MOV    DS,BP            ;Get Device Header attribute
  85.         MOV    AX,[SI+4]        ; byte before changing BP
  86.         MOV    CS:ATTR_BYTE,AH
  87.  
  88.         POP    DS            ;Restore
  89.         POP    AX
  90.  
  91.         PUSH    BP            ;Access to stack
  92.         MOV    BP,SP            ;Before we push anything
  93.  
  94.         MOV    WORD PTR CS:AX_REG,AX    ;Error status
  95.         MOV    WORD PTR CS:DI_REG,DI    ;Error code in lower half
  96.  
  97.         PUSHF                ;Save the state of the machine
  98.         PUSH    ES            ; because we're gonna make
  99.         PUSH    DS            ; a mess of it
  100.         PUSH    DI
  101.         PUSH    SI
  102.         PUSH    DX
  103.         PUSH    CX
  104.         PUSH    BX
  105.         PUSH    AX
  106.  
  107.         MOV    AX,CS            ;Set up access to local data
  108.         MOV    DS,AX
  109.         MOV    ES,AX
  110.  
  111.     ASSUME    DS:CSEG, ES:CSEG        ;Tell the assembler
  112. ;----------------------------------------------------------------------
  113. ; Save the details of the current screen for later restoration.
  114. ;----------------------------------------------------------------------
  115.         MOV    AH,0FH            ;Get current video mode fn
  116.         INT    10H            ;Thru BIOS
  117.         MOV    DISPLAY_PAGE,BH        ;Save current page
  118.  
  119.         MOV    AH,3            ;Get cursor position fn
  120.         INT    10H            ;Thru BIOS
  121.         MOV    CURSOR_POS,DX        ;Save position for
  122.                         ;restoration on exit
  123. ;----------------------------------------------------------------------
  124. ; Save section of screen we will be writing over.
  125. ;----------------------------------------------------------------------
  126.         MOV    BH,DISPLAY_PAGE
  127.         CLD                ;String moves forward
  128.         MOV    DI,OFFSET SCREEN_BUFFER    ;Destination for save
  129.         MOV    CX,NROW            ;Row loop
  130.         MOV    DH,BROW            ;Init row pointer
  131. ROW_LOOP1:
  132.         PUSH    CX            ;Prepare for...
  133.         MOV    CX,NCOL            ;...column loop
  134.         MOV    DL,BCOL            ;Column Pointer
  135. COL_LOOP1:
  136.         MOV    AH,2            ;Position cursor fn
  137.         INT    10H            ;Thru BIOS
  138.  
  139.         MOV    AH,8            ;Get char & attribute fn
  140.         INT    10H            ;Thru BIOS
  141.  
  142.         STOSW                ;ES:[di]<-ax ; di+=2
  143.  
  144.         INC    DL            ;Next column
  145.         LOOP    COL_LOOP1        ;Close Inner loop
  146.  
  147.         POP    CX            ;Return to outer loop
  148.         INC    DH            ;Next row
  149.         LOOP    ROW_LOOP1        ;Close Outer loop
  150.  
  151. ;----------------------------------------------------------------------
  152. ; Clear    a window (box) for our information on the screen.
  153. ;----------------------------------------------------------------------
  154.         MOV    AH,6            ;Scroll window fn
  155.         MOV    AL,0            ;Scroll entire window
  156.         MOV    CH,BROW            ;Upper row
  157.         MOV    CL,BCOL            ;Left column
  158.         MOV    DH,BROW + NROW - 1    ;Bottom row is lower
  159.         MOV    DL,BCOL + NCOL - 1    ;Right column
  160.         MOV    BH,BOX_ATTR        ;Window color
  161.         INT    10H            ;Thru BIOS
  162.  
  163. ;----------------------------------------------------------------------
  164. ; Say who we are and give some information as to what happened.
  165. ;----------------------------------------------------------------------
  166.         MOV    SI,OFFSET HEADER
  167.         CALL    WR_STRING
  168. ;----------------------------------------------------------------------
  169. ; if ( AH:7 == 0 )
  170. ;    disk_error
  171. ; else if ( ATTR_BYTE:7 == 0 )
  172. ;    bad_fat
  173. ; else
  174. ;    character_device
  175. ;----------------------------------------------------------------------
  176.         MOV    SI,OFFSET DISK_ERR    ;AH IS ERROR, DI OK
  177.         TEST    AX_REG[1],80H        ;Hi bit=0 if disk error
  178.         JZ    HARD_ERROR        ;Print and examine AL
  179.  
  180.         MOV    SI,OFFSET CHAR_DEV_ERR    ;Check Header for Bad Fat err
  181.         TEST    ATTR_BYTE,80H
  182.         JNZ    DI_CODE            ;else non-block device
  183.  
  184.         MOV    SI,OFFSET BAD_FAT_ERR
  185. HARD_ERROR:
  186.         CALL    WR_STRING
  187.  
  188.         MOV    AL,AX_REG[0]        ;Failing drive code
  189.         ADD    AL,'A'            ; convert to ascii
  190.         MOV    DRIVE_NAME,AL        ; and put in display string
  191.         MOV    SI,OFFSET DRIVE_MSG    ;In drive...
  192.         CALL    WR_STRING
  193.  
  194.         MOV    SI,OFFSET READ_OPER    ;Say what operation
  195.         TEST    AX_REG[1],1        ;0=Read, 1=Write
  196.         JZ    A20
  197.         MOV    SI,OFFSET WRITE_OPER
  198. A20:
  199.         CALL    WR_STRING
  200.  
  201.         MOV    SI,OFFSET AREA_MSG    ;Say what area
  202.         CALL    WR_STRING
  203.  
  204.         XOR    BH,BH            ;Leaving the area bits one
  205.         MOV    BL,AX_REG[1]        ; position to the left is the
  206.         AND    BL,6            ; same as multiplying by two
  207.         MOV    SI,AREA_TABLE[BX]    ;Offset into pointer table
  208. DI_CODE:
  209.         CALL    WR_STRING
  210.                         ;Interpret code in DI
  211.         XOR    BH,BH
  212.         MOV    BL,DI_REG        ;Get error code
  213.         SHL    BX,1            ;Make offset into table (*2)
  214.         MOV    SI,ERR_TABLE[BX]
  215.         CALL    WR_STRING
  216.  
  217. ;----------------------------------------------------------------------
  218. ; Perform a rudimentary traceback.  Display the available registers of the
  219. ;   original Int 21 and the program location it was called from.
  220. ;----------------------------------------------------------------------
  221.         MOV    DI,OFFSET REG_BLK1 + 5    ;Put digits here
  222.         MOV    AX,[BP+8]        ;Point to word on stack
  223.         CALL    HEX4            ;Convert to ascii in string
  224.         ADD    DI,8            ;Point to next location
  225.         MOV    AX,[BP+10]        ;...continue the process
  226.         CALL    HEX4
  227.         ADD    DI,8
  228.         MOV    AX,[BP+12]
  229.         CALL    HEX4
  230.         ADD    DI,8
  231.         MOV    AX,[BP+14]
  232.         CALL    HEX4
  233.         MOV    SI,OFFSET REG_BLK1
  234.         CALL    WR_STRING
  235.  
  236.         MOV    DI,OFFSET REG_BLK2 + 5    ;Repeat for 2nd set of REGS
  237.         MOV    AX,[BP+22]
  238.         CALL    HEX4
  239.         ADD    DI,8
  240.         MOV    AX,[BP+16]
  241.         CALL    HEX4
  242.         ADD    DI,8
  243.         MOV    AX,[BP+24]
  244.         CALL    HEX4
  245.         ADD    DI,8
  246.         MOV    AX,[BP+18]
  247.         CALL    HEX4
  248.         MOV    SI,OFFSET REG_BLK2
  249.         CALL    WR_STRING
  250.  
  251.         MOV    DI,OFFSET REG_BLK3 + 8    ;Repeat for CS and IP
  252.         MOV    AX,[BP+28]
  253.         CALL    HEX4
  254.         ADD    DI,5
  255.         MOV    AX,[BP+26]
  256.         CALL    HEX4
  257.         MOV    SI,OFFSET REG_BLK3
  258.         CALL    WR_STRING
  259.  
  260.         MOV    BH,DISPLAY_PAGE        ;Position for the ARI? msg
  261.         MOV    DH,BROW + 12        ;DH=row
  262.         MOV    DL,BCOL            ;DL=col
  263.  
  264.         MOV    AH,2            ;Set cursor posn fn
  265.         INT    10H            ;Thru BIOS
  266.  
  267. ;----------------------------------------------------------------------
  268. ; Restore the state of the machine when Int 24 occured
  269. ;----------------------------------------------------------------------
  270.         POP    AX
  271.         POP    BX
  272.         POP    CX
  273.         POP    DX
  274.         POP    SI
  275.         POP    DI
  276.         POP    DS
  277.         POP    ES
  278.         POPF
  279.         POP    BP
  280.     ASSUME    DS:NOTHING, ES:NOTHING
  281.  
  282. ;----------------------------------------------------------------------
  283. ; Here is the original Int 24 handler splice.  Simulate an interrupt
  284. ;----------------------------------------------------------------------
  285.         PUSHF                ;Push the flags
  286.         CLI                ;Disable interrupts
  287.         PUSH    CS            ;Push the CS register
  288.         MOV    DI,OFFSET CS:RET_TARGET    ;Get addr of next instr.
  289.         PUSH    DI            ; on stack too.
  290.         MOV    DI,WORD PTR CS:DI_REG    ;Restore register
  291. PREFIX:
  292.         DB    5 DUP(?)        ;First 5 bytes of old 24h
  293.         JMP    DWORD PTR CS:OLD_INT_24    ;Transfer control to old 24h
  294.  
  295. ;----------------------------------------------------------------------
  296. ;  IRET transfers control here.  Again, save the machine state and set up
  297. ;    registers to acess data.
  298. ;----------------------------------------------------------------------
  299. RET_TARGET:
  300.         PUSHF
  301.         PUSH    ES
  302.         PUSH    DS
  303.         PUSH    BP
  304.         PUSH    DI
  305.         PUSH    SI
  306.         PUSH    DX
  307.         PUSH    CX
  308.         PUSH    BX
  309.         PUSH    AX
  310.  
  311.         MOV    AX,CS
  312.         MOV    DS,AX
  313.         MOV    ES,AX
  314.     ASSUME    DS:CSEG, ES:CSEG        ;Tell the assembler
  315.  
  316. ;----------------------------------------------------------------------
  317. ;  Restore the screen to original state.
  318. ;----------------------------------------------------------------------
  319.         MOV    BH,DISPLAY_PAGE        ;Just to be sure, reset page
  320.         MOV    AH,2            ;Set cursor position fn
  321.         MOV    DH,BROW        ;Top of window
  322.         MOV    DL,BCOL        ;Column
  323.         INT    10H            ;Thru BIOS
  324.  
  325.         MOV    SI,OFFSET SCREEN_BUFFER    ;Origin for restoration
  326.         MOV    CX,NROW            ;Row loop
  327.         MOV    DH,BROW        ;Init row pointer
  328. ROW_LOOP2:
  329.         PUSH    CX            ;Prepare for...
  330.         MOV    CX,NCOL            ;...column loop
  331.         MOV    DL,BCOL        ;Column Pointer
  332. COL_LOOP2:
  333.         PUSH    CX            ;Need for write-char fn
  334.  
  335.         MOV    AH,2            ;Position cursor fn
  336.         INT    10H            ;Thru BIOS
  337.  
  338.         LODSW                ;AX <- [SI]
  339.                         ;AH=ATTR AL=CHAR
  340.         MOV    BL,AH            ;Put attribute where needed
  341.         MOV    AH,9            ;Write char fn
  342.         MOV    CX,01            ;Write one copy of char
  343.         INT    10H            ;Thru BIOS
  344.  
  345.         INC    DL            ;Next column
  346.         POP    CX            ;Restore Counter
  347.         LOOP    COL_LOOP2        ;Close Inner loop
  348.  
  349.         POP    CX            ;Return to outer loop
  350.         INC    DH            ;Next row
  351.         LOOP    ROW_LOOP2        ;Close Outer loop
  352.  
  353.         MOV    AH,2            ;Set Cursor position fn
  354.         MOV    DX,CURSOR_POS        ;Restore old cursor position
  355.         INT    10H            ;Thru BIOS
  356.  
  357.         POP    AX
  358.         POP    BX
  359.         POP    CX
  360.         POP    DX
  361.         POP    SI
  362.         POP    DI
  363.         POP    BP
  364.         POP    DS
  365.         POP    ES
  366.         POPF
  367.         IRET                ;And we return too
  368.  
  369. INT_24        ENDP
  370.  
  371. ;======================================================================
  372. ;  All access to the BIOS video interrupt comes through here.  Some BIOSs
  373. ;  destroy BP during a INT 10h call.
  374. ;----------------------------------------------------------------------
  375. VIDEO        PROC    NEAR
  376.  
  377.         PUSH    BP
  378.         INT    10H
  379.         POP    BP
  380.         RET
  381.  
  382. VIDEO        ENDP
  383.  
  384. ;======================================================================
  385. ;    HEX4 -  Convert the AX register to hexidecimal digits.
  386. ;        The characters produced are stored at ES:DI.
  387. ;        All regs preserved.
  388. ;----------------------------------------------------------------------
  389. HEX4    PROC    NEAR
  390.         PUSH    AX
  391.         PUSH    BX
  392.         PUSH    CX
  393.  
  394.         MOV    BX,AX
  395.         STD                ;String ptr decrement
  396.         ADD    DI,3            ;Point to end of string
  397.         MOV    CX,4
  398. H10:
  399.         MOV    AL,BL            ;Want lower half
  400.         AND    AL,0FH            ; of this byte
  401.         ADD    AL,90H            ;Convert AL to ASCII
  402.         DAA
  403.         ADC    AL,40H
  404.         DAA
  405.         STOSB                ;Store at ES:DI
  406.         SHR    BX,1
  407.         SHR    BX,1
  408.         SHR    BX,1
  409.         SHR    BX,1
  410.         LOOP    H10
  411.  
  412.         POP    CX
  413.         POP    BX
  414.         POP    AX
  415.         INC    DI
  416.         CLD
  417.         RET
  418. HEX4    ENDP
  419. ;======================================================================
  420. ; WR_STRING - write string to console at specified location.
  421. ;    The first two bytes of the string contain the column and row of the
  422. ;    display location.  The remainder of the string is ASCIIZ.
  423. ;    AX is destroyed, all other registers are preserved.
  424. ;----------------------------------------------------------------------
  425. WR_STRING    PROC    NEAR
  426.  
  427.         PUSH    BX
  428.         PUSH    DX
  429.         PUSH    SI
  430.  
  431.         MOV    BH,DISPLAY_PAGE
  432.         MOV    DX,[SI]            ;DH=row, DL=col
  433.         MOV    AH,2            ;Set cursor posn fn
  434.         INT    10H            ;Thru BIOS
  435.         INC    SI            ;Point to start of string
  436.         INC    SI
  437. NEXT_CHAR:
  438.         LODSB                ;Load char in AL from DS:SI
  439.         OR    AL,AL            ;If char is 0
  440.         JZ    END_STRING        ;End of ASCIIZ string
  441.         MOV    AH,0EH            ;Else, write TTY
  442.         INT    10H            ;Thru BIOS
  443.         JMP    SHORT NEXT_CHAR
  444. END_STRING:
  445.         POP    SI
  446.         POP    DX
  447.         POP    BX
  448.         RET
  449.  
  450. WR_STRING    ENDP
  451.  
  452. ;======================================================================
  453. PC        =    $
  454.  
  455. SCREEN_BUFFER    =    PC
  456. PC        =    PC + NROW * NCOL * 2
  457.  
  458. LASTBYTE    =    PC
  459.  
  460. ;======================================================================
  461. ;  Initialization Procedure
  462. ;  Patch command.com to load our handler as the new default
  463. ;----------------------------------------------------------------------
  464. INITIALIZE    PROC    NEAR
  465.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG    ;Set by loader.
  466.  
  467.         MOV    AH,9
  468.         MOV    DX,OFFSET COPYRIGHT
  469.         INT    21H
  470. ;----------------------------------------------------------------------
  471. ; Get the current address of Int 24 and save
  472. ;----------------------------------------------------------------------
  473.         MOV    AH,35H            ;Get Int vector
  474.         MOV    AL,24H            ;For this Int
  475.         INT    21H            ;Result in ES:BX
  476.     ASSUME    ES:NOTHING
  477.         CMP    BYTE PTR ES:[BX],0EAH    ;If code is jump
  478.         JNE    NOT_INSTALLED
  479.  
  480.         MOV    AX,4C01H        ;Terminate with error
  481.         INT    21H
  482. NOT_INSTALLED:
  483.         MOV    WORD PTR OLD_INT_24[0],BX    ;offset
  484.         MOV    WORD PTR OLD_INT_24[2],ES    ;segment
  485.  
  486. ;----------------------------------------------------------------------
  487. ; Copy the first five bytes of the DOS Int 24 handler to our handler.
  488. ;----------------------------------------------------------------------
  489.         MOV    CX,5            ;Move 5 bytes
  490.         PUSH    ES            ;From old handler (DS:SI)
  491.         POP    DS
  492.     ASSUME    DS:NOTHING
  493.         MOV    SI,BX
  494.  
  495.         PUSH    CS            ;To a safe place (ES:DI)
  496.         POP    ES
  497.     ASSUME    ES:CSEG
  498.         MOV    DI,OFFSET PREFIX
  499.         REP    MOVSB
  500.  
  501. ;----------------------------------------------------------------------
  502. ; Build our jump command inside the original Int 24 handler to
  503. ;    pass control immediately to our handler.
  504. ;----------------------------------------------------------------------
  505.         PUSH    DS            ;Point ES to
  506.         POP    ES            ; the old handler
  507.     ASSUME    ES:NOTHING
  508.         MOV    DI,BX            ;Write to ES:DI
  509.         MOV    AL,0EAH            ;Opcode for far jump
  510.         STOSB
  511.         MOV    AX,OFFSET INT_24    ;Offset of our handler
  512.         STOSW
  513.         MOV    AX,CS
  514.         STOSW
  515.         ADD    WORD PTR CS:OLD_INT_24,5 ;Point after jump
  516.  
  517. ;----------------------------------------------------------------------
  518. ; Terminate and stay resident.
  519. ;----------------------------------------------------------------------
  520.         MOV    AX,3100H
  521.         MOV    DX,(OFFSET LASTBYTE - OFFSET CSEG + 15) SHR 4
  522.         INT    21H
  523.  
  524. INITIALIZE    ENDP
  525.  
  526. CSEG    ENDS
  527.     END    ENTPT
  528.