Sign in to follow this  
Followers 0
monoceres

_WinAPI_setWindowsHookEx help

18 posts in this topic

#1 ·  Posted (edited)

Hi!

I'm having trouble getting _WinAPI_SetWindowsHookEx() to work.

What I'm basically want to do is been able to snap up messages that other applications receives, but it isn't as easy as I thought :)

Here's my current effort:

#Include <WinAPI.au3>
HotKeySet("{ESC}","close")
$callback=DllCallbackRegister("_Intercept","lresult","int;wparam;lparam")


Run("notepad.exe")
$module=_WinAPI_GetModuleHandle(WinGetHandle("Untitled - ")); I suspect that this is wrong, but hey! it isn't getting me an error.
$hook=_WinAPI_SetWindowsHookEx($WH_CALLWNDPROC,DllCallbackGetPtr($callback),$module)
Do
    Sleep(50)
Until 1+2=4

Func _Intercept($nCode,$wParam,$lParam)
    MsgBox(0,"Message Intercepted","Notepad.exe has recevied a message")
EndFunc

Func close()
;~   _WinAPI_UnhookWindowsHookEx($hook)
    DllCallbackFree($callback)
EndFunc

Where am I going wrong?

Edited by monoceres

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites



The hook procedure needs to be in a dll, that's the problem.

Share this post


Link to post
Share on other sites

Hi!

I'm having trouble getting _WinAPI_SetWindowsHookEx() to work.

What I'm basically want to do is been able to snap up messages that other applications receives, but it isn't as easy as I thought :)

Here's my current effort:

#Include <WinAPI.au3>
HotKeySet("{ESC}","close")
$callback=DllCallbackRegister("_Intercept","lresult","int;wparam;lparam")


Run("notepad.exe")
$module=_WinAPI_GetModuleHandle(WinGetHandle("Untitled - ")); I suspect that this is wrong, but hey! it isn't getting me an error.
$hook=_WinAPI_SetWindowsHookEx($WH_CALLWNDPROC,DllCallbackGetPtr($callback),$module)
Do
    Sleep(50)
Until 1+2=4

Func _Intercept($nCode,$wParam,$lParam)
    MsgBox(0,"Message Intercepted","Notepad.exe has recevied a message")
EndFunc

Func close()
;~   _WinAPI_UnhookWindowsHookEx($hook)
    DllCallbackFree($callback)
EndFunc

Where am I going wrong?

There are some examples in the forums like this one

which might help.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

There are some examples in the forums like this one

which might help.

That will only work with the low level keyboard and low level mouse hooks though.. The rest requires the hook procedure(function/callback) to be placed in a DLL..

Share this post


Link to post
Share on other sites

That will only work with the low level keyboard and low level mouse hooks though.. The rest requires the hook procedure(function/callback) to be placed in a DLL..

OK, looking at this I think you are correct.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

OK, looking at this I think you are correct.

This is actually the first time I run into something that seems to be totally impossible in autoit, that's sad.

But one thing I did notice, that page says that quote:

The global hooks are a shared resource, and installing one affects all applications in the same desktop as the calling thread. All global hook functions must be in libraries. Global hooks should be restricted to special-purpose applications or to use as a development aid during application debugging. Libraries that no longer need a hook should remove its hook procedure.

But it also says that WH_CALLWNDPROC can be global and thread. And thread is supposed to work, isn't it?


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

The hook procedure needs to be in a dll, that's the problem.

You cannot hook a function from a different process. In other words, you need to inject your code into the notepad process, then have it run and hook the function. The easiest and most common way is by injecting a dll, but it is not the only way.

Share this post


Link to post
Share on other sites

You cannot hook a function from a different process. In other words, you need to inject your code into the notepad process, then have it run and hook the function. The easiest and most common way is by injecting a dll, but it is not the only way.

That sounds difficult to me. It also sounds like you know something about this, so could you suggest somewhere I could read about this or give a link?

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

This is actually the first time I run into something that seems to be totally impossible in autoit, that's sad.

But one thing I did notice, that page says that quote:

But it also says that WH_CALLWNDPROC can be global and thread. And thread is supposed to work, isn't it?

Ah, yes, so it seems, I must've overlooked that when I was researching it. :)

