 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Sun May 20, 2007 9:49 am Post subject: WinEventHook example... |
|
|
The archive contains a small sample AHK script which uses a tiny DLL file loaded only into the AHK process to hook certain system events.
ie. window creation/deletion, menu navigation, alt-tab, selection changes, scrolling, window activation, foreground, etc., by using the SetWinEventHook function as found here: http://msdn2.microsoft.com/en-us/library/ms696160.aspx
The SendMessage function is used to inform the script, where lParam points to the hook callback function parameters on stack.
http://www.autohotkey.net/~JGR/wineventhook.rar
I first tried CBT hooks but overall things were flaky and unreliable...
I am also writing a multiple generic callback DLL, but the code is in such a mess as I tried to integrate a CBT hook into the same DLL, that I'm not going to post it now. It is mostly untested and needs fixing...
JGR |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 5581
|
Posted: Sun May 20, 2007 10:03 am Post subject: |
|
|
I have been waiting for something like this for a long time and much excited to see this.
Many Thanks!.
I downloaded and tried and the script prompts a missing "GetDeRefInteger()"
Please look into it.
PS: Wow! The DLL is just 2.52KB and can be easily included in an uncompiled script!  |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Sun May 20, 2007 10:10 am Post subject: |
|
|
I'm sure that I got it of of these forums or the AHK manual or something, but I can't find it now: so here it is, with it's accompanying functions:
| Code: | InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
GetDeRefInteger(pSource, pIsSigned = false, pSize = 4)
; pSource is an integer pointer to a raw/binary integer
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(pSource + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
SetDeRefInteger(pInteger, pDest, pSize = 4)
; The caller must ensure that *pDest has sufficient capacity and that pDest is a valid dereferencable integer pointer.
; To preserve any existing contents at *pDest, only pSize number of bytes are altered.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, pDest + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
} |
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3593 Location: Belgrade
|
Posted: Sun May 20, 2007 3:35 pm Post subject: |
|
|
Extraordinary work, thx.
So, does CBT hook works OK or not ? _________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Sun May 20, 2007 4:29 pm Post subject: |
|
|
The CBT hook only appeared to work on certain processes (not including explorer), I also managed to temporarily lock up my system while debugging it. The DLL has to be injected into all processes to work properly. Only about half of my running processes got injected.
The fact that the DLL is spread across multiple contexts introduces lots of headaches. I even needed to use a mutex...
I'm not going to continue working on the CBT hook, as it is too much of a pain, and didn't work well anyway... (A dodgy AHK script could bring the system to its knees quite easily)
JGR |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3593 Location: Belgrade
|
Posted: Sun May 20, 2007 4:49 pm Post subject: |
|
|
Injection is not the problem. There are thousand of ways.
If it works correctly in those half its OK.
You can test your hook if you set your dll to be loaded in all processes via 1 registry key (cant recall the name atm). That is one of the ways and it is limited as dll is loaded in all processes on next start up.
| Quote: | | I am also writing a multiple generic callback DLL, but the code is in such a mess as I tried to integrate a CBT hook into the same DLL | Good idea. _________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Sun May 20, 2007 5:02 pm Post subject: |
|
|
As for the automatic injection, I tried that, the key is: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs. That didn't work either.
The callback DLL is done now and is here (with hooks un-integrated): http://www.autohotkey.com/forum/viewtopic.php?t=19370
I'll post the hook dll (it should work with any of the windows hooks). Code to use it is clearly commented out in the archive in the first post.
I won't be making any more changes to it...
http://www.autohotkey.net/~JGR/cbthook.rar
JGR |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3593 Location: Belgrade
|
Posted: Sun May 20, 2007 5:10 pm Post subject: |
|
|
I will test it during next week and tell you what I think.
Thx again. _________________
 |
|
| Back to top |
|
 |
Supercalifragilistic Guest
|
Posted: Sun May 20, 2007 5:31 pm Post subject: |
|
|
Sorry if I distrub the genius corner
But I'm a noob in hooking. I know what the hooking process is supposed to do, but ... what is the purpose of your prog ?
I seen that AppsKey and End stops the hooking process, but I didn't seen what it does.
How your prog works ? What does it do ?
Is there a working example ?
What are the events which are hooked ?
More explanations, please.... |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Sun May 20, 2007 5:43 pm Post subject: |
|
|
The posted example displays a debug message whenever a (sub)window is created or sent to the foreground.
To see it you will need a debug viewer like this one, or just change the code to something more obvious, like FileWrite. (Don't try messagebox, you'll regret it).
It doesn't actually do anything useful at the moment per se, the idea is that you write the functional bit yourselves.
As for how it works: See here. The callback function is in the dll, and sends AHK a message, with a pointer to the parameters of the callback in lParam.
My advice, is that you read carefully about hooking before trying to use it. As if you're not careful, your system will take a *huge* performance hit/hanging. |
|
| Back to top |
|
 |
Supercalifragilistic Guest
|
Posted: Sun May 20, 2007 7:55 pm Post subject: |
|
|
| I'd tried your script with DebugView and ... I did not seen anything (I tried to open a sub-window by open a file in PSPad). It's probably too clever for me. Anyways, thanks for the explanations. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3593 Location: Belgrade
|
Posted: Mon May 21, 2007 8:33 am Post subject: |
|
|
What is the difference between SetEvenHook and SetWindowsHookEx
I never heard until today for the first one.
BTW, you should probably create better example with more clear hook unloading. Currently if you don't press a hotkey that says nothing, hook never gets unloaded. _________________

Last edited by majkinetor on Mon May 21, 2007 10:22 am; edited 1 time in total |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3593 Location: Belgrade
|
Posted: Mon May 21, 2007 8:38 am Post subject: |
|
|
Argh, I see... SetWinEventHook is acctually wrapper itself of Active Accessibility _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3593 Location: Belgrade
|
Posted: Mon May 21, 2007 10:12 am Post subject: |
|
|
This is working example:
| Code: | DetectHiddenWindows, On
event := 0x00008000 ;EVENT_OBJECT_CREATE
hwnd:=WinExist("ahk_pid " . DllCall("GetCurrentProcessId","Uint"))
msg := 0x550
hook_dll = wineventhook\wineventhook.dll
hHookModule := API_LoadLibrary(hook_dll)
hHook := Hook(hwnd, msg, event, event, "HookHandler")
return
!e:
Msgbox % "Unhook: " Unhook(hHook,msg)
return
HookHandler(wParam, lParam, msg, hwnd) {
msgbox Hello from hook
}
Hook(comm_hwnd, comm_msg, s_event, e_event, function, wparam=0) {
global hook_dll
r := DllCall(hook_dll "\reghook", "UInt", comm_hwnd, "UInt", COMM_MSG, "UInt", s_event, "UInt", e_event, "UInt", wparam)
if !r
return 0
OnMessage(COMM_MSG, function)
return r
}
Unhook(handle, com_msg) {
OnMessage(com_msg)
return DllCall("UnhookWinEvent", "UInt", handle)
}
API_LoadLibrary( dll ) {
return DllCall("LoadLibrary", "str", dll)
}
|
_________________
 |
|
| Back to top |
|
 |
new_noobie Guest
|
Posted: Mon May 21, 2007 10:22 am Post subject: |
|
|
Can anyone say for sure wheather this will work on win9x systems. I don't
have access to my XP box right now, so I tried the "EnumWindows.ahk" script
included in JGR's archive and corrupt's post in this thread, and they both
produce a message box with no output (well corrupt's shows Output1 and
Output2 without and data).
I did look at the msdn link given in the "WinEventHook example..." thread in
this forum and it says that SetWinEventHook is supported in win98 and later.
The box I tried the examples on is win98se. Can anyone show me what might be
needed to get it to work?
@JGR, can the dll be made to function on win9x if it does not now?
thx |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|