How can my app find the sender of a windows message?
Asked Answered
C

4

17

I have an app which uses a keyboard hook procedure in a library. The wParam in the hook for one message is 255 which we think is "(reserved / OEMClear)". I'd like to work out the source of this message as it causes my application to crash in the library, and given it shouldn't be happening it would be good to identify it. The message comes in repeatedly on only one PC we have - other computers don't see the message at all.

So, is there a way to trace the source of a message sent to a window please, or all those on the system?

Chablis answered 26/5, 2009 at 14:29 Comment(1)
The final solution for this, unfortunately, was a sticking plaster. I added another hook in my app which looks for this wParam value and doesn't call down the hook chain if matched. I'm making it PC specific (registry) but there seems to be something wrong with that PC.Chablis
R
7

There is no built-in way to find out who sent the window message, not even win32k keeps track of this; you might be able to find it out with a kernel debugger and a conditional breakpoint.

However, I would argue that you don't really need this information; you need to make your app properly handle any message sent to it.

Ramey answered 26/5, 2009 at 15:54 Comment(3)
I'd half agree - our purpose here is to find the cause, then we can judge the seriousness and handle it appropriately. I don't want to just stick a plaster over it in case it bites later, particularly as this is a commercial library that the fault fails in.Chablis
@mj2008: If you're deploying this to machines you don't fully control, you're going to get bitten; lots of badly-written apps send strange messages to all windows in attempts to do stuff and you have to deal with it elegantly. Just capture the messages you're interested in, and pass the rest along to the next hook in the chain.Ramey
I' d suggest to add the sender id to the message.Resonance
S
2

I came up with a technique for determining who is sending a win32 window message across threads/processes during one-off debugging/troubleshooting sessions. It requires making a couple of assumptions so it's not 100% reliable, but so far I haven't found a case where it didn't work.

The basic idea is to exploit the fact that, when the message arrives, the recipient window thread is typically blocked waiting in its message loop (specifically, GetMessage()). When the message is delivered, the sending thread readies the receiving thread, pulling it out of its wait state.

It turns out that Windows provides ways to precisely trace which threads are readying which other threads, using Event Tracing for Windows. Using this feature, it is often possible to determine which thread sent the message - it's the thread that readied the receiving thread. It's even possible to see what the call stack of the sending thread was at the time it sent the message, and even the kernel side (win32k) part of the stack!

The basic procedure goes like this:

  1. Use the Windows Performance Recorder to start a trace. Make sure to include the "CPU usage" profile.
  2. Trigger the sending of the message you are interested in.
  3. Stop the trace.
  4. Open the trace in the Windows performance Analyzer.
  5. In the "CPU Usage (Precise)" graph, "Stacks" graph preset, zoom in on the time the message was received.
    • One way is to locate the receiving thread and determine when it woke up.
    • If correlation is difficult, it might be worth instrumenting the receiving thread using e.g. TraceLogging to produce a clear reference time point.
  6. You should be able to find a context switch event where the receiving thread is readied in GetMessage.
  7. The "Readying Process", "Readying Thread Id" and "Readying Thread Stack" columns will then show the details of the readying thread, which is likely to be the sender of the message.

For example, in the below screenshot, TID 7640 receives a shell hook message originating from WindowsTerminal.exe, TID 1104:

WPA screenshot

Shaffert answered 5/2, 2022 at 11:28 Comment(0)
O
1

(I originally suggested using Spy++ or winspector, but they do not hook into the sending of messages. That doesn't even make sense! A window receives messages but they don't send them, a thread does that. I'll leave my suggestion about using a debugger.)

Sometimes debugging can help. Try downloading the windows PDB files and setting a breakpoint that hits only when one of these messages occur. Looking at the call stack at that point can often shed some light on why things are happening. Posted messages and messages send from other processes will foil this approach.

Obedient answered 26/5, 2009 at 15:24 Comment(1)
I looked at Winspector first (used it for years) but it doesn't show the source. The debugger may be the only choice...Chablis
A
-3

Im not sure if this does what you want it to but have a look at Process Monitor by sysinternals.

http:// technet.microsoft.com/en-us/sysinternals/bb896645.aspx

It shows everything that happens to a process so i assume it catches messages as well. The site was down at time of writing so i couldnt check.

Allograph answered 26/5, 2009 at 14:59 Comment(3)
Thanks - it doesn't appear to trace messages, but it lead me to msdn.microsoft.com/en-us/library/cc267862.aspx which details the debug options in the debug build. But nothing there for message tracing either!Chablis
I don't see windows messages as an 'operation' in Process Monitor.Obedient
Process Monitor does not monitor USER objects (like windows).Picrate

© 2022 - 2024 — McMap. All rights reserved.