home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MKHOOK1.ZIP / HOOK_KB.ASM < prev    next >
Assembly Source File  |  1992-09-05  |  24KB  |  592 lines

  1. ;---------------------------------------------------------------------------;
  2. ; M.F.Kaplon  Begun:Fri  06-12-1992  Revised:Sat  09-05-1992
  3. ; Title : hook_kb.asm
  4. ;
  5. ; INITIALIZES,CREATES MESSAGE QUEUE, REGISTERS CLASS,CREATES STANDARD WINDOW
  6. ; ESTABLISHES MAIN MESSAGE LOOP, ESTABLISHES MAIN WINDOW PROCEDURE, Reads in
  7. ; C:\os2\hook_kb.dat , Establishes Hook HK_INPUT, Filters Messages and
  8. ; takes apprpriate action.
  9. ;
  10. ; For System Function Calls
  11. ;
  12. ; 1 - Must use the C Calling Convention which means
  13. ;     Arguments Pushed on Stack in Reverse Order than declared in function
  14. ;     And the stack pointer reset after call.
  15. ;     This is done by the MACRO   $Call   defined in DOSWIN32.MAC
  16. ; 2 - Use  .MODEL FLAT. When using a pointer, all you have to do is push
  17. ;     the offset of the variable since in FLAT model everyting is NEAR
  18. ;     in the 32 bit space
  19. ; 3 - Uses an 8K stack
  20. ;
  21. ; It is assumed that the Developers toolkit for OS/2 2.0 is installed
  22. ; on the users C:drive in the default installation
  23. ;
  24. ; The files needed to create the functioning program are:
  25. ; doswin32.mac  Macros and Equates used by Program
  26. ; hook_kb.asm   Source for Executable  Assembled and Linked by mlc-w386.cmd
  27. ; hook_dll.def  Define file needed by IMPLIB and LINK386 for DLL
  28. ; hook_dll.asm  Source for DLL = Assembled and linked by dll-w386.cmd
  29. ; hook_kb.dat   Text File assigning programs to key strokes -read by hook_kb
  30. ;               The user creates this file according to structure outlined in
  31. ;               sample and it MUST BE LOCATED IN C:\OS2\DLL
  32. ; dll-w386.cmd  Command File to create the hook_dll.dll and copy to c:\os2\dll
  33. ; mlc-w386.cmd  Command File to Assemble and Link hook_kb.asm
  34. ;
  35. ; Except as noted, all files should be in the same directory.
  36. ; To assemble and link use the directory holding the above files as default
  37. ; and use the commands
  38. ; dll-w386  hook_dll;creates hook_dll.dll from hook_dll.asm,moves to c:\os2\dll
  39. ; mlc-w386  hook_kb ;creates hook_kb.exe from  hook_kb.asm
  40. ;
  41. ; kb_hook.exe is placed in the directory holding the above files
  42. ;
  43. ; There is one warning message
  44. ;
  45. ; LINK : warning L4036: no automatic data segment
  46. ;
  47. ; This message has to do with no DGROUP being defined
  48. ; It can be suppressed with DATA NONE in a "DEF" file
  49. ;
  50. ;---------------------------------------------------------------------------;
  51. ;USES HOOK HK_INPUT
  52. ;----------------- PRELIMINARIES ----------------
  53.  
  54. .386             ;preceeding .MODEL makes USE32 default
  55. .MODEL           FLAT,SYSCALL,OS_OS2
  56.  
  57. ;---------- Conditionally required equates -------------
  58. NUMBUFS          equ  1     ; Uncomment if need number routines
  59. DOSERROR         equ  1     ; Uncomment if need DosError Messages
  60.  
  61. INCL_WINERRORS   equ  1
  62. INCL_WIN         equ  1
  63. INCL_DOSMEMMGR   equ  1
  64. INCL_DOSFILEMGR  equ  1
  65.  
  66. INCLUDE        doswin32.mac             ;macros used by *.asm
  67.  
  68. INCLUDE        c:\toolkt20\asm\os2inc\os2def.inc ;structure defns includes POINTL
  69. INCLUDE        c:\toolkt20\asm\os2inc\pmwin.inc  ;structure defns POINTL defn required
  70. INCLUDE        c:\toolkt20\asm\os2inc\pmerr.inc  ;errors
  71. INCLUDE        c:\toolkt20\asm\os2inc\pmshl.inc
  72. INCLUDE        c:\toolkt20\asm\os2inc\bsememf.inc;memory
  73. INCLUDE        c:\toolkt20\asm\os2inc\bsedos.inc ;files
  74. INCLUDELIB     c:\toolkt20\os2lib\os2386.lib     ;Library
  75.  
  76.  
  77. ;---------- Prototype Definitions for MASM 6.0 -------------
  78. InitMainWindow Proto Near SYSCALL var1:DWORD,var2:DWORD,var3:DWORD
  79. MainPaint      Proto Near SYSCALL var1:DWORD
  80. MainKeyBoard   Proto Near SYSCALL var1:DWORD,var2:DWORD,var3:DWORD
  81.  
  82. ExecOnKB   STRUCT    ;Structure used in program-stores data from hook_kb.dat
  83.    Exec   DWORD   ?  ;Address of ASCIIZ str - name of exec program
  84.    CmdLn  DWORD   ?  ;Address of ASCIIZ str - command line parms
  85.    SessT   WORD   ?  ;Session Type
  86. ExecOnKB   ENDS
  87.  
  88. .STACK    8096   ;8K stack
  89.  
  90. .DATA
  91.  
  92. IFDEF NUMBUFS                      ;To use  UNCOMMENT NUMBUFS equate above
  93.   $DefineNumBufs
  94. ENDIF
  95. IFDEF DOSERROR
  96.    $DOSErrorMessages
  97. ENDIF
  98.  
  99. ;------------- handles --------
  100. hab            DWORD   ?           ;Anchor block Handle
  101. hmq            DWORD   ?           ;Message Queue Handle
  102. hwndMainFrame  DWORD   ?           ;Handle to Main Frame Window
  103. hwndMain       DWORD   ?           ;Handle to Client window
  104.  
  105. ;------------- Text Strings --------
  106. szAppName       BYTE   "Main0",0    ;Class Name of Window Procedure
  107. szWinTitle      BYTE   "** TSR **",0 ;Window Title
  108.  
  109. ;------------- Text Strings for WinMessageBox calls for Errors --------
  110.  
  111. msgModuleLoaded         BYTE "hook_KB Already Loaded",0
  112. msgInfo                 BYTE "Debug Info",0
  113. msgFileErr              BYTE "Incorrect hook_kb.dat File",0
  114.  
  115. ;------------- Styles --------
  116. msgBoxStyle    DWORD   (MB_YESNO OR MB_DEFBUTTON1)
  117. flStyle        DWORD   (CS_SIZEREDRAW OR CS_HITTEST)  ;Window Style
  118. flCtlData      DWORD   FCF_SYSMENU                    ;Invisible Window
  119.  
  120. ;------------- structures --------
  121. quemsg          QMSG    {,,,,,,}        ;Queue message structure
  122. AltX           ExecOnKB 10 dup({0,0,9}) ;Array for Alt-#  default Initialization
  123. CtrlX          ExecOnKB 10 dup({0,0,9}) ;Array for Ctrl-# default Initialization
  124.  
  125. ;------------- Miscellaneous --------
  126. parm1          DWORD   ?           ;handle of window sending message
  127. parm2          DWORD   ?           ;message id value
  128. parm3          DWORD   ?           ;message mp1
  129. parm4          DWORD   ?           ;message mp2
  130. parm5          DWORD   ?           ;message time
  131. Concanted       BYTE 64 dup(0)     ;buffer to hold concanted strings
  132. Alt_Ctrl       DWORD   ?           ;0/1 if Alt/Ctrl key struck
  133. Bits           DWORD   ?           ;Related to Scan Code
  134.  
  135. ;------------ Specific to TSR Hook  use -----
  136. DllLoadError    BYTE  100 dup(0)   ;Buffer for name of object contributing to error
  137. DllHandle      DWORD ?             ;Handle of Dynamic LInk Module returned here
  138. DllFullModName  BYTE  "c:\os2\dll\hook_dll.dll",0
  139. DllProcAddr1   DWORD ?             ;address of proc 1 in dynamic link module
  140.  
  141. ;- StartSession structure Offset ------------ Identification --------------
  142. StartData       WORD  32    ; 0  Length of Structure
  143.                 WORD  0     ; 2  Related 0 is independent, 1 is child
  144.                 WORD  0     ; 4  0/1 Start in Foreground/Background
  145.                 WORD  0     ; 6  Trace Option 0 is no trace
  146.                DWORD  0     ; 8  ProgramTitle 0 uses Program Name
  147.                DWORD  ?     ;12  Address of ASCZII string with fully qualified program name
  148.                DWORD  0     ;16  Address of Input Args to Pgm - 0 is none
  149.                DWORD  0     ;20  TermQ 0 is no Queue
  150.                DWORD  0     ;24  Environment - must be 0 for DOS
  151.                 WORD  0     ;28  InheritOp 0 Inherits Shell Environment
  152.                 WORD  ?     ;30  SessType see p.2-345 of Control Prog Ref.
  153.  
  154. SessID         DWORD  0     ;receives Session ID for Alt-1
  155. ProcID         DWORD  0     ;receives ProcessID  for Alt-1
  156.  
  157. ;----Shared Memory Variables---
  158. SharedMem      DWORD  ?     ;base address returned
  159. SharedMemName   BYTE  "\SHAREMEM\DATAE.DAT",0
  160. SharedMemFlags DWORD  12h   ;(PAG_COMMIT OR PAG_WRITE)
  161.  
  162. ;-------------- parameters for memory usage and file opening
  163. memAddr        DWORD   ?                        ;address of memory block
  164. memFlags       DWORD  13h ;(PAG_COMMIT OR (PAG_WRITE OR PAG_READ)) ;read-write access required
  165.  
  166. fName          BYTE    "c:\os2\hook_kb.dat",0   ;Address of data file
  167. fhandle        DWORD   ?                        ;Address of Handle for File
  168. fActionTaken   DWORD   ?                        ;Address for action taken
  169. fSize          DWORD   ?                        ;Logical size of file
  170. fAttribute     DWORD   0
  171. fOpenFlag      DWORD   OPEN_ACTION_OPEN_IF_EXISTS
  172. fOpenMode      DWORD   OPEN_SHARE_DENYNONE OR OPEN_ACCESS_READWRITE
  173. fExtaBuf       DWORD   0                        ;no extended attributes
  174.  
  175. fpointer0      DWORD   ?                        ;file pointer start file
  176. fpointer1      DWORD   ?                        ;file pointer end file
  177. EOFflag        DWORD   0                        ; EndOfFile flag
  178.  
  179. .CODE
  180.  
  181. startup:                         ;need to do this way with flat model
  182.  
  183. ;----------  ESTABLISH WINDOW ------------
  184.  
  185. ;-----Initialize Window -Anchor block handle returned = hab
  186. $Call WinInitialize,0            ;called with argument 0
  187. mov    hab,eax                   ;return value
  188. .IF hab == NULL
  189.     $Call WinTerminate,hab
  190.     $DosExit
  191. .ENDIF
  192.  
  193. ;-----Create MessageQue  QueueHandle returned = hmq
  194. $Call WinCreateMsgQueue,hab,0    ; 0 is default size of queue
  195. mov      hmq,eax                 ;returned queue handle
  196. .IF hmq == NULL
  197.    $WinErrMsg " : WinCreateMsgQueue"
  198.    $DosExit
  199. .ENDIF
  200.  
  201. ;---- Register Window Class Returned value is TRUE or FALSE
  202. $Call WinRegisterClass,hab,offset szAppName,offset MainWinProc,flStyle,0
  203. .IF eax == FALSE
  204.     $WinErrMsg " : WinRegisterClass"
  205.     $Call WinTerminate,hab
  206.     $DosExit
  207. .ENDIF
  208.  
  209. ;---- CreateStandard Window - Returns handle for Main Window Frame and client Window
  210. $Call WinCreateStdWindow,HWND_DESKTOP,WS_VISIBLE,offset flCtlData,offset szAppName,\
  211.                     offset szWinTitle,WS_VISIBLE,0,0,offset hwndMain
  212. mov   hwndMainFrame,eax          ;returned Frame Window handle
  213. .IF hwndMainFrame == 0
  214.    $WinErrMsg " : WinCreateStdWindow"
  215.    Call   ExitWin
  216. .ENDIF
  217.  
  218. ;------------  IS hook_DLL.DLL LOADED ? -------------------
  219.  
  220. $Call DosQueryModuleHandle,offset DllFullModName,offset DllHandle
  221. .IF  eax == 0    ;module already loaded
  222.      $Call WinMessageBox,HWND_DESKTOP,HWND_DESKTOP,offset msgModuleLoaded,NULL,0,msgBoxErrStyle
  223.      Call   ExitWin
  224. .ENDIF
  225.  
  226. ;----- ALLOCATE SHARED MEM AND PLACE HANDLE THERE ----
  227. $Call DosAllocSharedMem,offset SharedMem,offset SharedMemName,16,SharedMemFlags
  228. .IF eax > 0
  229.    $WinErrMsg " : DosAllocSharedMem"
  230.    Call   ExitWin
  231. .ENDIF
  232. mov    esi,SharedMem
  233. mov    eax,hwndMainFrame
  234. mov    [esi],eax     ;put window handle there
  235.  
  236. ;----------  IS Data File AVAILABLE AND VALID ? ------------
  237.  
  238. ;---------- First see if  hook_kb.dat exists in proper location ------
  239. $Call DosOpen,offset fName,offset fhandle,offset fActionTaken,fsize,fAttribute,fOpenFlag,fOpenMode,fExtaBuf
  240. .IF   eax != 0
  241.      $WinErrMsg " : DosOpen "
  242.      Call   ExitWin
  243. .ENDIF
  244.  
  245. ;------- get file size
  246. $Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
  247. .IF    eax != 0
  248.      $WinErrMsg " : DosSetFilePtr"
  249.       Call   ExitWin
  250. .ENDIF
  251.  
  252. $Call DosSetFilePtr,fhandle,0,FILE_END,offset fpointer1
  253. mov    eax,fpointer1
  254. sub    eax,fpointer0
  255. mov    fsize,eax        ;fsize now has file size
  256. add    eax,16           ;allow a little leeway in buffer
  257. ;------- now allocate memory for file buffer
  258. $Call DosAllocMem,offset memAddr,eax,memFlags
  259. .IF    eax != 0
  260.      $WinErrMsg " : DosAllocMem"
  261.      Call   ExitWin
  262. .ENDIF
  263.  
  264. ;------Read File Into buffer and Close file -------
  265. ;reposition to start of file
  266. $Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
  267. $Call DosRead,fHandle,memAddr,fsize,offset nwritten
  268. $Call DosClose,fHandle
  269.  
  270. ;------ Read Buffer and Initialize Arrays ALtX and CtrlX ----
  271. mov    esi,memAddr
  272. mov    ecx,0               ;Index and Counter for memAddr
  273.  
  274. .WHILE ecx <=  fsize
  275.     call   SkipSpaces        ;skip over any initial spaces
  276.     .BREAK .IF EOFflag == 1
  277.     call   SkipCommentsToEOL ;skip over comments and spaces to first valid entry
  278.     .BREAK .IF EOFflag == 1
  279.     call SkipSpaces          ;skip over initial spaces
  280.     .BREAK .IF EOFflag == 1
  281.     .IF (byte ptr [esi+ecx] == 'A' || byte ptr [esi+ecx] == 'a' || byte ptr [esi+ecx] == 'C' || byte ptr [esi+ecx] == 'c') && (byte ptr [esi+ecx+1] >= '0' && byte ptr [esi+ecx+1] <= '9')
  282.          inc   ecx           ;point to number
  283.          xor   eax,eax
  284.          xor   edx,edx
  285.          mov  al,byte ptr [esi+ecx]  ;get digit ID
  286.          sub  al,'0'         ;convert to decimal
  287.          .IF al == 0
  288.              add   al,9      ;0 is treated as 10th element, 1st is offset 0
  289.          .ELSE
  290.              dec   al        ;ALt1/Ctrl1 is array element 0
  291.          .ENDIF
  292.          mov      dl,10
  293.          mul      dl         ;ax has offset into array
  294.          inc      ecx        ;right after digit id A/C number
  295.     .ELSE
  296.          .CONTINUE
  297.     .ENDIF
  298.     .IF byte ptr[esi+ecx - 2] == 'A' || byte ptr[esi+ecx - 2] == 'a'
  299.           mov     edi,offset AltX      ;this is Alt Keys
  300.     .ENDIF
  301.     .IF byte ptr[esi+ecx - 2] == 'C' || byte ptr[esi+ecx - 2] ==  'c'
  302.           mov     edi,offset CtrlX     ;this is a Ctrl Key
  303.     .ENDIF
  304.     .IF edi == offset AltX || edi == offset CtrlX
  305.           mov     edx,eax              ;edx is offset into array
  306.           call    SkipSpaces           ;go to SessID
  307.           .BREAK .IF EOFflag == 1
  308.           xor     eax,eax
  309.           mov     al,byte ptr [esi+ecx] ;get sess type
  310.           sub     al,'0'                ;convert to  number
  311.           mov     word ptr [edi + edx+8],ax
  312.           inc     ecx
  313.           call    SkipSpaces            ;get to Exec string
  314.           .BREAK .IF EOFflag == 1
  315.           mov     eax,esi
  316.           add     eax,ecx               ;offset of exec
  317.           mov     [edi+edx],eax         ;store its address
  318.           ; have to go to end of Exec string and place a numeric 0 there
  319.           .WHILE  byte ptr [esi+ecx] != ' '
  320.                inc  ecx
  321.           .ENDW   ;exits    pointing to end of exec command
  322.           .BREAK .IF byte ptr[esi+ecx] != ' '
  323.              mov     byte ptr [esi+ecx],0
  324.           inc     ecx
  325.           call    SkipSpaces            ;get next parameter
  326.           .BREAK .IF EOFflag == 1
  327.           xor     eax,eax
  328.           .IF     byte ptr [esi+ecx]== '0'  ;no command line
  329.               mov     al,byte ptr [esi+ecx]
  330.               sub     al,'0'
  331.               mov     [edi+edx+4],eax
  332.           .ELSE                         ;its a string - copy its address
  333.               mov eax,esi
  334.               add eax,ecx               ;offset of command line
  335.               mov     [edi+edx+4],eax   ;store command line address
  336.               .IF   byte ptr [esi+ecx] != 22h  ;not a "
  337.                  .WHILE  byte ptr [esi+ecx] != ' ' && ecx < fsize  ;skip until a space
  338.                      .IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr  ; LF but no ";"
  339.                           Call DataFormatErr
  340.                      .ENDIF
  341.                       inc  ecx
  342.                  .ENDW                  ;exits  pointing to end of command line
  343.                 .BREAK .IF ecx >= fsize
  344.                  mov    byte ptr [esi+ecx],0 ;put 0 at end
  345.               .ELSE                     ;first char is a quote
  346.                  inc  ecx               ;move beyond it
  347.                  .WHILE byte ptr [esi+ecx] != 22h && ecx < fsize ; skip until a "
  348.                       inc  ecx
  349.                  .ENDW                  ;exits pointing to final quote
  350.                  .BREAK .IF ecx >= fsize
  351.                  inc    ecx
  352.                  .BREAK .IF byte ptr[esi+ecx] != ' '
  353.                  mov    byte ptr [esi+ecx],0 ;put 0 at end
  354.               .ENDIF
  355.           .ENDIF
  356.           ;inc    ecx
  357.           .BREAK .IF ecx >= fsize
  358.           xor    edi,edi                ;reset to 0 so test can be made
  359.           .WHILE byte ptr[esi+ecx] != ';' && ecx < fsize  ;go to next comment ;
  360.               .IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr  ; LF but no ";"
  361.                    Call DataFormatErr
  362.               .ENDIF
  363.               inc   ecx
  364.           .ENDW
  365.           .BREAK .IF ecx >= fsize
  366.           .CONTINUE
  367.     .ENDIF
  368. .ENDW
  369. ; See if Dat File properly read in
  370. .IF ecx < fsize
  371.      Call DataFormatErr
  372. .ENDIF
  373.  
  374. ;-----------  ESTABLISH THE HOOK -------------
  375.  
  376. ;The way to proceed is to install a System Hook. This has to go into a DLL
  377. ;otherwise it cannot be called by other programs. The procedure in hook_dll
  378. ;will inspect WM_CHAR to see if the one of the assigned keys is hit
  379. ;and if so posts a message to this program
  380. $Call DosLoadModule,offset DllLoadError,LENGTHOF DllLoadError,offset DllFullModName,offset DllHandle
  381. .IF eax != 0
  382.     $DosErrMsg " DosLoadModule"
  383. .ENDIF
  384. $Call DosQueryProcAddr,DllHandle,1,0,offset DllProcAddr1
  385. .IF eax != 0
  386.     $DosErrMsg " DosQueryProcAddr"
  387. .ENDIF
  388. $Call WinSetHook,hab,NULLHANDLE,HK_INPUT,DllProcAddr1,DllHandle
  389. .IF eax == 0
  390.     $WinErrMsg " WinSetHook"
  391. .ENDIF
  392.  
  393. ;---------  CREATE MAIN MESSAGE LOOP -----------
  394.  
  395. mml: $Call WinGetMsg,hab,offset quemsg,0,0,0    ;Note: differs from usual
  396. ;     .IF eax == TRUE                           ;msg loop - done so that program
  397.          $Call WinDispatchMsg,hab,offset quemsg ;can only be terminated
  398.          jmp   mml                              ;by the keystroke Alt-Del
  399. ;     .ENDIF                                    ;as notified from the DLL
  400.  
  401. ;Normally an Exit routine would go here, as indicated below but which
  402. ;is commented out. It is not required since it can never be reached.
  403. ;----------  EXIT ---------------
  404. ;$Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
  405. ;.IF    eax == 0
  406. ;     $WinErrMsg " : WinReleaseHook"
  407. ;.ENDIF
  408. ;$Call DosFreeModule,DllHandle
  409. ;.IF    eax != 0
  410. ;     $WinErrMsg " : DosFreeModule"
  411. ;.ENDIF
  412. ;$Call DosFreeMem,memAddr
  413. ;$Call WinDestroyWindow,hwndMainFrame
  414. ;call  ExitWin
  415.  
  416. ;---------------- End of Main Program -------------------
  417.  
  418. ;-------------  PROCESS MESSAGE QUEUE FOR hook_KB ------------
  419. ;------------------ MainWinProc -----------------
  420. ;parm1 = hwnd,parm2 = msg,parm3  = mp1,parm4 = mp2
  421. ;this is called from System and so has to do everything itself
  422. MainWinProc Proc Near
  423.     ;----------- Get Passed Parameters from Stack ------------
  424.     push   ebp           ;return address is 4 bytes and this push is 4 bytes
  425.     mov    ebp,esp       ;so first parameter is 8 bytes from top
  426.     mov    eax,[ebp+8]
  427.     mov    parm1,eax     ;hwnd
  428.     mov    eax,[ebp+12]
  429.     mov    parm2,eax     ;msg
  430.     mov    eax,[ebp+16]
  431.     mov    parm3,eax     ;mp1
  432.     mov    eax,[ebp+20]
  433.     mov    parm4,eax     ;mp2
  434.     mov    eax,[ebp+24]
  435.     mov    parm5,eax     ;time of message
  436.  
  437.     ;---------------- WM_CREATE ----------------
  438.     .IF parm2 == WM_CREATE
  439.          Invoke InitMainWindow,parm1,parm3,parm4
  440.     .ENDIF
  441.     ;---------------- WM_PAINT ----------------
  442.     .IF parm2 == WM_PAINT ; && parm1 == hwndMain
  443.        Invoke  MainPaint,parm1
  444.     .ENDIF
  445.     ;---------------- WM_CHAR ----------------
  446.     .IF parm2 == WM_CHAR
  447.        Invoke  MainKeyboard,parm3,parm4,parm1    ;sets return value
  448.     .ENDIF
  449.     ;---------------- WM_USER+200H ----------------
  450.     .IF parm2 == WM_USER+200h                    ;broadcasted message
  451.        ;------------ FILTER KEYSTROKES ------------
  452.        mov    bits,0
  453.        mov    ebx,parm3   ;[esi+8]     ;ebx has mp1
  454.        mov    ecx,KC_KEYUP
  455.        test   bx,cx
  456.        jnz    wm0             ;accept only on down strike
  457.        mov    ecx,KC_SCANCODE
  458.        test   bx,cx           ;test scan code
  459.        jz     wm0             ;jump if no valid scan code
  460.        mov    ebx,parm3   ;[esi+8]     ;mp1
  461.        xor    edx,edx
  462.        shld   edx,ebx,8       ;get high 8 bits of mp1 into dl
  463.        mov    ecx,KC_ALT       ;? Alt Key down when msg generated
  464.        test   bx,cx           ;test scan code
  465.        jz     wm1             ;jump if Alt Key Not Hit
  466.        mov    Alt_Ctrl,0      ;Alt Key Was Down
  467.        jmp    wm2
  468. wm1:   mov    ecx,KC_CTRL      ;? Ctrl-Key down
  469.        test   bx,cx
  470.        jz     wm0             ;Was neither
  471.        mov    Alt_Ctrl,1      ;Was Ctrl Key Down
  472. wm2:   ;if statement below is on this line gives assemble error
  473.        .IF    edx >= 2 && edx <= 11 || edx == 83   ;scan code for keys <1> <-> <0>
  474.            mov   bits,edx
  475.        .ELSE
  476.            jmp wm0            ;not in desired range
  477.        .ENDIF
  478.        .IF bits > 1 && edx != 83
  479.            sub    bits,2  ;scan code 2,3,...,11 now 0,1,2,....,9
  480.        .ENDIF
  481.         ;- Alt_Ctrl has Alt_Ctrl Flag and bits has offset number  0,1,2,3,4,5,6,7,8,9
  482.         ;  representing keys 1,2,3,4,5,6,7,8,9,0(10)
  483.         ;---------- bits also has  83  scan code for white Del
  484.        .IF bits == 83               ; Alt-Del (White Del key)
  485.             $Call DosFreeMem,memAddr
  486.             $Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
  487.             $Call DosFreeModule,DllHandle
  488.             $Call WinDestroyWindow,hwndMainFrame
  489.             Call  ExitWin
  490.        .ELSE      ;.ENDIF
  491.             mov  esi,offset StartData  ;data structure for DosStartSession
  492.             .IF  Alt_Ctrl == 0
  493.                 mov   ebx,offset AltX  ;Alt Definitions
  494.             .ENDIF
  495.             .IF  Alt_Ctrl == 1
  496.                 mov   ebx,offset CtrlX ;Ctrl Definitions
  497.             .ENDIF
  498.             mov    eax,bits
  499.             mul    ten            ;define in NUMBUFS
  500.             add    ebx,eax        ;element # of structure
  501.             .IF  word ptr [ebx+8] != 9
  502.                  $Call WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  503.                  mov  eax,[ebx]              ;address of Exec program
  504.                  mov  [esi+12],eax
  505.                  mov  eax,[ebx+4]            ;address of command line
  506.                  mov  [esi+16],eax
  507.                  mov   ax,word ptr [ebx+8]   ;Session type
  508.                  mov  [esi+30],ax
  509.                  $Call DosStartSession,esi,offset SessID,offset ProcID
  510.             .ENDIF
  511.        .ENDIF                                  ;End ELSE
  512.        mov  eax,TRUE                           ;Message Processed
  513.     .ENDIF                                      ;End WM_USER+100h
  514.    wm0:                                        ;not Processed
  515.    ;----- Restore Stack Pointer and Stack Status
  516.    mov      esp,ebp                           ;restore  stack pointer
  517.    pop      ebp
  518.    ;----- Default Procedure * Return Value in eax ------
  519.    $Call WinDefWindowProc,parm1,parm2,parm3,parm4
  520.    ret
  521. MainWinProc  endp
  522.  
  523. ;-------------- MainPaint * WM_PAINT --------------
  524. MainPaint  proc Near SYSCALL uses eax, var1:DWORD   ;var1 = hwnd
  525.       mov    eax,TRUE    ;  processed
  526.       ret
  527. MainPaint  endp
  528.  
  529. ;-------------- InitMainWindow * WM_CREATE --------------
  530. ;var1 = hwnd, var2 = mp1, var3 = mp2
  531. InitMainWindow Proc Near SYSCALL, var1:DWORD,var2:DWORD,var3:DWORD
  532.       mov    eax,TRUE    ;  processed
  533.        ret
  534. InitMainWindow Endp
  535.  
  536. ;-------------- MainKeyBoard * WM_CHAR --------------
  537. ;var1 = mp1,var2 = mp2,var3 = hwnd
  538. MainKeyBoard  Proc Near SYSCALL uses ebx ecx,var1:DWORD,var2:DWORD,var3:DWORD
  539.       mov    eax,TRUE    ;  processed
  540.       ret
  541. MainKeyBoard Endp
  542.  
  543. ;if there are spaces this exits pointing to next non-space else points to non-space
  544. SkipSpaces   proc    ;just skips over spaces
  545.    .WHILE ecx < fsize && byte ptr [esi+ecx] == ' '   ;spaces
  546.         inc ecx
  547.    .ENDW
  548.    .IF ecx >= fsize
  549.         mov EOFflag,1
  550.    .ENDIF
  551.     ret
  552. SkipSpaces   endp
  553.  
  554. SkipCommentsToEOL proc    ;skip from ; to beginning of next line
  555.     .IF byte ptr[esi+ecx] == ';' && ecx < fsize
  556.         inc    ecx
  557.         .WHILE byte ptr [esi+ecx] != 0ah && ecx < fsize  ;Line feed end of line
  558.             inc ecx
  559.         .ENDW                       ;points to 0ah if it exists if not EOF
  560.     .ELSE
  561.         mov     eax,ecx                  ;bytes processed appears in message
  562.         $WinDebugMessage msgFileErr
  563.         call ExitWin
  564.     .ENDIF
  565.     .IF  byte ptr[esi+ecx] != 0ah   ;must be EOF
  566.          mov    EOFflag,1
  567.     .ELSE                           ;it is end of line
  568.          inc    ecx                 ;goto next line
  569.          .IF    ecx >= fsize
  570.              mov    EOFflag,1
  571.          .ENDIF
  572.     .ENDIF
  573.     ret
  574. SkipCommentsToEOL endp
  575.  
  576. DataFormatErr   Proc
  577.     mov     eax,ecx            ;bytes processed appears in message
  578.     $WinDebugMessage msgFileErr
  579.     call ExitWin
  580.     ret
  581. DataFormatErr   EndP
  582.  
  583. ExitWin  Proc
  584.     $Call WinDestroyMsgQueue,hmq
  585.     $Call WinTerminate,hab
  586.     $DosExit    ;so exit
  587.     ret
  588. ExitWin  Endp
  589.  
  590. END   startup                       ;required
  591.  
  592.