home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol7n12.zip / ALLKEYS.ASM next >
Assembly Source File  |  1988-06-28  |  21KB  |  465 lines

  1. ;=============================================================================
  2. ; AllKeys- Returns popup stolen key combinations back to the applications.
  3. ;          Load "ALLKEYS" before and after your pop-ups.
  4. ;          Then press Ctrl-Alt-Z to toggle ALLKEYS on/off.
  5. ;          "beep..BEEP" signals all keys on. "BEEP..beep" signals all keys off.
  6. ;=============================================================================
  7. CSEG        SEGMENT   PARA PUBLIC 'CODE'
  8.             ASSUME    CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  9.             ORG       100H
  10.  
  11. FIRST:      JMP       INIT
  12.  
  13. COPYRIGHT   DB   "ALLKEYS 1.0 (c) 1988 Ziff Communications Co.",13,10
  14.             DB   "PC Magazine ",254," Robert L. Morton",13,10
  15.             DB   "Low copy installed",13,10,"$"
  16.  
  17. MESG1       DB   "ALLKEYS high copy installed",13,10
  18.             DB   "Ctrl-Alt-Z to toggle tsr's on/off",13,10,"$"
  19.  
  20. MESG2       DB   "ALLKEYS already installed high and low",13,10,"$"
  21.  
  22. MESG3       DB   "Vectors could not be restored - ALLKEYS disabled",13,10,"$"
  23.  
  24. MESG4       DB   "ALLKEYS not loaded yet",13,10,"$"
  25.  
  26. MESG5       DB   "ALLKEYS un-installed",13,10,"$"
  27.  
  28. ORIG_INT9   DW   0,0               ;The original int 9 vector
  29. ORIG_INT16  DW   0,0               ;The original int 16h vector
  30.  
  31. USED_INT9   DW   0,0               ;The used int 9 vector
  32. USED_INT16  DW   0,0               ;The used int 16h vector
  33.  
  34. HOTKEY      DB   44                ;Our HOT key: "Z"
  35. SHIFT_MASK  DB   0CH               ;Our shift mask: "Ctrl-Alt"
  36.  
  37. ALLKEYS     DB   0                 ;Allkeys on/off status flag.
  38.  
  39. DISABLE     DB   0                 ;If set to 1, Allkeys will not respond
  40.                                    ;  to Ctrl-Alt-Z combination and all
  41.                                    ;  keystrokes will be processed normally.
  42.  
  43. TONE_LOW    DW   500               ;Low boundary "beep"
  44. TONE_HIGH   DW   1500              ;High boundary "BEEP"
  45. TONE_STEP   DW   500               ;Step between tones
  46. TONE_LENGTH DW   50                ;Length of each tone
  47.  
  48. ;-----------------------------------------------------------------------------
  49. ; New interrupt 9 handling routine.
  50. ;-----------------------------------------------------------------------------
  51. NEW_INT9    PROC      NEAR
  52.             ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING, SS:NOTHING
  53.  
  54.             STI                                   ;Enable interrupts
  55.             PUSH      AX                          ;Save AX
  56.  
  57.             CMP       CS:DISABLE,0                ;Are we disabled?
  58.             JNE       KB1                         ;Jump out if so.
  59.  
  60.             IN        AL,60H                      ;Get key just pressed
  61.             CMP       AL,CS:HOTKEY                ;Was it our HOT key?
  62.             JNE       KB2                         ;If not, jump KB2
  63.  
  64.             MOV       AH,2                        ;Get shift status.
  65.             INT       16H
  66.             AND       AL,0FH                      ;Mask out shift keys
  67.             CMP       AL,CS:SHIFT_MASK            ;Was it our shift mask?
  68.             JNE       KB2                         ;If not, jump KB2
  69.  
  70.             CALL      KB_RESET                    ;Reset keyboard
  71.  
  72.             XOR       CS:ALLKEYS,0FFH             ;Toggle request flag
  73.  
  74.             CALL      BEEP_STATUS                 ;Beep Allkeys' status
  75.  
  76. KB1:        POP       AX                          ;Restore AX
  77.             JMP       DWORD PTR CS:USED_INT9      ;Exit through popup chain
  78.  
  79. KB2:        CMP       CS:ALLKEYS,0                ;Allkeys' request flag set?
  80.             JE        KB1                         ;If not, jump KB1
  81.             POP       AX                          ;Restore AX
  82.             JMP       DWORD PTR CS:ORIG_INT9      ;Skip popup chain and exit
  83.                                                   ;  directly to original.
  84. NEW_INT9    ENDP
  85.  
  86. ;-----------------------------------------------------------------------------
  87. ; New interrupt 16h handling routine.
  88. ;-----------------------------------------------------------------------------
  89. NEW_INT16   PROC      NEAR
  90.             ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING, SS:NOTHING
  91.  
  92.             STI                                   ;Enable interrupts
  93.             CMP       CS:DISABLE,0                ;Are we disabled?
  94.             JNE       INT16_OUT                   ;Jump out if so.
  95.  
  96.             CMP       CS:ALLKEYS,0                ;Allkeys' request flag set?
  97.             JE        INT16_OUT                   ;No - Leave through used 16h
  98.             JMP       DWORD PTR CS:ORIG_INT16     ;Yes- Leave through original
  99. INT16_OUT:  JMP       DWORD PTR CS:USED_INT16
  100.  
  101. NEW_INT16   ENDP
  102.  
  103. ;-----------------------------------------------------------------------------
  104. ;  Routine to beep Allkeys' status through the speaker.
  105. ;  If Allkeys is on, "beep..BEEP". If Allkeys is off, "BEEP..beep".
  106. ;-----------------------------------------------------------------------------
  107. BEEP_STATUS PROC      NEAR
  108.             ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING, SS:NOTHING
  109.  
  110.             PUSH      CX                          ;Save needed registers
  111.             PUSH      DS
  112.  
  113.             PUSH      CS                          ;Point DS to our data
  114.             POP       DS
  115.             ASSUME    DS:CSEG
  116.  
  117.             CMP       ALLKEYS,0                   ;Allkeys off?
  118.             JE        BS2                         ;If so, jump BS2
  119.  
  120. ;Allkeys on - Ascend from a LOW tone to a HIGH tone.
  121.  
  122.             MOV       CX,TONE_LOW                 ;Start at the bottom
  123. BS1:        CALL      SOUND                       ;Make the sound
  124.             ADD       CX,TONE_STEP                ;Add the next step
  125.             CMP       CX,TONE_HIGH                ;Are we over the top?
  126.             JNA       BS1                         ;No - then keep on going
  127.             JMP       BS_OUT                      ;Yes- then jump out
  128.  
  129. ;Allkeys off- Descend from a HIGH tone to a LOW tone.
  130.  
  131. BS2:        MOV       CX,TONE_HIGH                ;Start at the top
  132. BS3:        CALL      SOUND                       ;Make the sound
  133.             SUB       CX,TONE_STEP                ;Subtract the next step
  134.             CMP       CX,TONE_LOW                 ;Are we below the bottom?
  135.             JNB       BS3                         ;No, then keep on going
  136.  
  137. BS_OUT:     POP       DS                          ;Restore used registers
  138.             POP       CX
  139.             RET
  140.  
  141. BEEP_STATUS ENDP
  142.  
  143. ;-----------------------------------------------------------------------------
  144. ; Routine to produce a sound through the speaker.
  145. ; CX contains the frequency. Variable TONE_LENGTH contains the length.
  146. ;-----------------------------------------------------------------------------
  147. SOUND       PROC      NEAR
  148.             ASSUME    CS:CSEG, DS:CSEG, ES:NOTHING, SS:NOTHING
  149.  
  150.             PUSH      AX                          ;Save needed registers
  151.             PUSH      CX
  152.             PUSH      DX
  153.  
  154. ;Convert the frequency.
  155.  
  156.             MOV       DX,12h                      ;Upper part
  157.             MOV       AX,34DEh                    ;Lower part
  158.             DIV       CX                          ;Divide by frequency
  159.             MOV       CX,AX                       ;to get quotient.
  160.  
  161. ;Set the tone.
  162.  
  163.             MOV       AL,CL                       ;Send low byte
  164.             OUT       42h,AL                      ;out to the timer.
  165.             MOV       AL,CH                       ;Send high byte
  166.             OUT       42h,AL                      ;out to the timer.
  167.  
  168. ;Turn the tone  on.
  169.  
  170.             IN        AL,61h                      ;Get contents of system port B
  171.             OR        AL,3                        ;Turn speaker and timer on
  172.             OUT       61h,AL                      ;Send out new values to port B
  173.  
  174. ;Delay
  175.  
  176.             MOV       CX,TONE_LENGTH              ;Put delay count in CX
  177.             CALL      DELAY                       ;Delay
  178.  
  179. ;Turn the tone  off.
  180.  
  181.             IN        AL,61h                      ;Get port B again
  182.             AND       AL,0FCh                     ;Turn off timer and speaker
  183.             OUT       61h,AL
  184.             POP       DX                          ;Restore used registers
  185.             POP       CX
  186.             POP       AX
  187.             RET
  188.  
  189. SOUND       ENDP
  190.  
  191. ;-----------------------------------------------------------------------------
  192. ; Routine to delay. CX contains the factor.
  193. ;-----------------------------------------------------------------------------
  194. DELAY       PROC      NEAR
  195.  
  196.             PUSH      CX                          ;Save outside CX
  197.             MOV       CX,0FFH                     ;Move timing constant in CX
  198. DELAY1:     LOOP      DELAY1                      ;Loop for inside
  199.             POP       CX                          ;Restore outside CX
  200.             LOOP      DELAY                       ;Loop for outside
  201.             RET
  202.  
  203. DELAY       ENDP
  204.  
  205. ;-----------------------------------------------------------------------------
  206. ; Routine to reset keyboard and 8259 interrupt controller.
  207. ;-----------------------------------------------------------------------------
  208. KB_RESET    PROC      NEAR
  209.  
  210.             IN        AL,61H                      ;Get control port value
  211.             MOV       AH,AL                       ;Save in AH
  212.             OR        AL,80H                      ;Set bit 7
  213.             OUT       61H,AL                      ;Output reset value
  214.             MOV       AL,AH                       ;Send original value...
  215.             JMP       SHORT $+2                   ;Take your time
  216.             OUT       61H,AL                      ;...to enable keyboard
  217.             CLI                                   ;No interrupts now
  218.             MOV       AL,20H                      ;Send end of interrupt
  219.             OUT       20H,AL                      ;value to 8259.
  220.             STI                                   ;Re-enable interrupts
  221.             RET
  222.  
  223. KB_RESET    ENDP
  224.  
  225. ;-----------------------------------------------------------------------------
  226. ; Initialization for Allkeys....
  227. ;-----------------------------------------------------------------------------
  228. INIT        PROC      NEAR
  229.             ASSUME    CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  230.  
  231. ;Check if the "/U" parameter was entered on the command line.
  232.  
  233.             MOV       SI,80h                      ;Point to parm line
  234.             CMP       BYTE PTR [SI],0             ;Any chars entered?
  235.             JNE       INIT1                       ;Yes-jump init1
  236.             JMP       INIT8                       ;No -jump init8
  237.  
  238. INIT1:      MOV       CL,[SI]                     ;Put parm length in CL
  239.             XOR       CH,CH                       ;Make 16 bit
  240.             INC       SI                          ;Point to next byte
  241.             CLD                                   ;Forward
  242.  
  243. INIT2:      LODSB                                 ;Load a byte into AL
  244.             CMP       AL,"/"                      ;Is it our switch?
  245.             JE        INIT3                       ;Jump if so
  246.             LOOP      INIT2                       ;Keep on looking
  247.             JMP       INIT8                       ;No switch found. Jump init8.
  248.  
  249. INIT3:      AND       BYTE PTR [SI],0DFh          ;Change char to uppercase
  250.             CMP       BYTE PTR [SI],"U"           ;Is it a "U"?
  251.             JE        INIT4                       ;Yes-jump init4
  252.             JMP       INIT8                       ;No -jump init8
  253.  
  254. ;"/U" parameter found. Make sure we're loaded.
  255.  
  256. INIT4:      CALL      SEC_COPY                    ;Check for a second copy.
  257.             JC        INIT5                       ;Jump if found.
  258.  
  259.             MOV       DX,OFFSET MESG4             ;Print error message
  260. ERR_EXIT:   MOV       AH,9
  261.             INT       21H
  262.  
  263.             MOV       AX,4C01h                    ;Terminate with errorlevel 1
  264.             INT       21H
  265.  
  266. ;Modify resident copy to avoid future searches.
  267.  
  268. INIT5:      ASSUME    DS:CSEG, ES:NOTHING
  269.  
  270.             PUSH      ES                          ;Point DS at the resident
  271.             POP       DS                          ;  copy of Allkeys.
  272.             XOR       AX,AX                       ;Point ES at the int vector
  273.             MOV       ES,AX                       ;  table at bottom of memory.
  274.  
  275.             MOV       WORD PTR [FIRST],0FFh       ;This instruction modifies it
  276.  
  277. ;Check if int 9 and 16h vectors point to the resident copy.
  278.  
  279.             MOV       AX,DS                       ;Put seg of orig copy in AX
  280.             CMP       AX,ES:[  9*4+2]             ;Compare it to int 9 seg
  281.             JNE       INIT6                       ;Jump if different
  282.             CMP       AX,ES:[16h*4+2]             ;Compare it to int 16h seg
  283.             JNE       INIT6                       ;Jump if different
  284.  
  285. ;Int 9 and 16h vectors point to resident copy.
  286. ;Restore int 9 and 16h vectors and release resident copy from memory.
  287. ;Then terminate.
  288.  
  289.             ASSUME    DS:NOTHING, ES:CSEG
  290.  
  291.             PUSH      DS                          ;Point ES at the resident
  292.             POP       ES                          ;  copy of Allkeys.
  293.  
  294.             MOV       AX,2509H                    ;Restore interrupt 9
  295.             MOV       DX,ES:[USED_INT9  ]
  296.             MOV       DS,ES:[USED_INT9+2]
  297.             INT       21H
  298.  
  299.             MOV       AX,2516H                    ;Restore interrupt 16h
  300.             MOV       DX,ES:[USED_INT16  ]
  301.             MOV       DS,ES:[USED_INT16+2]
  302.             INT       21H
  303.  
  304.             MOV       AH,49H                      ;Have DOS release it from
  305.             INT       21H                         ;  memory.
  306.  
  307.             ASSUME    DS:CSEG, ES:CSEG
  308.             PUSH      CS                          ;Point DS back at our data
  309.             POP       DS
  310.  
  311.             MOV       DX,OFFSET MESG5             ;Display status message.
  312. OK_EXIT:    MOV       AH,9
  313.             INT       21H
  314.  
  315.             MOV       AX,4C00h                    ;Terminate with no errorlevel
  316.             INT       21H
  317.  
  318. ;Int 9 and 16h vectors do not point to resident copy.
  319. ;Check if resident copy was only installed LOW.
  320.  
  321. INIT6:      CMP       USED_INT9,0                 ;Only installed LOW?
  322.             JNE       INIT7                       ;Jump if not
  323.  
  324. ;Allkeys only installed LOW.
  325. ;Just simply release it from memory and terminate.
  326.  
  327.             ASSUME    DS:CSEG, ES:CSEG
  328.  
  329.             PUSH      DS                          ;Point ES at the resident
  330.             POP       ES                          ;  copy of Allkeys.
  331.             PUSH      CS                          ;Point DS back to our data.
  332.             POP       DS
  333.  
  334.             MOV       AH,49H                      ;Have DOS release it from
  335.             INT       21H                         ;  memory.
  336.  
  337.             MOV       DX,OFFSET MESG5             ;Display OK message
  338.             JMP       OK_EXIT                     ;  and terminate.
  339.  
  340. ;Allkeys installed HIGH and LOW.
  341. ;Set DISABLE flag to disable Allkeys. Then terminate.
  342.  
  343. INIT7:      MOV       DISABLE,1                   ;Disable Allkeys
  344.  
  345.             MOV       DX,OFFSET MESG3             ;Print error message
  346.             JMP       ERR_EXIT                    ;  and terminate.
  347.  
  348.  
  349. ;"/U" parameter wasn't entered. Check to see if Allkeys already loaded.
  350.  
  351. INIT8:      ASSUME    DS:CSEG, ES:CSEG
  352.  
  353.             CALL      SEC_COPY                    ;Check for a second copy
  354.             JC        INIT9                       ;Jump if found
  355.  
  356. ;Second copy not found.
  357. ;Release the environment to conserve memory.
  358. ;Save the current interrupts 9 and 16h. Then TSR.
  359.  
  360.             ASSUME    DS:CSEG, ES:NOTHING
  361.  
  362.             MOV       AX,WORD PTR DS:[2CH]        ;Release the environment.
  363.             MOV       ES,AX
  364.             MOV       AH,49H
  365.             INT       21H
  366.  
  367.             MOV       AX,3509H                    ;Get interrupt 9
  368.             INT       21H
  369.             MOV       [ORIG_INT9  ],BX            ;Save the offset
  370.             MOV       [ORIG_INT9+2],ES            ;Save the segment
  371.  
  372.             MOV       AX,3516H                    ;Get interrupt 16h
  373.             INT       21H
  374.             MOV       [ORIG_INT16  ],BX           ;Save the offset
  375.             MOV       [ORIG_INT16+2],ES           ;Save the segment
  376.  
  377.             MOV       DX,OFFSET COPYRIGHT         ;Display copyright
  378.             MOV       AH,9
  379.             INT       21H
  380.  
  381.             MOV       AX,3100h                     ;Terminate and leave all
  382.             MOV       DX,(OFFSET INIT - OFFSET CSEG + 15) SHR 4
  383.             INT       21H                          ;  code but the init portion
  384.                                                    ;  resident in memory. (TSR)
  385.  
  386. ;Second copy was found.
  387. ;Make sure Allkeys not already installed high and low.
  388.  
  389. INIT9:      ASSUME    DS:CSEG, ES:CSEG
  390.  
  391.             PUSH      ES                          ;Point DS at the original
  392.             POP       DS                          ;  copy of Allkeys.
  393.  
  394.             CMP       USED_INT9,0                 ;Already installed high & low?
  395.             JE        INIT10                      ;Jump if not.
  396.  
  397.             MOV       DX,OFFSET MESG2             ;Display error message
  398.             JMP       ERR_EXIT                    ;  and terminate.
  399.  
  400. ;Obtain and save the used interrupts 9 and 16h to the original copy.
  401.  
  402. INIT10:     ASSUME    DS:CSEG, ES:NOTHING
  403.  
  404.             MOV       AX,3509H                    ;Get used interrupt 9
  405.             INT       21H
  406.             MOV       [USED_INT9  ],BX            ;Save the offset
  407.             MOV       [USED_INT9+2],ES            ;Save the segment
  408.  
  409.             MOV       AX,3516H                    ;Get used interrupt 16h
  410.             INT       21H
  411.             MOV       [USED_INT16  ],BX           ;Save the offset
  412.             MOV       [USED_INT16+2],ES           ;Save the segment
  413.  
  414. ;Activate Allkeys by pointing interrupt vectors 9 and 16h
  415. ;to the resident copy's new interrupt 9 and 16h handlers.
  416.  
  417.             MOV       AX,2509H                    ;Set interrupt 9
  418.             MOV       DX,OFFSET NEW_INT9
  419.             INT       21H
  420.  
  421.             MOV       AX,2516H                    ;Set interrupt 16h
  422.             MOV       DX,OFFSET NEW_INT16
  423.             INT       21H
  424.  
  425.             MOV       DX,OFFSET MESG1             ;Display ready message
  426.             JMP       OK_EXIT                     ;  and terminate.
  427.  
  428. INIT        ENDP
  429.  
  430.  
  431. ;-----------------------------------------------------------------------------
  432. ; Routine to search through memory for a previous loaded copy of Allkeys.
  433. ; If found, on return, CF will be set and ES will point to previous copy.
  434. ;-----------------------------------------------------------------------------
  435. SEC_COPY    PROC      NEAR
  436.             ASSUME    CS:CSEG, DS:CSEG, ES:NOTHING, SS:CSEG
  437.  
  438.             MOV       WORD PTR [FIRST],0          ;Modify to avoid false alarm
  439.             MOV       BX,600h                     ;BX= start of our search
  440.             MOV       AX,CS                       ;AX= end of our search
  441.             CLD                                   ;Forward
  442. NEXT_PARA:
  443.             INC       BX                          ;Next paragraph
  444.             CMP       AX,BX                       ;If current paragraph...
  445.             MOV       ES,BX                       ;Set search segment
  446.             JE        END_SEARCH                  ;...stop
  447.  
  448.             MOV       SI,OFFSET FIRST             ;Compare FIRST label
  449.             MOV       DI,SI                       ;Offset is same
  450.             MOV       CX,16                       ;Only FIRST 16 bytes
  451.             REP       CMPSB                       ;Compare DS:SI TO ES:DI
  452.             OR        CX,CX                       ;All matched?
  453.             JNZ       NEXT_PARA                   ;No, keep on looking.
  454.  
  455.             STC                                   ;Found a copy in memory.
  456.             RET                                   ;  Set CF and RETurn.
  457.  
  458. END_SEARCH: CLC                                   ;Didn't find a copy.
  459.             RET                                   ;  Clear CF and RETurn.
  460.  
  461. SEC_COPY    ENDP
  462.  
  463. CSEG        ENDS
  464.             END       FIRST
  465.