How to hook Windows Messages

Nov 2, 2010 at 11:42 PM

Hi,

I'm trying to figure how I could hook Windows Messages from an application using EasyHook. I used to do this using CBT hook, but that is not an option on Vista/7.

Anyone knows how can this be done? For example, I have an external application that is writing to a Rich Edit Control some texts. Using Spy++ I see that every time it writes new text on it, it sends an EM_REPLACESEL Message. I would like to hook that message to be able to replicate what is written in real time.

Any help would be appreciated. Thanks!

Nov 3, 2010 at 3:45 PM

Hook GetMessage in User32.dll. That's how programs retrieves their messages, Then simply filter down the messages you are interested in. Be aware that some message may short-circuit, so maybe you could also hook PostMessage() and SendMessage() and all the others. (See docs on SendMessage about short-circuit.)

Nov 3, 2010 at 10:05 PM

Hey! Finally I got it. I had to use SendMessage because it was a sending message but finally worked.

Thanks a lot :)

Nov 8, 2010 at 10:42 AM

Can you post the code you use? It will be useful for others too.

Nov 10, 2010 at 8:59 AM

Yes of course!

On run:

_sendMessageHook = LocalHook.Create(
                    LocalHook.GetProcAddress("user32.dll", "SendMessageW"),
                    new DSendMessage(SendMessage_Hooked),
                    this);

Outside function:

[UnmanagedFunctionPointer(CallingConvention.StdCall,
        CharSet = CharSet.Unicode,
        SetLastError = true)]
        delegate void DSendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
        static void SendMessage_Hooked(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            try
            {
                if (msg == ApiCalls.EM_REPLACESEL)
                {
                    Main This = (Main)HookRuntimeInfo.Callback;
                    string text = System.Runtime.InteropServices.Marshal.PtrToStringUni(lParam);
                    This.Interface.OnEMReplacesel(hWnd, text);
                }
            }
            catch (Exception ex)
            {
                 Main This = (Main)HookRuntimeInfo.Callback;
                 This.Interface.ReportException(ex);
            }

            // call original API...
            ApiCalls.SendMessageW(hWnd, msg, wParam, lParam);
        }

The  DLL Import:

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

In my case (and the 99% one) the unicode version is called and not the ansi one, that's why I'm using UNICODE always. I use an open source software called "WinAPIOverride32" to check it.

Dec 22, 2010 at 3:22 PM

can you post more example how to do this. Example of the full code