News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Mouse Hook

Started by Ksbunker, January 27, 2007, 07:36:22 AM

Previous topic - Next topic

Ksbunker

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

TomRiddle

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?

MichaelW

In your hook procedure (MouseProc) check wParam for the mouse message WM_LBUTTONDOWN.
eschew obfuscation

Ksbunker

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

TomRiddle

#4
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.

MichaelW

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.
eschew obfuscation

Ksbunker

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.

Ksbunker

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

MichaelW

What about your resource definition?
eschew obfuscation

Ksbunker

;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

MichaelW

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.
eschew obfuscation

Ksbunker

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?

Ksbunker

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...

MichaelW

You obviously have access to the tutorial, I assumed you would find the solution.
eschew obfuscation

Ksbunker

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.