home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / tools / hookbsm / hookkbsm.asm < prev    next >
Encoding:
Assembly Source File  |  1993-05-01  |  70.7 KB  |  1,732 lines

  1. ;---------------------------------------------------------------------------;
  2. ; M.F.Kaplon  Begun:Wed  09-30-1992    Revised:Sat  05-01-1993
  3. ; Title : hookkbsm.asm
  4. ;
  5. ; "Copyright 1992 M.F. Kaplon"
  6. ;
  7. ;  10-27-92  Add ShutDown Procedure via Shift-Alt-End(White)
  8. ;  11-04-92  Add Display of Small Window in Lower Right Hand Corner
  9. ;  11-06-92  Display Text in Window for RecordOff,Recording,Playback
  10. ;  11-18-92  Finally got Macro Recording to Sort of Work
  11. ;  11-30-92  Write out Message Records to Disk File in ASCII #'s in HEX
  12. ;            S-C-PgDn writes out the current macro to hookkbsm.mac
  13. ;  12-07-92  Revised Key Assignments
  14. ;            Start Macro Recording              S-C-LeftArrow(White)
  15. ;            End   Macro Recording              S-C-RightArrow(White)
  16. ;            PlayBack Macro                     S-C-Ins(White)
  17. ;            Open Small OS/2 Window             S-A-Ins(White)
  18. ;            Display ProgramDefined HotKeys     S-A-?  c:\os2\hot-keys.prg
  19. ;            Display UserDefined HotKeys        S-C-?  c:\os2\hot-keys.usr
  20. ;            Write Current Macro to ASCII File  S-C-PgDn(White)
  21. ;  12-14-92  Add inclusion of WindowNames, obtained from TaskList
  22. ;            for each Handle obtained when Recording. Window Names will
  23. ;            be first 28 characters of name in TaskList(this is default width)
  24. ;  12-27-92  Restructured to allow revision of hookkbsm.dat and updating
  25. ;            by hotkey activation. Hot Key Assigned = Shift-Alt-UpArrow
  26. ;            Displays message DAT Updated in window.
  27. ;  04-13-93  Unable to effect release of DLL from Memory. It is FREED
  28. ;            but somehow there must still be a reference to it since it
  29. ;            is not released from memory. Replace JMP's with Calls to DLL
  30. ;  04-30-93  The reason getting errors on editin file was that some editors
  31. ;            put Ctrl-Z at EOF and as written was not acceptable. Changed to
  32. ;            accept that.
  33. ;
  34. ; INITIALIZES,CREATES MESSAGE QUEUE, REGISTERS CLASS,CREATES STANDARD WINDOW
  35. ; ESTABLISHES MAIN MESSAGE LOOP, ESTABLISHES MAIN WINDOW PROCEDURE, Reads in
  36. ; C:\os2\hookkbsm.dat, Establishes Hook to HK_INPUT and INITIALIZE which are
  37. ; procedures in HOOKDLSM.DLL, Receives Filtered Messages from hookdlsm
  38. ; where mp1 = Alt/Ctrl flag, mp2 = scan code and
  39. ; takes appropriate action. Uses WM_USER+300h to receive message.
  40. ;
  41. ; For System Function Calls
  42. ;
  43. ; 1 - Must use the C Calling Convention which means
  44. ;     Arguments Pushed on Stack in Reverse Order than declared in function
  45. ;     And the stack pointer reset after call.
  46. ;     This is done by the MACRO   $Call   defined in DOSWIN32.MAC
  47. ; 2 - Use  .MODEL FLAT. When using a pointer, all you have to do is push
  48. ;     the offset of the variable since in FLAT model everyting is NEAR
  49. ;     in the 32 bit space
  50. ; 3 - Uses a  16K stack
  51. ;
  52. ; It is assumed that the Developers toolkit for OS/2 2.0 is installed
  53. ; on the users C:drive in the default installation. The assembler
  54. ; used is MicroSoft's MASM 6.00B
  55. ;
  56. ; The files needed to create the functioning program are:
  57. ; doswin32.mac  Macros and Equates used by Program
  58. ; hookkbsm.asm  Source for Executable  Assembled and Linked by mlc-w386.cmd
  59. ; hookdlsm.def  Define file needed by IMPLIB and LINK386 for DLL
  60. ; hookdlsm.asm  Source for DLL = Assembled and linked by dll-w386.cmd
  61. ; hookkbsm.dat  Text File assigning USER defined programs to key strokes,
  62. ;               read by hookkbsm The user creates this file according to the
  63. ;               structure outlined in sample. MUST BE LOCATED IN C:\OS2\DLL
  64. ; hot-keys.usr  Text file Template to be filled in reflecting USER defined
  65. ;               hotkeys as defined in hookkbsm.dat. This is displayed when
  66. ;               Shift-Ctrl-/(?) is struck.
  67. ; hot-keys.prg  Text File containing program defined (hard coded) key
  68. ;               assignments. Actuated by Shift-Alt-?. DO NOT CHANGE
  69. ; BOTH hot-keys.usr and hot-keys.prg must be in C:\os2\
  70. ; dll-w386.cmd  Command File to create the hookdlsm.dll and copy to c:\os2\dll
  71. ; mlc-w386.cmd  Command File to Assemble and Link hookkbsm.asm
  72. ;
  73. ; Except as noted, all files should be in the same directory.
  74. ; To assemble and link use the directory holding the above files as default
  75. ; and use the commands
  76. ; dll-w386  hookdlsm ;creates hookdlsm.dll from hookdlsm.asm,moves to c:\os2\dll
  77. ; mlc-w386  hookkbsm ;creates hookkbsm.exe from  hookkbsm.asm
  78. ;
  79. ; hookkbsm.exe is placed in the directory holding the above files
  80. ;
  81. ; There is one warning message
  82. ;
  83. ; LINK : warning L4036: no automatic data segment
  84. ;
  85. ; This message has to do with no DGROUP being defined
  86. ; It can be suppressed with DATA NONE in a "DEF" file
  87. ;
  88. ; A command processor is called into a 2-line window centered in the screen
  89. ; by the keystroke combination Shift-Alt-=(white upper keys)
  90. ; The default command processor is c:\os2\cmd.exe
  91. ; To load a different one to be called in the window pass its entire
  92. ; file specification on the command line when hookkbsm is called as
  93. ;
  94. ; start hookkbsm c:\4os2\4os2.exe
  95. ;
  96. ; In calling the procedure "Initialize" in hookdlsm.dll values are
  97. ; passed and returned in registers and the procedures are called by JUMPs
  98. ; after placing the values in the registers, pushing ECS and the offset
  99. ; of the return location. The functions examine the registers and take
  100. ; appropriate action.
  101. ;
  102. ; The example uses the 4OS2 command processor
  103. ;---------------------------------------------------------------------------;
  104. ;USES HOOK HK_INPUT and INITIALIZE: both in HOOKFLSM.DLL
  105. ;----------------- PRELIMINARIES ----------------
  106.  
  107. .386             ;preceeding .MODEL makes USE32 default
  108. .MODEL           FLAT,SYSCALL,OS_OS2
  109.  
  110. ;---------- Conditionally required equates -------------
  111. NUMBUFS            equ    1     ; Uncomment if need number routines
  112. ;DOSERROR           equ    1     ; Uncomment if need DosError Messages
  113.  
  114. TaskListHandle     equ    004001CCh  ;handle of Task List Window
  115. RecdLnth           equ    28
  116. RecdLnth_x_3       equ    28*3
  117.  
  118. INCL_WINERRORS     equ    1
  119. INCL_WIN           equ    1
  120. INCL_DOSMEMMGR     equ    1
  121. INCL_DOSFILEMGR    equ    1
  122. INCL_WINSWITCHLIST equ    1
  123. INCL_GPICONTROL    equ    1
  124. INCL_DEV           equ    1
  125.  
  126. INCLUDE        doswin32.mac                      ;macros used by *.asm
  127. INCLUDE        c:\toolkt20\asm\os2inc\os2def.inc ;structure defns includes POINTL
  128. INCLUDE        c:\toolkt20\asm\os2inc\pmwin.inc  ;structure defns POINTL defn required
  129. INCLUDE        c:\toolkt20\asm\os2inc\pmgpi.inc  ;graphics
  130. INCLUDE        c:\toolkt20\asm\os2inc\pmdev.inc  ;devices
  131. INCLUDE        c:\toolkt20\asm\os2inc\pmerr.inc  ;errors
  132. INCLUDE        c:\toolkt20\asm\os2inc\pmshl.inc
  133. INCLUDE        c:\toolkt20\asm\os2inc\bsememf.inc;memory
  134. INCLUDE        c:\toolkt20\asm\os2inc\bsedos.inc ;files
  135. INCLUDELIB     c:\toolkt20\os2lib\os2386.lib     ;Library
  136.  
  137.  
  138. ExecOnKB     STRUCT      ;Structure used in program-stores data from hook_kb.dat
  139.    Exec     DWORD   ?    ;Address of ASCIIZ str - name of exec program
  140.    CmdLn    DWORD   ?    ;Address of ASCIIZ str - command line parms
  141.    SessT     WORD   ?    ;Session Type
  142. ExecOnKB       ENDS      ;structure length now = 22
  143.  
  144. LenExec     equ    10    ;length of ExecOn Kb
  145.  
  146. .STACK    16384          ;16K stack
  147.  
  148. .DATA
  149.  
  150. IFDEF NUMBUFS                      ;To use  UNCOMMENT NUMBUFS equate above
  151.   $DefineNumBufs
  152. ENDIF
  153. IFDEF DOSERROR
  154.    $DOSErrorMessages
  155. ENDIF
  156.  
  157. ; Copyright Notice
  158. notice          BYTE   "Copyright 1992 M.F. Kaplon"
  159.  
  160. ;------------- handles --------
  161. hab             DWORD   0           ;Anchor block Handle
  162. hmq             DWORD   0           ;Message Queue Handle
  163. hwndMainFrame   DWORD   0           ;Handle to Main Frame Window of application hwndmain
  164. hwndMain        DWORD   0           ;Handle to client application window hwndMain
  165. hps             DWORD   0           ;Presentation Space Handle
  166. hwndActiveFrame DWORD   0           ;FrameWindowHandle of hwndActive
  167. hwndActive      DWORD   0           ;ACtive Window
  168. hwndFocus       DWORD   0           ;Window with Current Focus
  169. henum           DWORD   0           ;WindowEnumerationHandle
  170. hwndNext0       DWORD   0           ;Temporary Window Handles
  171. hwndNext1       DWORD   0           ;Temporary Window Handles
  172. hwndNext2       DWORD   0           ;Temporary Window Handles
  173.  
  174. ;------------- GPI & DEV variables --------
  175. hdc             DWORD   0           ;Device handle
  176. xPelsPerMeter   DWORD   ?           ;horizontal resolution of device in pels per meter
  177. yPelsPerMeter   DWORD   ?           ;vertical resolution of device in pels per meter
  178. DivideByHoriz    WORD  23           ;divisor for horizontal
  179. DivideByVert     WORD  70           ;divisor for vertical 60 originally
  180. ScreenWidth     DWORD   0           ;ScreenWidth in PELS
  181. PspSize         SIZEL  {0,0}        ;Presentaton Space size same as default
  182.  
  183. ;------------- Text Strings --------
  184. szAppName             BYTE   "Main0",0    ;Class Name of Window Procedure
  185. szWinTitle            BYTE   "HooK",0     ;Window Title
  186. szDebugMsg            BYTE   "  SwitchHandle",0
  187. textMsgOn             BYTE   "Recording",0
  188. textMsgPlay           BYTE   "PlayBack",0
  189. textMsgUpdateDat      BYTE   "USER Updated",0
  190.  
  191. msgFileErr            BYTE "hookkbsm.dat File format Error - Aborting",0
  192. msgDosLoadModule      BYTE "  DosLoadModule",0
  193. msgDosQueryProc1Addr  BYTE "  DosQueryProc1Addr",0
  194. msgDosQueryProc2Addr  BYTE "  DosQueryProc2Addr",0
  195.  
  196. ;------------- Styles --------
  197. msgBoxStyle     DWORD   (MB_YESNO OR MB_DEFBUTTON1)
  198. flStyle         DWORD   WS_SYNCPAINT ; OR CS_HITTEST ;Window Style Automatic Update
  199. flCtlData       DWORD   (((( FCF_SYSMENU       OR \    ;Window Control Styles
  200.                             FCF_MINMAX)        OR \
  201.                             FCF_TASKLIST)      OR \
  202.                             FCF_SIZEBORDER)    OR \
  203.                             FCF_TITLEBAR ) ;    OR \
  204.                          ;  FCF_SHELLPOSITION)        ;not reqd if sizing
  205.  
  206. ;------------- structures --------
  207. quemsg           QMSG    {}              ;Queue message structure
  208. rect            RECTL    {,,,}           ;Rectangle structure
  209. AltX            ExecOnKB 36 dup({0,0,9}) ;Array for  Alt-# 0-9,A-Z default Initialization
  210. CtrlX           ExecOnKB 36 dup({0,0,9}) ;Array for Ctrl-# 0-9,A-Z default Initialization
  211. WinPosX         DWORD    0               ;Window Position x
  212. WinPosY         DWORD    0               ;Window Position y
  213. ;------------- Miscellaneous --------
  214. parm1           DWORD   ?           ;handle of window sending message
  215. parm2           DWORD   ?           ;message id value
  216. parm3           DWORD   ?           ;message mp1
  217. parm4           DWORD   ?           ;message mp2
  218. parm5           DWORD   ?           ;message time
  219. param1          DWORD   ?           ;mp1 of message
  220. param2          DWORD   ?           ;mp2 of message
  221. nwritten        DWORD   ?
  222. Alt_Ctrl        DWORD   ?           ;0/1 if Alt/Ctrl key struck
  223. 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 ;
  224. 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 ;
  225. lookup2          BYTE   'Z'-37h,'X'-37h,'C'-37h,'V'-37h,'B'-37h,'N'-37h,'M'-37h                         ;35,33,12,31,11,23,22 ;
  226. textPos         DWORD   DT_CENTER OR DT_VCENTER      ;Position of text on screen
  227.  
  228. ExitMsg          BYTE  "          !! <Esc> Aborts Close Down !!",0
  229. ExitTitle        BYTE  "Close OS/2 ??",0
  230. RemoveTitle      BYTE  "Remove HOOKKBSM ??",0
  231. RemoveMsg        BYTE  "         !! <Esc> Aborts Closing TSR !!",0
  232. RecordOn         BYTE   0     ;flag indicates MacroRecording Off/On/Playback = 0/1/2
  233. LeftX           DWORD   0     ;coordinates for screen rectangle
  234. LowerY          DWORD   0
  235. RightX          DWORD   ?
  236. UpperY          DWORD   ?
  237.  
  238. ;------------ Specific to TSR Hook  use -----
  239. DllLoadError     BYTE  100 dup(0)   ;Buffer for name of object contributing to error
  240. DllHandle       DWORD 0             ;Handle of Dynamic LInk Module returned here
  241. DllFullModName   BYTE  "c:\os2\dll\hookdlsm.dll",0
  242. DllProcAddr1    DWORD 0             ;address of proc 1 in dynamic link module
  243. DllProcAddr2    DWORD 0             ;address of proc 2 in exec module
  244.  
  245.  
  246. ;- StartSession structure Offset ------------ Identification --------------
  247. StartData        WORD  32    ; 0  Length of Structure for all but Shift-Alt-W
  248.                  WORD  0     ; 2  Related 0 is independent, 1 is child
  249.                  WORD  0     ; 4  0/1 Start in Foreground/Background
  250.                  WORD  0     ; 6  Trace Option 0 is no trace
  251.                 DWORD  0     ; 8  ProgramTitle 0 uses Program Name
  252.                 DWORD  ?     ;12  Address of ASCZII string with fully qualified program name
  253.                 DWORD  0     ;16  Address of Input Args to Pgm - 0 is none
  254.                 DWORD  0     ;20  TermQ 0 is no Queue
  255.                 DWORD  0     ;24  Environment - must be 0 for DOS
  256.                  WORD  0     ;28  InheritOp 0 Inherits Shell Environment
  257.                  WORD  ?     ;30  SessType see p.2-345 of Control Prog Ref.
  258.                 DWORD  ?     ;32  ICON File
  259.                 DWORD  ?     ;36  PgmHandle
  260.                  WORD 8000h  ;40  PgmControl-use specified size for S-A-Ins
  261.                  WORD 140    ;42  InitXPos  for Shift-Alt-=
  262.                  WORD 200    ;44  InitYPos  for Shift-Alt-=
  263.                  WORD 350    ;46  InitXSize for Shift-Alt-=
  264.                  WORD  60    ;48  InitYSize for Shift-Alt-=
  265.  
  266. SessID          DWORD  0     ;receives Session ID for Alt-1
  267. ProcID          DWORD  0     ;receives ProcessID  for Alt-1
  268. TitleAlt         BYTE  "Alt- ",0  ;space filled in with 3 or letter
  269. TitleCtl         BYTE  "Ctl- ",0  ;space filled in with 3 or letter
  270. HotKeyID         BYTE   ?         ;Identifies HotKey Selected
  271. InsProg          BYTE  "c:\os2\cmd.exe",0,0,0,0,0,0,0,0,0,0 ; default assigned to Shift-Alt-=(White)
  272. DisplayUser      BYTE  "type c:\os2\hot-keys.usr & pause & exit",0 ;display User Hot Key Assignments
  273. DisplayPrg       BYTE  "type c:\os2\hot-keys.prg & pause & exit",0 ;display Prog Hot Key Assignments
  274. DosEnvValue      BYTE  "DPMI_DOS_API=ENABLED",0
  275.  
  276. ;-------------- parameters for memory usage and file opening
  277. memAddr         DWORD   0                        ;address of memory block
  278. MemFlags        DWORD  (PAG_COMMIT OR (PAG_WRITE OR PAG_READ)) ;read-write access required
  279. JR_Count        DWORD   0                        ;Count of records recorded
  280. JR_Counter      DWORD   0                        ;Counter for recording records
  281. PB_Ctr          DWORD   0                        ;PlayBack record counter
  282. msgParms        DWORD   0                        ;offset of PlayBackQMSG in dll
  283. MaxCount        DWORD   2660 ;Maximum qmsg structure counts
  284. AddrCtr         DWORD   0    ;increment counter
  285. loopCtr         DWORD   0
  286.  
  287. fName            BYTE    "c:\os2\hookkbsm.dat",0  ;Address of data file
  288. fhandle         DWORD   ?                        ;Address of Handle for File
  289. fActionTaken    DWORD   ?                        ;Address for action taken
  290. fSize           DWORD   ?                        ;Logical size of file
  291. fAttribute      DWORD   0
  292. fOpenFlag       DWORD   OPEN_ACTION_OPEN_IF_EXISTS
  293. fOpenMode       DWORD   OPEN_SHARE_DENYNONE OR OPEN_ACCESS_READWRITE
  294. fExtaBuf        DWORD   0                        ;no extended attributes
  295.  
  296. fmName           BYTE    "c:\hookkbsm.mac",0      ;Address of data file
  297. fmhandle        DWORD   ?                        ;Address of Handle for File
  298. fmActionTaken   DWORD   ?                        ;Address for action taken
  299. fmSize          DWORD   ?                        ;Logical size of file
  300. fmAttribute     DWORD   FILE_NORMAL              ;Read or Write
  301. fmOpenFlag      DWORD   OPEN_ACTION_CREATE_IF_NEW OR OPEN_ACTION_OPEN_IF_EXISTS
  302. fmOpenMode      DWORD   OPEN_SHARE_DENYNONE OR OPEN_ACCESS_READWRITE
  303. fmExtaBuf       DWORD   0                        ;no extended attributes
  304. fmWritten       DWORD   0                        ;bytes written per write
  305. fmPtrLoc        DWORD   0                        ;File Pointer Locationn
  306. fmBuffer         BYTE   82 dup(' '),13,10        ;Buffer for writing a record
  307. fmHeader         BYTE   "WinHandle MessageID msgParam1 msgParam2  msgTime  X_ScreenP Y_ScreenP TaskListName",13,10
  308. NoNameListed     BYTE   "NoNameinList"           ;Error Message
  309. NameHitFlag     DWORD   0                        ;0/1 Name notin/isin TaskList
  310. HandFromMsg     DWORD   0                        ;handle from msgQueue
  311. TaskNameAddr    DWORD   ?                        ;Address of TaskListName
  312. fpointer0       DWORD   ?                        ;file pointer start file
  313. fpointer1       DWORD   ?                        ;file pointer end file
  314. EOFflag         DWORD   0                        ;EndOfFile flag
  315.  
  316. ;------------ switch list parameters -------------
  317. numitems        DWORD   ?                        ;#items in list
  318. baseaddr        DWORD   ?                        ;of SWBLOCK {,}
  319.  
  320. ClassNameBuf     BYTE   20 dup(0)                ;Buffer for ClassNameID
  321. CoverPage        BYTE   "CLASS_COVERPAGE "        ;name for comparison
  322. WinTypeFlag     DWORD   0                        ;0/1 is Text/PM
  323. CurrentTime     DWORD   ?                        ;Store Time Delay
  324. UpdateDat       DWORD   0                        ;FlagFor Update Display
  325.  
  326. .CODE
  327.  
  328. startup:                         ;need to do this way with flat model
  329.  
  330. ;----------  GET COMMANDLINE PARMS -------
  331. $GetCmdLine                    ;macro esi has offset of command line
  332. .WHILE byte ptr [esi] != 0     ;go past program name
  333.       inc    esi
  334. .ENDW
  335. inc    esi                     ;now points to  1st space after command name
  336. mov    eax,0
  337. .WHILE  byte ptr [esi] != 0    ;go to end of command line
  338.      .WHILE byte ptr [esi] == ' '
  339.           inc   esi
  340.      .ENDW
  341.      .IF byte ptr [esi] != ' ' && byte ptr [esi] != 0; if not a space
  342.           mov    edi,offset InsProg   ;destination
  343.          .WHILE byte ptr [esi] != ' ' && byte ptr [esi] != 0
  344.               mov   al,byte ptr[esi]
  345.               mov   [edi],al
  346.               inc   esi
  347.               inc   edi
  348.               inc   eax
  349.          .ENDW
  350.          mov  al,0
  351.          mov  [edi],al          ;terminating NULL
  352.      .ENDIF
  353. .ENDW                          ;if eax non 0 has cmd line parm length
  354.  
  355. ;----------  ESTABLISH WINDOW ------------
  356.  
  357. ;-----Initialize Window -Anchor block handle returned = hab
  358. $Call WinInitialize,0            ;called with argument 0
  359. mov    hab,eax                   ;return value
  360. .IF hab == NULL
  361.     $Alarm0
  362.     $Call WinTerminate,hab
  363.     $DosExit
  364. .ENDIF
  365.  
  366. ;-----Create MessageQue  QueueHandle returned = hmq
  367. $Call WinCreateMsgQueue,hab,0    ; 0 is default size of queue
  368. mov      hmq,eax                 ;returned queue handle
  369. .IF hmq == NULL
  370.    $WinErrMsg " : WinCreateMsgQueue"
  371.    $DosExit
  372. .ENDIF
  373.  
  374. ;---- Register Window Class Returned value is TRUE or FALSE
  375. $Call WinRegisterClass,hab,offset szAppName,offset MainWinProc,flStyle,0
  376. .IF eax == FALSE
  377.     $WinErrMsg " : WinRegisterClass"
  378.     $Call WinTerminate,hab
  379.     $DosExit
  380. .ENDIF
  381.  
  382. ;---- CreateStandard Window - Returns handle for Main Window Frame and client Window
  383. $Call WinCreateStdWindow,HWND_DESKTOP,WS_VISIBLE,offset flCtlData,offset szAppName,\
  384.                     offset szWinTitle,0,0,0,offset hwndMain
  385. mov   hwndMainFrame,eax          ;returned Frame Window handle
  386. .IF eax == 0
  387.    $WinErrMsg " : WinCreateStdWindow"
  388.    Call   ExitWin
  389. .ENDIF
  390.  
  391. Call GetWinResolution
  392. Call DefineWindowSize
  393. Call SetWindow
  394. ;
  395.  
  396. ;The way to proceed is to install a System Hook. This has to go into a DLL
  397. ;otherwise it cannot be called by other programs. The procedure in hook_dls
  398. ;will inspect WM_CHAR and if the ShiftKey and one of Alt or Ctrl key is down
  399. ;and if there is a valid Scan Code THEN
  400. ;it redefine the msg ID of that message as WM_USER+cfffh so it goes nowhere
  401. ;and then post a message to this program with the mp1 and mp2 parms
  402. ;using WM_USER+300h
  403.  
  404. ;------------  IS hookDLSM.DLL LOADED ? -------------------
  405. $Call DosQueryModuleHandle,offset DllFullModName,offset DllHandle
  406. .IF  eax == 0    ;module already loaded
  407.    $Alarm0
  408.    ;  $WinInfMsg  "      HOOKDLSM Already Loaded"
  409. .ENDIF
  410. ;---- Reads In hookkbsm.dat and writes to memory buffer
  411.    Call ReadDatFile
  412. ;---------  ALLOCATE MEMORY FOR SWITCH LIST STRUCTURE -------
  413.    Call SwitchListAlloc
  414.    $Call DosLoadModule,offset DllLoadError,LENGTHOF DllLoadError,offset DllFullModName,offset DllHandle
  415.    .IF eax != 0
  416.       $WinErrMsg " DosLoadModule"
  417. ;      Call   UnloadKBHook
  418.    .ENDIF
  419. .If DllProcAddr1 == 0
  420.     $Call DosQueryProcAddr,DllHandle,1,0,offset DllProcAddr1
  421.     .IF eax != 0
  422.         $WinDebugMessage msgDosQueryProc1Addr
  423. ;        Call   UnloadKBHook
  424.     .ENDIF
  425. .ENDIF
  426.  
  427. .IF DllProcAddr2 == 0
  428.     $Call DosQueryProcAddr,DllHandle,2,0,offset DllProcAddr2  ;JournalRecordHook
  429.     .IF eax != 0
  430.         $WinDebugMessage msgDosQueryProc2Addr
  431. ;        Call   UnloadKBHook
  432.     .ENDIF
  433. .ENDIF
  434.  
  435. $Call WinSetHook,hab,NULLHANDLE,HK_INPUT,DllProcAddr1,DllHandle
  436. .IF eax == 0
  437.    $WinErrMsg " WinSetINPUTHook"
  438.    Call   UnloadKBHook
  439. .ENDIF
  440.  
  441. ;------ pass the window frame handle in ebx
  442. ;-----  returns PlayBackQMSG in eax
  443. ;esp checks before and after call
  444. mov    ebx,hwndMainFrame  ;value of this
  445. mov    eax,0              ;Initialization Identifier
  446. call    DllProcAddr2
  447. mov    msgParms,eax       ;address of message variables from DLL when Recording
  448. ;$WinInfMsg  "   address of msgParms"   ;OK
  449. ;msgParms    offset   Variable
  450. ;              0      hwnd
  451. ;              4      msgID
  452. ;              8      mp1
  453. ;             12      mp2
  454. ;             16      time
  455. ;             20      x coordinate (Screen Based)
  456. ;             24      y coordinate (Screen Based)
  457.  
  458. ;---------  CREATE MAIN MESSAGE LOOP -----------
  459.  
  460. mml: $Call WinGetMsg,hab,offset quemsg,0,0,0    ;Note: differs from usual
  461.      .IF eax == TRUE                            ;msg loop - done so that program
  462.          $Call WinDispatchMsg,hab,offset quemsg ;can only be terminated
  463.          jmp   mml                              ;by the keystroke Shift-Alt-Del
  464.      .ELSE                                      ;or by Alt-F4 or Alt-Close
  465.          Call  UnloadKBHOok                     ;when Window has focus
  466.          mov   eax,TRUE
  467.          jmp   mml                              ;if ESc option chosen
  468.      .ENDIF                                     ;as notified from the DLL
  469.  
  470. ;Normally an Exit routine would go here, as indicated below but which
  471. ;is commented out. It is not required since it can never be reached.
  472. ;----------  EXIT ---------------
  473. ;Call UnloadKBHOok
  474. ;.ENDIF            ;Tue  04-13-1993
  475. ;---------------- End of Main Program -------------------
  476.  
  477. ;-------------  PROCESS MESSAGE QUEUE FOR hook_KB ------------
  478. ;------------------ MainWinProc -----------------
  479. ;parm1 = hwnd,parm2 = msg,parm3  = mp1,parm4 = mp2
  480. ;this is called from System and so has to do everything itself
  481. MainWinProc Proc Near
  482.     ;----------- GET PASSED PARAMETERS FROM STACK ------------
  483.     push   ebp           ;return address is 4 bytes and this push is 4 bytes
  484.     mov    ebp,esp       ;so first parameter is 8 bytes from top
  485.     mov    eax,[ebp+8]
  486.     mov    parm1,eax     ;hwnd
  487.     mov    eax,[ebp+12]
  488.     mov    parm2,eax     ;msg
  489.     mov    eax,[ebp+16]
  490.     mov    parm3,eax     ;mp1
  491.     mov    eax,[ebp+20]
  492.     mov    parm4,eax     ;mp2
  493.     mov    eax,[ebp+24]
  494.     mov    parm5,eax     ;time of message
  495.    ;----- RESTORE STACK POINTER AND STACK STATUS  ---
  496.     mov      esp,ebp     ;restore  stack pointer
  497.     pop      ebp
  498.     pusha
  499.     ;---------------- WM_CREATE ----------------
  500.     .IF parm2 == WM_CREATE
  501.          Call InitMainWindow
  502.          jmp  wm0
  503.     .ENDIF
  504.     ;---------------- WM_PAINT ----------------
  505.     .IF parm2 == WM_PAINT ; && parm1 == hwndMain
  506.          Call MainPaint
  507.          jmp  wm0
  508.     .ENDIF
  509.     ;---------------- WM_CHAR ----------------
  510.     .IF parm2 == WM_CHAR
  511.          Call MainKeyboard
  512.          jmp  wm0
  513.     .ENDIF
  514.     ;---------------- WM_SIZE ------------
  515.     .IF parm2 == WM_SIZE
  516.          jmp  wm0
  517.     .ENDIF
  518.     ;---------------- WM_USER+300H ----------------
  519.     .IF parm2 == WM_USER+300h                    ;posted message
  520.     ;if here know that Shift Key was down and at least one of Alt or Ctrl
  521.     ;GET SCAN CODE AND ALT/CTRL FLAG
  522.          mov    edx,parm4       ;scan code
  523.          mov    eax,parm3       ;Alt/Ctrl Flag = 0/1
  524.          mov    Alt_Ctrl,eax    ;Alt-Ctrl flag
  525.     ;Test for Shift-Alt-Del(white) for Unloading KBHook
  526.          .IF edx == 83 && Alt_Ctrl == 0      ; Shift-Alt-Del (White Del key)
  527.             Call UnloadKBHook
  528.             jmp     wm0
  529.          .ENDIF
  530.     ;Test for Shift-Alt-End(white) for CloseDown
  531.          .IF  edx == 79 && Alt_Ctrl == 0      ;Shift-Alt-End(White)
  532.             Call  CloseDown                   ;Tue  04-13-1993
  533.             jmp   wm0
  534.          .ENDIF
  535.     ;Test for Shift-Ctrl-LeftArrow - Start Record
  536.          .IF  edx == 75 && Alt_Ctrl == 1      ;Shift-Ctrl-LeftArrow(White)
  537.             Call  RecordMacroON
  538.             jmp   wm0
  539.          .ENDIF
  540.     ;Test for Shift-Ctrl-RightArrow  - Stop Record
  541.          .IF  edx == 77 && Alt_Ctrl == 1      ;Shift-Ctrl-RightArrow(White)
  542.             Call  RecordMacroOFF
  543.             jmp   wm0
  544.          .ENDIF
  545.     ;Test for Shift-Ctrl-Ins(white)    - Playback Record Parms Basis
  546.          .IF  edx == 82 && Alt_Ctrl == 1      ;Shift-Ctrl-Ins(White)
  547.             Call  PlaybackMacro
  548.             jmp   wm0
  549.          .ENDIF
  550.     ;Test for Shift_Ctrl-PgDn(White)   - Write Macro File Out
  551.          .IF  edx == 81 && Alt_Ctrl == 1      ;Shift-Ctrl-PgDn(White)
  552.             Call  WriteMacroAsciiHex
  553.             jmp   wm0
  554.          .ENDIF
  555.     ;Test for Shift-Ctrl-5(white)    - ProgramTestCtrl
  556.          .IF  edx == 76 && Alt_Ctrl == 1      ;Shift-Ctrl-5(White)
  557.             Call  ProgramTestCtrl
  558.             jmp   wm0
  559.          .ENDIF
  560.     ;Test for Shift-Alt-5(white)    - ProgramTestAlt
  561.          .IF  edx == 76 && Alt_Ctrl == 0      ;Shift-Alt-5(White)
  562.             Call  ProgramTestAlt
  563.             jmp   wm0
  564.          .ENDIF
  565.     ;Test for Shift-Alt-UpArrow    - Call ReadDatFile Update hookkbsm.dat
  566.          .IF  edx == 72 && Alt_Ctrl == 0      ;Shift-Alt-UpArrow(White)
  567.             mov   UpdateDat,1
  568.             $Call WinInvalidateRect,hwndMain,offset rect,TRUE
  569.             mov   edx,2500
  570.             Call  TimeDelay
  571.             Call  ReadDatFile
  572.             mov   UpdateDat,0
  573.             $Call WinInvalidateRect,hwndMain,offset rect,TRUE  ;reset
  574.             jmp   wm0
  575.          .ENDIF
  576.  
  577. ;ELSE TEST FOR ASSIGNED KEYS
  578. ;SETUP DATA STRUCTURES FOR ACTIVATING HOT KEY
  579. ;---- Code in this group places the offset into the array ExecOnKB into EDX
  580.          .IF  edx == 82 && Alt_Ctrl == 0      ;Shift-Alt-Ins
  581.               mov    esi,offset StartData     ;data structure for DosStartSession
  582.               mov    word ptr StartData,50    ;for Alt-=
  583.               mov    HotKeyID,'Ω'             ;For Program Title
  584.               mov    edi,offset TitleAlt
  585.               mov    cl,HotKeyID
  586.               mov    byte ptr [edi+4],cl
  587.               mov    dword ptr[esi+8],offset TitleAlt  ;program title
  588.               $Call  WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  589.               mov    eax,offset InsProg       ;address of Exec program
  590.               mov    [esi+12],eax
  591.               mov    dword ptr[esi+16],0      ;no command line
  592.               mov    word ptr[esi+30],2       ;Session Type
  593.               jmp    wmexe
  594.          .ELSE
  595.               mov    word ptr StartData,32
  596.          .ENDIF
  597.          .IF  edx == 53 && Alt_Ctrl == 1      ; Shift-Ctrl-?:/  key
  598.               mov    esi,offset StartData     ;data structure for DosStartSession
  599.               mov    word ptr StartData,32    ;
  600.               mov    HotKeyID,'?'             ;For Program Title
  601.               mov    edi,offset TitleAlt
  602.               mov    cl,HotKeyID
  603.               mov    byte ptr [edi+4],cl
  604.               mov    dword ptr[esi+8],offset TitleAlt  ;program title
  605.               $Call  WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  606.               mov    eax,offset InsProg   ;address of Exec program
  607.               mov    [esi+12],eax
  608.               mov    eax,offset DisplayUser
  609.               mov    dword ptr[esi+16],eax    ; command line
  610.               mov    word ptr[esi+30],2       ;Session Type
  611.               jmp    wmexe
  612.          .ENDIF
  613.          .IF  edx == 53 && Alt_Ctrl == 0      ; Shift-Alt-?:/  key
  614.               mov    esi,offset StartData     ;data structure for DosStartSession
  615.               mov    word ptr StartData,32    ;
  616.               mov    HotKeyID,'/'             ;For Program Title
  617.               mov    edi,offset TitleAlt
  618.               mov    cl,HotKeyID
  619.               mov    byte ptr [edi+4],cl
  620.               mov    dword ptr[esi+8],offset TitleAlt  ;program title
  621.               $Call  WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  622.               mov    eax,offset InsProg   ;address of Exec program
  623.               mov    [esi+12],eax
  624.               mov    eax,offset DisplayPrg
  625.               mov    dword ptr[esi+16],eax    ; command line
  626.               mov    word ptr[esi+30],2       ;Session Type
  627.               jmp    wmexe
  628.          .ENDIF
  629.          .IF    edx >= 2 && edx <= 11     ;scan code for 1..9,0
  630.              .IF  edx >= 2 && edx <= 10
  631.                  sub   edx,1       ;convert to number 1 - 9
  632.              .ELSE
  633.                  mov   edx,0       ; 0 offset for 0
  634.              .ENDIF
  635.              mov   HotKeyID,dl
  636.              add   HotKeyID,30h    ;convert to ASCII
  637.              jmp   wmok
  638.          .ENDIF
  639.           xor   ecx,ecx
  640.          .IF  edx >= 16 && edx <= 25; && edx != 17 ; q,w,e,r,t,y,u,i,o,p
  641.                mov   esi,offset lookup0
  642.                sub   edx,16
  643.                jmp   wmoj
  644.          .ENDIF
  645.          .IF edx >= 30 && edx <= 38 ; a,s,d,f,g,h,j,k,l
  646.                mov   esi,offset lookup1
  647.                sub   edx,30
  648.                jmp   wmoj
  649.          .ENDIF
  650.          .IF  edx >= 43 && edx <= 50  ;z,x,c,v,b,n,m
  651.                mov   esi,offset lookup2
  652.                sub   edx,44
  653.                jmp   wmoj
  654.          .ELSE
  655.                jmp   wm0
  656.          .ENDIF
  657. wmoj:     mov   cl,byte ptr [esi+edx]  ;cl has value - cl+37h is UC letter
  658.           mov   HotKeyID,cl            ;identifies letter
  659.           add   HotKeyID,37h
  660.           xor   edx,edx
  661.           mov   dl,cl
  662. wmok:     ;- Alt_Ctrl has Alt_Ctrl Flag and dl has offset into array
  663.          .IF  edx >= 0 && edx <= 35
  664.               xor  eax,eax
  665.               mov   al,dl
  666.               mov  esi,offset StartData  ;data structure for DosStartSession
  667.               .IF  Alt_Ctrl == 0
  668.                   mov   ebx,offset AltX  ;Alt Definitions
  669.                   mov   edi,offset TitleAlt
  670.                   mov   cl,HotKeyID
  671.                   mov   byte ptr [edi+4],cl
  672.                   mov   dword ptr[esi+8],offset TitleAlt  ;program title
  673.               .ENDIF
  674.               .IF  Alt_Ctrl == 1
  675.                   mov   ebx,offset CtrlX ;Ctrl Definitions
  676.                   mov   edi,offset TitleCtl
  677.                   mov   cl,HotKeyID
  678.                   mov   byte ptr [edi+4],cl
  679.                   mov   dword ptr[esi+8],offset TitleCtl  ;program title
  680.               .ENDIF
  681.               mov    cl,LenExec
  682.               mul    cl             ;Structure Length ten
  683.               add    ebx,eax        ;element # of structure
  684.               ;[ebx+8] != 9 is flag that keystroke is assigned
  685.               .IF  word ptr [ebx+8] != 9
  686.                    $Call WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
  687.                    mov  eax,[ebx]              ;address of Exec program
  688.                    mov  [esi+12],eax
  689.                    mov  eax,[ebx+4]            ;address of command line
  690.                    mov  [esi+16],eax
  691.                    mov  ax,word ptr [ebx+8]    ;Session type
  692.                    mov  [esi+30],ax
  693.                   .IF ax == 4 || ax == 7    ;set environment string DPMI_DOS_API for Borland IDE
  694.                       mov dword ptr[esi+24],offset DosEnvValue
  695.                   .ELSE
  696.                       mov  dword ptr[esi+24],0   ;default value reset
  697.                   .ENDIF
  698. ;GO THRU SWITCH LIST TO SEE IF HOT KEY ACTIVE
  699.                    ;-- called before DosStartSession to see if program loaded
  700.                    ;-- esi=offset into StartData
  701.                    ;-- go thru Switch List to see if loaded and if so switch to
  702.                    ;-- The test made on 4th char of TitleAlt/TitleCtl which
  703.                    ;-- is the title in the window and Task List
  704. wmexe:             pusha
  705.                    $NumSwitchListEntries
  706.                    mov  numitems,eax      ;number of switch list entries
  707.                    dec numitems
  708.                    Call GetSwitchList     ;activate structure
  709.                    mov  edi,baseaddr      ;address of switch list
  710.                    mov  ecx,0
  711.                    .IF  Alt_Ctrl == 0
  712.                         mov    bl,'A'
  713.                    .ELSE
  714.                         mov    bl,'C'
  715.                    .ENDIF
  716.                    .WHILE  ecx < numitems           ;starts at offset 0
  717.                        mov   al,byte ptr[edi+40]  ;5-th char TaskList title
  718.                        mov   dl,byte ptr[edi+36]  ;1stChar of Title A/C
  719.                        ;IF ACTIVE SWITCH TO
  720.                        .IF al == HotKeyID && bl == dl
  721.                             ;Now Switch to that window - get switch handle
  722.                             mov  eax,[edi+4]
  723.                             $Call WinSwitchToProgram,eax
  724.                             popa
  725.                             jmp  wm0                ;do not reload
  726.                        .ENDIF
  727.                        inc   ecx
  728.                        add   edi,swblksize           ;next element in structure
  729.                    .ENDW
  730.                    popa
  731.                    ;ELSE ACTIVATE HOT KEY PROGRAM
  732.                    $Call DosStartSession,esi,offset SessID,offset ProcID
  733.               .ENDIF
  734.          .ENDIF
  735.     .ENDIF                                     ;End WM_USER+300h
  736.    wm0:popa
  737.    ;----- Default Procedure * Return Value in eax ------
  738.    $Call WinDefWindowProc,parm1,parm2,parm3,parm4
  739.    ret
  740. MainWinProc  endp
  741.  
  742. ;-------------- MainPaint * WM_PAINT --------------
  743. MainPaint  proc
  744.       $Call WinBeginPaint,hwndMain,NULL,offset rect    ;offset rect
  745.       mov  hps,eax        ;returns cache presentation space handle
  746.       $Call WinQueryWindowRect,hwndMain,offset rect
  747.       $Call WinFillRect,hps,offset rect,CLR_YELLOW  ;SYSCLR_WINDOW
  748.       .IF RecordOn == 1
  749.           $Call WinDrawText,hps,-1,offset textMsgOn,offset rect,CLR_BLUE,CLR_YELLOW,TextPos
  750.       .ENDIF
  751.       .IF RecordOn == 2
  752.           $Call WinDrawText,hps,-1,offset textMsgPlay,offset rect,CLR_BLUE,CLR_YELLOW,TextPos
  753.       .ENDIF
  754.       .IF UpdateDat == 1
  755.           $Call WinDrawText,hps,-1,offset textMsgUpdateDat,offset rect,CLR_BLUE,CLR_YELLOW,TextPos
  756.       .ENDIF
  757.       $Call WinEndPaint,hps
  758.       mov   eax,TRUE
  759.       ret
  760. MainPaint  endp
  761.  
  762. ;-------------- InitMainWindow * WM_CREATE --------------
  763. ;var1 = hwnd, var2 = mp1, var3 = mp2
  764. InitMainWindow Proc
  765.        $Call WinDefWindowProc,parm1,parm2,parm3,parm4
  766.        ret
  767. InitMainWindow Endp
  768.  
  769. ;-------------- MainKeyBoard * WM_CHAR --------------
  770. ;var1 = mp1,var2 = mp2,var3 = hwnd
  771. MainKeyBoard  Proc
  772.       $Call WinDefWindowProc,parm1,parm2,parm3,parm4
  773.       ret
  774. MainKeyBoard Endp
  775.  
  776. ExitWin  Proc
  777.     $Call WinDestroyMsgQueue,hmq
  778.     $Call WinTerminate,hab
  779.     $Call DosFreeModule,DllHandle
  780.     $DosExit    ;so exit
  781.     ret
  782. ExitWin  Endp
  783.  
  784. SwitchListAlloc  Proc          ;allocate memory for a switch list of 30
  785.     mov     ecx,00000002h   ;write access flags for Dos alloc
  786.     or      ecx,00000010h   ;page commit
  787.     $Call DosAllocMem,offset baseaddr,3000,ecx
  788.     .IF  eax != 0
  789.        $WinErrMsg  " : DosAllocMem SwitchList"
  790.        Call Exitwin
  791.     .ENDIF
  792.     ret
  793. SwitchListAlloc  Endp
  794.  
  795. GetSwitchList   Proc   ;puts address into baseaddr
  796.     pusha
  797.     $Call  WinQuerySwitchList,hab,baseaddr,3000
  798.     .IF eax == 0
  799.         $WinErrMsg " : WinQuerySwitchList"
  800.         Call ExitWin
  801.     .ENDIF
  802.     popa
  803.     ret
  804. GetSwitchList   Endp
  805.  
  806. ;---- This procedure uses the handle returned from the message and uses
  807. ;---- that to obtain the first 24 characters of the name associated
  808. ;---- with that handle from SwitchList for which space is already allocated
  809. ;---- this is called with handle in eax
  810. GetNameFromHandle  Proc
  811.     pusha
  812.     $Call  WinQuerySwitchList,hab,baseaddr,3000
  813.     mov   numitems,eax      ;number of switch list entries
  814.     mov   edi,baseaddr      ;address of switch list
  815.     mov   ecx,1
  816.     mov   NameHitFlag,0     ;reset
  817.     mov   eax,HandFromMsg
  818.     .WHILE  ecx <= numitems           ;starts at offset 0
  819.          ;--- This group displays SwitchList Title and Iconsn
  820.          .IF   eax == [edi+8]        ;hwnd of FrameWindow of Program returned by msgQueue
  821.                mov    NameHitFlag,1
  822.                mov    eax,edi
  823.                add    eax,36         ;address of name
  824.                mov    TaskNameAddr,eax
  825.               .BREAK
  826.          .ENDIF
  827. ;         .IF   eax == [edi+12]        ;hwnd of FrameWindow of Program returned by msgQueue
  828. ;               mov    NameHitFlag,1   ;ICON
  829. ;               mov    eax,edi
  830. ;               add    eax,36         ;address of name
  831. ;               mov    TaskNameAddr,eax
  832. ;              .BREAK
  833. ;         .ENDIF;  Not Required
  834. ;         .IF   eax == [edi+16]        ;hwnd of FrameWindow of Program returned by msgQueue
  835. ;               mov    NameHitFlag,1   ;PROGRAM
  836. ;               mov    eax,edi
  837. ;               add    eax,36         ;address of name
  838. ;               mov    TaskNameAddr,eax
  839. ;              .BREAK
  840. ;         .ENDIF ;   Plays No role
  841.          ;;--- Displays programTitles
  842.          push  ecx
  843.          $Call WinQueryWindow,HandFromMsg,QW_PARENT
  844.          pop   ecx
  845.          .BREAK .IF eax == 0
  846.          .IF   eax == [edi+8]        ;hwnd of FrameWindow of Program returned by msgQueue
  847.                mov    NameHitFlag,1
  848.                mov    eax,edi
  849.                add    eax,36         ;address of name
  850.                mov    TaskNameAddr,eax
  851.               .BREAK
  852.          .ENDIF
  853.          inc   ecx
  854.          add   edi,swblksize           ;next element in structure
  855.     .ENDW
  856.     .IF  NameHitFlag == 0
  857.          mov  TaskNameAddr,offset NoNameListed
  858.     .ENDIF
  859.     popa
  860.     ret
  861. GetNameFromHandle  Endp
  862.  
  863. CloseDown       Proc
  864.     $Call WinMessageBox,HWND_DESKTOP,HWND_DESKTOP,offset ExitMsg,offset ExitTitle,0,MB_OKCANCEL
  865.     .IF eax != MBID_CANCEL
  866.         $Call WinShutdownSystem,hab,hmq
  867.         $Call DosFreeMem,memAddr
  868.         $Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
  869.         $Call DosFreeModule,DllHandle
  870.         $Call WinDestroyWindow,hwndMainFrame
  871.         Call  ExitWin
  872.     .ENDIF
  873.     ret
  874. CloseDown       Endp
  875.  
  876. UnloadKBHook   Proc
  877.     $Alarm0
  878.     $Call WinMessageBox,HWND_DESKTOP,HWND_DESKTOP,offset RemoveMsg,offset RemoveTitle,0,MB_OKCANCEL
  879.     .IF eax != MBID_CANCEL
  880.         $Call DosFreeMem,memAddr
  881.         .IF eax != 0
  882.             $WinErrMsg " : DosFreeRegularMem"
  883.         .ENDIF
  884.         $Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
  885.         .IF eax == 0
  886.            $WinErrMsg " : WinReleasInputHook-1"
  887.         .ENDIF
  888.         $Call DosFreeModule,DllHandle
  889.         .IF  eax != 0
  890.             $WinErrMsg "  : DosFreeModule-DLL"
  891.         .ENDIF
  892.         $Call WinDestroyWindow,hwndMainFrame
  893.         .IF  eax == 0
  894.             $WinErrMsg " : WinDestroyWindow"
  895.         .ENDIF
  896.         Call  ExitWin
  897.     .ENDIF
  898.     mov  eax,TRUE
  899.     ret
  900. UnloadKBHook   Endp
  901.  
  902. ;----- Gets horizontal and vertical window resolution
  903. GetWinResolution  Proc
  904.     $Call WinGetPS,HWND_DESKTOP
  905.     mov   hps,eax              ;presentation space
  906.     .IF eax == 0
  907.        $WinErrMsg "  WinGetPS"
  908.       Call   ExitWin
  909.     .ENDIF
  910.  
  911.     $Call GpiQueryDevice,hps
  912.     mov   hdc,eax              ;device handle
  913.     .IF eax == 0 || eax == HDC_ERROR
  914.        $WinErrMsg "  GpiQueryDevice"
  915.        Call   ExitWin
  916.     .ENDIF
  917.  
  918. ;---- will get horizontal and vertical resolution in one read
  919. ;---- xPelsPerMeter and yPelsPerMeter are consecutive
  920.     $Call DevQueryCaps,hdc,CAPS_HORIZONTAL_RESOLUTION,2,offset xPelsPerMeter
  921.     .IF eax == 0
  922.        $WinErrMsg " : DosQueryCapsHorizontal"
  923.        Call   ExitWin
  924.     .ENDIF
  925. ;---- Get Screen Width in PELS
  926.     $Call DevQueryCaps,hdc,CAPS_WIDTH,1,offset ScreenWidth
  927.     .IF eax == 0
  928.        $WinErrMsg " : DosQueryCapsScreenWidth"
  929.        Call   ExitWin
  930.     .ENDIF
  931.  
  932.     $Call WinReleasePS,hps
  933.     ret
  934. GetWinResolution  Endp
  935.  
  936. ;----- Fills RECT structure for window size ---
  937. DefineWindowSize  Proc
  938.     xor   edx,edx
  939.     mov   eax,xPelsPerMeter    ;basevalue is 2667 before divide
  940.     div   DivideByHoriz
  941.     mov   RightX,eax
  942.  
  943.     xor   edx,edx
  944.     mov   eax,yPelsPerMeter    ;basevalue is 2667 before divide
  945.     div   DivideByVert
  946. ;    mov   ebx,eax
  947. ;    shr   eax,2                ;divide eax by 4
  948. ;    mov   UpperY,ebx
  949. ;    sub   UpperY,eax
  950.     mov    UpperY,eax
  951.  
  952.     mov   esi,offset rect
  953.     mov   eax,LeftX
  954.     mov   [esi],eax
  955.     mov   eax,LowerY
  956.     mov   [esi+4],eax
  957.     mov   eax,RightX
  958.     mov   [esi +8],eax
  959.     mov   eax,UpperY
  960.     mov   [esi+12],eax
  961.     ret
  962. DefineWindowSize  Endp
  963.  
  964. ;------ sets window position ---
  965. SetWindow   Proc
  966.     mov   ebx,SWP_SIZE
  967.     or    ebx,SWP_MOVE
  968.     mov   eax,ScreenWidth
  969.     sub   eax,Rightx
  970. ;    sub   eax,14                    ;attempting to offset a bit
  971.     ;--- Put in Lower Right Hand Corner
  972.     $Call WinSetWindowPos,hwndMainFrame,0,eax,0,RightX,UpperY,ebx
  973.     .IF eax == 0
  974.         $WinErrMsg " WinSetWindowsPos"
  975.     .ENDIF
  976.     ret
  977. SetWindow   Endp
  978.  
  979. RecordMacroON Proc   ;esp checks before and after call
  980.     .IF  RecordOn == 0
  981.         mov   RecordOn,1
  982.         mov    JR_Count,0        ;as is done in call
  983.         mov    JR_Counter,0      ;as is done in call
  984.         mov    AddrCtr,0
  985.         $Call WinInvalidateRect,hwndMain,offset rect,TRUE
  986.         mov    eax,1             ;in DLL JR_Counter->0,RecordOn->1
  987.         call    DllProcAddr2
  988.     .ENDIF
  989.     ret
  990. RecordMacroON  Endp
  991.  
  992. ; When turning OFF the Shift-Ctrl-Ins key strokes are recorded. They
  993. ; contribute 6 counts tothe records. A single key stroke (down and up)
  994. ; contributes 2 counts to the record.
  995. RecordMacroOFF   Proc   ;esp checks before and after calls
  996.     pusha
  997.     .IF  RecordOn == 1
  998.         mov    RecordOn,0
  999.         mov    eax,2             ;JR_Counter,JR_Count,RecordON->0
  1000.         call    DllProcAddr2      ;Returns JR_Count in eax
  1001.         mov    JR_Count,eax      ;JR_Counter returned from DLL
  1002.         $Call WinInvalidateRect,hwndMain,offset rect,TRUE
  1003.     .ENDIF
  1004.     popa
  1005.     ret
  1006. RecordMacroOFF       Endp
  1007. ;
  1008. PlaybackMacro  Proc
  1009.     .IF RecordOn == 1
  1010.         Call RecordMacroOff
  1011.         mov  JR_Count,0
  1012.          mov    eax,0
  1013.          $WinInfMsg   " !! Aborting Macro Recording - Cannot PlayBack while Recording !!"
  1014.         ret
  1015.     .ENDIF
  1016.     .IF  JR_Count == 0  || JR_Count == 8     ;8 is 3 StartUp and 5 Close WM_CHAR messages
  1017.          mov    eax,0
  1018.          $WinInfMsg   " Messages to Play back !!"
  1019.          ret
  1020.     .ENDIF
  1021.     pusha
  1022.     .IF  RecordOn == 0 && JR_Count > 8 ;edi saved across calls
  1023.         mov  eax,JR_Count
  1024.         sub  eax,8             ;Omit 3 start and 5 terminating messages
  1025. ;        $WinInfMsg   " Messages to Play back !!"
  1026. ;---- Temporarily Release HotKey Activation, Display "Playback" message
  1027. ;     If release hook then during playback ALt-x/Ctrl-X assignments appear
  1028. ;        $Call WinReleaseHook,hab,NULLHANDLE,HK_INPUT,DllProcAddr1,DllHandle
  1029.         mov   RecordOn,2
  1030.         $Call WinInvalidateRect,hwndMain,offset rect,TRUE
  1031. ;----  Now Playback the Macro
  1032.         mov   esi,msgParms           ;block holding playback records
  1033.         add   esi,RecdLnth_x_3       ;no include 1st 3 msgs which are KeyUp of Shift-Ctrl-LeftArrow StartUp Sequence
  1034.         mov   ecx,9                  ;Omit 3 start 5 ending messages
  1035.         mov   ebx,0
  1036.         mov   edx,0                  ;value for first time around
  1037.         .WHILE  ecx <= JR_Count
  1038.             .IF edx > 0  ;&& dword ptr[esi+ebx+4] != WM_TIMER
  1039.                  Call TimeDelay
  1040.             .ENDIF
  1041.             pusha
  1042.             Call UseCurWindows
  1043.             popa
  1044.             mov   eax,[esi+ebx+16] ;time of this just played
  1045.             inc   ecx
  1046.             add   ebx,RecdLnth
  1047.             mov   edx,[esi+ebx+16] ;time of message coming up
  1048.             sub   edx,eax          ;time diff between messages
  1049.         .ENDW
  1050. ;        mov   eax,ecx
  1051. ;        dec   eax
  1052. ;        $WinInfMsg "       Records Played Back"
  1053.         ;---- Restore to non Playback
  1054.         mov   RecordOn,0      ;reset to no recording
  1055.         $Call WinInvalidateRect,hwndMain,offset rect,TRUE
  1056. ;        $Call WinSetHook,hab,NULLHANDLE,HK_INPUT,DllProcAddr1,DllHandle
  1057.     .ENDIF
  1058.     popa
  1059.     ret
  1060. PlaybackMacro  Endp
  1061.  
  1062. ;---- Called by PlayBack to use Current Windows which are either
  1063. ;---- ACtive Windows (mouse related) or windows with focus (KBoard related)
  1064. UseCurWindows   Proc
  1065. ;---- WM_CHAR ----
  1066.      ;--- Code here ensures that window with focus gets WM_CHAR messages
  1067.      ;--- Using only those on the Down Stroke
  1068.     ;Test for Shift-Alt-Ins(white)     -
  1069.      .IF  [esi+4+ebx] ==  WM_CHAR  && byte ptr[esi+8+ebx] > 40H   ;Up stroke
  1070.          mov    eax,TRUE
  1071.          ret
  1072.      .ENDIF
  1073.      .IF  [esi+4+ebx] ==  WM_CHAR  && byte ptr[esi+8+ebx] <= 40H  ;down stroke
  1074.          ;---  Code below ensures that no messages called by Alt/Ctrl -Key
  1075.          ;---- Are Called with Shift Alt/Ctrl-Key sequence in playback
  1076.          ;---  If Alt/Ctrl down lowest byte of param2=0
  1077.          ;---  AND next lowest byte is Scan Code of Key Struck
  1078.          ;---  If Shift Down Test Lowest Word of param1 for KC_SHIFT
  1079.          mov     edx,[esi+12+ebx] ;param2
  1080.          .IF     dh != 0 && dl == 0 ;Alt/Ctrl down and ScanCode valid
  1081.              test   [esi+8+ebx],KC_SHIFT   ;is ShiftKey Down
  1082.              jz     NoShft
  1083.              mov   eax,TRUE
  1084.              ret
  1085.          .ENDIF
  1086. NoShft:  $Call WinQueryFocus,HWND_DESKTOP    ;window handle returned in EAX
  1087.          $Call WinSendMsg,eax,WM_CHAR,[esi+8+ebx],[esi+12+ebx]  ;this works
  1088.          mov   eax,TRUE
  1089.          ret
  1090.      .ENDIF
  1091.  
  1092. ;---- WM_MOUSEMOVE ----
  1093. ;---- The parms here are x,y coordinates relative to Screen
  1094. ;---- x = 0, y = 0 is lower left corner
  1095.      .IF   dword ptr[esi+4+ebx] == WM_MOUSEMOVE || dword ptr[esi+4+ebx] == WM_MOUSELAST
  1096.           $Call  WinSetPointerPos,HWND_DESKTOP,dword ptr[esi+20+ebx],dword ptr[esi+24+ebx]
  1097.           mov   eax,TRUE
  1098.           ret
  1099.      .ENDIF
  1100.  
  1101. ;---- WM_BUTTON1DOWN=WM_BUTTON1CLICK WM_SINGLESELECT WM_BUTTON1DBLCLK WM_BUTTON1UP  WM_BUTTON1MOTIONSTART || [esi+4+ebx] == WM_BUTTON1MOTIONEND----
  1102.      .IF  [esi+4+ebx] == WM_BUTTON1DOWN || [esi+4+ebx] == WM_BUTTON1UP || [esi+4+ebx] == WM_BUTTON1DBLCLK || [esi+4+ebx] == WM_BUTTON1MOTIONSTART || [esi+4+ebx] == WM_BUTTON1MOTIONEND || [esi+4+ebx] == WM_BUTTON1CLICK ;| [esi+4+ebx] == WM_SINGLESELECT
  1103.           ;--- This gets handle of active window from DeskTop
  1104.           mov   eax,[esi+20+ebx]        ;X Screen Coordinate
  1105.           mov   WinPosX,eax
  1106.           mov   eax,[esi+24+ebx]        ;Y Screen Coordinate
  1107.           mov   WinPosY,eax
  1108.           $Call WinWindowFromPoint,HWND_DESKTOP,offset WinPosX,TRUE
  1109.           mov   hwndActive,eax
  1110.           $Call WinSetFocus,HWND_DESKTOP,eax
  1111.           $Call WinSendMsg,hwndActive,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this works
  1112.           mov   eax,TRUE
  1113.           ret
  1114.      .ENDIF
  1115.  
  1116. ;---- WM_BUTTON2DOWN  WM_BUTTON2UP WM_BUTTON2DBLCLK  WM_BUTTON2MOTIONSTART  WM_BUTTON2MOTIONEND WM_BUTTON2CLICK ----
  1117.      .IF  [esi+4+ebx] == WM_BUTTON2DOWN || [esi+4+ebx] == WM_BUTTON2UP || [esi+4+ebx] == WM_BUTTON2DBLCLK || [esi+4+ebx] == WM_BUTTON2MOTIONSTART || [esi+4+ebx] == WM_BUTTON2CLICK
  1118.           ;--- This gets handle of active window from DeskTop
  1119.           mov   eax,[esi+20+ebx]        ;X Screen Coordinate
  1120.           mov   WinPosX,eax
  1121.           mov   eax,[esi+24+ebx]        ;Y Screen Coordinate
  1122.           mov   WinPosY,eax
  1123.           $Call WinWindowFromPoint,HWND_DESKTOP,offset WinPosX,TRUE
  1124.           mov   hwndActive,eax
  1125.           $Call WinSetFocus,HWND_DESKTOP,eax
  1126.           $Call WinSendMsg,hwndActive,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this works
  1127.          mov   eax,TRUE
  1128.          ret
  1129.      .ENDIF
  1130.  
  1131. ;---- WM_ related to mouse drag
  1132.      .IF   dword ptr[esi+4+ebx] == WM_BEGINDRAG || dword ptr[esi+4+ebx] == WM_ENDDRAG || [esi+4+ebx] == WM_BUTTON2MOTIONEND
  1133.           mov   eax,[esi+20+ebx]        ;X Screen Coordinate
  1134.           mov   WinPosX,eax
  1135.           mov   eax,[esi+24+ebx]        ;Y Screen Coordinate
  1136.           mov   WinPosY,eax
  1137.           $Call WinWindowFromPoint,HWND_DESKTOP,offset WinPosX,TRUE
  1138.           mov   hwndActive,eax
  1139. ;          .IF word ptr [esi+8+ebx] == TRUE   ;was from Pointer event
  1140. ;               $Call DosBeep,100,1000
  1141. ;               mov   eax,[esi+12+ebx]    ;parm2
  1142. ;               xor   ecx,ecx
  1143. ;               mov   cx,ax               ;y coordinate
  1144. ;               shr   eax,16              ;move x coord to ax
  1145. ;               $Call WinSetWindowPos,hwndActive,eax,ecx,NULL,NULL,SWP_MOVE
  1146. ;               .IF eax == 0
  1147. ;                   $WinInfMsg  " WinSetWindowPos Err"
  1148. ;               .ENDIF
  1149. ;          .ENDIF
  1150.           $Call WinSetFocus,HWND_DESKTOP,hwndActive
  1151.           $Call WinSendMsg,hwndActive,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this works
  1152.           ret
  1153.      .ENDIF
  1154.  
  1155. ;---- WM_TASKLIST 082H----
  1156. ;---- Task List -- TaskList Handle is Unique,TaskListHandle equ 004001CCh
  1157. ;---- Though there are other messages associated with the Task List
  1158. ;---- 80H = SH_TASKLIST 81h = SH_TASKMANAGER 82H = SH_TASKACTIVATE
  1159. ;---- ALso 02f43h and 02F42h seem associated
  1160. ;---- If this not included Ctrl-Esc not recognized on playback
  1161. ;---- Inclusion of 2F43H below meakes Macro Playback involving Ctrl-Esc work incorrectly
  1162. ;---- Inclusion of 81h makes no difference
  1163. ;---- Inclusion of 80h makes no difference
  1164. ;---- Inclusion of 1003H makes no difference but does display TaskLIst at End
  1165.      .IF dword ptr[esi+ebx+4] == 82h
  1166.          $Call WinSetFocus,HWND_DESKTOP,TaskListHandle
  1167.          $Call WinSendMsg,TaskListHandle,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this works
  1168.          mov   eax,TRUE
  1169.          ret
  1170.      .ENDIF
  1171.  
  1172. ;     .IF dword ptr[esi+4+ebx] == 405h   ;seems to make no difference
  1173. ;         $Call WinSendMsg,00200138h,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]
  1174. ;         mov   eax,TRUE
  1175. ;         ret
  1176. ;     .ENDIF
  1177.  
  1178. ;---- WM_OPEN WM_CLOSE WM_SYSCOMMAND WM_COMMAND
  1179. ;---- Inclusion of WM_CONTROL seems to make no difference
  1180.      .IF [esi+4+ebx] == WM_OPEN || [esi+4+ebx] == WM_CLOSE || [esi+4+ebx] == WM_SYSCOMMAND || [esi+4+ebx] == WM_COMMAND || [esi+4+ebx] == WM_CONTROL || dword ptr[esi+4+ebx] == 185h
  1181.           $Call WinQueryFocus,HWND_DESKTOP
  1182.           $Call WinSendMsG,eax,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this works
  1183.          mov   eax,TRUE
  1184.          ret
  1185.      .ENDIF
  1186.  
  1187. ;---- WM_PAINT ----
  1188.      .IF   [esi+4+ebx] == WM_PAINT
  1189.          $Call WinQueryFocus,HWND_DESKTOP
  1190.          $Call WinSendMsg,eax,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this works
  1191.          mov   eax,TRUE
  1192.          ret
  1193.      .ENDIF
  1194.  
  1195. ;---- WM_USER+300h --- Send message to this Program (= hwndMain) for action
  1196.      .IF   [esi+4+ebx] == WM_USER+300h
  1197.          $Call WinSendMsg,hwndMain,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]
  1198.          mov   eax,TRUE
  1199.          ret
  1200.      .ENDIF
  1201.  
  1202. ;---- WM_ALL_THE_REST ----
  1203. ;---- Since we do not know what window to send them to
  1204. ;    $Call WinQueryFocus,HWND_DESKTOP                           ;including this and
  1205. ;    $Call WinSendMsg,eax,[esi+4+ebx],[esi+8+ebx],[esi+12+ebx]  ;this seems to make no difference
  1206.      mov   eax,TRUE
  1207.      ret            ;for all those messages not explicitly handled
  1208. UseCurWindows   Endp
  1209.  
  1210. ;---- Called with window handle in eax -
  1211. FocusClass    Proc
  1212.      pusha
  1213.      $Call  WinQueryWindow,eax,QW_NEXT
  1214.      $Call  WinQueryClassName,eax,16,offset ClassNameBuf
  1215.      mov    esi,offset ClassNameBuf
  1216.      mov    edi,offset CoverPage
  1217.      mov    ecx,1
  1218.      mov    ebx,0
  1219.      .WHILE ecx <= 4
  1220.             mov   eax,[esi+ebx]
  1221.             cmp   eax,[edi+ebx]
  1222.             jne   nomtch
  1223.             add   ebx,4
  1224.             inc   ecx
  1225.      .ENDW
  1226. ;---- If got here there was a match
  1227.      $Call DosBeep,100,1000
  1228. nomtch: popa
  1229.      ret
  1230. FocusClass    Endp
  1231.  
  1232. ;--- Will Display handle of Window Under Mouse and WindowClass and
  1233. ;--- Then whether 16/32 bit
  1234. ProgramTestAlt  Proc      ;Use for testing things  Shift-Alt-5(white)
  1235.     pusha
  1236.     $Call WinQueryFocus,HWND_DESKTOP    ;get current focus to save
  1237.     push   eax
  1238.     $Call WinQueryPointerPos,HWND_DESKTOP,offset WinPosX
  1239.     ;--- IF FALSE is chosen returns Handle of Frame Window under HWND_DESKTOP
  1240.     ;--- IF  TRUE is chosen returns Handle of Actual Window
  1241.     $Call WinWindowFromPoint,HWND_DESKTOP,offset WinPosX,TRUE
  1242.     mov   hwndNext0,eax
  1243.     $WinInfMsg  " is Handle of Window Under Mouse"
  1244.     $Call WinQueryClassName,hwndNext0,16,offset ClassNameBuf
  1245.     mov   eax,hwndNext0
  1246.     $WinDebugMessage   ClassNameBuf
  1247.     $Call WinQueryWindowModel,eax        ;0 = 16 bit, 1 = 32 bit
  1248.     .IF  eax == 0
  1249.          mov   eax,16
  1250.     .ELSEIF  eax == 1
  1251.          mov   eax,32
  1252.     .ENDIF
  1253.     $WinInfMsg  "   Bit Window"
  1254.     $Call WinQueryWindow,hwndNext0,QW_OWNER
  1255.     $WinInfMsg  " is Owner of window under mouse"
  1256.     $Call WinQueryWindow,hwndNext0,QW_PARENT
  1257.     $WinInfMsg  " is Parent of window under mouse"
  1258.     pop   eax
  1259.     $Call WinSetFocus,HWND_DESKTOP,eax
  1260.     popa
  1261.     ret
  1262. ProgramTestAlt  Endp
  1263.  
  1264. ProgramTestCtrl  Proc      ;Use for testing things  Shift-Ctrl-5(white)
  1265.     pusha
  1266.     $Call WinQueryPointerPos,HWND_DESKTOP,offset WinPosX
  1267.     ;--- IF FALSE is chosen returns Handle of Frame Window under HWND_DESKTOP
  1268.     ;--- IF  TRUE is chosen returns Handle of Actual Window
  1269.     $Call WinWindowFromPoint,HWND_DESKTOP,offset WinPosX,FALSE
  1270.     mov   hwndNext0,eax
  1271.     $WinInfMsg  "      Handle of Frame of Window Under Mouse"
  1272.     $Call WinBeginEnumWindows,hwndNext0      ;HWND_DESKTOP
  1273.     .IF  eax == PMERR_INVALID_HWND
  1274.          $WinInfMsg   "  Error Calling WinBeginEnumWindows"
  1275.          jmp   xptc
  1276.     .ENDIF
  1277.     mov   henum,eax           ;enum handle
  1278.     mov   ecx,0
  1279.     .WHILE TRUE
  1280.          push   ecx
  1281.          $Call WinGetNextWindow,henum
  1282.          pop    ecx
  1283.          .BREAK .IF eax == 0
  1284.          .IF  ecx == 0
  1285.               mov   hwndNext0,eax
  1286.          .ENDIF
  1287.          .IF  ecx == 1
  1288.               mov   hwndNext1,eax
  1289.          .ENDIF
  1290.          .IF  ecx == 2
  1291.               mov   hwndNext2,eax
  1292.          .ENDIF
  1293.          push   ecx
  1294.          $WinInfMsg  "     Window Handle Value"
  1295.          pop    ecx
  1296.          inc   ecx
  1297.     .ENDW
  1298.     mov  eax,ecx
  1299.     $WinInfMsg   "     Number of Windows below Frame Window"
  1300.     $Call WinEndEnumWindows,henum
  1301.  
  1302.     mov   eax,hwndNext0
  1303.     $Call WinQueryClassName,hwndNext0,7,offset ClassNameBuf
  1304.     mov   eax,hwndNext0
  1305.     $WinDebugMessage   ClassNameBuf
  1306.  
  1307.     $WinInfMsg   "   Enumerating Children of Window to Left"
  1308.     $Call WinBeginEnumWindows,hwndNext0
  1309.     .IF  eax == PMERR_INVALID_HWND
  1310.          $WinInfMsg   "  Error Calling WinBeginEnumWindowsNext0"
  1311.          jmp   xptc
  1312.     .ENDIF
  1313.     mov   henum,eax           ;enum handle
  1314.     .WHILE TRUE
  1315.          $Call WinGetNextWindow,henum
  1316.          .BREAK .IF eax == 0
  1317.          push  eax
  1318.          $Call WinQueryClassName,eax,20,offset ClassNameBuf
  1319.          pop   eax            ;handle back
  1320.          $WinDebugMessage   ClassNameBuf
  1321.     .ENDW
  1322.     $Call WinEndEnumWindows,henum
  1323.     .IF eax == 0
  1324.         $WinInfMsg  "  WinEndEnumWindows"
  1325.     .ENDIF
  1326. xptc: popa
  1327.     ret
  1328. ProgramTestCtrl  Endp
  1329.  
  1330. ;------Write Macro to File  Format is in ASCII HEX in LF/CR separated records
  1331. ;      hwnd msgID mp1 mp2 Time Coord
  1332. ;      Activated by Shift-Ctrl-PgDn(White)
  1333. ;      Format 8 DWords into HEX using $DWordtoHex, copy from DW_Buff to
  1334. ;      fmBuffer, space separating each Dword then write out to file
  1335. ;      The handle at offset 8 in switch structure is handle of parent
  1336. ;      frame of window identified by hwnd in quemsg structure
  1337. WriteMacroAsciiHex   Proc      ;Write Macro to File
  1338.     pusha
  1339.     ;--- first set file size to correspond to number of messages
  1340.     ;fsize = #records x 84 + header
  1341.     mov   eax,JR_Count
  1342.     mov   ecx,84
  1343.     mul   ecx
  1344.     add   eax,84            ;header size
  1345.     mov   fmsize,eax
  1346.     $Call DosOpen,offset fmName,offset fmhandle,offset fmActionTaken,fmsize,fmAttribute,fmOpenFlag,fmOpenMode,fmExtaBuf
  1347.     .IF   eax != 0
  1348.          $WinInfMsg " : DosOpenMacroFile "
  1349.          ret
  1350.     .ENDIF
  1351.     ;----- first write header line
  1352.     $Call DosWrite,fmhandle,offset fmHeader,84,offset fmWritten
  1353.     ;----- then actual data records
  1354.     mov    ebx,msgParms           ;Address of Source
  1355.     mov    edx,JR_Count
  1356.     .WHILE edx > 0
  1357.         mov   ecx,1
  1358.         mov   esi,offset fmBuffer
  1359.         .WHILE ecx <= 7
  1360.             mov  eax,[ebx]
  1361.             .IF  ecx == 1     ;handle from msgparms
  1362.                 mov   HandFromMsg,eax   ;value to be passed
  1363.                 pusha
  1364.                 Call GetNameFromHandle   ;value of handle passed in HandFromMsg
  1365.                 mov  edi,TaskNameAddr    ;address of TaskListName returned
  1366.                 mov  edx,1
  1367.                 add  esi,70
  1368.                 .WHILE  edx <= 12        ;copy to fmBuffer
  1369.                     mov   al,byte ptr[edi]
  1370.                     .IF   al == 13 || al == 10  ;CR or LF
  1371.                         .BREAK
  1372.                     .ENDIF
  1373.                     mov   [esi],al
  1374.                     inc   edx
  1375.                     inc   esi
  1376.                     inc   edi
  1377.                 .ENDW
  1378.                 .IF edx != 13             ;need to fill out with spaces
  1379.                     dec   edx
  1380.                     dec   esi
  1381.                    .WHILE  edx <= 12
  1382.                        mov  byte ptr [esi]," "
  1383.                        inc  esi
  1384.                        inc  edx
  1385.                    .ENDW
  1386.                 .ENDIF
  1387.                 popa
  1388.             .ENDIF
  1389.              mov    eax,[ebx]
  1390.              Call   DwordToHex
  1391.              inc    ecx
  1392.              add    ebx,4                 ;get next parm
  1393.              add    esi,10
  1394.         .ENDW
  1395.         dec   edx
  1396.  
  1397.         $Call DosWrite,fmhandle,offset fmBuffer,84,offset fmWritten
  1398.         .IF   eax != 0
  1399.              $WinInfMsg " : DosWrite "
  1400.              ret
  1401.         .ENDIF
  1402.     .ENDW
  1403.     $Call DosSetFileSize,fmHandle,fmSize
  1404.     $Call DosClose,fmHandle
  1405.     .IF   eax != 0
  1406.          $WinInfMsg " : DosCloseMacroFile "
  1407.          ret
  1408.     .ENDIF
  1409.     popa
  1410.     ret
  1411. WriteMacroAsciiHex   Endp
  1412.  
  1413. ;---- Inserts a TimeDelay of milliseconds  in edx register
  1414. ;---- probably is resolution of timer
  1415. TimeDelay  Proc
  1416.     pusha
  1417.     $Call WinGetCurrentTime,hab
  1418.     mov   CurrentTime,eax
  1419.     add   CurrentTime,edx
  1420.     .WHILE eax < CurrentTime
  1421.         $Call WinGetCurrentTime,hab
  1422.     .ENDW
  1423.     popa
  1424.     ret
  1425. TimeDelay Endp
  1426.  
  1427. ReadDatFile   Proc
  1428. ;----------  IS Data File AVAILABLE AND VALID ? ------------
  1429. ;---------- First see if  hookkbsm.dat exists in proper location ------
  1430.      mov   EOFFlag,0       ;initial value
  1431.      $Call DosOpen,offset fName,offset fhandle,offset fActionTaken,fsize,fAttribute,fOpenFlag,fOpenMode,fExtaBuf
  1432.      .IF   eax != 0
  1433.           $WinErrMsg " : DosOpen "
  1434.           Call   ExitWin
  1435.      .ENDIF
  1436. ;------- get file size
  1437.      $Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
  1438.      .IF    eax != 0
  1439.           $WinErrMsg " : DosSetFilePtr"
  1440.           Call   ExitWin
  1441.      .ENDIF
  1442.      $Call DosSetFilePtr,fhandle,0,FILE_END,offset fpointer1
  1443.      mov    eax,fpointer1
  1444.      sub    eax,fpointer0
  1445.      mov    fsize,eax        ;fsize now has file size
  1446.      add    eax,16           ;allow a little leeway in buffer
  1447.      push   eax
  1448. ;;------- now allocate memory for file buffers
  1449.      .IF memAddr != 0      ;not first time around
  1450.           $Call DosFreeMem,memAddr
  1451.           .IF eax != 0
  1452.               $WinErrMsg " : DosFreeRegularMem"
  1453.           .ENDIF
  1454.      .ENDIF
  1455.      pop    eax            ;get back size needed
  1456.      $Call DosAllocMem,offset memAddr,eax,memFlags
  1457.      .IF    eax != 0
  1458.           $WinErrMsg " : DosAllocMem FileBuf"
  1459.           Call   ExitWin
  1460.      .ENDIF
  1461. ;------Read File Into buffer and Close file -------
  1462. ;reposition to start of file
  1463.      $Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
  1464.      $Call DosRead,fHandle,memAddr,fsize,offset nwritten
  1465.      $Call DosClose,fHandle
  1466.      mov   eax,fsize
  1467. ;------ Reset SessT of ExecONKB arrays to 9
  1468.      mov   edi,offset AltX
  1469.      mov   esi,offset CtrlX
  1470.      mov   ecx,1
  1471.      mov   ebx,10
  1472.      .WHILE  ecx <= 36
  1473.           mov  word ptr[edi+ebx],9
  1474.           mov  word ptr[esi+ebx],9
  1475.           inc  ecx
  1476.           add  ebx,10
  1477.      .ENDW
  1478. ;------ Read Buffer and Initialize Arrays ALtX and CtrlX ----
  1479.      mov    esi,memAddr
  1480.      mov    ecx,0               ;Index and Counter for memAddr
  1481.      .WHILE ecx <=  fsize && byte ptr [esi+ecx] != 26   ;Ctrl-Z  Fri  04-30-1993
  1482.          call   SkipSpaces        ;skip over any initial spaces
  1483.          .BREAK .IF EOFflag == 1
  1484.          call   SkipCommentsToEOL ;skip over comments and spaces to first valid entry
  1485.          .BREAK .IF EOFflag == 1
  1486.          call SkipSpaces          ;skip over initial spaces
  1487.          .BREAK .IF EOFflag == 1
  1488.          .IF (byte ptr [esi+ecx] == 'A' || byte ptr [esi+ecx] == 'a' || byte ptr [esi+ecx] == 'C' || byte ptr [esi+ecx] == 'c')
  1489.               inc   ecx           ;point to number or letter
  1490.               xor   eax,eax
  1491.               xor   edx,edx
  1492.               mov  al,byte ptr [esi+ecx]  ;get digit or letter ID
  1493.              .IF  (al >= '0' && al <= '9')
  1494.                   sub  al,'0'         ;convert to decimal
  1495.              .ENDIF
  1496.              .IF  al  >= 'a'
  1497.                   sub  al,32          ;convert to UpperCase
  1498.              .ENDIF
  1499.              .IF  (al >= 'A' && al <= 'Z')
  1500.                   sub  al,37h          ;convert to decimal 10 +
  1501.              .ENDIF
  1502.               mov      dl,LenExec ;Length of Structure    10
  1503.               mul      dl         ;ax has offset into array
  1504.               inc      ecx        ;right after digit/letter id A/C number
  1505.          .ELSE
  1506.               .CONTINUE           ;go around again
  1507.          .ENDIF
  1508.          .IF byte ptr[esi+ecx - 2] == 'A' || byte ptr[esi+ecx - 2] == 'a'
  1509.                mov     edi,offset AltX      ;this is Alt Keys
  1510.          .ENDIF
  1511.          .IF byte ptr[esi+ecx - 2] == 'C' || byte ptr[esi+ecx - 2] ==  'c'
  1512.                mov     edi,offset CtrlX     ;this is a Ctrl Key
  1513.          .ENDIF
  1514.          .IF edi == offset AltX || edi == offset CtrlX
  1515.                mov     edx,eax              ;edx is offset into array
  1516.                call    SkipSpaces           ;go to SessID
  1517.                .BREAK .IF EOFflag == 1
  1518.                xor     eax,eax
  1519.                mov     al,byte ptr [esi+ecx] ;get sess type
  1520.                sub     al,'0'                ;convert to  number
  1521.                mov     word ptr [edi + edx+8],ax
  1522.                inc     ecx
  1523.                call    SkipSpaces            ;get to Exec string
  1524.                .BREAK .IF EOFflag == 1
  1525.                mov     eax,esi
  1526.                add     eax,ecx               ;offset of exec
  1527.                mov     [edi+edx],eax         ;store its address
  1528.                ; have to go to end of Exec string and place a numeric 0 there
  1529.                .WHILE  byte ptr [esi+ecx] != ' '
  1530.                     inc  ecx
  1531.                .ENDW   ;exits    pointing to end of exec command
  1532.                .BREAK .IF byte ptr[esi+ecx] != ' '
  1533.                   mov     byte ptr [esi+ecx],0
  1534.                inc     ecx
  1535.                call    SkipSpaces            ;get next parameter
  1536.                .BREAK .IF EOFflag == 1
  1537.                xor     eax,eax
  1538.                .IF     byte ptr [esi+ecx]== '0'  ;no command line
  1539.                    mov     al,byte ptr [esi+ecx]
  1540.                    sub     al,'0'
  1541.                    mov     [edi+edx+4],eax
  1542.                .ELSE                         ;its a string - copy its address
  1543.                    mov eax,esi
  1544.                    add eax,ecx               ;offset of command line
  1545.                    .IF   byte ptr [esi+ecx] != 22h  ;not a "
  1546.                       mov     [edi+edx+4],eax   ;store command line address
  1547.                       .WHILE  byte ptr [esi+ecx] != ' ' && ecx < fsize  ;skip until a space
  1548.                           .IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr  ; LF but no ";"
  1549.                                Call DataFormatErr
  1550.                           .ENDIF
  1551.                            inc  ecx
  1552.                       .ENDW                  ;exits  pointing to end of command line
  1553.                      .BREAK .IF ecx >= fsize
  1554.                       mov    byte ptr [esi+ecx],0 ;put 0 at end
  1555.                    .ELSE                     ;first char is a quote
  1556.                       inc  ecx               ;move beyond it
  1557.                       inc  eax
  1558.                       mov     [edi+edx+4],eax   ;store command line address
  1559.                       .WHILE byte ptr [esi+ecx] != 22h && ecx < fsize ; skip until a "
  1560.                            inc  ecx
  1561.                       .ENDW                  ;exits pointing to final quote
  1562.                       mov    byte ptr [esi+ecx],0 ;put 0 at end
  1563.                       .BREAK .IF ecx >= fsize
  1564.                       inc    ecx
  1565.                       .BREAK .IF byte ptr[esi+ecx] != ' '
  1566.                    .ENDIF
  1567.                .ENDIF
  1568.                .BREAK .IF ecx >= fsize || byte ptr[esi+ecx] == 26 ;Ctrl-Z
  1569.                xor    edi,edi                ;reset to 0 so test can be made
  1570.                .WHILE byte ptr[esi+ecx] != ';' && ecx < fsize  ;go to next comment ;
  1571.                    .IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr  ; LF but no ";"
  1572.                         Call DataFormatErr
  1573.                    .ENDIF
  1574.                    inc   ecx
  1575.                .ENDW
  1576.                .BREAK .IF ecx >= fsize || byte ptr[esi+ecx] == 26 ;Ctrl-Z
  1577.                .CONTINUE
  1578.          .ENDIF
  1579.      .ENDW
  1580. ; See if Dat File properly read in
  1581.      .IF byte ptr [esi+ecx] == 26   ;Ctrl-Z
  1582. ;         $WinErrMsg " : Ctrl-Z here"
  1583.      .ELSEIF ecx < fsize
  1584.           Call DataFormatErr
  1585.      .ENDIF
  1586.      ret
  1587. ReadDatFile   Endp
  1588.  
  1589. ;if there are spaces this exits pointing to next non-space else points to non-space
  1590. SkipSpaces   proc    ;just skips over spaces
  1591.    .WHILE ecx < fsize && byte ptr [esi+ecx] == ' '   ;spaces
  1592.         inc ecx
  1593.    .ENDW
  1594.    .IF ecx >= fsize || byte ptr [esi+ecx] == 26  ; Ctrl-Z  Sat  05-01-1993
  1595.         mov EOFflag,1
  1596.    .ENDIF
  1597.     ret
  1598. SkipSpaces   endp
  1599.  
  1600. SkipCommentsToEOL proc    ;skip from ';' to beginning of next line
  1601.     .IF byte ptr[esi+ecx] == ';' && ecx < fsize  ;if a comment
  1602.         inc    ecx
  1603.         .WHILE byte ptr [esi+ecx] != 0ah && ecx < fsize  ;Line feed end of line
  1604.             inc ecx
  1605.         .ENDW                       ;points to 0ah if it exists if not EOF
  1606.         .IF byte ptr[esi+ecx] == 26 ; Ctrl-Z
  1607.             mov EOFflag,1
  1608.         .ENDIF
  1609.     .ELSE
  1610.         mov    eax,ecx              ;bytes processed appears in message
  1611.         call DataFormatErr
  1612.     .ENDIF
  1613.     .IF  byte ptr[esi+ecx] != 0ah   ;must be EOF
  1614.          mov    EOFflag,1
  1615.     .ELSE                           ;it is end of line
  1616.          inc    ecx                 ;goto next line
  1617.          .IF    ecx >= fsize || byte ptr[esi+ecx] == 26  ; Ctrl-Z
  1618.              mov    EOFflag,1
  1619.          .ENDIF
  1620.     .ENDIF
  1621.     ret
  1622. SkipCommentsToEOL endp
  1623.  
  1624. DataFormatErr   Proc
  1625.     mov     eax,ecx            ;bytes processed appears in message
  1626.     mov     ecx,fsize
  1627.     sub     ecx,eax
  1628.     .IF     ecx >= 4           ;Sat  05-01-1993
  1629.         $WinDebugMessage msgFileErr
  1630.         call ExitWin           ;Fri  04-30-1993
  1631.     .ENDIF
  1632.     ret
  1633. DataFormatErr   EndP
  1634.  
  1635. END   startup                       ;required
  1636.  
  1637.  
  1638. ;---- This procedure places the window handle of the true Client Window
  1639. ;---- in the variable hwndActive. It obtains the handle of the Frame
  1640. ;---- Window that is on TOP and uses WinEnumWindows and WinQueryClass
  1641. ;---- to obtain the handle of the Client window which is the window
  1642. ;---- with Class not starting with "#"
  1643. ;GetClientWinHandle  Proc
  1644. ;    push  ebx
  1645. ;    $Call WinQueryActiveWindow,HWND_DESKTOP
  1646. ;    $WinInfMsg  "      is Active Frame"
  1647. ;    mov   hwndActiveFrame,Eax
  1648. ;    $Call WinBeginEnumWindows,hwndActiveFrame
  1649. ;    .IF  eax == PMERR_INVALID_HWND
  1650. ;         $WinInfMsg   "  Error Calling WinBeginEnumWindows"
  1651. ;         ret
  1652. ;    .ENDIF
  1653. ;    mov   henum,eax           ;enum handle
  1654. ;    mov   eax,hwndActiveFrame ;top window
  1655. ;    $Call WinEndEnumWindows,henum
  1656. ;
  1657. ;    $Call WinBeginEnumWindows,hwndActiveFrame
  1658. ;    mov   henum,eax           ;enum handle
  1659. ;    mov   ecx,0
  1660. ;    .WHILE TRUE
  1661. ;         $Call WinGetNextWindow,henum
  1662. ;         .IF eax == 0  && ecx == 0   ; no more
  1663. ;               mov  eax,hwndActiveFrame
  1664. ;               $WinInfMsg  "  Has no children"
  1665. ;               .Break
  1666. ;         .Endif
  1667. ;         push  eax
  1668. ;         $Call WinQueryClassName,eax,20,offset ClassNameBuf
  1669. ;         pop   eax            ;handle back
  1670. ;         mov   ebx,offset ClassNameBuf
  1671. ;         .IF   byte ptr [ebx] != "#"   ;this is the Client window
  1672. ;               mov   WinFlag,1
  1673. ;               mov   hwndActive,eax    ;handle of Client window
  1674. ;               $WinDebugMessage   ClassNameBuf
  1675. ;               .BREAK                  ;exit
  1676. ;         .ENDIF
  1677. ;    .ENDW
  1678. ;    .IF  WinFlag !=1
  1679. ;         $WinInfMsg   "No Match to !=# "
  1680. ;    .ENDIF
  1681. ;    $Call WinEndEnumWindows,henum
  1682. ;    pop   ebx
  1683. ;    ret
  1684. ;GetClientWinHandle  Endp
  1685.  
  1686. ;FillPlaybackDispatchMsg  Proc
  1687. ;    mov   ebx,0
  1688. ;    mov   esi,m_esi
  1689. ;;    mov   edi,offset pb_qmsg
  1690. ;    .WHILE  ebx <= 20
  1691. ;        mov   eax,[esi]       ;0:hwnd 4:msgID 8:mp1 12:mp2 16:time 20:coordinates
  1692. ;        mov   [edi+ebx],eax   ;edi always points to offset of pb_qmsg
  1693. ;        add   ebx,4
  1694. ;        add   esi,4           ;this leaves esi pointing to next record in block
  1695. ;    .ENDW
  1696. ;    add   m_esi,RecdLnth
  1697. ;    $Call WinDispatchMsg,hab,edi  ;offset pb_qmsg
  1698. ;    ret
  1699. ;FillPlaybackDispatchMsg  Endp
  1700.  
  1701. ;---- Determines whether the windowed program is Text or a PM Program.
  1702. ;---- If the Window Class is SHIELD it is text, otherwise it is PM
  1703. ;---- Called Only on KeyDown parameter
  1704. ;WindowType    Proc
  1705. ;    pusha
  1706. ;    mov   WinTypeFlag,0       ;0 is SHIELD type Window Class
  1707. ;    $Call WinQueryPointerPos,HWND_DESKTOP,offset WinPosX
  1708. ;    ;--- IF FALSE is chosen returns Handle of Frame Window under HWND_DESKTOP
  1709. ;    ;--- IF  TRUE is chosen returns Handle of Actual Window
  1710. ;    $Call WinWindowFromPoint,HWND_DESKTOP,offset WinPosX,TRUE
  1711. ;    mov   hwndNext0,eax
  1712. ;    $Call WinQueryClassName,hwndNext0,7,offset ClassNameBuf
  1713. ;    mov   esi,offset ClassNameBuf
  1714. ;    cmp   byte ptr [esi],'S'
  1715. ;    jne   NotPM
  1716. ;    cmp   byte ptr [esi+1],'H'
  1717. ;    jne   NotPM
  1718. ;    cmp   byte ptr [esi+2],'I'
  1719. ;    jne   NotPM
  1720. ;    cmp   byte ptr [esi+3],'E'
  1721. ;    jne   NotPM
  1722. ;    cmp   byte ptr [esi+4],'L'
  1723. ;    jne   NotPM
  1724. ;    cmp   byte ptr [esi+5],'D'
  1725. ;    jne   NotPM
  1726. ;    mov   WinTypeFlag,1
  1727. ;NotPM: popa
  1728. ;    ret
  1729. ;WindowType    Endp
  1730.  
  1731.  
  1732.