Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

using WH_CALLWNDPROCRET correctly

150 views
Skip to first unread message

Nonso Nosiri

unread,
Dec 12, 2021, 11:31:46 PM12/12/21
to
Hi,
I am using a hook with the WH_CALLWNDPROCRET flag to intercept a hwnd's procedure messages and intercept WM_INPUT and WM_PAINT, but I am having problems with it.

I cast the LPARAM to a CWPRETSTRUCT pointer according to msdn: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-hookproc
But unfortunately, the "message" member in the struct is not used the same way as in a normal procedure callback function: https://docs.microsoft.com/en-us/windows/win32/winmsg/using-window-procedures
It's either that or it is garbage data.

Am I using it wrong? would you mind creating a small code example that could help me? Or pointing out my errors, I would really appreciate it.

This is the code I'm using: https://pastebin.com/DNZhUP4m

Thanks in advance,
Chinomso Nosiri.

JJ

unread,
Dec 13, 2021, 12:12:24 AM12/13/21
to
What do you meant by "the same way"?
What exactly are you expecting, and what exactly are you getting?

R.Wieser

unread,
Dec 13, 2021, 12:43:38 PM12/13/21
to
Chinomso,

I argree with JJ. Without knowing what you are getting and what you are
expecting instead it's rather hard (understatement) to know what, if
anything, is going wrong.


To test I just added that SetWindowsHookEx call to a basic dialog and in the
callback I "dumped" the arguments to the callback as well the pointed-to
structure, and got a rather recognisable list, including the WM_PAINT
message.

Alas, my language of choice is Assembly, so there is a good chance its
rather meaningless to you. Than again ...

Please do notice that I've got some arguments to the involved functions set
to Zero. Just might make the difference.

;-- Initialisation :

call GetCurrentThreadId
call SetWindowsHookExA,WH_CALLWNDPROCRET,offset HookProcCB,0,eax

;-- callback function:

HookProcCB proc
arg @@wMsg:DWORD,@@wParam:DWORD,@@lParam:DWORD
uses ebx,esi,edi
local @@sBuffer[MAX_PATH]:BYTE

Debug_HexLongNR,[@@wMsg]
Debug_HexLongNR,[@@wParam]
Debug_HexLongNR,[@@lParam]
Debug_Chr,'- '

mov ebx,[@@lParam]
Debug_HexLongNR,[ebx].CWPRET_lResult
Debug_HexLongNR,[ebx].CWPRET_lParam
Debug_HexLongNR,[ebx].CWPRET_wParam
Debug_HexLongNR,[ebx].CWPRET_lMessage
Debug_HexLongNR,[ebx].CWPRET_hWnd
Debug_wMsg,[ebx].CWPRET_lMessage

call CallNextHookEx,0,[@@wMsg],[@@wParam],[@@lParam]
ret
HookProcCB endp

;-- Result :
00000000 00000000 0012FDD4 - 00000000 00000000 00000003 00000127 009F0276
WM_CHANGEUISTATE
00000000 00000000 0012FE94 - 00000000 00000000 00000001 00000018 009F0276
WM_SHOWWINDOW
00000000 00000000 0012FE7C - 00000000 0012FED4 00000000 00000046 009F0276
WM_WINDOWPOSCHANGING
00000000 00000000 0012FE94 - 00000000 00000468 00000001 0000001C 009F0276
WM_ACTIVATEAPP
....
00000000 00000000 0012FE94 - 00000000 003B012C 00000000 00000005 009F0276
WM_SIZE
00000000 00000000 0012FE94 - 00000000 001701C6 00000000 00000003 009F0276
WM_MOVE
00000000 00000000 0012FE88 - 00000000 00000000 00000000 0000000F 009F0276
WM_PAINT
00000000 00000000 0012FDBC - 00000000 00000000 00000001 00000085 00060280
WM_NCPAINT
...
00000000 00000000 0012F8C8 - 00000000 002F0268 020003E9 00000111 009F0276
WM_COMMAND
00000000 00000000 0012FA78 - 00000001 00000000 009F0276 00000008 002F0268
WM_KILLFOCUS
00000000 00000000 0012FA78 - 00000000 00000000 002F0268 00000007 009F0276
WM_SETFOCUS
00000000 00000000 0012FA48 - 00000000 0012FAA0 00000000 00000046 009F0276
WM_WINDOWPOSCHANGING
00000000 00000000 0012FA48 - 00000000 0012FAA0 00000000 00000047 009F0276
WM_WINDOWPOSCHANGED
00000000 00000000 0012FBE8 - 00000000 00000000 00000000 00000010 009F0276
WM_CLOSE
00000000 00000000 0012FCC4 - 00000000 000902EC 0000F060 00000112 009F0276
WM_SYSCOMMAND

