home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
MKHKB2.ZIP
/
HOOK_KBS.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-10-27
|
33KB
|
791 lines
;---------------------------------------------------------------------------;
; M.F.Kaplon Begun:Fri 06-12-1992 Revised:Tue 10-27-1992
; Title : hook_kbs.asm
;
; "Copyright 1992 M.F. Kaplon"
;
; Tue 10-27-1992 Revision Adds ShutDown Procedure via Shift-Alt-End(White)
;
; INITIALIZES,CREATES MESSAGE QUEUE, REGISTERS CLASS,CREATES STANDARD WINDOW
; ESTABLISHES MAIN MESSAGE LOOP, ESTABLISHES MAIN WINDOW PROCEDURE, Reads in
; C:\os2\hook_kbs.dat , Establishes Hook HK_INPUT, Reeived Filtered Messages
; from hook_dls , mp1 = Alt/Ctrl flag, mp2 = scan code and
; takes appropriate action. Uses WM_USER+300h to receive message.
;
; For System Function Calls
;
; 1 - Must use the C Calling Convention which means
; Arguments Pushed on Stack in Reverse Order than declared in function
; And the stack pointer reset after call.
; This is done by the MACRO $Call defined in DOSWIN32.MAC
; 2 - Use .MODEL FLAT. When using a pointer, all you have to do is push
; the offset of the variable since in FLAT model everyting is NEAR
; in the 32 bit space
; 3 - Uses an 8K stack
;
; It is assumed that the Developers toolkit for OS/2 2.0 is installed
; on the users C:drive in the default installation
;
; The files needed to create the functioning program are:
; doswin32.mac Macros and Equates used by Program
; hook_kbs.asm Source for Executable Assembled and Linked by mlc-w386.cmd
; hook_dls.def Define file needed by IMPLIB and LINK386 for DLL
; hook_dls.asm Source for DLL = Assembled and linked by dll-w386.cmd
; hook_kbs.dat Text File assigning programs to key strokes -read by hook_kb
; The user creates this file according to structure outlined in
; sample and it MUST BE LOCATED IN C:\OS2\DLL
; dll-w386.cmd Command File to create the hook_dls.dll and copy to c:\os2\dll
; mlc-w386.cmd Command File to Assemble and Link hook_kbs.asm
;
; Except as noted, all files should be in the same directory.
; To assemble and link use the directory holding the above files as default
; and use the commands
; dll-w386 hook_dls;creates hook_dls.dll from hook_dls.asm,moves to c:\os2\dll
; mlc-w386 hook_kb ;creates hook_kbs.exe from hook_kbs.asm
;
; kb_hooks.exe is placed in the directory holding the above files
;
; There is one warning message
;
; LINK : warning L4036: no automatic data segment
;
; This message has to do with no DGROUP being defined
; It can be suppressed with DATA NONE in a "DEF" file
;
; A command processor is called into a 2-line window centered in the screen
; by the keystroke combination Shit-Alt-Ins(white)
; The default command processor is c:\os2\cmd.exe
; To load a different one to be called in the window pass its entire
; file specification on the command line when hook_kbs is called as
;
; hook_kbs c:\4os2\4os2.exe
;
; The example uses the 4OS2 command processor
;---------------------------------------------------------------------------;
;USES HOOK HK_INPUT
;----------------- PRELIMINARIES ----------------
.386 ;preceeding .MODEL makes USE32 default
.MODEL FLAT,SYSCALL,OS_OS2
;---------- Conditionally required equates -------------
NUMBUFS equ 1 ; Uncomment if need number routines
DOSERROR equ 1 ; Uncomment if need DosError Messages
INCL_WINERRORS equ 1
INCL_WIN equ 1
INCL_DOSMEMMGR equ 1
INCL_DOSFILEMGR equ 1
INCL_WINSWITCHLIST equ 1
INCLUDE doswin32.mac ;macros used by *.asm
INCLUDE c:\toolkt20\asm\os2inc\os2def.inc ;structure defns includes POINTL
INCLUDE c:\toolkt20\asm\os2inc\pmwin.inc ;structure defns POINTL defn required
INCLUDE c:\toolkt20\asm\os2inc\pmerr.inc ;errors
INCLUDE c:\toolkt20\asm\os2inc\pmshl.inc
INCLUDE c:\toolkt20\asm\os2inc\bsememf.inc;memory
INCLUDE c:\toolkt20\asm\os2inc\bsedos.inc ;files
INCLUDELIB c:\toolkt20\os2lib\os2386.lib ;Library
;---------- Prototype Definitions for MASM 6.0 -------------
InitMainWindow Proto Near SYSCALL var1:DWORD,var2:DWORD,var3:DWORD
MainPaint Proto Near SYSCALL var1:DWORD
MainKeyBoard Proto Near SYSCALL var1:DWORD,var2:DWORD,var3:DWORD
ExecOnKB STRUCT ;Structure used in program-stores data from hook_kb.dat
Exec DWORD ? ;Address of ASCIIZ str - name of exec program
CmdLn DWORD ? ;Address of ASCIIZ str - command line parms
SessT WORD ? ;Session Type
ExecOnKB ENDS ;structure length now = 22
LenExec equ 10 ;length of ExecOn Kb
.STACK 8096 ;8K stack
.DATA
IFDEF NUMBUFS ;To use UNCOMMENT NUMBUFS equate above
$DefineNumBufs
ENDIF
IFDEF DOSERROR
$DOSErrorMessages
ENDIF
; Copyright Notice
notice BYTE "Copyright 1992 M.F. Kaplon"
;------------- handles --------
hab DWORD ? ;Anchor block Handle
hmq DWORD ? ;Message Queue Handle
hwndMainFrame DWORD ? ;Handle to Main Frame Window
hwndMain DWORD ? ;Handle to Client window
;------------- Text Strings --------
szAppName BYTE "Main0",0 ;Class Name of Window Procedure
szWinTitle BYTE "** TSR **",0 ;Window Title
szDebugMsg BYTE " SwitchHandle",0
;------------- Text Strings for WinMessageBox calls for Errors --------
msgModuleLoaded BYTE "hook_KBS Already Loaded",0
msgInfo BYTE "Debug Info",0
msgFileErr BYTE "Incorrect hook_kbs.dat File",0
;------------- Styles --------
msgBoxStyle DWORD (MB_YESNO OR MB_DEFBUTTON1)
flStyle DWORD (CS_SIZEREDRAW OR CS_HITTEST) ;Window Style
flCtlData DWORD FCF_SYSMENU ;Invisible Window
;------------- structures --------
quemsg QMSG {,,,,,,} ;Queue message structure
AltX ExecOnKB 37 dup({0,0,9}) ;Array for Alt-# 0-9,A-Z,A-Ins default Initialization
CtrlX ExecOnKB 36 dup({0,0,9}) ;Array for Ctrl-# 0-9,A-Z default Initialization
;------------- Miscellaneous --------
parm1 DWORD ? ;handle of window sending message
parm2 DWORD ? ;message id value
parm3 DWORD ? ;message mp1
parm4 DWORD ? ;message mp2
parm5 DWORD ? ;message time
Concanted BYTE 64 dup(0) ;buffer to hold concanted strings
Alt_Ctrl DWORD ? ;0/1 if Alt/Ctrl key struck
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 ;
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 ;
lookup2 BYTE 'Z'-37h,'X'-37h,'C'-37h,'V'-37h,'B'-37h,'N'-37h,'M'-37h ;35,33,12,31,11,23,22 ;
ExitMsg BYTE " !! <Esc> Aborts Close Down !!",0
ExitTitle BYTE "Close OS/2 ??",0
;------------ Specific to TSR Hook use -----
DllLoadError BYTE 100 dup(0) ;Buffer for name of object contributing to error
DllHandle DWORD ? ;Handle of Dynamic LInk Module returned here
DllFullModName BYTE "c:\os2\dll\hook_dls.dll",0
DllProcAddr1 DWORD ? ;address of proc 1 in dynamic link module
;- StartSession structure Offset ------------ Identification --------------
StartData WORD 32 ; 0 Length of Structure for all but Shift-Alt-W
WORD 0 ; 2 Related 0 is independent, 1 is child
WORD 0 ; 4 0/1 Start in Foreground/Background
WORD 0 ; 6 Trace Option 0 is no trace
DWORD 0 ; 8 ProgramTitle 0 uses Program Name
DWORD ? ;12 Address of ASCZII string with fully qualified program name
DWORD 0 ;16 Address of Input Args to Pgm - 0 is none
DWORD 0 ;20 TermQ 0 is no Queue
DWORD 0 ;24 Environment - must be 0 for DOS
WORD 0 ;28 InheritOp 0 Inherits Shell Environment
WORD ? ;30 SessType see p.2-345 of Control Prog Ref.
DWORD ? ;32 ICON File
DWORD ? ;36 PgmHandle
WORD 8000h ;40 PgmControl-use specified size for Shift-Alt-Ins
WORD 140 ;42 InitXPos for Shift-Alt-Ins
WORD 200 ;44 InitYPos for Shift-Alt-Ins
WORD 350 ;46 InitXSize for Shift-Alt-Ins
WORD 60 ;48 InitYSize for Shift-Alt-Ins
SessID DWORD 0 ;receives Session ID for Alt-1
ProcID DWORD 0 ;receives ProcessID for Alt-1
TitleAlt BYTE "Alt- ",0 ;space filled in with 3 or letter
TitleCtl BYTE "Ctl- ",0 ;space filled in with 3 or letter
HotKeyID BYTE ? ;Identifies HotKey Selected
InsProg BYTE "c:\os2\cmd.exe",0,0,0,0,0,0,0,0,0,0 ; default assigned to Shift-Alt-Ins
DosEnvValue BYTE "DPMI_DOS_API=ENABLED",0
;----Shared Memory Variables---
SharedMem DWORD ? ;base address returned
SharedMemName BYTE "\SHAREMEM\DATAS.DAT",0
SharedMemFlags DWORD 12h ;(PAG_COMMIT OR PAG_WRITE)
;-------------- parameters for memory usage and file opening
memAddr DWORD ? ;address of memory block
memFlags DWORD 13h ;(PAG_COMMIT OR (PAG_WRITE OR PAG_READ)) ;read-write access required
fName BYTE "c:\os2\hook_kbs.dat",0 ;Address of data file
fhandle DWORD ? ;Address of Handle for File
fActionTaken DWORD ? ;Address for action taken
fSize DWORD ? ;Logical size of file
fAttribute DWORD 0
fOpenFlag DWORD OPEN_ACTION_OPEN_IF_EXISTS
fOpenMode DWORD OPEN_SHARE_DENYNONE OR OPEN_ACCESS_READWRITE
fExtaBuf DWORD 0 ;no extended attributes
fpointer0 DWORD ? ;file pointer start file
fpointer1 DWORD ? ;file pointer end file
EOFflag DWORD 0 ;EndOfFile flag
;------------ switch list parameters -------------
numitems DWORD ? ;#items in list
baseaddr DWORD ? ;of SWBLOCK {,}
.CODE
startup: ;need to do this way with flat model
;---------- GET COMMANDLINE PARMS -------
$GetCmdLine ;macro esi has offset of command line
.WHILE byte ptr [esi] != 0 ;go past program name
inc esi
.ENDW
inc esi ;now points to 1st space after command name
mov eax,0
.WHILE byte ptr [esi] != 0 ;go to end of command line
.WHILE byte ptr [esi] == ' '
inc esi
.ENDW
.IF byte ptr [esi] != ' ' && byte ptr [esi] != 0; if not a space
mov edi,offset InsProg ;destination
.WHILE byte ptr [esi] != ' ' && byte ptr [esi] != 0
mov al,byte ptr[esi]
mov [edi],al
inc esi
inc edi
inc eax
.ENDW
mov al,0
mov [edi],al ;terminating NULL
.ENDIF
.ENDW ;if eax non 0 has cmd line parm length
;---------- ESTABLISH WINDOW ------------
;-----Initialize Window -Anchor block handle returned = hab
$Call WinInitialize,0 ;called with argument 0
mov hab,eax ;return value
.IF hab == NULL
$Call WinTerminate,hab
$DosExit
.ENDIF
;-----Create MessageQue QueueHandle returned = hmq
$Call WinCreateMsgQueue,hab,0 ; 0 is default size of queue
mov hmq,eax ;returned queue handle
.IF hmq == NULL
$WinErrMsg " : WinCreateMsgQueue"
$DosExit
.ENDIF
;---- Register Window Class Returned value is TRUE or FALSE
$Call WinRegisterClass,hab,offset szAppName,offset MainWinProc,flStyle,0
.IF eax == FALSE
$WinErrMsg " : WinRegisterClass"
$Call WinTerminate,hab
$DosExit
.ENDIF
;---- CreateStandard Window - Returns handle for Main Window Frame and client Window
$Call WinCreateStdWindow,HWND_DESKTOP,WS_VISIBLE,offset flCtlData,offset szAppName,\
offset szWinTitle,WS_VISIBLE,0,0,offset hwndMain
mov hwndMainFrame,eax ;returned Frame Window handle
.IF hwndMainFrame == 0
$WinErrMsg " : WinCreateStdWindow"
Call ExitWin
.ENDIF
;------------ IS hook_DLL.DLL LOADED ? -------------------
$Call DosQueryModuleHandle,offset DllFullModName,offset DllHandle
.IF eax == 0 ;module already loaded
$Call WinMessageBox,HWND_DESKTOP,HWND_DESKTOP,offset msgModuleLoaded,NULL,0,msgBoxErrStyle
Call ExitWin
.ENDIF
;----- ALLOCATE SHARED MEM AND PLACE HANDLE THERE ----
$Call DosAllocSharedMem,offset SharedMem,offset SharedMemName,32,SharedMemFlags
.IF eax > 0
$WinErrMsg " : DosAllocSharedMem"
Call ExitWin
.ENDIF
mov esi,SharedMem
mov eax,hwndMainFrame
mov [esi],eax ;put window handle there
;---------- IS Data File AVAILABLE AND VALID ? ------------
;---------- First see if hook_kb.dat exists in proper location ------
$Call DosOpen,offset fName,offset fhandle,offset fActionTaken,fsize,fAttribute,fOpenFlag,fOpenMode,fExtaBuf
.IF eax != 0
$WinErrMsg " : DosOpen "
Call ExitWin
.ENDIF
;------- get file size
$Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
.IF eax != 0
$WinErrMsg " : DosSetFilePtr"
Call ExitWin
.ENDIF
$Call DosSetFilePtr,fhandle,0,FILE_END,offset fpointer1
mov eax,fpointer1
sub eax,fpointer0
mov fsize,eax ;fsize now has file size
add eax,16 ;allow a little leeway in buffer
;------- now allocate memory for file buffer
$Call DosAllocMem,offset memAddr,eax,memFlags
.IF eax != 0
$WinErrMsg " : DosAllocMem FileBuf"
Call ExitWin
.ENDIF
;------Read File Into buffer and Close file -------
;reposition to start of file
$Call DosSetFilePtr,fhandle,0,FILE_BEGIN,offset fpointer0
$Call DosRead,fHandle,memAddr,fsize,offset nwritten
$Call DosClose,fHandle
;------ Read Buffer and Initialize Arrays ALtX and CtrlX ----
mov esi,memAddr
mov ecx,0 ;Index and Counter for memAddr
.WHILE ecx <= fsize
call SkipSpaces ;skip over any initial spaces
.BREAK .IF EOFflag == 1
call SkipCommentsToEOL ;skip over comments and spaces to first valid entry
.BREAK .IF EOFflag == 1
call SkipSpaces ;skip over initial spaces
.BREAK .IF EOFflag == 1
.IF (byte ptr [esi+ecx] == 'A' || byte ptr [esi+ecx] == 'a' || byte ptr [esi+ecx] == 'C' || byte ptr [esi+ecx] == 'c')
inc ecx ;point to number or letter
xor eax,eax
xor edx,edx
mov al,byte ptr [esi+ecx] ;get digit or letter ID
.IF (al >= '0' && al <= '9')
sub al,'0' ;convert to decimal
.ENDIF
.IF al >= 'a'
sub al,32 ;convert to UpperCase
.ENDIF
.IF (al >= 'A' && al <= 'Z')
sub al,37h ;convert to decimal 10 +
.ENDIF
mov dl,LenExec ;Length of Structure 10
mul dl ;ax has offset into array
inc ecx ;right after digit/letter id A/C number
.ELSE
.CONTINUE
.ENDIF
.IF byte ptr[esi+ecx - 2] == 'A' || byte ptr[esi+ecx - 2] == 'a'
mov edi,offset AltX ;this is Alt Keys
.ENDIF
.IF byte ptr[esi+ecx - 2] == 'C' || byte ptr[esi+ecx - 2] == 'c'
mov edi,offset CtrlX ;this is a Ctrl Key
.ENDIF
.IF edi == offset AltX || edi == offset CtrlX
mov edx,eax ;edx is offset into array
call SkipSpaces ;go to SessID
.BREAK .IF EOFflag == 1
xor eax,eax
mov al,byte ptr [esi+ecx] ;get sess type
sub al,'0' ;convert to number
mov word ptr [edi + edx+8],ax
inc ecx
call SkipSpaces ;get to Exec string
.BREAK .IF EOFflag == 1
mov eax,esi
add eax,ecx ;offset of exec
mov [edi+edx],eax ;store its address
; have to go to end of Exec string and place a numeric 0 there
.WHILE byte ptr [esi+ecx] != ' '
inc ecx
.ENDW ;exits pointing to end of exec command
.BREAK .IF byte ptr[esi+ecx] != ' '
mov byte ptr [esi+ecx],0
inc ecx
call SkipSpaces ;get next parameter
.BREAK .IF EOFflag == 1
xor eax,eax
.IF byte ptr [esi+ecx]== '0' ;no command line
mov al,byte ptr [esi+ecx]
sub al,'0'
mov [edi+edx+4],eax
.ELSE ;its a string - copy its address
mov eax,esi
add eax,ecx ;offset of command line
.IF byte ptr [esi+ecx] != 22h ;not a "
mov [edi+edx+4],eax ;store command line address
.WHILE byte ptr [esi+ecx] != ' ' && ecx < fsize ;skip until a space
.IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr ; LF but no ";"
Call DataFormatErr
.ENDIF
inc ecx
.ENDW ;exits pointing to end of command line
.BREAK .IF ecx >= fsize
mov byte ptr [esi+ecx],0 ;put 0 at end
.ELSE ;first char is a quote
inc ecx ;move beyond it
inc eax
mov [edi+edx+4],eax ;store command line address
.WHILE byte ptr [esi+ecx] != 22h && ecx < fsize ; skip until a "
inc ecx
.ENDW ;exits pointing to final quote
mov byte ptr [esi+ecx],0 ;put 0 at end
.BREAK .IF ecx >= fsize
inc ecx
.BREAK .IF byte ptr[esi+ecx] != ' '
.ENDIF
.ENDIF
.BREAK .IF ecx >= fsize
xor edi,edi ;reset to 0 so test can be made
.WHILE byte ptr[esi+ecx] != ';' && ecx < fsize ;go to next comment ;
.IF byte ptr[esi+ecx] == lf || byte ptr[esi+ecx] == cr ; LF but no ";"
Call DataFormatErr
.ENDIF
inc ecx
.ENDW
.BREAK .IF ecx >= fsize
.CONTINUE
.ENDIF
.ENDW
; See if Dat File properly read in
.IF ecx < fsize
Call DataFormatErr
.ENDIF
;--------- ALLOCATE MEMORY FOR SWITCH LIST STRUCTURE -------
mov ecx,00000002h ;write access flags for Dos alloc
or ecx,00000010h ;page commit
$Call DosAllocMem,offset baseaddr,3000,ecx
.IF eax != 0
$WinErrMsg " : DosAllocMem SwitchList"
Call ExitWin
.ENDIF
;----------- ESTABLISH THE HOOK -------------
;The way to proceed is to install a System Hook. This has to go into a DLL
;otherwise it cannot be called by other programs. The procedure in hook_dls
;will inspect WM_CHAR and if the ShiftKey and one of Alt or Ctrl key is down
;and if there is a valid Scan Code THEN
;it redefine the msg ID of that message as WM_USER+cfffh so it goes nowhere
;and then post a message to this program with the mp1 and mp2 parms
;using WM_USER+300h
$Call DosLoadModule,offset DllLoadError,LENGTHOF DllLoadError,offset DllFullModName,offset DllHandle
.IF eax != 0
$WinErrMsg " DosLoadModule"
.ENDIF
$Call DosQueryProcAddr,DllHandle,1,0,offset DllProcAddr1
.IF eax != 0
$WinErrMsg " DosQueryProcAddr"
.ENDIF
$Call WinSetHook,hab,NULLHANDLE,HK_INPUT,DllProcAddr1,DllHandle
.IF eax == 0
$WinErrMsg " WinSetHook"
.ENDIF
;--------- CREATE MAIN MESSAGE LOOP -----------
mml: $Call WinGetMsg,hab,offset quemsg,0,0,0 ;Note: differs from usual
; .IF eax == TRUE ;msg loop - done so that program
$Call WinDispatchMsg,hab,offset quemsg ;can only be terminated
jmp mml ;by the keystroke Shift-Alt-Del
; .ENDIF ;as notified from the DLL
;Normally an Exit routine would go here, as indicated below but which
;is commented out. It is not required since it can never be reached.
;---------- EXIT ---------------
;$Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
;.IF eax == 0
; $WinErrMsg " : WinReleaseHook"
;.ENDIF
;$Call DosFreeModule,DllHandle
;.IF eax != 0
; $WinErrMsg " : DosFreeModule"
;.ENDIF
;$Call DosFreeMem,memAddr
;$Call WinDestroyWindow,hwndMainFrame
;call ExitWin
;---------------- End of Main Program -------------------
;------------- PROCESS MESSAGE QUEUE FOR hook_KB ------------
;------------------ MainWinProc -----------------
;parm1 = hwnd,parm2 = msg,parm3 = mp1,parm4 = mp2
;this is called from System and so has to do everything itself
MainWinProc Proc Near
;----------- GET PASSED PARAMETERS FROM STACK ------------
push ebp ;return address is 4 bytes and this push is 4 bytes
mov ebp,esp ;so first parameter is 8 bytes from top
mov eax,[ebp+8]
mov parm1,eax ;hwnd
mov eax,[ebp+12]
mov parm2,eax ;msg
mov eax,[ebp+16]
mov parm3,eax ;mp1
mov eax,[ebp+20]
mov parm4,eax ;mp2
mov eax,[ebp+24]
mov parm5,eax ;time of message
;----- RESTORE STACK POINTER AND STACK STATUS ---
mov esp,ebp ;restore stack pointer
pop ebp
;---------------- WM_CREATE ----------------
.IF parm2 == WM_CREATE
Invoke InitMainWindow,parm1,parm3,parm4
.ENDIF
;---------------- WM_PAINT ----------------
.IF parm2 == WM_PAINT ; && parm1 == hwndMain
Invoke MainPaint,parm1
.ENDIF
;---------------- WM_CHAR ----------------
.IF parm2 == WM_CHAR
Invoke MainKeyboard,parm3,parm4,parm1 ;sets return value
.ENDIF
;---------------- WM_USER+0CFFFH ----------------
; .IF parm2 == WM_USER+0CFFFh ;diverted message
; mov eax,TRUE
; .ENDIF ;makes no diff
;---------------- WM_USER+300H ----------------
.IF parm2 == WM_USER+300h ;posted message
;if here know that Shift Key was down and at least one of Alt or Ctrl
;GET SCAN CODE AND ALT/CTRL FLAG
mov edx,parm4 ;scan code
mov eax,parm3 ;Alt/Ctrl Flag = 0/1
mov Alt_Ctrl,eax ;Alt-Ctrl flag
.IF edx == 83 ; Alt-Del (White Del key)
$Call DosFreeMem,memAddr
$Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
$Call DosFreeModule,DllHandle
$Call WinDestroyWindow,hwndMainFrame
Call ExitWin
.ENDIF
;Test for Shift-Alt-End(white) for CloseDown
.IF edx == 79 && Alt_Ctrl == 0 ;Shift-Alt-End(White)
Call CloseDown
.ENDIF
;ELSE TEST FOR ASSIGNED KEYS
;SETUP DATA STRUCTURES FOR ACTIVATING HOT KEY
;---- Code in this group places the offset into the array ExecOnKB into EDX
.IF edx == 82 && Alt_Ctrl == 0 ;Shift-Alt-Ins(White)
mov esi,offset StartData ;data structure for DosStartSession
mov word ptr StartData,50 ;for Alt-Ins
mov HotKeyID,'Ω' ;For Program Title
mov edi,offset TitleAlt
mov cl,HotKeyID
mov byte ptr [edi+4],cl
mov dword ptr[esi+8],offset TitleAlt ;program title
$Call WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
mov eax,offset InsProg ;address of Exec program
mov [esi+12],eax
mov dword ptr[esi+16],0 ;no command line
mov word ptr[esi+30],2 ;Session Type
jmp wmexe
.ELSE
mov word ptr StartData,32
.ENDIF
.IF edx >= 2 && edx <= 11 ;scan code for 1..9,0' || dl >= 'A' && dl <= 'Z'
.IF edx >= 2 && edx <= 10
sub edx,1 ;convert to number 1 - 9
.ELSE
mov edx,0 ; 0 offset for 0
.ENDIF
mov HotKeyID,dl
add HotKeyID,30h ;convert to ASCII
jmp wmok
.ENDIF
xor ecx,ecx
.IF edx >= 16 && edx <= 25; && edx != 17 ; q,w,e,r,t,y,u,i,o,p
mov esi,offset lookup0
sub edx,16
jmp wmoj
.ENDIF
.IF edx >= 30 && edx <= 38 ; a,s,d,f,g,h,j,k,l
mov esi,offset lookup1
sub edx,30
jmp wmoj
.ENDIF
.IF edx >= 43 && edx <= 50 ;z,x,c,v,b,n,m
mov esi,offset lookup2
sub edx,44
jmp wmoj
.ELSE
jmp wm0
.ENDIF
wmoj: mov cl,byte ptr [esi+edx] ;cl has value - cl+37h is UC letter
mov HotKeyID,cl ;identifies letter
add HotKeyID,37h
xor edx,edx
mov dl,cl
wmok: ;- Alt_Ctrl has Alt_Ctrl Flag and dl has offset into array
.IF edx >= 0 && edx <= 35
xor eax,eax
mov al,dl
mov esi,offset StartData ;data structure for DosStartSession
.IF Alt_Ctrl == 0
mov ebx,offset AltX ;Alt Definitions
mov edi,offset TitleAlt
mov cl,HotKeyID
mov byte ptr [edi+4],cl
mov dword ptr[esi+8],offset TitleAlt ;program title
.ENDIF
.IF Alt_Ctrl == 1
mov ebx,offset CtrlX ;Ctrl Definitions
mov edi,offset TitleCtl
mov cl,HotKeyID
mov byte ptr [edi+4],cl
mov dword ptr[esi+8],offset TitleCtl ;program title
.ENDIF
mov cl,LenExec
mul cl ;Structure Length ten
add ebx,eax ;element # of structure
;[ebx+8] != 9 is flag that keystroke is assigned
.IF word ptr [ebx+8] != 9
$Call WinSetFocus,HWND_DESKTOP,hwndMainFrame ;required for program started to be in foreground
mov eax,[ebx] ;address of Exec program
mov [esi+12],eax
mov eax,[ebx+4] ;address of command line
mov [esi+16],eax
mov ax,word ptr [ebx+8] ;Session type
mov [esi+30],ax
.IF ax == 4 || ax == 7 ;set environment string DPMI_DOS_API for Borland IDE
mov dword ptr[esi+24],offset DosEnvValue
.ELSE
mov dword ptr[esi+24],0 ;default value reset
.ENDIF
;GO THRU SWITCH LIST TO SEE IF HOT KEY ACTIVE
;-- called before DosStartSession to see if program loaded
;-- esi=offset into StartData
;-- go thru Switch List to see if loaded and if so switch to
;-- The test made on 4th char of TitleAlt/TitleCtl which
;-- is the title in the window and Task List
wmexe: pusha
$NumSwitchListEntries
mov numitems,eax ;number of switch list entries
dec numitems
Call GetSwitchList ;activate structure
mov edi,baseaddr ;address of switch list
mov ecx,0
.IF Alt_Ctrl == 0
mov bl,'A'
.ELSE
mov bl,'C'
.ENDIF
.WHILE ecx < numitems ;starts at offset 0
mov al,byte ptr[edi+40] ;5-th char TaskList title
mov dl,byte ptr[edi+36] ;1stChar of Title A/C
;IF ACTIVE SWITCH TO
.IF al == HotKeyID && bl == dl
;Now Switch to that window - get switch handle
mov eax,[edi+4]
$Call WinSwitchToProgram,eax
popa
jmp wm0 ;do not reload
.ENDIF
inc ecx
add edi,swblksize ;next element in structure
.ENDW
popa
;ELSE ACTIVATE HOT KEY PROGRAM
$Call DosStartSession,esi,offset SessID,offset ProcID
.ENDIF
.ENDIF
.ENDIF ;End WM_USER+300h
wm0:
;----- Default Procedure * Return Value in eax ------
$Call WinDefWindowProc,parm1,parm2,parm3,parm4
ret
MainWinProc endp
;-------------- MainPaint * WM_PAINT --------------
MainPaint proc Near SYSCALL uses eax, var1:DWORD ;var1 = hwnd
mov eax,TRUE ; processed
ret
MainPaint endp
;-------------- InitMainWindow * WM_CREATE --------------
;var1 = hwnd, var2 = mp1, var3 = mp2
InitMainWindow Proc Near SYSCALL, var1:DWORD,var2:DWORD,var3:DWORD
mov eax,TRUE ; processed
ret
InitMainWindow Endp
;-------------- MainKeyBoard * WM_CHAR --------------
;var1 = mp1,var2 = mp2,var3 = hwnd
MainKeyBoard Proc Near SYSCALL uses ebx ecx,var1:DWORD,var2:DWORD,var3:DWORD
mov eax,FALSE ; not processed
ret
MainKeyBoard Endp
;if there are spaces this exits pointing to next non-space else points to non-space
SkipSpaces proc ;just skips over spaces
.WHILE ecx < fsize && byte ptr [esi+ecx] == ' ' ;spaces
inc ecx
.ENDW
.IF ecx >= fsize
mov EOFflag,1
.ENDIF
ret
SkipSpaces endp
SkipCommentsToEOL proc ;skip from ; to beginning of next line
.IF byte ptr[esi+ecx] == ';' && ecx < fsize
inc ecx
.WHILE byte ptr [esi+ecx] != 0ah && ecx < fsize ;Line feed end of line
inc ecx
.ENDW ;points to 0ah if it exists if not EOF
.ELSE
mov eax,ecx ;bytes processed appears in message
$WinDebugMessage msgFileErr
call ExitWin
.ENDIF
.IF byte ptr[esi+ecx] != 0ah ;must be EOF
mov EOFflag,1
.ELSE ;it is end of line
inc ecx ;goto next line
.IF ecx >= fsize
mov EOFflag,1
.ENDIF
.ENDIF
ret
SkipCommentsToEOL endp
DataFormatErr Proc
mov eax,ecx ;bytes processed appears in message
$WinDebugMessage msgFileErr
call ExitWin
ret
DataFormatErr EndP
ExitWin Proc
$Call WinDestroyMsgQueue,hmq
$Call WinTerminate,hab
$DosExit ;so exit
; ret
ExitWin Endp
SwitchListAlloc Proc ;allocate memory for a switch list of 30
mov ecx,00000002h ;write access flags for Dos alloc
or ecx,00000010h ;page commit
$Call DosAllocMem,offset baseaddr,3000,ecx
.IF eax != 0
$WinErrMsg " : DosAllocMem SwitchList"
Call Exitwin
.ENDIF
ret
SwitchListAlloc Endp
GetSwitchList Proc
pusha
$Call WinQuerySwitchList,hab,baseaddr,3000
.IF eax == 0
$WinErrMsg " : WinQuerySwitchList"
Call ExitWin
.ENDIF
popa
ret
GetSwitchList Endp
CloseDown Proc
$Alarm
$Call WinMessageBox,HWND_DESKTOP,HWND_DESKTOP,offset ExitMsg,offset ExitTitle,0,MB_OKCANCEL
.IF eax != MBID_CANCEL
$Call WinShutdownSystem,hab,hmq
$Call DosFreeMem,memAddr
$Call WinReleaseHook,hab,NULL,HK_INPUT,[DllProcAddr1],DllHandle
$Call DosFreeModule,DllHandle
$Call WinDestroyWindow,hwndMainFrame
Call ExitWin
.ENDIF
ret
CloseDown Endp
END startup ;required