Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

WinEventHook example...


  • Please log in to reply
14 replies to this topic
JGR
  • Members
  • 59 posts
  • Last active: Feb 07 2012 08:49 PM
  • Joined: 15 Jun 2006
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.microso...y/ms696160.aspx
The SendMessage function is used to inform the script, where lParam points to the hook callback function parameters on stack.

https://ahknet.autoh...ineventhook.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

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
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! :D

JGR
  • Members
  • 59 posts
  • Last active: Feb 07 2012 08:49 PM
  • Joined: 15 Jun 2006
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:

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)
}


majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Extraordinary work, thx.

So, does CBT hook works OK or not ?
Posted Image

JGR
  • Members
  • 59 posts
  • Last active: Feb 07 2012 08:49 PM
  • Joined: 15 Jun 2006
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

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
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.

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

JGR
  • Members
  • 59 posts
  • Last active: Feb 07 2012 08:49 PM
  • Joined: 15 Jun 2006
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.autohotke...pic.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...

https://ahknet.autoh...JGR/cbthook.rar

JGR

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
I will test it during next week and tell you what I think.

Thx again.
Posted Image

Supercalifragilistic
  • Guests
  • Last active:
  • Joined: --
Sorry if I distrub the genius corner :D :D :D
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....

JGR
  • Members
  • 59 posts
  • Last active: Feb 07 2012 08:49 PM
  • Joined: 15 Jun 2006
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.

Supercalifragilistic
  • Guests
  • Last active:
  • Joined: --
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.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
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.
Posted Image

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Argh, I see... SetWinEventHook is acctually wrapper itself of Active Accessibility
Posted Image

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
This is working example:


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) 
}


Posted Image

new_noobie
  • Guests
  • Last active:
  • Joined: --
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