home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HOOKKBS.ZIP / hook_kbs.asm < prev    next >
Assembly Source File  |  1992-09-26  |  33KB  |  777 lines

  1. ;---------------------------------------------------------------------------;
  2. ; M.F.Kaplon  Begun:Fri  06-12-1992  Revised:Fri  09-25-1992
  3. ; Title : hook_kbs.asm
  4. ;
  5. ; "Copyright 1992 M.F. Kaplon"
  6. ;
  7. ; INITIALIZES,CREATES MESSAGE QUEUE, REGISTERS CLASS,CREATES STANDARD WINDOW
  8. ; ESTABLISHES MAIN MESSAGE LOOP, ESTABLISHES MAIN WINDOW PROCEDURE, Reads in
  9. ; C:\os2\hook_kbs.dat , Establishes Hook HK_INPUT, Reeived Filtered Messages
  10. ; from hook_dls , mp1 = Alt/Ctrl flag, mp2 = scan code and
  11. ; takes appropriate action. Uses WM_USER+300h to receive message.
  12. ;
  13. ; For System Function Calls
  14. ;
  15. ; 1 - Must use the C Calling Convention which means
  16. ;     Arguments Pushed on Stack in Reverse Order than declared in function
  17. ;     And the stack pointer reset after call.
  18. ;     This is done by the MACRO   $Call   defined in DOSWIN32.MAC
  19. ; 2 - Use  .MODEL FLAT. When using a pointer, all you have to do is push
  20. ;     the offset of the variable since in FLAT model everyting is NEAR
  21. ;     in the 32 bit space
  22. ; 3 - Uses an 8K stack
  23. ;
  24. ; It is assumed that the Developers toolkit for OS/2 2.0 is installed
  25. ; on the users C:drive in the default installation
  26. ;
  27. ; The files needed to create the functioning program are:
  28. ; doswin32.mac  Macros and Equates used by Program
  29. ; hook_kbs.asm   Source for Executable  Assembled and Linked by mlc-w386.cmd
  30. ; hook_dls.def  Define file needed by IMPLIB and LINK386 for DLL
  31. ; hook_dls.asm  Source for DLL = Assembled and linked by dll-w386.cmd
  32. ; hook_kbs.dat  Text File assigning programs to key strokes -read by hook_kb
  33. ;               The user creates this file according to structure outlined in
  34. ;               sample and it MUST BE LOCATED IN C:\OS2\DLL
  35. ; dll-w386.cmd  Command File to create the hook_dls.dll and copy to c:\os2\dll
  36. ; mlc-w386.cmd  Command File to Assemble and Link hook_kbs.asm
  37. ;
  38. ; Except as noted, all files should be in the same directory.
  39. ; To assemble and link use the directory holding the above files as default
  40. ; and use the commands
  41. ; dll-w386  hook_dls;creates hook_dls.dll from hook_dls.asm,moves to c:\os2\dll
  42. ; mlc-w386  hook_kb ;creates hook_kbs.exe from  hook_kbs.asm
  43. ;
  44. ; kb_hooks.exe is placed in the directory holding the above files
  45. ;
  46. ; There is one warning message
  47. ;
  48. ; LINK : warning L4036: no automatic data segment
  49. ;
  50. ; This message has to do with no DGROUP being defined
  51. ; It can be suppressed with DATA NONE in a "DEF" file
  52. ;
  53. ;---------------------------------------------------------------------------;
  54. ;USES HOOK HK_INPUT
  55. ;----------------- PRELIMINARIES ----------------
  56.  
  57. .386             ;preceeding .MODEL makes USE32 default
  58. .MODEL           FLAT,SYSCALL,OS_OS2
  59.  
  60. ;---------- Conditionally required equates -------------
  61. NUMBUFS            equ    1     ; Uncomment if need number routines
  62. DOSERROR           equ    1     ; Uncomment if need DosError Messages
  63.  
  64. INCL_WINERRORS     equ    1
  65. INCL_WIN           equ    1
  66. INCL_DOSMEMMGR     equ    1
  67. INCL_DOSFILEMGR    equ    1
  68. INCL_WINSWITCHLIST equ    1
  69.  
  70. INCLUDE        doswin32.mac             ;macros used by *.asm
  71.  
  72. INCLUDE        c:\toolkt20\asm\os2inc\os2def.inc ;structure defns includes POINTL
  73. INCLUDE        c:\toolkt20\asm\os2inc\pmwin.inc  ;structure defns POINTL defn required
  74. INCLUDE        c:\toolkt20\asm\os2inc\pmerr.inc  ;errors
  75. INCLUDE        c:\toolkt20\asm\os2inc\pmshl.inc
  76. INCLUDE        c:\toolkt20\asm\os2inc\bsememf.inc;memory
  77. INCLUDE        c:\toolkt20\asm\os2inc\bsedos.inc ;files
  78. INCLUDELIB     c:\toolkt20\os2lib\os2386.lib     ;Library
  79.  
  80. ;---------- Prototype Definitions for MASM 6.0 -------------
  81. InitMainWindow Proto Near SYSCALL var1:DWORD,var2:DWORD,var3:DWORD
  82. MainPaint      Proto Near SYSCALL var1:DWORD
  83. MainKeyBoard   Proto Near SYSCALL var1:DWORD,var2:DWORD,var3:DWORD
  84.  
  85. ExecOnKB     STRUCT      ;Structure used in program-stores data from hook_kb.dat
  86.    Exec     DWORD   ?    ;Address of ASCIIZ str - name of exec program
  87.    CmdLn    DWORD   ?    ;Address of ASCIIZ str - command line parms
  88.    SessT     WORD   ?    ;Session Type
  89. ExecOnKB    ENDS         ;structure length now = 22
  90.  
  91. LenExec     equ    10    ;length of ExecOn Kb
  92.  
  93. .STACK    8096   ;8K stack
  94.  
  95. .DATA
  96.  
  97. IFDEF NUMBUFS                      ;To use  UNCOMMENT NUMBUFS equate above
  98.   $DefineNumBufs
  99. ENDIF
  100. IFDEF DOSERROR
  101.    $DOSErrorMessages
  102. ENDIF
  103.  
  104. ; Copyright Notice
  105. notice          BYTE   "Copyright 1992 M.F. Kaplon"
  106.  
  107. ;------------- handles --------
  108. hab            DWORD   ?           ;Anchor block Handle
  109. hmq            DWORD   ?           ;Message Queue Handle
  110. hwndMainFrame  DWORD   ?           ;Handle to Main Frame Window
  111. hwndMain       DWORD   ?           ;Handle to Client window
  112.  
  113. ;------------- Text Strings --------
  114. szAppName       BYTE   "Main0",0    ;Class Name of Window Procedure
  115. szWinTitle      BYTE   "** TSR **",0 ;Window Title
  116. szDebugMsg      BYTE   "  SwitchHandle",0
  117. ;------------- Text Strings for WinMessageBox calls for Errors --------
  118.  
  119. msgModuleLoaded         BYTE "hook_KBS Already Loaded",0
  120. msgInfo                 BYTE "Debug Info",0
  121. msgFileErr              BYTE "Incorrect hook_kbs.dat File",0
  122.  
  123. ;------------- Styles --------
  124. msgBoxStyle    DWORD   (MB_YESNO OR MB_DEFBUTTON1)
  125. flStyle        DWORD   (CS_SIZEREDRAW OR CS_HITTEST)  ;Window Style
  126. flCtlData      DWORD   FCF_SYSMENU                    ;Invisible Window
  127.  
  128. ;------------- structures --------
  129. quemsg          QMSG    {,,,,,,}        ;Queue message structure
  130. AltX           ExecOnKB 37 dup({0,0,9}) ;Array for  Alt-# 0-9,A-Z,A-Ins default Initialization
  131. CtrlX          ExecOnKB 36 dup({0,0,9}) ;Array for Ctrl-# 0-9,A-Z default Initialization
  132.  
  133. ;------------- Miscellaneous --------
  134. parm1          DWORD   ?           ;handle of window sending message
  135. parm2          DWORD   ?           ;message id value
  136. parm3          DWORD   ?           ;message mp1
  137. parm4          DWORD   ?           ;message mp2
  138. parm5          DWORD   ?           ;message time
  139. Concanted       BYTE 64 dup(0)     ;buffer to hold concanted strings
  140. Alt_Ctrl       DWORD   ?           ;0/1 if Alt/Ctrl key struck
  141. lookup0         BYTE   'Q'-37h,'W'-37h,'E'-37h,'R'-37h,'T'-37h,'Y'-37h,'U'-37h,'I'-37h,'O'-37h,'P'-37h ;26,32,14,27,29,34,30,18,24,25 ;
  142. lookup1         BYTE   'A'-37h,'S'-37h,'D'-37h,'F'-37h,'G'-37h,'H'-37h,'J'-37h,'K'-37h,'L'-37h         ;10,28,13,15,16,17,19,20,21 ;
  143. lookup2         BYTE   'Z'-37h,'X'-37h,'C'-37h,'V'-37h,'B'-37h,'N'-37h,'M'-37h                         ;35,33,12,31,11,23,22 ;
  144.  
  145. ;------------ Specific to TSR Hook  use -----
  146. DllLoadError    BYTE  100 dup(0)   ;Buffer for name of object contributing to error
  147. DllHandle      DWORD ?             ;Handle of Dynamic LInk Module returned here
  148. DllFullModName  BYTE  "c:\os2\dll\hook_dls.dll",0
  149. DllProcAddr1   DWORD ?             ;address of proc 1 in dynamic link module
  150.  
  151. ;- StartSession structure Offset ------------ Identification --------------
  152. StartData       WORD  32    ; 0  Length of Structure for all but Shift-Alt-W
  153.                 WORD  0     ; 2  Related 0 is independent, 1 is child
  154.                 WORD  0     ; 4  0/1 Start in Foreground/Background
  155.                 WORD  0     ; 6  Trace Option 0 is no trace
  156.                DWORD  0     ; 8  ProgramTitle 0 uses Program Name
  157.                DWORD  ?     ;12  Address of ASCZII string with fully qualified program name
  158.                DWORD  0     ;16  Address of Input Args to Pgm - 0 is none
  159.                DWORD  0     ;20  TermQ 0 is no Queue
  160.                DWORD  0     ;24  Environment - must be 0 for DOS
  161.                 WORD  0     ;28  InheritOp 0 Inherits Shell Environment
  162.                 WORD  ?     ;30  SessType see p.2-345 of Control Prog Ref.
  163.                DWORD  ?     ;32  ICON File
  164.                DWORD  ?     ;36  PgmHandle
  165.                 WORD 8000h  ;40  PgmControl-use specified size for Shift-Alt-W
  166.                 WORD 140    ;42  InitXPos  for Shift-Alt-W
  167.                 WORD 200    ;44  InitYPos  for Shift-Alt-W
  168.                 WORD 350    ;46  InitXSize for Shift-Alt-W
  169.                 WORD  60    ;48  InitYSize for Shift-Alt-W
  170.  
  171. SessID         DWORD  0     ;receives Session ID for Alt-1
  172. ProcID         DWORD  0     ;receives ProcessID  for Alt-1
  173. TitleAlt        BYTE  "Alt- ",0  ;space filled in with 3 or letter
  174. TitleCtl        BYTE  "Ctl- ",0  ;space filled in with 3 or letter
  175. HotKeyID        BYTE   ?         ;Identifies HotKey Selected
  176. InsProg         BYTE  "c:\4os2\4os2.exe",0 ; assigned to Shift-Alt-Ins
  177. DosEnvValue     BYTE  "DPMI_DOS_API=ENABLED",0
  178. ;----Shared Memory Variables---
  179. SharedMem      DWORD  ?     ;base address returned
  180. SharedMemName   BYTE  "\SHAREMEM\DATAS.DAT",0
  181. SharedMemFlags DWORD  12h   ;(PAG_COMMIT OR PAG_WRITE)
  182.  
  183. ;-------------- parameters for memory usage and file opening
  184. memAddr        DWORD   ?                        ;address of memory block
  185. memFlags       DWORD  13h ;(PAG_COMMIT OR (PAG_WRITE OR PAG_READ)) ;read-write access required
  186.  
  187. fName          BYTE    "c:\os2\hook_kbs.dat",0  ;Address of data file
  188. fhandle        DWORD   ?                        ;Address of Handle for File
  189. fActionTaken   DWORD   ?                        ;Address for action taken
  190. fSize          DWORD   ?                        ;Logical size of file
  191. fAttribute     DWORD   0
  192. fOpenFlag      DWORD   OPEN_ACTION_OPEN_IF_EXISTS
  193. fOpenMode      DWORD   OPEN_SHARE_DENYNONE OR OPEN_ACCESS_READWRITE
  194. fExtaBuf       DWORD   0                        ;no extended attributes
  195.  
  196. fpointer0      DWORD   ?                        ;file pointer start file
  197. fpointer1      DWORD   ?                        ;file pointer end file
  198. EOFflag        DWORD   0                        ;EndOfFile flag
  199. ;------------ switch list parameters -------------
  200. numitems       DWORD   ?                        ;#items in list
  201. baseaddr       DWORD   ?                        ;of SWBLOCK {,}
  202.  
  203. .CODE
  204.  
  205. startup:                         ;need to do this way with flat model
  206.  
  207. ;----------  GET COMMANDLINE PARMS -------
  208. ;$GetCmdLine                    ;macro
  209. ;.WHILE byte ptr [esi] != 0     ;go past program name
  210. ;      inc    esi
  211. ;.ENDW
  212. ;inc    esi                     ;now points to  1st space after command name
  213. ;mov    eax,0
  214. ;.WHILE  byte ptr [esi] != 0    ;go to end of command line
  215. ;     .WHILE byte ptr [esi] == ' '
  216. ;          inc   esi
  217. ;     .ENDW
  218. ;     .IF byte ptr [esi] != ' ' && byte ptr [esi] != 0; if a space
  219. ;         inc    esi
  220. ;         inc    eax
  221. ;         .WHILE byte ptr [esi] != ' ' && byte ptr [esi] != 0
  222. ;              inc   esi
  223. ;         .ENDW
  224. ;     .ENDIF
  225. ;.ENDW                          ;if eax non 0 has cmd line parm
  226. ;
  227. ;.IF eax > 0                    ;turn shft flag on
  228. ;    mov   shft_flag,1
  229. ;.ENDIF
  230.  
  231. ;----------  ESTABLISH WINDOW ------------
  232.  
  233. ;-----Initialize Window -Anchor block handle returned = hab
  234. $Call WinInitialize,0            ;called with argument 0
  235. mov    hab,eax                   ;return value
  236. .IF hab == NULL
  237.     $Call WinTerminate,hab
  238.     $DosExit
  239. .ENDIF
  240.  
  241. ;-----Create MessageQue  QueueHandle returned = hmq
  242. $Call WinCreateMsgQueue,hab,0    ; 0 is default size of queue
  243. mov      hmq,eax                 ;returned queue handle
  244. .IF hmq == NULL
  245.    $WinErrMsg " : WinCreateMsgQueue"
  246.    $DosExit
  247. .ENDIF
  248.  
  249. ;---- Register Window Class Returned value is TRUE or FALSE
  250. $Call WinRegisterClass,hab,offset szAppName,offset MainWinProc,flStyle,0
  251. .IF eax == FALSE
  252.     $WinErrMsg " : WinRegisterClass"
  253.     $Call WinTerminate,hab
  254.     $DosExit
  255. .ENDIF
  256.  
  257. ;---- CreateStandard Window - Returns handle for Main Window Frame and client Window
  258. $Call WinCreateStdWindow,HWND_DESKTOP,WS_VISIBLE,offset flCtlData,offset szAppName,\
  259.                     offset szWinTitle,WS_VISIBLE,0,0,offset hwndMain
  260. mov   hwndMainFrame,eax          ;returned Frame Window handle
  261. .IF hwndMainFrame == 0
  262.    $WinErrMsg " : WinCreateStdWindow"
  263.    Call   ExitWin
  264. .ENDIF
  265.  
  266. ;------------  IS hook_DLL.DLL LOADED ? -------------------
  267.  
  268. $Call DosQueryModuleHandle,offset DllFullModName,offset DllHandle
  269. .IF  eax == 0    ;module already loaded
  270.      $Call WinMessageBox,HWND_DESKTOP,HWND_DESKTOP,offset msgModuleLoaded,NULL,0,msgBoxErrStyle
  271.      Call   ExitWin
  272. .ENDIF
  273.  
  274. ;----- ALLOCATE SHARED MEM AND PLACE HANDLE THERE ----
  275. $Call DosAllocSharedMem,offset SharedMem,offset SharedMemName,32,SharedMemFlags
  276. .IF eax > 0
  277.    $WinErrMsg " : DosAllocSharedMem"
  278.    Call   ExitWin
  279. .ENDIF
  280. mov    esi,SharedMem
  281. mov    eax,hwndMainFrame
  282. mov    [esi],eax     ;put window handle there
  283.  
  284. ;----------  IS Data File AVAILABLE AND VALID ? ------------
  285.  
  286. ;---------- First see if  hook_kb.dat exists in proper location ------
  287. $Call DosOpen,offset fName,offset fhandle,offset fActionTaken,fsize,fAttribute,fOpenFlag,fOpenMode,fExtaBuf
  288. .IF   eax != 0
  289.      $WinErrMsg " : DosOpen "
  290.      Call   ExitWin
  291. .ENDIF
  292.  
  293. ;------- get file size
  294. $Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
  295. .IF    eax != 0
  296.      $WinErrMsg " : DosSetFilePtr"
  297.       Call   ExitWin
  298. .ENDIF
  299.  
  300. $Call DosSetFilePtr,fhandle,0,FILE_END,offset fpointer1
  301. mov    eax,fpointer1
  302. sub    eax,fpointer0
  303. mov    fsize,eax        ;fsize now has file size
  304. add    eax,16           ;allow a little leeway in buffer
  305. ;------- now allocate memory for file buffer
  306. $Call DosAllocMem,offset memAddr,eax,memFlags
  307. .IF    eax != 0
  308.      $WinErrMsg " : DosAllocMem FileBuf"
  309.      Call   ExitWin
  310. .ENDIF
  311.  
  312. ;------Read File Into buffer and Close file -------
  313. ;reposition to start of file
  314. $Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
  315. $Call DosRead,fHandle,memAddr,fsize,offset nwritten
  316. $Call DosClose,fHandle
  317.  
  318. ;------ Read Buffer and Initialize Arrays ALtX and CtrlX ----
  319. mov    esi,memAddr
  320. mov    ecx,0               ;Index and Counter for memAddr
  321.  
  322. .WHILE ecx <=  fsize
  323.     call   SkipSpaces        ;skip over any initial spaces
  324.     .BREAK .IF EOFflag == 1
  325.     call   SkipCommentsToEOL ;skip over comments and spaces to first valid entry
  326.     .BREAK .IF EOFflag == 1
  327.     call SkipSpaces          ;skip over initial spaces
  328.     .BREAK .IF EOFflag == 1
  329.     .IF (byte ptr [esi+ecx] == 'A' || byte ptr [esi+ecx] == 'a' || byte ptr [esi+ecx] == 'C' || byte ptr [esi+ecx] == 'c')
  330.          inc   ecx           ;point to number or letter
  331.          xor   eax,eax
  332.          xor   edx,edx
  333.          mov  al,byte ptr [esi+ecx]  ;get digit or letter ID
  334.         .IF  (al >= '0' && al <= '9')
  335.              sub  al,'0'         ;convert to decimal
  336.         .ENDIF
  337.         .IF  al  >= 'a'
  338.              sub  al,32          ;convert to UpperCase
  339.         .ENDIF
  340.         .IF  (al >= 'A' && al <= 'Z')
  341.              sub  al,37h          ;convert to decimal 10 +
  342.         .ENDIF
  343.          mov      dl,LenExec ;Length of Structure    10
  344.          mul      dl         ;ax has offset into array
  345.          inc      ecx        ;right after digit/letter id A/C number
  346.     .ELSE
  347.          .CONTINUE
  348.     .ENDIF
  349.     .IF byte ptr[esi+ecx - 2] == 'A' || byte ptr[esi+ecx - 2] == 'a'
  350.           mov     edi,offset AltX      ;this is Alt Keys
  351.     .ENDIF
  352.     .IF byte ptr[esi+ecx - 2] == 'C' || byte ptr[esi+ecx - 2] ==  'c'
  353.           mov     edi,offset CtrlX     ;this is a Ctrl Key
  354.     .ENDIF
  355.     .IF edi == offset AltX || edi == offset CtrlX
  356.           mov     edx,eax              ;edx is offset into array
  357.           call    SkipSpaces           ;go to SessID
  358.           .BREAK .IF EOFflag == 1
  359.           xor     eax,eax
  360.           mov     al,byte ptr [esi+ecx] ;get sess type
  361.           sub     al,'0'                ;convert to  number
  362.           mov     word ptr [edi + edx+8],ax
  363.           inc     ecx
  364.           call    SkipSpaces            ;get to Exec string
  365.           .BREAK .IF EOFflag == 1
  366.           mov     eax,esi
  367.           add     eax,ecx               ;offset of exec
  368.           mov     [edi+edx],eax         ;store its address
  369.           ; have to go to end of Exec string and place a numeric 0 there
  370.           .WHILE  byte ptr [esi+ecx] != ' '
  371.                inc  ecx
  372.           .ENDW   ;exits    pointing to end of exec command
  373.           .BREAK .IF byte ptr[esi+ecx] != ' '
  374.              mov     byte ptr [esi+ecx],0
  375.           inc     ecx
  376.           call    SkipSpaces            ;get next parameter
  377.           .BREAK .IF EOFflag == 1
  378.           xor     eax,eax
  379.           .IF     byte ptr [esi+ecx]== '0'  ;no command line
  380.               mov     al,byte ptr [esi+ecx]
  381.               sub     al,'0'
  382.               mov     [edi+edx+4],eax
  383.           .ELSE                         ;its a string - copy its address
  384.               mov eax,esi
  385.               add eax,ecx               ;offset of command line
  386.               mov     [edi+edx+4],eax   ;store command line address
  387.               .IF   byte ptr [esi+ecx] != 22h  ;not a "
  388.                  .WHILE  byte ptr [esi+ecx] != ' ' && ecx < fsize  ;skip until a space
  389.                      .IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr  ; LF but no ";"
  390.                           Call DataFormatErr
  391.                      .ENDIF
  392.                       inc  ecx
  393.                  .ENDW                  ;exits  pointing to end of command line
  394.                 .BREAK .IF ecx >= fsize
  395.                  mov    byte ptr [esi+ecx],0 ;put 0 at end
  396.               .ELSE                     ;first char is a quote
  397.                  inc  ecx               ;move beyond it
  398.                  .WHILE byte ptr [esi+ecx] != 22h && ecx < fsize ; skip until a "
  399.                       inc  ecx
  400.                  .ENDW                  ;exits pointing to final quote
  401.                  .BREAK .IF ecx >= fsize
  402.                  inc    ecx
  403.                  .BREAK .IF byte ptr[esi+ecx] != ' '
  404.                  mov    byte ptr [esi+ecx],0 ;put 0 at end
  405.               .ENDIF
  406.           .ENDIF
  407.           ;inc    ecx
  408.           .BREAK .IF ecx >= fsize
  409.           xor    edi,edi                ;reset to 0 so test can be made
  410.           .WHILE byte ptr[esi+ecx] != ';' && ecx < fsize  ;go to next comment ;
  411.               .IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr  ; LF but no ";"
  412.                    Call DataFormatErr
  413.               .ENDIF
  414.               inc   ecx
  415.           .ENDW
  416.           .BREAK .IF ecx >= fsize
  417.           .CONTINUE
  418.     .ENDIF
  419. .ENDW
  420. ; See if Dat File properly read in
  421. .IF ecx < fsize
  422.      Call DataFormatErr
  423. .ENDIF
  424.  
  425. ;---------  ALLOCATE MEMORY FOR SWITCH LIST STRUCTURE -------
  426. mov     ecx,00000002h   ;write access flags for Dos alloc
  427. or      ecx,00000010h   ;page commit
  428. $Call DosAllocMem,offset baseaddr,3000,ecx
  429. .IF  eax != 0
  430.     $WinErrMsg  " : DosAllocMem SwitchList"
  431.     Call ExitWin
  432. .ENDIF
  433.  
  434. ;-----------  ESTABLISH THE HOOK -------------
  435.  
  436. ;The way to proceed is to install a System Hook. This has to go into a DLL
  437. ;otherwise it cannot be called by other programs. The procedure in hook_dls
  438. ;will inspect WM_CHAR and if the ShiftKey and one of Alt or Ctrl key is down
  439. ;and if there is a valid Scan Code THEN
  440. ;it redefine the msg ID of that message as WM_USER+cfffh so it goes nowhere
  441. ;and then post a message to this program with the mp1 and mp2 parms
  442. ;using WM_USER+300h
  443. $Call DosLoadModule,offset DllLoadError,LENGTHOF DllLoadError,offset DllFullModName,offset DllHandle
  444. .IF eax != 0
  445.     $WinErrMsg " DosLoadModule"
  446. .ENDIF
  447. $Call DosQueryProcAddr,DllHandle,1,0,offset DllProcAddr1
  448. .IF eax != 0
  449.     $WinErrMsg " DosQueryProcAddr"
  450. .ENDIF
  451. $Call WinSetHook,hab,NULLHANDLE,HK_INPUT,DllProcAddr1,DllHandle
  452. .IF eax == 0
  453.     $WinErrMsg " WinSetHook"
  454. .ENDIF
  455.  
  456. ;---------  CREATE MAIN MESSAGE LOOP -----------
  457.  
  458. mml: $Call WinGetMsg,hab,offset quemsg,0,0,0    ;Note: differs from usual
  459. ;     .IF eax == TRUE                           ;msg loop - done so that program
  460.          $Call WinDispatchMsg,hab,offset quemsg ;can only be terminated
  461.          jmp   mml                              ;by the keystroke Shift-Alt-Del
  462. ;     .ENDIF                                    ;as notified from the DLL
  463.  
  464. ;Normally an Exit routine would go here, as indicated below but which
  465. ;is commented out. It is not required since it can never be reached.
  466. ;----------  EXIT ---------------
  467. ;$Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
  468. ;.IF    eax == 0
  469. ;     $WinErrMsg " : WinReleaseHook"
  470. ;.ENDIF
  471. ;$Call DosFreeModule,DllHandle
  472. ;.IF    eax != 0
  473. ;     $WinErrMsg " : DosFreeModule"
  474. ;.ENDIF
  475. ;$Call DosFreeMem,memAddr
  476. ;$Call WinDestroyWindow,hwndMainFrame
  477. ;call  ExitWin
  478.  
  479. ;---------------- End of Main Program -------------------
  480.  
  481. ;-------------  PROCESS MESSAGE QUEUE FOR hook_KB ------------
  482. ;------------------ MainWinProc -----------------
  483. ;parm1 = hwnd,parm2 = msg,parm3  = mp1,parm4 = mp2
  484. ;this is called from System and so has to do everything itself
  485. MainWinProc Proc Near
  486.     ;----------- GET PASSED PARAMETERS FROM STACK ------------
  487.     push   ebp           ;return address is 4 bytes and this push is 4 bytes
  488.     mov    ebp,esp       ;so first parameter is 8 bytes from top
  489.     mov    eax,[ebp+8]
  490.     mov    parm1,eax     ;hwnd
  491.     mov    eax,[ebp+12]
  492.     mov    parm2,eax     ;msg
  493.     mov    eax,[ebp+16]
  494.     mov    parm3,eax     ;mp1
  495.     mov    eax,[ebp+20]
  496.     mov    parm4,eax     ;mp2
  497.     mov    eax,[ebp+24]
  498.     mov    parm5,eax     ;time of message
  499.    ;----- RESTORE STACK POINTER AND STACK STATUS  ---
  500.     mov      esp,ebp     ;restore  stack pointer
  501.     pop      ebp
  502.  
  503.     ;---------------- WM_CREATE ----------------
  504.     .IF parm2 == WM_CREATE
  505.          Invoke InitMainWindow,parm1,parm3,parm4
  506.     .ENDIF
  507.     ;---------------- WM_PAINT ----------------
  508.     .IF parm2 == WM_PAINT ; && parm1 == hwndMain
  509.        Invoke  MainPaint,parm1
  510.     .ENDIF
  511.     ;---------------- WM_CHAR ----------------
  512.     .IF parm2 == WM_CHAR
  513.        Invoke  MainKeyboard,parm3,parm4,parm1    ;sets return value
  514.     .ENDIF
  515.     ;---------------- WM_USER+0CFFFH ----------------
  516. ;    .IF parm2 == WM_USER+0CFFFh                  ;diverted message
  517. ;        mov    eax,TRUE
  518. ;    .ENDIF                                       ;makes no diff
  519.     ;---------------- WM_USER+300H ----------------
  520.     .IF parm2 == WM_USER+300h                    ;posted message
  521.     ;if here know that Shift Key was down and at least one of Alt or Ctrl
  522.     ;GET SCAN CODE AND ALT/CTRL FLAG
  523.          mov    edx,parm4       ;scan code
  524.          mov    eax,parm3       ;Alt/Ctrl Flag = 0/1
  525.          mov    Alt_Ctrl,eax    ;Alt-Ctrl flag
  526. ;         mov    ebx,parm3   ;[esi+8]     ;ebx has mp1
  527. ;         mov    ecx,KC_KEYUP
  528. ;         test   bx,cx
  529. ;         jnz    wm0             ;accept only on down stroke
  530. ;         jz    wm0             ;accept only on up strike
  531. ;         mov    ecx,KC_ALT       ;? Alt Key down when msg generated
  532. ;         test   bx,cx           ;test scan code
  533. ;         jz     wm1             ;jump if Alt Key Not Hit
  534. ;         mov    Alt_Ctrl,0      ;Alt Key Was Down
  535. ;         jmp    wm2
  536. ;wm1:     mov    ecx,KC_CTRL     ;? Ctrl-Key down
  537. ;         test   bx,cx
  538. ;         jz     wm0             ;Was neither
  539. ;         mov    Alt_Ctrl,1      ;Was Ctrl Key Down
  540. ;wm2:     ;if statement below is on this line gives assemble error
  541. ;         xor    edx,edx
  542. ;         shld   edx,ebx,8       ;get high 8 bits of mp1 into dl
  543.          .IF edx == 83           ; Alt-Del (White Del key)
  544.             $Call DosFreeMem,memAddr
  545.             $Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
  546.             $Call DosFreeModule,DllHandle
  547.             $Call WinDestroyWindow,hwndMainFrame
  548.             Call  ExitWin
  549.          .ENDIF
  550. ;ELSE TEST FOR ASSIGNED KEYS
  551. ;SETUP DATA STRUCTURES FOR ACTIVATING HOT KEY
  552. ;---- Code in this group places the offset into the array ExecOnKB into EDX
  553.          .IF  edx == 82 && Alt_Ctrl == 0      ;Shift-Alt-Ins(White)
  554.               mov    esi,offset StartData     ;data structure for DosStartSession
  555.               mov    word ptr StartData,50    ;for Alt-Ins
  556.               mov    HotKeyID,'Ω'             ;For Program Title
  557.               mov    edi,offset TitleAlt
  558.               mov    cl,HotKeyID
  559.               mov    byte ptr [edi+4],cl
  560.               mov    dword ptr[esi+8],offset TitleAlt  ;program title
  561.               $Call  WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  562.               mov    eax,offset InsProg       ;address of Exec program
  563.               mov    [esi+12],eax
  564.               mov    dword ptr[esi+16],0      ;no command line
  565.               mov    word ptr[esi+30],2       ;Session Type
  566.               jmp    wmexe
  567.          .ELSE
  568.               mov    word ptr StartData,32
  569.          .ENDIF
  570.          .IF    edx >= 2 && edx <= 11     ;scan code for 1..9,0' || dl >= 'A' && dl <= 'Z'
  571.              .IF  edx >= 2 && edx <= 10
  572.                  sub   edx,1       ;convert to number 1 - 9
  573.              .ELSE
  574.                  mov   edx,0       ; 0 offset for 0
  575.              .ENDIF
  576.              mov   HotKeyID,dl
  577.              add   HotKeyID,30h    ;convert to ASCII
  578.              jmp   wmok
  579.          .ENDIF
  580.           xor   ecx,ecx
  581.          .IF  edx >= 16 && edx <= 25; && edx != 17 ; q,w,e,r,t,y,u,i,o,p
  582.                mov   esi,offset lookup0
  583.                sub   edx,16
  584.                jmp   wmoj
  585.          .ENDIF
  586.          .IF edx >= 30 && edx <= 38 ; a,s,d,f,g,h,j,k,l
  587.                mov   esi,offset lookup1
  588.                sub   edx,30
  589.                jmp   wmoj
  590.          .ENDIF
  591.          .IF  edx >= 43 && edx <= 50  ;z,x,c,v,b,n,m
  592.                mov   esi,offset lookup2
  593.                sub   edx,44
  594.                jmp   wmoj
  595.          .ELSE
  596.                jmp   wm0
  597.          .ENDIF
  598. wmoj:     mov   cl,byte ptr [esi+edx]  ;cl has value - cl+37h is UC letter
  599.           mov   HotKeyID,cl            ;identifies letter
  600.           add   HotKeyID,37h
  601.           xor   edx,edx
  602.           mov   dl,cl
  603. wmok:     ;- Alt_Ctrl has Alt_Ctrl Flag and dl has offset into array
  604.          .IF  edx >= 0 && edx <= 35
  605.               xor  eax,eax
  606.               mov   al,dl
  607.               mov  esi,offset StartData  ;data structure for DosStartSession
  608.               .IF  Alt_Ctrl == 0
  609.                   mov   ebx,offset AltX  ;Alt Definitions
  610.                   mov   edi,offset TitleAlt
  611.                   mov   cl,HotKeyID
  612.                   mov   byte ptr [edi+4],cl
  613.                   mov   dword ptr[esi+8],offset TitleAlt  ;program title
  614.               .ENDIF
  615.               .IF  Alt_Ctrl == 1
  616.                   mov   ebx,offset CtrlX ;Ctrl Definitions
  617.                   mov   edi,offset TitleCtl
  618.                   mov   cl,HotKeyID
  619.                   mov   byte ptr [edi+4],cl
  620.                   mov   dword ptr[esi+8],offset TitleCtl  ;program title
  621.               .ENDIF
  622.               mov    cl,LenExec
  623.               mul    cl             ;Structure Length ten
  624.               add    ebx,eax        ;element # of structure
  625.               ;[ebx+8] != 9 is flag that keystroke is assigned
  626.               .IF  word ptr [ebx+8] != 9
  627.                    $Call WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  628.                    mov  eax,[ebx]              ;address of Exec program
  629.                    mov  [esi+12],eax
  630.                    mov  eax,[ebx+4]            ;address of command line
  631.                    mov  [esi+16],eax
  632.                    mov   ax,word ptr [ebx+8]   ;Session type
  633.                    mov  [esi+30],ax
  634.                   .IF ax == 4 || ax == 7    ;set environment string DPMI_DOS_API for Borland IDE
  635.                       mov dword ptr[esi+24],offset DosEnvValue
  636.                   .ELSE
  637.                       mov  dword ptr[esi+24],0   ;default value reset
  638.                   .ENDIF
  639. ;GO THRU SWITCH LIST TO SEE IF HOT KEY ACTIVE
  640.                    ;-- called before DosStartSession to see if program loaded
  641.                    ;-- esi=offset into StartData
  642.                    ;-- go thru Switch List to see if loaded and if so switch to
  643.                    ;-- The test made on 4th char of TitleAlt/TitleCtl which
  644.                    ;-- is the title in the window and Task List
  645. wmexe:             pusha
  646.                    $NumSwitchListEntries
  647.                    mov  numitems,eax      ;number of switch list entries
  648.                    dec numitems
  649.                    Call GetSwitchList     ;activate structure
  650.                    mov  edi,baseaddr      ;address of switch list
  651.                    mov  ecx,0
  652.                    .IF  Alt_Ctrl == 0
  653.                         mov    bl,'A'
  654.                    .ELSE
  655.                         mov    bl,'C'
  656.                    .ENDIF
  657.                    .WHILE  ecx < numitems           ;starts at offset 0
  658.                        mov   al,byte ptr[edi+40]  ;5-th char TaskList title
  659.                        mov   dl,byte ptr[edi+36]  ;1stChar of Title A/C
  660.                        ;IF ACTIVE SWITCH TO
  661.                        .IF al == HotKeyID && bl == dl
  662.                             ;Now Switch to that window - get switch handle
  663.                             mov  eax,[edi+4]
  664.                             $Call WinSwitchToProgram,eax
  665.                             popa
  666.                             jmp  wm0                ;do not reload
  667.                        .ENDIF
  668.                        inc   ecx
  669.                        add   edi,swblksize           ;next element in structure
  670.                    .ENDW
  671.                    popa
  672.                    ;ELSE ACTIVATE HOT KEY PROGRAM
  673.                    $Call DosStartSession,esi,offset SessID,offset ProcID
  674. ;                   mov   eax,TRUE   ;USE WITH WinSendMsg
  675. ;                   ret
  676.               .ENDIF
  677.          .ENDIF
  678.     .ENDIF                                     ;End WM_USER+300h
  679.    wm0:
  680.    ;----- Default Procedure * Return Value in eax ------
  681.    $Call WinDefWindowProc,parm1,parm2,parm3,parm4
  682.    ret
  683. MainWinProc  endp
  684.  
  685. ;-------------- MainPaint * WM_PAINT --------------
  686. MainPaint  proc Near SYSCALL uses eax, var1:DWORD   ;var1 = hwnd
  687.       mov    eax,TRUE    ;  processed
  688.       ret
  689. MainPaint  endp
  690.  
  691. ;-------------- InitMainWindow * WM_CREATE --------------
  692. ;var1 = hwnd, var2 = mp1, var3 = mp2
  693. InitMainWindow Proc Near SYSCALL, var1:DWORD,var2:DWORD,var3:DWORD
  694.       mov    eax,TRUE    ;  processed
  695.        ret
  696. InitMainWindow Endp
  697.  
  698. ;-------------- MainKeyBoard * WM_CHAR --------------
  699. ;var1 = mp1,var2 = mp2,var3 = hwnd
  700. MainKeyBoard  Proc Near SYSCALL uses ebx ecx,var1:DWORD,var2:DWORD,var3:DWORD
  701.       mov    eax,FALSE    ; not processed
  702.       ret
  703. MainKeyBoard Endp
  704.  
  705. ;if there are spaces this exits pointing to next non-space else points to non-space
  706. SkipSpaces   proc    ;just skips over spaces
  707.    .WHILE ecx < fsize && byte ptr [esi+ecx] == ' '   ;spaces
  708.         inc ecx
  709.    .ENDW
  710.    .IF ecx >= fsize
  711.         mov EOFflag,1
  712.    .ENDIF
  713.     ret
  714. SkipSpaces   endp
  715.  
  716. SkipCommentsToEOL proc    ;skip from ; to beginning of next line
  717.     .IF byte ptr[esi+ecx] == ';' && ecx < fsize
  718.         inc    ecx
  719.         .WHILE byte ptr [esi+ecx] != 0ah && ecx < fsize  ;Line feed end of line
  720.             inc ecx
  721.         .ENDW                       ;points to 0ah if it exists if not EOF
  722.     .ELSE
  723.         mov     eax,ecx                  ;bytes processed appears in message
  724.         $WinDebugMessage msgFileErr
  725.         call ExitWin
  726.     .ENDIF
  727.     .IF  byte ptr[esi+ecx] != 0ah   ;must be EOF
  728.          mov    EOFflag,1
  729.     .ELSE                           ;it is end of line
  730.          inc    ecx                 ;goto next line
  731.          .IF    ecx >= fsize
  732.              mov    EOFflag,1
  733.          .ENDIF
  734.     .ENDIF
  735.     ret
  736. SkipCommentsToEOL endp
  737.  
  738. DataFormatErr   Proc
  739.     mov     eax,ecx            ;bytes processed appears in message
  740.     $WinDebugMessage msgFileErr
  741.     call ExitWin
  742.     ret
  743. DataFormatErr   EndP
  744.  
  745. ExitWin  Proc
  746.     $Call WinDestroyMsgQueue,hmq
  747.     $Call WinTerminate,hab
  748.     $DosExit    ;so exit
  749. ;    ret
  750. ExitWin  Endp
  751.  
  752. SwitchListAlloc  Proc          ;allocate memory for a switch list of 30
  753.     mov     ecx,00000002h   ;write access flags for Dos alloc
  754.     or      ecx,00000010h   ;page commit
  755.     $Call DosAllocMem,offset baseaddr,3000,ecx
  756.     .IF  eax != 0
  757.        $WinErrMsg  " : DosAllocMem SwitchList"
  758.        Call Exitwin
  759.     .ENDIF
  760.     ret
  761. SwitchListAlloc  Endp
  762.  
  763. GetSwitchList   Proc
  764.     pusha
  765.     $Call  WinQuerySwitchList,hab,baseaddr,3000
  766.     .IF eax == 0
  767.         $WinErrMsg " : WinQuerySwitchList"
  768.         Call ExitWin
  769.     .ENDIF
  770.     popa
  771.     ret
  772. GetSwitchList   Endp
  773.  
  774.  
  775. END   startup                       ;required
  776.  
  777.