简体   繁体   中英

CallWindowProc crash on exit

In order to hook a wndproc , I write a wndprochook and use SetWindowLong :

wndproc=(WNDPROC)GetWindowLong(hwnd_1,GWL_WNDPROC);
SetWindowLong(hwnd_1,GWL_WNDPROC,(LONG)wndprochook);

Now I have to do something in wndproc and at the end of the function, I call the original wndproc :

return wndproc(hwnd, uMsg, wParam, lParam);

It fails, but thank god I find CallWindowProc :

return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);

Now it's working. So Question1: Why do we have to use CallWindowProc ? What's missing when simply calling wndproc ?

The hook is working good, but when I quit the program, it crashes. Of course, everything is done and the crash doesn't actually affect anything. But it's still bad to see a crash. So Question2: What may happened here and how to fix it?

I'm sorry that I have no information about how the original program closes itself, since all that I do is just hooking the wndproc to capture some messages. So I'm just hoping someone experienced enough who have ever encountered similar situations before could help.

From the documentation of CallWindowProc :

“If this value is obtained by calling the GetWindowLong function with the nIndex parameter set to GWL_WNDPROC or DWL_DLGPROC , it is actually either the address of a window or dialog box procedure, or a special internal value meaningful only to CallWindowProc

You can't call the “special internal value“ except by doing the same as CallWindowProc does, and the easiest way to do that is to call CalLWindowProc

By the way, have a look at SetWindowSubclass , it may ease things for you.

Regarding Question 2:

From comments on another answer, it sounds like your subclass wndprochook is in a DLL that's injected into a process. If that's the case, then during exit, your DLL may be unloaded while there are still messages pending for the window. So the Window's class still points to your wndproc, but that code is unloaded, so it crashes.

The safest thing to do is probably to restore the original wndproc before you shut down. For example, when your subclass sees WM_DESTROY or perhaps WM_NCDESTROY, you essentially reverse the steps you did when you subclassed the window: restore the original wndproc field in the window class, before doing your CallWindowProc with that message. Your code will no longer be called, even if a few more messages trickle in for that window.

thx to Adrian McCarthy.

Private Function WndProc(ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case MSG
    Case WM_CUT, WM_PASTE, WM_CLEAR
        WndProc= 1
    Case WM_DESTROY, WM_NCDESTROY
        Call UnHookRKey(hWnd)
    Case Else
        WndProc= CallWindowProc(lngPrevWndProc, hWnd, MSG, wParam, lParam)
End Select

End Function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM