Log in

View Full Version : MFC42 problem


naides
December 10th, 2003, 14:03
I am working on an application that has grayed-out menu 'save' options.
I can locate when the app is graying out the disabled options by using the API EnableMenuItem deep inside MFC42 code.
My problem is that I cannot trace my way back into the App code, where the decision enabled or disabled is made.
The Call Stack does not show when my App called MFC42.
If I trace forward from inside MFC42 I never return back to my App code.
The "flag" that signals my menu option as disabled (0x0403)is pushed into the MF42 stack by another MFC42 function, an that one from anther MFC42 and so on to at least 7 layers so BPM on that flags is not useful, unless I wish to reverse all the MFC menu handling routines.

I have found very little documentation on MFC42 internal structure,
so trying to figure out what for instance ordinal 0763 means or does is not helping, nor wich ordinals are used for menu handling routines

Clandestiny wrote a tutorial in which he mentions backtracing from MFC back into the app code, but he did not mention how.

As a side note, I know that ungraying a menu item 'save' is not enough to activating it, but I have already found the code that does the saving, I just need to ungray it, then I can direct it to the right routine.

If anybody has any information about: How MFC and the App comunicate.

Any links to documentation on MFC menu API or MFC in general. Most links I found are not very RCE informative.

Thanks a lot.

esther
December 10th, 2003, 15:05
Well even msdn lacks of information on these ordinals....

I assume you have read Spath's tutoria on enable menu items....

Kayaker
December 10th, 2003, 15:56
Hiya

You could check out the search hits for AFX_MSGMAP_ENTRY, both Zairon and Clandestiny wrote something about the structure and it might help. AfxFindMessageEntry function is used to retrieve where MFC messages are checked.

You should also check out the Menu Enabling Project we had, there was one piece of advice - the decision to enable or disable a menu item in a drop down list is usually made when the main menu item is clicked on. So this is why a BMSG on wm_command on the hwnd of the main menu bar is a good message to track...

If your mfc app behaves in a normal manner, when you click on a menu item this should send a wm_command message where wParam is the Menu item ID (any one will do to start with). From this you should be able to find the main (or subclassed) message handling routine, and from there you should find where your 'disabling' routine is *started* from, which is probably what you're looking for, the first 'signpost'. Just set a conditional breakpoint somewhere near the start of the msg handler with the menu item id (wparam) of interest. From the msg handler is where EnableMenuItem is likely called from before it disappears into MFC-land, and you can probably tweak the parameters to your preference right there...

Check out that project and see if the technique might work for you.
http://www.woodmann.com/forum/showthread.php?t=126&highlight=menu+enabling

Cheers,
Kayaker

Kayaker
December 10th, 2003, 17:41
Now that I have a bit more time.. The tricky part with using BMSG messages like this is actually breaking into the apps code, in Win98 I had found that for most apps SI broke into some intermediate system code where the jump address was mysteriously hard coded. It did this presumably through (but not directly part of) the K32Thk1632Prolog/Epilog sequence, which was another way to trace back into application code. This is discussed further in the mini project.

For Win2K I have found a similar thing, for example a BMSG (wm_command, wm_timer, wm_gettext) that I was using with a Delphi app, Softice broke into the short sequence:
Call CF0F8
jmp 41B448 -> exact start of main message handling routine.

This is the same pattern I noticed in Win98. There is likely a similar prolog (system code) -> call to appl. code -> return to epilog (system code) setup in Win2K/XP behind all this as well. The K32Thk1632Prolog/Epilog route was originally mentioned by Lord Soth. At some point I was hoping to find if a comparable Win2K code sequence which jumps from kernel->user is being used, but SI breaking in this manner on BMSG bp's is sort of a 'shortcut' to the msg handler. This should make sense once you've experienced it.

K.

Solomon
December 10th, 2003, 22:42
It will be easier to trace MFC applications by making a MFC42.NMS from MFC42.PDB which can be got from VC++ 6 installation.

Load MFC42.NMS into SoftICE, then you can read all the symbols in MFC. Be sure that MFC42.DLL matches MFC42.PDB. This also works for MFC70/MFC71 DLLs using MFC70.PDB/MFC71.PDB.

cRk
December 10th, 2003, 23:53
just set your break point as usual you'll be on the .dll code but after hitting couple of time F8 you'll be on the program code after C3 then you'll see the call in the program code which used the mfc...dll

Regards!

naides
December 11th, 2003, 17:18
Thank you all for the good will and time. While I am not done with it, I am certainly getting closer to solve the mistery.
Solomon suggestion was particularly helpful. I d/l MFC42.pdb and applied to Sice, and more importantly IDA, along with the VC++ FLIRT, and now most MFC42 ordinal calls have quite explicit names, which I can search in the MSDN site and have a clearer idea about the code.
The miniproject thread also contains some pointers that I was not able to find in Clandestiny and +spath's tuts.
Gr8, Thanks
N

naides
December 22nd, 2003, 15:58
An it did it.
Clandestiny Tut is a gem.

The way I was able to get out of the MFC code woods was by using the Backtrace device and catching the fleeting moments in which the code comes back from MFC42 into the App code. I compared the backtrace when a menu item was enabled with the trace when the menu item was grayed and forced towards the enabled path.

Note on the side: BPR does not work in Athlon AMD CPU (Old News ) and did not work in a Pentium 4. (Using windows 98 of course) Has anybody tried BPR in a P4?