My intentions are as follows. To code a program that records the location (i.e. [x,y]) of left mouse button clicks in a specific target window.
I understand all of iczelions mouse hook tute. But I am having difficulty figuring out how to make it so that only left mouse button clicks are recorded from within a specified window. *I think* i've got it so that only when the cursor is over the target window the message will get process however as for when the left mouse button is pressed, im bamboozled! ;-(
MouseProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
.data
szTarget db "target_class", 0
.code
invoke CallNextHookEx,hHook,nCode,wParam,lParam
mov edx,lParam
assume edx:PTR MOUSEHOOKSTRUCT
invoke WindowFromPoint,[edx].pt.x,[edx].pt.y
Invoke GetClassName, eax, ADDR szClass, SIZEOF szClass
invoke lstrcmp, ADDR szTarget, ADDR szClass
cmp eax, 0
jne FIN
invoke PostMessage,hWnd,WM_MOUSEHOOK,eax,0
FIN:
assume edx:nothing
xor eax,eax
ret
MouseProc endp
...
szFormat db "(%d, %d), 0
...
.IF uMsg == WM_MOUSEHOOK
Invoke wsprintf, ADDR szBuffer, ADDR szFormat, [edi].pt.x, [edi].pt.y
Invoke SetDlgItemText, hWnd, IDC_EDIT, ADDR szBuffer
.ENDIF
The above doesn't work ;-( Puzzled
Quote from: Ksbunker on January 27, 2007, 07:36:22 AM
...
szFormat db "(%d, %d), 0
...
.IF uMsg == WM_MOUSEHOOK
Invoke wsprintf, ADDR szBuffer, ADDR szFormat, [edi].pt.x, [edi].pt.y
Invoke SetDlgItemText, hWnd, IDC_EDIT, ADDR szBuffer
.ENDIF
szFormat db "(%d, %d), 0
Shouldn't there be an end quotation there?
In your hook procedure (MouseProc) check wParam for the mouse message WM_LBUTTONDOWN.
I appreciate your help guys. Thanks a lot. However I still have several errors, must noticeably in the EXE with the WM_MOUSEHOOK command and the [edi].pt.x and [edi].pt.y
DLL;
MouseProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
invoke CallNextHookEx,hHook,nCode,wParam,lParam
mov edx,lParam
assume edx:PTR MOUSEHOOKSTRUCT
invoke WindowFromPoint,[edx].pt.x,[edx].pt.y
mov ebx, wParam
.IF ebx == WM_LBUTTONDOWN
Invoke PostMessage, hWnd, WM_MOUSEHOOK, eax, 0
.ENDIF
assume edx:nothing
xor eax,eax
ret
MouseProc endp
EXE; (Fails to Assemble the EXE at line 'Invoke wsprintf...' says pt is the error. Exact message commented below)
.elseif uMsg == WM_MOUSEHOOK
Invoke wsprintf, ADDR szBuffer, ADDR szFormat, eax, [edi].pt.x, [edi].pt.y ;Error! Undefined symbol : pt
invoke SendMessage, hList, LB_ADDSTRING,0, ADDR szBuffer
Invoke SendMessage, hList, WM_VSCROLL, SB_BOTTOM, 0
Okay, here is the problem, the [edx] ptr was ONLY for the DLL, what your WM_MOUSEHOOK is sending is the Window Handle that the point was on, it is located in wParam.
I assume you want the cordinates it sends? Hmm, make an equate WM_MOUSEHOOKPOINT, check for it in the App, and have wParam contain X and lParam contain Y. That's about how I would do it anyways.
I hope this helps.
:D
P.S. We can probably help more if you attach your code.
To pass the coordinates of the mouse cursor you could encode them into a DWORD (using 16 bits for each coordinate) and pass it in the lParam parameter of the PostMessage function.
I wasn't fully aware of how postmessage() worked with the last two parameters and all, but now I see you can store information/data in them. So basically, the only way I can transfer information across from the dll to my exe is if I include it in either wParam or lParam?
Hopefully there will be no more posts, however thats not a promise.
After further investigation with OllyDbg, it never actually breaks on my WM_MOUSEHOOK message at all!? I can't seem to find any errors. I may put this project aside untill my progress with my asm. TomRiddle, as you requested is the entire source below ;)
exe;
Quote.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include shell32.inc
includelib user32.lib
includelib kernel32.lib
includelib shell32.lib
WndProc PROTO :HWND, :DWORD, :DWORD, :DWORD
;---------------------
;
.data
DllName db 'DLL.dll',0
szInstallHook db 'InstallHook',0
szFormat db "(%d, %d)", 0
;---------------------
;
.data?
hInstance HINSTANCE ?
pInstallHook dd ?
hHookDll dd ?
hHook dd ?
hList dd ?
;---------------------
;
.const
IDD_DIALOG = 1000
IDC_EXIT = 1001
IDC_LISTBOX = 1002
WM_MOUSEHOOK equ WM_USER+6
;---------------------
;
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, IDD_DIALOG, NULL, OFFSET WndProc, NULL
invoke ExitProcess, eax
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL szBuffer[128]:byte
.if uMsg == WM_INITDIALOG
INVOKE SetWindowPos, hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_NOSIZE Or SWP_NOMOVE
Invoke GetDlgItem, hWnd, IDC_LISTBOX
mov hList, eax
invoke LoadLibrary,OFFSET DllName
mov hHookDll, eax
invoke GetProcAddress,hHookDll,OFFSET szInstallHook
mov pInstallHook,eax
call pInstallHook
mov hHook,eax
.elseif uMsg == WM_MOUSEHOOK
mov eax, wParam ;[edi].pt.x
mov ebx, lParam ;[edi].pt.y
Invoke wsprintf, ADDR szBuffer, ADDR szFormat, eax, ebx
invoke SendMessage, hList, LB_ADDSTRING,0, ADDR szBuffer
Invoke SendMessage, hList, WM_VSCROLL, SB_BOTTOM, 0
.elseif uMsg == WM_COMMAND
.if wParam == IDC_EXIT
JMP thedoor
.endif
.elseif uMsg == WM_CLOSE
thedoor:
invoke FreeLibrary,hHookDll
invoke ExitProcess, 0
.endif
xor eax,eax
ret
WndProc endp
end start
.486
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
MouseProc PROTO :DWORD, :DWORD, :DWORD
InstallHook PROTO :DWORD
.data?
hInstance dd ? ;Dll's module handle
hHook dd ? ;Hook handle
hWnd dd ?
.const
WM_MOUSEHOOK equ WM_USER+6
.code
DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
mov eax,hInst
mov hInstance,eax
.IF reason== DLL_THREAD_DETACH || reason== DLL_PROCESS_DETACH
.IF hHook
invoke UnhookWindowsHookEx,hHook
.ENDIF
.ENDIF
mov eax,TRUE
ret
DllEntry Endp
InstallHook proc hwnd:DWORD
push hwnd
pop hWnd
invoke SetWindowsHookEx, WH_MOUSE, OFFSET MouseProc, hInstance, 0
mov hHook,eax
ret
InstallHook endp
MouseProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
invoke CallNextHookEx,hHook,nCode,wParam,lParam
mov edx,lParam
assume edx:PTR MOUSEHOOKSTRUCT
Invoke WindowFromPoint,[edx].pt.x,[edx].pt.y
mov ebx, wParam
.IF ebx == WM_LBUTTONDOWN
Invoke PostMessage, hWnd, WM_MOUSEHOOK, [edx].pt.x, [edx].pt.y
.ENDIF
assume edx:nothing
xor eax,eax
ret
MouseProc endp
End DllEntry
What about your resource definition?
;This Resource Script was generated by WinAsm Studio.
#define IDC_EXIT 1001
#define IDD_DIALOG 1000
#define IDC_LISTBOX 1002
IDD_DIALOG DIALOGEX 10,10,137,101
CAPTION "WH_MOUSE Example"
FONT 0,""
STYLE 0x10ca0880
EXSTYLE 0x00000000
BEGIN
CONTROL "EXIT",IDC_EXIT,"Button",0x50010000,2,82,134,18,0x00000000
CONTROL "",IDC_LISTBOX,"ListBox",0x50010140,3,2,133,78,0x00000200
END
I can see three serious problems with your code:
WndProc is not preserving EBX.
The call to pInstallHook is not passing hWnd.
In MouseProc the call to WindowFromPoint is destroying the value in EDX.
Much thanks to you!
Added 'push hWnd' before the call, fixed.
Removed the WindowFromPoint, fixed.
And added ..PROC uses ebx nCode:.....
However, now it appears as though only clicks from within my window get recorded. I'm sure ive read a solution to this by uer f-four somewhere on this board. Ill have a look. In the mean time, any idea on how to rectify that?
As previously mentioned, the message only gets processed when a click occurs from within my program window. How can I fix this? I thought by Definition system wide hooks worked worked on the whole system, but for some reason that doesn't seem to the be case...
You obviously have access to the tutorial, I assumed you would find the solution.
It said something about shared memory access for the hWnd dd ? and setting the shared section via link. However I didn't fully understand it.