home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HOOKKBS.ZIP / hook_kbs.doc < prev    next >
Text File  |  1992-10-17  |  23KB  |  455 lines

  1. Document File for hook_kbs program
  2.  
  3. From : Morton F. Kaplon  CIS : 73457,437
  4.        1047 Johnston Drive
  5.        Bethlehem PA 18017
  6.        (215)758-9686
  7.  
  8. Revised and Updated : Sat  10-17-1992
  9.  
  10. Subject : Hooking the Keyboard in OS/2 2.0 and Assigning HotKeys
  11.  
  12. INTRODUCTION
  13.  
  14.   HOOK_KBS is an OS/2 equivalent of a DOS TRS program. HotKeys are defined in
  15.   a user created data file that assigns to a HotKey a command to execute; the
  16.   data file is read by the program when loaded. Once loaded it intercepts the
  17.   message stream and inspects all WM_CHAR messages, the equivalent in DOS of
  18.   hooking the Keyboard Interrupt. When a key stroke meeting a HotKey
  19.   definition is detected, it takes appropriate action otherwise it passes
  20.   things along. The action taken is that of executing the assigned command
  21.   which may be a COM, EXE, CMD, or BAT file or loading an instance of the
  22.   command processor for either OS/2 or DOS. Thus you may activate a program or
  23.   load an instance of the command processor at the flick of a HotKey without
  24.   having to access an ICON.
  25.  
  26.   HOOK_KBS works in conjunction with HOOK_DLS, a dynamic link module. HOOK_KBS
  27.   loads HOOK_DLS which captures Key Strokes (via sampling the systen nessage
  28.   queue) from all Windows BUT Full Screen OS/2 or DOS. The KeyStrokes
  29.   assignments are USER DEFINED in a data file named HOOK_KBS.DAT and the
  30.   program recognizes keystrokes assigned to Shift-Alt-X  and Shift-Ctrl-X
  31.   where X is 0.....9 and A...Z independent of case (The restriction on X is
  32.   mine and is changeable of course). There are two combinations Shift-Alt-Del
  33.   and Shift-Alt-Ins (both white keys) that are hard coded into the program.
  34.   Shift-Alt-Del unloads the program and Shift-Alt-Ins pops up a small OS/2
  35.   window in the center of the screen. These, as is true for the other key
  36.   stroke combinations, may be called from anywhere, except for the Full Screen
  37.   sessions noted above.
  38.  
  39.   To capture from Full Screen OS/2 or DOS would require an additional program
  40.   but since my principal purpose was to create a program that would allow me
  41.   to capture keystrokes independent of where I was working and since not using
  42.   Full Screen has advantages in flexibility, I decided to go without it. For
  43.   DOS windows you may in fact readily switch back and forth from Full Screen
  44.   to Windowed via the Alt-Home combination so nothing is really lost there.
  45.  
  46.   The reason for requiring the triplet combination of Shift-Alt-X or
  47.   Shift-Ctrl-X is that besides the large number of pre-assigned keys in OS/2,
  48.   many programs use keystroke combinations for accessing specific features and
  49.   if the Hot Key is to be useful, it should not conflict. I can only remember
  50.   one program that I have seen over the years which used a Shift-Alt-X or
  51.   Shift-Ctrl-X combination and so it seems to be a fairly safe one, and one
  52.   that should not lead to conflicts. In filtering KeyStrokes the program
  53.   rejects all but the combinations Shift-Alt-X and Shift-Ctrl-X so that the
  54.   usual run of keystroke assignments of Alt-X or Ctrl-X and all Function key
  55.   combinations will be unaffected. Keystrokes are recognized on the down
  56.   stroke. I would note that the Shift-Alt or Shift-Ctrl combination is
  57.   particularly easy to access on those keyboards where the Shift Key sits
  58.   vertically between the Ctrl and Alt keys.
  59.  
  60.   As presently configured, once a key stroke combination has activated a
  61.   program, using that combination a second time will not open an additional
  62.   instance of the program but will switch back to the original. HOWEVER, IF
  63.   the opened window was used to load another program (such as a command
  64.   processor window might), then that window loses its unique identity and
  65.   using the same HotKey will activate another copy. The reason for this is
  66.   that the Identity of each window is determined by its Window title which is
  67.   defined as "Alt-X" or "Ctl-X" where X is the key used. The window popped up
  68.   with Shift-Alt-Ins has the letter ID "Ω". If another program is started from
  69.   an open window, its program title is noted as "prgname.ext Alt-X" or
  70.   "prgname.ext Ctl-X", where ext is the program's extension, and is thus not
  71.   recognized as an already existing window title.
  72.  
  73.   The program is written in 32 bit Assembler.
  74.  
  75. OVERVIEW
  76.  
  77.   FILES REQUIRED TO CREATE HOOK_KBS.EXE AND HOOK_DLS.DLL
  78.  
  79.   DOSWIN32.MAC  Macros and Equates used by Programs
  80.  
  81.   HOOK_KBS.ASM  Source for Executable, Assembled and Linked by MLC-W386.CMD
  82.  
  83.   HOOK_DLS.DEF  Define file needed by IMPLIB and linker for HOOK_DLS.ASM
  84.  
  85.   HOOK_DLS.ASM  Source for HOOK_DLS.DLL, Assembled and linked by DLL-W386.CMD
  86.  
  87.   DLL-W386.CMD  IMPLIB and HOOK_DLS.DEF create C:\TOOLKT20\OS2LIB\HOOK_DLS.LIB
  88.                 MASM then assembles HOOK_DLS.ASM, LINK386 produces HOOK_DLS.DLL
  89.                 and HOOK_DLS.DLL is copied to C:\OS2\DLL directory.
  90.  
  91.   MLC-W386.CMD  MASM assembles HOOK_KBS.ASM and LINK386 produces HOOK_KBS.EXE
  92.  
  93.  
  94.   To ASSEMBLE and LINK use the directory holding the above files as the
  95.   default and the two commands below to produce the necessary files.
  96.  
  97.   DLL-W386  HOOK_DLS
  98.   MLC-W386  HOOK_KBS
  99.  
  100.   FILES REQUIRED TO EXECUTE HOOK_KBS.EXE
  101.  
  102.   HOOK_KBS.DAT  Text File assigning programs to key strokes-read by HOOK_KBS.
  103.                 The user creates this file according to the structure outlined
  104.                 in the sample. MUST BE LOCATED IN C:\OS2. Edit the sample to
  105.                 fit your needs. Note that my assignment to C0 (Shift-Ctrl-0)
  106.                 displays a file which I have configured to list the Hot Key
  107.                 assignments. It serves as a useful reminder and I would
  108.                 recommend each user to make such an assignment. The one I
  109.                 use is a reasonable template and is included as HOT-KEY.MNU.
  110.                 All assignments fit on one screen in the default window size.
  111.  
  112.   HOOK_KBS.EXE  Exec file created above
  113.  
  114.   HOOK_DLS.DLL  Dynamic Load File Created Above - must be in C:\OS2\DLL
  115.  
  116.   DO NOT RENAME HOOK_DLS.* or HOOK_KBS.DAT as those names are coded into
  117.                 HOOK_KBS.ASM .
  118.  
  119.   The assembler used is MASM 6.0 including its built in MACROS for control
  120.   structures and segment definitions.
  121.  
  122.   The 32 bit linker (LINK386) and the 32 bit library, along with the necessary
  123.   INC files require the user to have the OS/2 TOOLKIT as well as MASM 6.0 to
  124.   assemble the program.
  125.  
  126.   PROGRAM METHOD
  127.  
  128.   The system message queue is hooked using the HK_INPUT parameter. The
  129.   function which samples the message queue is in HOOK_DLS.DLL. In the section
  130.   "Input Hook", p. 30-2 in the Programming Guide, Vol. II, it states : "The
  131.   system calls an input_hook function whenever the WinGetMsg or WinPeekMsg
  132.   functions is about to return a message."
  133.  
  134.   The installed procedure, InputHook, in HOOK_DLS.DLL tests for WM_CHAR and
  135.   when detected it further tests to see if the key combination Shift-Alt-X or
  136.   Shift-Ctrl-X was struck, with X (as defined above) on the down stroke. If
  137.   that criteria is met its POSTS to HOOK_KBS, via the API function WinPostMsg,
  138.   the message WM_USER+300h. The mp1 parameter of that message holds a flag
  139.   indicating whether Alt or Ctl was down and the mp2 parameter has the scan
  140.   code for the key X that was struck.
  141.  
  142.   HOOK_KBS determines if the Key actually struck was assigned in the file
  143.   HOOK_KBS.DAT and if so reads its parameters into the appropriate data
  144.   structure required to execute the program. The Shift-Alt-Del key-stroke is
  145.   assigned to removing the DLL from memory and closing the program, equivalent
  146.   to unloading a TSR in DOS.
  147.  
  148.   The main program, HOOK_KBS.EXE, a PM program, sets up the hook, receives the
  149.   message indicated above and takes the appropriate action depending on the
  150.   Key Stroke. The program is established as Invisible and Not listed in the
  151.   Window List. The program should be launched from an OS/2 window with the
  152.   START command, i.e. "START HOOK_KBS". That command can be placed in a
  153.   STARTUP.CMD for automatic loading. If you modify the file HOOK_KBS.DAT, you
  154.   must unload HOOK_KBS by Shift-Alt-Del(white key) and then reload it to
  155.   activate the new set of key assignments.
  156.  
  157.   The program automatically sets DPMI_DOS_API=ENABLED for programs whose
  158.   session type (DOS full or windowed) is defined as 4 or 7 in hook_kbs.dat.
  159.   This enables the Dos Protected Mode Interface for the DOS session. If the
  160.   Session type value of 0 is used, DPMI is not enabled as above. It is
  161.   interesting to note that setting that parameter is done by passing the
  162.   DosStartSession data structure an address holding the text string above,
  163.   even though the manual states that the field for a DOS session is reserved
  164.   and must be ZERO. Unfortunately, there are quite a few errors in the OS/2
  165.   Technical Library, but fortunately a lot of people to inform you about them.
  166.  
  167.   The flow of HOOK_KBS is delineated below. The same headings are listed in
  168.   the source code in HOOK_KBS.ASM.
  169.  
  170.  
  171.   PROGRAM FLOW : HOOK_KBS
  172.  
  173.   PRELIMINARIES
  174.     Define Model and Calling Protocol
  175.     Equates for Using Macros in .DATA section
  176.     Equates for INC files
  177.     Include file listings
  178.     Prototype definitions for MASM
  179.     Structure definition for storing info on Program Assignment to Keys
  180.  
  181.   .STACK   defines an 8KB stack
  182.  
  183.   .DATA    contains variables,parameters and strings required for .CODE section
  184.  
  185.   .CODE    outlined below
  186.  
  187.   ESTABLISH WINDOW
  188.     WinInitialize             ;Initialize
  189.     WinCreateMessageQueue     ;Create a Message Queue
  190.     WinRegisterClass          ;Registers and identifies MainWinProc as name
  191.                               ;of Procedure for messages
  192.     WinCreateStdWindow        ;Creates window - here it is made Invisible,etc.
  193.  
  194.   IS HOOK_DLS.DLL LOADED ?    ;If yes, display message and exit
  195.  
  196.   ALLOCATE SHARED MEM AND STORE Handle Returned by WinCreateStdWindow
  197.     This is required in order to pass the Handle to HOOK_DLS
  198.  
  199.   IS DATA FILE AVAILABLE AND VALID ?
  200.     Load C:\OS2\HOOK_KBS.DAT  ;If it does not exist, exit with Error Message
  201.     Get HOOK_KBS.DAT FileSize ;Required by program for subsequent use
  202.     AllocateMemoryBuffer      ;Buffer for User Key assignments from DataFile
  203.     Copy HOOK_KBS.DAT->Buffer ;Read File into Buffer
  204.     Close HOOK_KBS.DAT        ;No longer needed
  205.     Process Data in Buffer    ;If Format Not Correct, EXIT with  Message
  206.  
  207.   ALLOCATE MEMORY FOR SWITCH LIST STRUCTURE
  208.     Do once since size needed can change as programs loaded/unloaded.
  209.  
  210.   ESTABLISH THE HOOK
  211.     DosLoadModule             ;Loads HOOK_DLS.DLL
  212.     DosQueryProcAddr          ;Get the address of the function in the DLL
  213.     WinSetHook                ;Uses the Address above and HK_INPUT to set HOOK
  214.  
  215.   CREATE MAIN MESSAGE LOOP    ;Standard PM requirement but EXIT TEST is
  216.                               ;commented out - a WM_QUIT message has no
  217.                               ;impact here
  218.  
  219.   EXIT ROUTINE                ;Note this is commented out but is included
  220.                               ;to demonstrate the overall structure of
  221.                               ;setting up a PM program
  222.  
  223.   PROCESS MESSAGE QUEUE       ;The heart of a PM program
  224.  
  225.     MainWinProc               ;Processes message queue
  226.       GET PASSED PARAMETERS FROM STACK
  227.  
  228.       RESTORE STACK POINTER AND STACK STATUS
  229.  
  230.       TEST SYSTEM QUEUE FOR MESSAGES FROM
  231.  
  232.         WM_CREATE
  233.  
  234.         WM_PAINT
  235.  
  236.         WM_CHAR
  237.  
  238.         WM_USER+300h          ;dispatched from hook_dls.dll
  239.         IF msg = WM_USER+300h
  240.           GET SCAN CODE AND ALT/CTRL FLAG
  241.           IF Alt-Del struck
  242.             Release DLL,Memory, Close Queues and Windows and Exit
  243.           ELSE TEST FOR ASSIGNED KEYS
  244.             SETUP DATA STRUCTURES FOR ACTIVATING HOT KEY
  245.             GO THRU SWITCH LIST TO SEE IF HOT KEY ACTIVE
  246.                IF ACTIVE SWITCH TO
  247.                ELSE ACTIVATE HOT KEY PROGRAM
  248.           ENDIF
  249.         ENDIF
  250.  
  251.   END  PROGRAM FLOW : HOOK_KBS
  252.  
  253.   The flow of HOOK_DLS is delineated below. The same headings are listed in
  254.   HOOK_KBS.DLL.
  255.  
  256.   PROGRAM FLOW : HOOK_DLS
  257.  
  258.   PRELIMINARIES
  259.     Define Model and Calling Protocol
  260.     Equates for INC files
  261.     Include file listings
  262.  
  263.   .STACK   defines a 2KB stack
  264.  
  265.   .DATA    contains variables,parameters and strings required for .CODE section
  266.  
  267.   .CODE    delineated below
  268.  
  269.   ESTABLISH InputHook
  270.  
  271.   GET PARAMETERS FROM STACK
  272.  
  273.   GET ADDRESS OF SHARED MEMORY
  274.  
  275.       Get Handle Of Hook_kbs and Release Shared Memory
  276.  
  277.   IF WM_CHAR MESSAGE DETECTED
  278.        Save mp1 and mp2 of WM_CHAR message
  279.        Test for Shift Key,Alt/Ctrl Down and Valid Scan Key
  280.        IF ScanCode & Shift & one of Alt or Ctrl down
  281.            Send original message nowhere via WM_USER+0cfffh
  282.            WinPostMessage to HOOK_KBS via WM_USER+300h ;with ALt/Ctrl Flag and
  283.        ENDIF                                           ;ScanCode as parms
  284.   ENDIF
  285.  
  286.   END PROGRAM FLOW : HOOK_DLS
  287.  
  288. DISCUSSION
  289.  
  290.  
  291.   DOSWIN32.MAC  (Macros and Equates used by Program)
  292.  
  293.   This file contains the equates, EXTRN declarations, MACROS and Procedures
  294.   used in the ASM files. The EXTRN declarations include many more than those
  295.   used in the program but represent the accrued list of those used so far in
  296.   my OS/2 assembler programming. (As I use a new one, I just add it).
  297.  
  298.   Included are two defines used in the .DATA section of hook_kbs.asm. The
  299.   single most important MACRO is $CALL. This allows one to list parameters
  300.   after the function name in the same order as they are listed in the OS/2 2.0
  301.   Technical Manuals (and as called in C) . The macro pushes them on the stack
  302.   in the correct order and resets the stack pointer after the call. It could
  303.   clearly easily be extended to accomodate a longer parameter list. Following
  304.   that are several useful macros and three others defined via equates.
  305.  
  306.   For displaying error messages and rudimentary inline debugging, there are
  307.   three macros named $DosErrMsg, $WinErrMsg and $WinDebugMessage . The first
  308.   two are meant to be called after an API function call to display the error
  309.   number for the function used. Information on the success of the call is
  310.   returned in EAX and this must be tested. Note EAX returns differently for
  311.   DOS than for WIN calls. The user passes the text string for the Function
  312.   used on the parameter line for the $XXXErrMsg. $DosErrMsg can only be used
  313.   in Text Windows while $WinErrMsg only in PM windows.
  314.  
  315.   Finally there are several macros and procedures used for Binary <-> ASCII
  316.   conversion for both Decimal and Hex, and also for displaying numerical
  317.   results in Binary form. Not all of these are used but are included as a part
  318.   of the overall package. Note that in 32 bit mode, it is most convenient to
  319.   do all these conversion as DWORDS. These are required for numerical to ASCII
  320.   conversion for the error messages.
  321.  
  322.   HOOK_DLS.DEF
  323.  
  324.   This file is required by both IMPLIB and LINK386 in the creation of
  325.   HOOK_DLS.DLL. It identifies the function(s) exported from the DLL.
  326.  
  327.   HOOK_DLS.ASM
  328.  
  329.   This file represents the dynamic link code. It contains one function, named
  330.   InputHook whose syntax is defined by OS/2 on page 30-2 of the Programming
  331.   Guide, Vol II of the OS/2 Technical Library. This DLL monitors the system
  332.   message queue and looks for the message WM_CHAR.
  333.  
  334.   Since I decided to use WinPostMsg to return information to hook_kbs, its
  335.   handle is required in this program. The simplest way seemed to be to pass it
  336.   in a shared memory region established by hook_kbs. Thus the first task done
  337.   by the function InputHook, after setting itself up, is to get the address of
  338.   the shared memory region and to obtain the handle of hook_kbs that was placed
  339.   there by hook_kbs. After that is done, the shared memory is released.
  340.  
  341.   The program then waits for a message WM_CHAR and when that is detected the
  342.   Keyboard Parameters are tested to see if they meet the HotKey criteria. If
  343.   they do not, the message is passed on. If they do, a flag denoting whether
  344.   the Alt or Ctrl key was down is equated to the mp1 parameter and the scan
  345.   code value equated to the mp2 parameter of the message WM_USER+300h which is
  346.   posted to HOOK_KBS by WinPostMsg.
  347.  
  348.   This DLL is released from memory when hook_kbs is closed.
  349.  
  350.   HOOK_KBS
  351.  
  352.   The first four WIN... function calls are a standard calling sequence in
  353.   setting up a PM program. Since a PM program cannot display text using DOS
  354.   write calls, error messages cannot be displayed with Window Message Calls
  355.   until the Window is initialized with the first call.
  356.  
  357.   After the window is established a test is done to see if HOOK_DLS is loaded.
  358.   If it is a message is given and the program terminates. A Shared Memory area
  359.   is then established. Its sole use in this program is to furnish a method of
  360.   passing HOOK_KBS's handle to HOOK_DLS. This is done following the call to
  361.   DosAllocSharedMem. Note that eax is now tested for a non-zero value
  362.   indicating an error, as contrasted to Win calls where a 0 returned in eax
  363.   indicates an error.
  364.  
  365.   Next the program attempts to load the data file C:\OS2\HOOK_KBS.DAT. If it
  366.   does not exist, an error message is displayed and the program terminates. If
  367.   it loads, its size is obtained (note the calls are rather similar to what
  368.   you would do in DOS) and that value is used to create a buffer to hold the
  369.   file in memory. The file is read into the buffer and then closed. The big
  370.   .WHILE loop reads the buffer and assigns the Addresses of the Executable
  371.   program name and Command Line parameters and the Session type to the
  372.   appropriate member of the Structure ExecOnKb and places a 0 at the end of
  373.   strings in order that they meet the requirement of being ASCIIZ strings. If
  374.   the count of characters read in the buffer does not equal the file size or
  375.   if the data file was not properly formatted, an error message is displayed
  376.   and the program terminated; the error message displays the number of bytes
  377.   of the buffer processed when the program terminated.
  378.  
  379.   If everything is in order, a large memory block is defined to hold the data
  380.   structure of the Switch List (which is used to determine if a program is
  381.   loaded or not) and then the HOOK is established with the next three calls to
  382.   DosLoadModule, DosQueryProcAddr and WinSetHook.
  383.  
  384.   The Main Message Loop is next established. Normally this loop is exited when
  385.   WM_QUIT is received and the exit code is executed to gracefully terminate
  386.   the program. However, in this program, to ensure that it is terminated only
  387.   by the Key Combination Alt-Del, the Main Message Loop is not exitable (I
  388.   have commented out the normal tests) and I have included the Exit code only
  389.   for purposes of demonstration of what a more normal program would look like.
  390.  
  391.   The procedure MainWinProc examines the message queue. It first sets up to
  392.   get the parameters passed on the stack and goes through a series of tests
  393.   for specific messages. In a C program this would usually be a Case
  394.   statement. There is no requirement for these tests to do anything in this
  395.   case since the window is invisible but they are required to respond to
  396.   certain system calls.
  397.  
  398.   The heart of the program is the test for WM_USER+300h . WM_USER defines a
  399.   lower limit for message IDs that is (presumably) guaranteed not to conflict
  400.   with any system messages. I have arbitrarily used WM_USER + 300h. HOOK_DLS
  401.   uses this message ID in posting its information to this programs message
  402.   queue. First a test is done to see whether Alt-Del was struck and if so, the
  403.   system is closed and exited. If not, tests are done to see whether the Scan
  404.   Code of the key struck is in the list read from HOOK_KBS.DAT. A test is
  405.   first done to see if the (white)Insert key was struck, and if not, a test is
  406.   done for the rest of the possible assignments.
  407.  
  408.   Depending on the key combination struck, the address of the program, address
  409.   of the command line parameters, the Session Type for the Key Combination
  410.   identified in the message and the Program Title ( based on the Key
  411.   combination ) are obtained and inserted into the StartData structure
  412.   required for the DosStartSession function. The Switch (Task) list is then
  413.   examined to see if the HotKey program is already loaded and its identity
  414.   unchanged. If it is, it is switched to, else DosStartSession is then called
  415.   with appropriate parameters.
  416.  
  417.   Note that WinSetFocus is called before DosStartSession. The programs started
  418.   by DosStartSession will not be in the foreground unless the program calling
  419.   DosStartSession is in the foreground and it seems reasonable that programs
  420.   called with a "HotKey" want to be in the foreground.
  421.  
  422.   The six procedures at the very end are just routines used by parts of the
  423.   code in the program.
  424.  
  425.   I have found this program very useful, particularly with respect to programs
  426.   using COM ports. Since OS/2 will not allow you to have two programs open at
  427.   the same time that use the same COM port, this affords a rapid means of
  428.   serially accessing programs sharing a common COM port. Another use I have
  429.   found effective is to assign MENUS to some of the Hot Keys. In my sample
  430.   HOOK_KBS.DAT file, the assignment Aq (Alt-q) to loadq.cmd, is a CMD file
  431.   that displays a menu for editing a variety of different files and the
  432.   assignment Ar (Alt-r) to viewref.cmd displays a menu whose choices allow you
  433.   to View the various OnLine References of OS/2 and Toolkit20. You can readily
  434.   assign any program assigned to an ICON to a hot key, presuming the program
  435.   has an executable form or can be called as a parameter to another program.
  436.   But by far I have found it an efficient expediter for rapidly accessing
  437.   programs without changing anything on your DeskTop.
  438.  
  439.   As it was with TSR's in DOS, you must be careful of your assignments so that
  440.   required keys in programs are not made unavailable. That stricture was
  441.   reflected in my choice of keys to assign and reflects my particular
  442.   concerns. A natural question to ask is - are there any problems with other
  443.   programs that may be sampling the system message queue ?
  444.  
  445.   Included in OS/2 and the Toolkit are the following programs that I am aware
  446.   of which are "resident" in the above sense:
  447.  
  448.     PULSE    From Productivity Group - Samples Processor Activity
  449.     KWIKINF  From OS/2 ToolKit20     - An  OnLineReference Access
  450.     PMSPY    From OS/2 ToolKit20     - A Message queue trace
  451.  
  452.   I have not detected any problems with HOOK_KBS loaded with any or all of the
  453.   above programs active, independent of the order of loading.
  454.  
  455.