GetMessage ignores posted messages received during the execution of a WinEvent callback

Article ID: 2682659 - View products that this article applies to.
Expand all | Collapse all

SYMPTOMS

GetMessage appears not to receive messages that are posted while a WinEvent callback function is being executed. If another message enters the queue, both messages will be received and processed.

CAUSE

There is a known issue with GetMessage and the use of WinEvent callbacks that themselves use Windows messages. GetMessage ignores a message that is received during the execution of the callback. Therefore, in particular, if the callback function calls PostThreadMessage, that message will not register until another message enters the queue (for example, due to a mouse movement); at that point, both the earlier posted message and the new message will register and be processed.

RESOLUTION

To work around this block, we recommend using MsgWaitForMultipleObjects and PeekMessage instead of GetMessage. It is also necessary to create a new event that can be sent from the WinEvent handler to wake up the message loop.

MORE INFORMATION

Here is a code fragment that includes a generic message loop and a WinEvent handler:


// Main message loop of thread that called SetWinEventHook while(GetMessage(&msg, NULL, 0, 0))
{
 ... process message here ...
}

void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD eventId,
HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread,
DWORD dwmsEventTime)
{
... process winevent here ...
}


GetMessage can block in the above fragment after failing to register a message sent from WinEventProc. Instead, use MsgWaitForMultipleObjects and PeekMessage together with declaring and using a special wake-up event from the handler back to the message loop, as shown in this fragment:

HANDLE ghMessageReadyEvent = NULL; // Event used to wake up the main thread

ghMessageReadyEvent = CreateEvent(NULL, FALSE/*bManualReset*/,
FALSE/*bIntialState*/, NULL);

// Main message loop of thread that called SetWinEventHook
//
// We can't reliably use GetMessage here. If a posted message is received
// while we're in a reentrant call to WinEventProc, when the WinEventProc
// returns, GetMessage does not recognize that a message has been
// received and just blocks. To avoid this we use
// MsgWaitForMultipleObjects + PeekMessage. Code at the end of the
// WinEventProc checks if a posted message was received during the
// callback using PeekMessage; if so, it sets the event which causes
/ MsgWaitForMultipleObjects to wake up.
//
// Note that MsgWaitForMultipleObjects usually only wakes up if a message
// is received during it. Even with QS_ALLPOSTMESSAGE, it only wakes up
// if a message is received between it and the most recent PeekMessage,
// so we have to call PeekMessage *before* calling it in case there are
// multiple queued-up messages.

for(;;)
{
BOOL fGot = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if(!fGot)
{
MsgWaitForMultipleObjects(1, &ghMessageReadyEvent,
FALSE/*bWaitAll*/, INFINITE,
QS_ALLEVENTS | QS_ALLPOSTMESSAGE);
fGot = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
}
if(!fGot)
{
continue;
}
... process message here ...
}


void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD eventId,
HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread,
DWORD dwmsEventTime)
{
... process winevent here ...

// Before we return, check if posted messages were received during this
// callback. If so, fire the event to ensure that we do process them.

MSG msg;
if(PeekMessage(&msg, (HWND)-1, WM_USER + 1, WM_USER + 2,
PM_NOREMOVE | PM_QS_POSTMESSAGE))
{
SetEvent(ghMessageReadyEvent);
}
}
Note This is a "FAST PUBLISH" article created directly from within the Microsoft support organization. The information contained herein is provided as-is in response to emerging issues. As a result of the speed in making it available, the materials may include typographical errors and may be revised at any time without notice. See Terms of Use for other considerations.

Properties

Article ID: 2682659 - Last Review: June 4, 2012 - Revision: 1.0
APPLIES TO
  • Windows Server 2008 Enterprise
  • Windows 7 Enterprise
  • Windows 7 Professional
  • Windows 7 Ultimate
  • Microsoft Windows Server 2003 R2 Datacenter Edition (32-Bit x86)
  • Microsoft Windows Server 2003 R2 Datacenter x64 Edition
  • Microsoft Windows Server 2003 R2 Datacenter x64 Edition with Service Pack 2
  • Microsoft Windows Server 2003 R2 Enterprise Edition (32-Bit x86)
  • Microsoft Windows Server 2003 R2 Enterprise Edition KN
  • Microsoft Windows Server 2003 R2 Enterprise x64 Edition
  • Microsoft Windows Server 2003 R2 Standard Edition (32-bit x86)
  • Microsoft Windows Server 2003 R2 Standard Edition KN
  • Microsoft Windows Server 2003 R2 Standard x64 Edition
  • Windows Vista Business
  • Windows Vista Business 64-bit Edition
  • Windows Vista Business N
  • Windows Vista Business N 64-bit Edition
  • Windows Vista Enterprise
  • Windows Vista Enterprise 64-bit Edition
  • Windows Vista Home Basic
  • Windows Vista Home Basic 64-bit Edition
  • Windows Vista Home Basic Beta
  • Windows Vista Home Basic N
  • Windows Vista Home Basic N 64-bit Edition
  • Windows Vista Home Premium
  • Windows Vista Home Premium 64-bit Edition
Keywords: 
KB2682659

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com