Hope that helps.

Regards,
Rudy Wieser


Nonso Nosiri

unread,
Dec 13, 2021, 2:37:50 PM12/13/21
to
Hi, sorry for the late response.

In my hook procedure I am expecting the LPARAM to point to a valid CWPRETSTRUCT with window procedure message like WM_PAINT which has a value of 15, it is called repeatedly, no? However, I am getting 32 and 132 and I do not know what cases these are. they do not match any of the window proc messages. And the docs contain vague info about that the struct will actually hold: https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-cwpretstruct neither does it describe the procedure helpfully: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-hookproc

Fortunately, for my use case, I was able to resolve the problem last night via subclassing the window procedure function: https://docs.microsoft.com/en-us/windows/win32/winmsg/about-window-procedures#window-procedure-subclassing

But for the unforeseeable future, I still want to know what was wrong here.

Nonso Nosiri

unread,
Dec 13, 2021, 2:39:56 PM12/13/21
to
Just a small edit...

by "window procedure message like" I mean the message member in the struct "UINT message;"

R.Wieser

unread,
Dec 13, 2021, 4:13:24 PM12/13/21
to
Chinomso,

> with window procedure message like WM_PAINT which has a value of 15, it
> is called
> repeatedly, no?

That fully depends on what you do with the window you created. My full
list (from creation of the dialog upto closing it) only shows it twice.

Though you can "force" the message, simply by (partially)
covering-and-uncovering your window.

> However, I am getting 32 and 132 and I do not know what cases these are.
> they do not match any of the window proc messages.

Than I've got a nice list for you. Not all of them, but quite a bunch :

https://wiki.winehq.org/List_Of_Windows_Messages

> And the docs contain vague info about that the struct will actually hold:

What does "actually hold" mean ? Are you referring to the variables
themselves ? If so, what what in the (I assume) description is not clear
to you ? Or perhaps to the variable types ? You're a bit vague about it
yourself ...

> But for the unforeseeable future, I still want to know what was wrong
> here.

Without the "garbage data" you got we can only guess.

> I was able to resolve the problem last night via subclassing the window
> procedure function

As mentioned, I had no problem getting the hook to run and produce the data
I posted using a simple dialog.

Regards,
Rudy Wieser


Paul N

unread,
Dec 15, 2021, 12:46:16 PM12/15/21
to
On Monday, December 13, 2021 at 9:13:24 PM UTC, R.Wieser wrote:
> Chinomso,
> > with window procedure message like WM_PAINT which has a value of 15, it
> > is called
> > repeatedly, no?
> That fully depends on what you do with the window you created. My full
> list (from creation of the dialog upto closing it) only shows it twice.
>
> Though you can "force" the message, simply by (partially)
> covering-and-uncovering your window.

I think the recommended way to get a WM_PAINT message is by using InvalidateRect, though there are no doubt other ways.

But covering and uncovering the window may not now work. In early versions of Windows, Windows itself did not store what any particular window looked like, so if a window was uncovered a WM_PAINT was needed to tell the window to draw (part or all of) itself on the screen. Since Vista there is apparently a thing called Desktop Window Manager, all the windows are actually stored and the DWM puts them all together appropriately. See https://en.wikipedia.org/wiki/Desktop_Window_Manager .

R.Wieser

unread,
Dec 15, 2021, 1:20:33 PM12/15/21
to
Paul,

> I think the recommended way to get a WM_PAINT message is by using
> InvalidateRect,
> though there are no doubt other ways.

:-) My idea was to provide a quick "does this button work?!" test. After
that ? Who knows.

> Since Vista there is apparently a thing called Desktop Window Manager, all
> the
> windows are actually stored and the DWM puts them all together
> appropriately.
> See https://en.wikipedia.org/wiki/Desktop_Window_Manager .

I was not aware of that change. Thanks for the heads-up.

Regards,
Rudy Wieser


0 new messages