You cannot hook a function from a different process. In other words, you need to inject your code into the notepad process, then have it run and hook the function. The easiest and most common way is by injecting a dll, but it is not the only way.

Yes, well that's basically what a hook does.. except from the ones that can have the callback function inside another thread, they don't need to have their code "injected" afaik.

But I'd have to disagree with you that injecting a dll would be the easiest way if you can just define the callback function inside your own thread, instead of injecting it.. I like stand-alone more that having my script to have to carry a dll file with it..

Share this post


Link to post
Share on other sites

Well I found even more disappointing news: http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx

It says that you can only examine the messages, not modify them, which kinda makes the original idea with the code useless. To block certain messages, like the destroy window message.

The idea was to make a better alternative to this: http://www.autoitscript.com/forum/index.php?showtopic=74245 because I thought that it couldn't be that hard to stop applications from receiving messages, but I guess I was wrong.


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

That sounds difficult to me. It also sounds like you know something about this, so could you suggest somewhere I could read about this or give a link?

http://www.codeproject.com/KB/threads/winspy.aspx

That is one of the best sources that I always send people to, unfortunately it is difficult material to understand that will be even more difficult if you do not know C++.

Share this post


Link to post
Share on other sites

You cannot hook a function from a different process. In other words, you need to inject your code into the notepad process, then have it run and hook the function. The easiest and most common way is by injecting a dll, but it is not the only way.

I don't believe this is correct.

The dllCallBack function was designed to handle CallWndProc hook procedure by the looks of it...

Did you ever get passed this monoceres?

;===============================================================================
;
; Function Name:    _DllCallBack
; Description:      Registers a callback function and creates a stub which handles incoming calls.
; Parameter(s):     $sFunction - Name of callback function
;                   $sParameters - DllStruct like parameter definition (only 32 and 64bit datatypes supported)
;                   $nOptions, Optional - Can be one or more (add them together) of the folowing constants:
;                       $_DllCallBack_StdCall (0)  - Use 'stdcall' calling method (Default)
;                       $_DllCallBack_Cdecl (1)    - Use 'cdecl' calling method
;                       $_DllCallBack_Sync (2)     - Enable Critical Section (see Remarks)
;                       $_DllCallBack_Subclass (4) - Enable Subclassing (see Remarks)
;                       $_DllCallBack_Struct (8)   - Pass the struct to the handler function (see Remarks)
;                       $_DllCallBack_Debug (1024) - Enable breakpoint (requires a JIT debugger)
; Requirement(s):
; Return Value(s):  Pointer to created stub or NULL on error
; @error Value(s):  1 = Error allocating memory
;                   2 = Error Loading User32.dll or Kernel32.dll
;                   3 = Failed to get the address of SendMessage, EnterCriticalSection, LeaveCriticalSection or CallWindowProc
;                   4 = Too many callbacks
;                   5 = GUIRegisterMsg() Failed
;                   6 = $sParameters Fromat wrong
;                   7 = Error calling InitializeCriticalSection
;
; Author(s):        Florian Fida
; Remarks:          The number of coexistent callback stubs is limited to 64.
;                   Windows message WM_USER + 0x7BFF is used by this function.
;
;                   If Subclassing is enabled the callback function must not call 'CallWindowProc' itself.
;                   If the Function processes the message it should return NULL if not is has to return a Pointer
;                   to the previous 'WindowProc' Function.
;
;                   Critical sections allow better synchronisation, if a multithreaded library calls
;                   the callback function, enable this option.
;
;                   Passing the struct requires the callback function to accept one parameter which is the
;                   Struct defined in $sParameters. This allows the modification of the stack.
;
;===============================================================================

Share this post


Link to post
Share on other sites

Did you ever get passed this monoceres?

No, I gave it up since it since the CallWndProc callback didn't provide the functionality I needed (see my last post).


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

No, I gave it up since it since the CallWndProc callback didn't provide the functionality I needed (see my last post).

Modifying them is a problem, however, you can chose to not call CallNextHookEX after examining certain messages, which would prevent the destination window from receiving them I thought...

Share this post


Link to post
Share on other sites

Modifying them is a problem, however, you can chose to not call CallNextHookEX after examining certain messages, which would prevent the destination window from receiving them I thought...

It says CallNextHookEx. The original WindowProc is not a hook. All that does is fails to call any other hooks in the system after yours.

