When a command is invoked via a keyboard shortcut in an MFC application under Windows 7, the application won’t crash even if some illegal operation such as divison by zero or an access violation occurs during the execution of the command handler. How ever The same command invoked via the menu will crash as expected.
This behaviour occurs under Windows 7 but not under Windows XP (I have no Vista to check). It doesn’t matter if the application has been compiled with Visual Studio 6 or with Visual Studio 2010 and if MFC is linked statically or not and if it’s the release or the debug build.
This is obviously a major problem, because in case of an access violation or some other problem, the command stops prematurely, potentially leaving data in an undefined state and the application just continues as if nothing had happened. Every MFC application in the world is potentially concerned by this problem.
The problem can be circumvented by implementing a special stub command handler for every keyboard shortcut. These stub commands then just put the WM_COMMAND back into the message via the PostMessage function.
The complete Visual Studio 6 and 2010 projects of a very simple stub application that demonstrates the problem and the solution can be found here:
http://www.epsitec.ch/download/mfccrash/mfccrash.zip
So the the actuel question is: does anybody know what’s going on ? And can anyone suggest a more elegant sulution that the one I have found ?
It is actually a KB976038 issue. The reason why only keyboard shortcut invoked commands are concerned is because MFC calls them via the ::TranslateAccelerator(m_hWnd, hAccel, pMsg) function. This function goes into kernel mode at some time (see stack dumps below) and then goes back into user mode and there lies the problem.
The idea of implementing a special stub command handler for every keyboard shortcut and then putting the WM_COMMAND back into the message queue, as I mentioned in the question, is definitely not good.
To cure the problem properly I reimplemented the OnCommand function in the CMainFrame class as this:
Now every time a crash occurs in one of the commands, it will be catched by the RecordExceptionInfo function. For implementing the RecordExceptionInfo function, have a look at Hans Dietrich’s excellent article on Codeproject.
Stack dumps
Stack dump for command invoked via menu: We don’t go into kernel mode before arriving in the OnAppAbout function:
Stack dump for command invoked via a keyboard shortcut. We go into kernel mode before arriving in the OnAppAbout function, watch out for the line starting with NTDLL: