I still can't get this to work. Could it be that mIRC unloads the DLL upon exit before the WM_DESTROY message is received?

Using thread hooks I have determined that this is "probably" what does happen. That's a problem, here's why...

Say a DLL is subclassing the mIRC app, on WM_CLOSE it does nothing. Now the DLL is unloaded... The return value of WM_CLOSE is going to return to the subclassed callback, which is no longer in memory, regardless of what WND_PROC was changed to.

To prevent problems, unsubclassing must be completed when WM_CLOSE is received, then return 0L to the current WM_CLOSE message and PostMessage(WM_CLOSE) again so that the subclassed procedure is out of the chain when WM_CLOSE is processed by mIRC.

Now the problem is "Confirm on Exit"... WM_CLOSE can either finish closing or be canceled. If we unsubclass in WM_CLOSE before knowing this, and exit is canceled, mIRC will continue to run but now be unsubclassed.