Hi, I'm tinkering with journal hooks for an interactive help system. MSDN says that the callback for WH_JOURNALRECORD utilizes an EVENTMSG struct, but in the Iczelion tutorial 24 the structure is referenced as a MOUSEHOOKSTRUCT - two totally different things. I'm trying this code to display all values but it crashes... any ideas? Debugging HookProc is exceedingly difficult, OllyDbg likes to lock up and terminate the callback thread in-situ...
;Main DlgProc
.elseif eax==WM_RBUTTONUP ; temporary, for allowing one journal message display
mov CapMsg,1
.data
CapFmt1 db 'nCode: %s',13,10,'wParam: %s',13,10,'lParam: %s',13,10,13,10,0
CapFmt2 db 'EVENTMSG.message: %s',13,10,'EVENTMSG.paramL: %s',13,10
db 'EVENTMSG.paramH: %s',13,10,'EVENTMSG.time: %s',13,10
db 'EVENTMSG.hwnd: %s',0
.data?
CapRes1 db 512 dup(?)
CapRes2 db 512 dup(?)
Cap1 db 16 dup(?)
Cap2 db 16 dup(?)
Cap3 db 16 dup(?)
Cap4 db 16 dup(?)
Cap5 db 16 dup(?)
Cap6 db 16 dup(?)
Cap7 db 16 dup(?)
Cap8 db 16 dup(?)
CapMsg db ?
.code
HookProc proc nCode:DWORD, wParam:DWORD, lParam:DWORD
; * nCode specifies the hook code.
; * wParam and lParam contain additional information about the event
;The lParam parameter is a pointer to an EVENTMSG structure containing
;information about a message removed from the system queue. The hook
;procedure must record the contents of the structure by copying them
;to a buffer or file. wParam is not used. (MSDN)
.if CapMsg ; display one set of parameters
mov CapMsg,0 ; only display one messagebox!
invoke dw2a,[nCode],addr Cap1 ; convert returned vals to strings
invoke dw2a,[wParam],addr Cap2
invoke dw2a,[lParam],addr Cap3
invoke wsprintf,addr CapRes1,addr CapFmt1,addr Cap1,addr Cap2,addr Cap3
mov edx,lParam ; EVENTMSG structure?
assume edx:ptr EVENTMSG
invoke dw2a,[edx].message,addr Cap4
invoke dw2a,[edx].paramL,addr Cap5
invoke dw2a,[edx].paramH,addr Cap6
invoke dw2a,[edx].time,addr Cap7
invoke dw2a,[edx].hwnd,addr Cap8
assume edx:nothing
invoke wsprintf,addr CapRes2,addr CapFmt2,addr Cap4,addr Cap5,addr Cap6,addr Cap7,addr Cap8
invoke lstrcat,addr CapRes1,addr CapRes2
invoke MessageBox,hWnd,addr CapRes1,0,MB_OK
.endif
.if nCode==HC_ACTION
mov edx,lParam ; existing Iczelion proc, more-or-less
assume edx:ptr MOUSEHOOKSTRUCT
invoke WindowFromPoint,[edx].pt.x,[edx].pt.y
invoke PostMessage,hWnd,WM_MOUSEHOOK,eax,0
assume edx:nothing
@@:
invoke CallNextHookEx,hHook,nCode,wParam,lParam
xor eax,eax
ret
.elseif nCode<0 ; nCode values below zero must not be parsed
jmp @B
.else
invoke Beep,100,1000 ; if some funky error happens
call StopJournalHook ; don't bother trying to continue
.endif
xor eax,eax
ret
HookProc endp
Aaahaa, I was being dumb again. :bg dw2a uses EDX and was overwriting the other code... using EDI instead works.
mov edi,lParam ; EVENTMSG structure?
assume edi:ptr EVENTMSG
invoke dw2a,[edi].message,addr Cap4
invoke dw2a,[edi].paramL,addr Cap5
invoke dw2a,[edi].paramH,addr Cap6
invoke dw2a,[edi].time,addr Cap7
invoke dw2a,[edi].hwnd,addr Cap8
assume edi:nothing
(http://heliosstudios.net/temp/wh_journalrecord.png)
Another thing you want to watch for in creating global system hooks. Is that you don't create an infinite loop on accident. (It may be 100 percent logical that it should work, but I've run into situtations, where I was hooking the msg procdures, and I called a function in my hook, that eventually called the sendmessage function to a window that wasn't my own. That one really got to me until I used one of my previous versions of the program to anaylze my newer version.