now there is a little catch about the hook procedure. remember that the hooks are chained in a linked list with the most recently installed hook at the head of the list. when an event occurs, windows will call only the first hook in the chain. it's your hook procedure's responsibility to call the next hook in the chain. you can choose not to call the next hook but you'd better know what you're doing. most of the time, it's a good practice to call the next procedure so other hooks can have a shot at the event. you can call the next hook by calling callnexthookex which has the following prototype:
callnexthookex proto hhook:dword, ncode:dword, wparam:dword, lparam:dwordan important note about remote hooks: the hook procedure must reside in a dll which will be mapped into other processes. when windows maps the dll into other processes, it will not map the data section(s) into the other processes. in short, all processes share a single copy of code but they will have their own private copy of the dll's data section! this can be a big surprise to the unwary. you may think that when you store a value into a variable in the data section of a dll, that value will be shared among all processes that load the dll into their process address space. it's simply not true. in normal situation, this behavior is desirable since it provides the illusion that each process has its own copy of the dll. but not when windows hook is concerned. we want the dll to be identical in all processes, including the data. the solution: you must mark the data section as shared. you can do this by specifying the section(s) attribute in the linker switch. for masm, you need to use this switch:
- hhook is your own hook handle. the function uses this handle to traverse the linked list and search for the hook procedure it should call next.
- ncode, wparam and lparam you can just pass those three values you receive from windows to callnexthookex.
/section:<section name>, sthe name of the initialized data section is .data and the uninitialized data is .bss. for example if you want to assemble a dll which contains a hook procedure and you want the uninitialized data section to be shared amoung processes, you must use the following line:
link /section:.bss,s /dll /subsystem:windows ..........s attribute marks the section as shared.
example:
there are two modules: one is the main program which will do the gui part and the other is the dll that will install/uninstall the hook.;--------------------------------------------- this is the source code of the main program --------------------------------------
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include mousehook.inc
includelib mousehook.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
wsprintfa proto c :dword,:dword,:vararg
wsprintf textequ <wsprintfa>
.const
idd_maindlg equ 101
idc_classname equ 1000
idc_handle equ 1001
idc_wndproc equ 1002
idc_hook equ 1004
idc_exit equ 1005
wm_mousehook equ wm_user+6
dlgfunc proto :dword,:dword,:dword,:dword
.data
hookflag dd false
hooktext db "&hook",0
unhooktext db "&unhook",0
template db "%lx",0
.data?
hinstance dd ?
hhook dd ?
.code
start:
invoke getmodulehandle,null
mov hinstance,eax
invoke dialogboxparam,hinstance,idd_maindlg,null,addr dlgfunc,null
invoke exitprocess,null
dlgfunc proc hdlg:dword,umsg:dword,wparam:dword,lparam:dword
local hlib:dword