home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MKHKB2.ZIP / HOOK_KBS.ASM < prev    next >
Assembly Source File  |  1992-10-27  |  33KB  |  791 lines

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