As for CallWindowProc(), totally separate function. You use that when you sub-class a window. Sub-classing is done in-process (and typically on an window by window basis). When you replace the window's original WindowProc with a custom one, you need to call the original WindowProc by CallWindowProc() in order to get the default behavior back (since presumably you aren't changing all the original behavior, just a small portion). This is not the same thing as hooking.

The rules for hooking are pretty simple. If you want to hook something on the current thread, that's fine, you can do that in-process because the callback function is in the same address space. Do you want to hook something in another application? The function has to be in the address space of the other application. This is typically achieved by loading a DLL in that address space. A global hook is loaded by Windows for you so you don't have to do other forms of injection which are messy.

In order to stop a window from receiving messages, or filter certain messages, it would need to be sub-classed. Since we are talking about application windows not in the current process, this is not trivial to do. It would involve injecting a DLL into the process and the DLL would then use conventional sub-classing techniques to process the messages. Clearly not something you can achieve in AutoIt since you can't create a DLL (Though there are even nastier non-DLL methods, I'm sure).

Lastly, the obligatory bitching. Read MSDN on stuff - first. Don't make asinine statements about what you think. What you think is irrelevant when there is documentation for this stuff. There's no point in spreading misinformation because you can't be arsed to spend a few minutes trying to understand something on MSDN. I know all of this stuff is well documented on MSDN as one of the very first C++ programs I wrote used hooks and I managed to figure it out just fine from MSDN.

Share this post


Link to post
Share on other sites

It says CallNextHookEx. The original WindowProc is not a hook. All that does is fails to call any other hooks in the system after yours.

As for CallWindowProc(), totally separate function. You use that when you sub-class a window. Sub-classing is done in-process (and typically on an window by window basis). When you replace the window's original WindowProc with a custom one, you need to call the original WindowProc by CallWindowProc() in order to get the default behavior back (since presumably you aren't changing all the original behavior, just a small portion). This is not the same thing as hooking.

The rules for hooking are pretty simple. If you want to hook something on the current thread, that's fine, you can do that in-process because the callback function is in the same address space. Do you want to hook something in another application? The function has to be in the address space of the other application. This is typically achieved by loading a DLL in that address space. A global hook is loaded by Windows for you so you don't have to do other forms of injection which are messy.

In order to stop a window from receiving messages, or filter certain messages, it would need to be sub-classed. Since we are talking about application windows not in the current process, this is not trivial to do. It would involve injecting a DLL into the process and the DLL would then use conventional sub-classing techniques to process the messages. Clearly not something you can achieve in AutoIt since you can't create a DLL (Though there are even nastier non-DLL methods, I'm sure).

Lastly, the obligatory bitching. Read MSDN on stuff - first. Don't make asinine statements about what you think. What you think is irrelevant when there is documentation for this stuff. There's no point in spreading misinformation because you can't be arsed to spend a few minutes trying to understand something on MSDN. I know all of this stuff is well documented on MSDN as one of the very first C++ programs I wrote used hooks and I managed to figure it out just fine from MSDN.

Thx for spelling that out muttley

Your insightful input is most welcome no matter what form it comes in Valik.

My knowledge of windows API is limited at best, I'm working through it on the need to know basis. I don't know exactly what the OP was trying to achieve, but what I'm curious to find out is if it is possible to use the DllCallBack function to hook a thread using the WH_CALLWNDPROCRET hook, similar to what Larry did in his example...(I'm not trying to change anything, just grab it using a different hook)

http://www.autoitscript.com/forum/index.ph...=55694&st=0

Share this post


Link to post
Share on other sites

My knowledge of windows API is limited at best, I'm working through it on the need to know basis. I don't know exactly what the OP was trying to achieve, but what I'm curious to find out is if it is possible to use the DllCallBack function to hook a thread using the WH_CALLWNDPROCRET hook,

It's very simple. Is the thread in your process? Then yes, you can hook it. Is the thread in another process? No, you can't hook it without a global callback which must be in a DLL.

Share this post


Link to post
Share on other sites

It's very simple. Is the thread in your process? Then yes, you can hook it. Is the thread in another process? No, you can't hook it without a global callback which must be in a DLL.

Oh well...Guess I'm off to download TinyC

Thanks for helping out.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0