home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_01_03 / 1n03025a < prev    next >
Text File  |  1990-04-03  |  11KB  |  424 lines

  1. ;                -----  LISTING 1  -----
  2.  
  3. ;    File:  CTRL_C.ASM
  4.  
  5. title Ctrl-C handler   -   Ctrl-Break handler
  6.  
  7. COMMENT @
  8.   ----------------------------------------------------
  9.  
  10.   Microsoft MASM 5.0
  11.   Standard C calling conventions
  12.  
  13.   Author:  David Burki
  14.   ----------------------------------------------------
  15.  
  16.                -----  SUMMARY  -----
  17.  
  18.  Traps Ctrl-C keystrokes utilizing a "back-end"
  19.  filtering process attached to the BIOS keyboard I/O
  20.  routine (INT 16h) and traps Ctrl-Break keystrokes by
  21.  replacing INT 1bh.  INT 23h is also be replaced in
  22.  order to trap the undocumented Ctrl-2 Alt-3 key
  23.  combinations.
  24.  
  25.  There are two callable entry points to this code:
  26.     _capture()
  27.         Installs the new interrupt vectors and stores
  28.         the address of the calling programs variable
  29.         (an int) in the code segment addressable variable
  30.         "flag".  Sets the local cs referenced variable
  31.         "replaced" to true to prevent _release() from
  32.         trying to restore vectors from garbage.
  33.     _release()
  34.         Checks the cs referenced "replaced" flag to
  35.         avoid restoring vectors never saved. Restores
  36.         the replaced vectors to their original values
  37.         once _capture() has been called, this procedure
  38.         MUST be executed before the application terminates,
  39.         or INT 16h & 1bh will be left pointing to random
  40.         code and a reboot will be necessary.
  41.         The application may capture and release as many
  42.         times as necessary during it's execution.
  43.  
  44.     Sample call from C:
  45.         int b_flag = 0;
  46.         main()
  47.           {        /* NOTE: b_flag cast as a far ptr */
  48.           capture( (far *)&b_flag );
  49.           .
  50.           .
  51.           release();
  52.           }
  53.   ----------------------------------------------------
  54. END COMMENT @
  55.  
  56. ;match the model directive with the application model
  57. .model large
  58.  
  59.  
  60.  
  61. ; ----------------------------------------------------
  62. ;  MACROs and EQUATES
  63. ; ----------------------------------------------------
  64. sim_int macro  num
  65.     pushf
  66.     call    cs:orig_&num
  67. endm
  68.  
  69. TRUE    equ     1
  70. FALSE   equ     0
  71.  
  72. ;       large model flag parameter equates
  73. if @CODESIZE
  74.    FLG_OFF equ  [bp+6]
  75.    FLG_SEG equ  [bp+8]
  76. ;       small model flag parameter equates
  77. else
  78.    FLG_OFF equ  [bp+4]
  79.    FLG_SEG equ  [bp+6]
  80. endif
  81.  
  82.  
  83. .code
  84.  
  85. ; ----------------------------------------------------
  86. ;The replaced address and the flag pointer are in the
  87. ;code segment so they will be accessable to the
  88. ;interrupt replacement code.
  89. ; ----------------------------------------------------
  90.  
  91. ; far address of application program's Ctrl-C/Break
  92. ; detected flag
  93. flag      dd    0
  94.  
  95. orig_16h  dd    0           ;far addresses of
  96. orig_1bh  dd    0           ;   the original
  97. orig_23h  dd    0           ;       vectors
  98.  
  99. ; flag to let capture() & release() know there are
  100. ; valid addresses in org_??h
  101. replaced  db    FALSE
  102.  
  103.  
  104. assume ds:@curseg
  105.  
  106. ; ----------------------------------------------------
  107. ;the following "installation" procedure is a near call
  108. ;even in the large model environment
  109. ; ----------------------------------------------------
  110. install_vectors proc near
  111.  
  112. ;get current int 16h vector
  113.     mov     ax,3516h
  114.     int     21h
  115.     mov     word ptr orig_16h,bx
  116.  
  117. ;save the vector we found
  118.     mov     word ptr orig_16h+2,es
  119.  
  120. ;get address of new handler
  121.     lea     dx,sixteen_handler
  122.  
  123. ;set the vector to point
  124. ;to our routine
  125.     mov     ax,2516h
  126.     int     21h
  127.  
  128. ; ----------------------------------------------------
  129. ;replacement of 1bh is mandatory if you want to prevent
  130. ;int 1bh (Ctrl-Break) from setting the flag DOS looks at
  131. ; ----------------------------------------------------
  132.  
  133. ;get current int 1bh vector
  134.     mov     ax,351bh
  135.     int     21h
  136.     mov     word ptr orig_1bh,bx
  137.  
  138. ;save the vector we found
  139.     mov     word ptr orig_1bh+2,es
  140.  
  141. ;get address of new handler
  142.     lea     dx,int1b_handler
  143.  
  144. ;set the vector to point
  145. ;to our routine
  146.     mov     ax,251bh
  147.     int     21h
  148.  
  149. ; ----------------------------------------------------
  150. ;replacement of 23h is *not* necessary to trap Ctrl-C
  151. ;or Ctrl-Break, however, if you want to break from your
  152. ;code using Ctrl-2 or Alt-3, int 23h is where we'll make
  153. ;a call to release() so the installed interrupt handlers
  154. ;will be un-installed, thus preventing a system hang on
  155. ;return to DOS.
  156. ; ----------------------------------------------------
  157.  
  158. ;get current int 23h vector
  159.     mov     ax,3523h
  160.     int     21h
  161.     mov     word ptr orig_23h,bx
  162.  
  163. ;save the vector we found
  164.     mov     word ptr orig_23h+2,es
  165.  
  166. ;get address of new handlers
  167.     lea     dx,int23_handler
  168.  
  169. ;set the vector to point
  170. ;to our routine
  171.     mov     ax,2523h
  172.     int     21h
  173.     ret
  174. install_vectors endp
  175.  
  176.  
  177. ; ----------------------------------------------------
  178. ;_capture uses the ".model" memory model near/far proc
  179. ;  NOTE: The parameter "flag" is ALWAYS passed as a far
  180. ;        pointer.
  181. ; ----------------------------------------------------
  182. public  _capture     
  183. _capture proc  
  184.  
  185. ;establish the stack frame
  186.     push    bp
  187.     mov     bp,sp
  188.  
  189. ;save the application programs ds & es registers
  190.     push    ds
  191.     push    es
  192.  
  193. ;make ds point to the code segment for vector swaps
  194.     push    cs
  195.     pop     ds
  196.  
  197. ;check if already installed
  198.     cmp     replaced,TRUE
  199.     jz      capture_exit
  200.  
  201. ;get the offset and segment of application "break_flag"
  202.     mov     ax,word ptr FLG_OFF
  203.     mov     word ptr flag,ax
  204.     mov     ax,word ptr FLG_SEG
  205.     mov     word ptr flag+2,ax
  206.  
  207. ;install the replacements
  208. ; NOTE:  near overides for when large model
  209.     call    near ptr install_vectors
  210.  
  211. ;flag that things have changed
  212.     mov     byte ptr replaced,TRUE
  213.  
  214. ;restore registers and stack frame
  215. capture_exit:
  216.     pop     es
  217.     pop     ds
  218.     pop     bp
  219.     ret
  220. _capture endp
  221.  
  222. assume cs:@curseg, ds:nothing, es:nothing
  223.  
  224.  
  225. ; ----------------------------------------------------
  226. ;_release uses the default memory model near/far proc
  227. ;restores interrupt 16h, 1bh & 23h to what they were
  228. ;before capture changed them
  229. ; ----------------------------------------------------
  230. public _release
  231. _release proc
  232.  
  233. ;save regs used locally
  234.     push    ds
  235.     push    dx
  236.  
  237. ;save the flags in case this routine has been called
  238. ;by the int 23h handler
  239.     pushf
  240.  
  241. ;check that _capture() has installed the handlers
  242.     cmp     cs:replaced,TRUE
  243.     jnz     release_exit
  244.  
  245. ;ds:dx gets the address of the saved original
  246. ;interrupt 16h vector
  247.     lds     dx,cs:orig_16h
  248.  
  249. ;reset the int 16h vector
  250.     mov     ax,2516h
  251.     int     21h
  252.  
  253. ;ds:dx gets the address of the saved original
  254. ;interrupt 1bh vector
  255.     lds     dx,cs:orig_1bh
  256.  
  257. ;reset the int 1bh vector
  258.     mov     ax,251bh
  259.     int     21h
  260.  
  261. ;ds:dx gets the address of the saved original
  262. ;interrupt 23h vector
  263.     lds     dx,cs:orig_23h
  264.  
  265. ;reset the int 23h vector
  266.     mov     ax,2523h
  267.     int     21h
  268.  
  269. ;indicate that vectore are no longer replaced
  270.     mov     cs:replaced, FALSE
  271.  
  272. release_exit:
  273. ;restore flags, dx & ds
  274.     popf
  275.     pop     dx
  276.     pop     ds
  277.     ret
  278. _release endp
  279.  
  280.  
  281. assume cs:@curseg, ds:nothing, es:nothing
  282.  
  283. ;place to store the int 16h function parameter
  284. ;re-entrancy is not a problem
  285. save_funct      db      ?
  286.  
  287.  
  288. ; ----------------------------------------------------
  289. ;sixteen_handler is a far proc regardless of the memory
  290. ;model specified in the ".model" directive since it is
  291. ;an interrupt replacement routine
  292. ; ----------------------------------------------------
  293. sixteen_handler proc far
  294.  
  295. ;save the function value
  296.     mov     cs:save_funct,ah
  297.  
  298. ;convert to the non-extended numbers
  299.     and     ah,11101111b
  300.  
  301. ;is it a shift status request
  302.     cmp     ah,2
  303.  
  304. ;lower than shift status request, we'll take care of it
  305.     jb      not_shift_status_req
  306.  
  307. ;put back the callers function, pass it to the BIOS &
  308. ;   don't come back here
  309.     mov     ah,cs:save_funct
  310.     jmp     cs:orig_16h
  311.  
  312. not_shift_status_req:
  313. ;if it is it a "is_keyready" call handle it in the
  314. ;keyready_call block of code
  315.     cmp     ah,1
  316.     jz      keyready_call
  317.  
  318. ;must be a "get_key" request
  319. get_key_call:
  320.  
  321. ;restore the callers original function value
  322.     mov     ah,cs:save_funct
  323.  
  324. ;simulate an interrupt
  325.     sim_int 16h
  326.  
  327. ;did the BIOS return the Ctrl-C keycode
  328.     cmp     ax,2e03h
  329.  
  330. ;no, so we can return to caller
  331.     jnz     iret_back
  332.  
  333. ;the BIOS returned a Ctrl-C keycode, so
  334. ;set the flag in the application program
  335.     call    near ptr set_flag
  336.  
  337. ;the Ctrl-C key is thrown away so go back and get
  338. ;another key
  339.     jmp     get_key_call
  340.  
  341. keyready_call:
  342. ;restore the callers original function value
  343.     mov     ah,cs:save_funct
  344.  
  345. ;simulate an interrupt
  346.     sim_int 16h
  347.  
  348. ;if the zero flag is set (by the BIOS), the keyboard
  349. ;buffer is empty - ok to return to caller
  350.     jz      ok_to_go_back
  351.  
  352. ;compare the key at the head of the keyboard buffer with
  353. ;the Ctrl-C keycode.  This compare will leave the Z flag
  354. ;indicating a key is available.
  355.     cmp     ax,2e03h
  356.     jnz     ok_to_go_back
  357.  
  358. ;key was Ctrl-C, set the application program flag
  359.     call    near ptr set_flag
  360.  
  361. ;remove Ctrl-C keycode from the keyboard buffer
  362.     mov     ah,0
  363.     sim_int 16h
  364.  
  365. ;loop back to see if a non Ctrl-C key is ready
  366.     jmp     keyready_call
  367.  
  368. ok_to_go_back:
  369. ;throw away flags of our caller and return
  370.     ret     2
  371.  
  372. iret_back:
  373. ;restore callers flags on return
  374.     iret
  375. sixteen_handler endp
  376.  
  377.  
  378. ; ----------------------------------------------------
  379. ;int1b_handler is a far proc regardless of memory model
  380. ;   set the application program flag and return
  381. ; ----------------------------------------------------
  382. int1b_handler proc far
  383.     call    near ptr set_flag
  384.     iret
  385. int1b_handler endp
  386.  
  387.  
  388. ; ----------------------------------------------------
  389. ;int23_handler is a far proc regardless of memory model
  390. ;  used here to allow Ctrl-2 or Alt-3 to "break" the
  391. ;  program execution
  392. ;
  393. ;restore the original vectors and execute the original
  394. ;Ctrl-C interrupt handler
  395. ; ----------------------------------------------------
  396. int23_handler proc far
  397.     call    _release
  398.     jmp     cs:orig_23h
  399. int23_handler endp
  400.  
  401.  
  402. ; ----------------------------------------------------
  403. ;set_flag is a near procedure regardless of memory model
  404. ;
  405. ; Use the address passed to _capture() and set the
  406. ; integer refrenced to one.
  407. ; ----------------------------------------------------
  408. set_flag proc near
  409.     push    ds
  410.     push    si
  411.  
  412. ;get the address of the application break flag
  413.     lds     si,cs:flag
  414.  
  415. ;set the flag to one
  416.     mov     word ptr [si],1
  417.     pop     si
  418.     pop     ds
  419.     ret
  420. set_flag endp
  421.  
  422. end
  423.  
  424.