PRB: One Cause of RIP 0x0140 in USER When Accessing Menu

ID Number: Q74736

3.00

WINDOWS

Summary:

SYMPTOMS

When running an application under the debugging version of Windows

3.0, USER fatal exits with error code 0x0140 when accessing a menu.

CAUSE

The TranslateAccelerator function is not re-entrant in Windows

version 3.0 and, if re-entered, is likely to cause a FatalExit

(RIP) 0x0140 when a menu is accessed.

Applications may use a separate message loop to perform background

processing for a process, such as repaginating a large document or

recalculating a large table. Often this process is started in

response to a particular WM_COMMAND message that may be generated

by a menu selection or a keyboard accelerator.

Inside this secondary message loop, the application may again call

TranslateAccelerator. When this process terminates and the original

WM_COMMAND message is completely processed, the menu will have been

destroyed.

RESOLUTION

To avoid this situation, an application should post a message to

itself to begin the processing. This allows TranslateAccelerator to

finish before the processing begins and the secondary message loop

is entered.

More Information:

When TranslateAccelerator detects a keystroke that is present in the

accelerator table, it sets a flag in the internal menu structure and

sends a WM_COMMAND message to the application. The flag set in the

structure indicates that TranslateAccelerator is in a SendMessage

state.

When this SendMessage call returns, TranslateAccelerator clears this

flag if it is set, or destroys the menu if it is clear. A menu must

only be destroyed when an accelerator caused a menu to be displayed.

This does not occur when an application is running in a normal or

maximized state.

If TranslateAccelerator is called a second time from within the

processing of the first WM_COMMAND message, it will clear the flag set

in the menu structure. When the first call to TranslateAccelerator

returns from its SendMessage, the cleared flag causes the

application's top-level menu to be destroyed. The next time the menu

is accessed, USER will RIP with code 0x0140: Invalid Local Handle

because the menu handle was invalidated with DestroyMenu.

By posting a message in response to the first WM_COMMAND message, the

application allows TranslateAccelerator to return from SendMessage and

exit, which ensures the menu state is properly maintained.