IME crashes when processing a window message sent from another thread

Describes a scenario where an Input Method Editor (IME) crashes while processing a window message sent from another thread, and where the window procedure handling the message calls an Imm* function such as ImmSetOpenStatus.

Symptoms

An application using an IME crashes under one of these conditions:

  • A user interface (UI) thread calls the TranslateMessage function as a part of the message loop.
  • Another thread sends a window message to a window owned by the UI thread.
  • The window procedure handling the window message sent by the other thread calls an Imm* function, such as ImmSetOpenStatus.

Cause

An IME included with Windows 10 may call the PeekMessage function when the IME is called by the TranslateMessage function to process a keyboard input. PeekMessage will process any pending window messages sent by other threads. This can result in a reentrancy issue when the window procedure processing the sent message calls an Imm* function and leaves the IME in an unexpected state.

Workaround

Avoid calling Imm* functions while the IME is processing another window message.

More information

The PeekMessage documentation contains the following:

During this call, the system delivers pending and non-queued messages sent to windows owned by the calling thread using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. The first queued message matching the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are processed in this order:

  • Sent messages
  • Posted messages
  • Input (hardware) messages and system internal events
  • Sent messages (again)
  • WM_PAINT messages
  • WM_TIMER messages

Note

Sent window messages are non-queued messages. The message filter specified when calling PeekMessage call doesn't apply to sent messages.