Microsoft KB Archive/179692

= An HRESULT of 0x80010005 error occurs when you try to call methods on a COM server in Visual C++ =

Article ID: 179692

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 4.2 Enterprise Edition

 Microsoft Visual C++ 4.2 Enterprise Edition

 Microsoft Visual C++ 5.0 Enterprise Edition

 Microsoft Visual C++ 6.0 Enterprise Edition</li></ul>

 Microsoft Visual C++ 4.2 Professional Edition</li></ul>

 Microsoft Visual C++ 4.2 Professional Edition</li></ul>

 Microsoft Visual C++ 5.0 Professional Edition</li></ul>

 Microsoft Visual C++ 6.0 Professional Edition</li></ul>

 Microsoft Visual C++ 6.0 Standard Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q179692

<div class="summary_section">

SUMMARY
When calling methods on a COM server from within OnDraw or a WM_PAINT message handler of an MFC client application, you may receive an HRESULT of 0x80010005 (RPC_E_CANTCALLOUT_INEXTERNALCALL - it is illegal to call out while inside message filter) as the return value of a COM call to a server.

<div class="moreinformation_section">

MORE INFORMATION
MFC has a default implementation of IMessageFilter(COleMessageFilter). IMessageFilter is used by COM servers and clients to selectively handle incoming and outgoing COM messages while waiting for a response from synchronous calls. MFC's implementation allows processing of WM_PAINT messages (to keep the UI updated) on the COM client side, while waiting on a synchronous COM call to a server (for example, a call to an automation method). This is done through IMessageFilter::MessagePending. Thus, when calling a COM server method inside of a WM_PAINT handler, you could already be in the middle of a call to the server, and therefore receive the error 0x80010005.

As with any Windows application, the code in WM_PAINT handlers should be minimal. If at all possible, do not have any calls to COM servers in WM_PAINT handlers.

To resolve this problem you could use any one of the following three workarounds:  In the WM_PAINT handler, post yourself a user-defined message; in the handler for the user-defined message, make the call to the COM server.</li> Create a secondary UI thread that creates and makes all calls to the COM servers.</li>  Modify MFC's default implementation of MessageFilter::MessagePending, which currently processes WM_PAINT messages. To do this, derive a class from COleMessageFilter and override the virtual function OnMessagePending: CMyMessageFilter : public COleMessageFilter {        virtual BOOL OnMessagePending(const MSG* pMsg); }

BOOL CMyMessageFilter::OnMessagePending(const MSG* pMsg) {        //The base class function dispatches WM_PAINT //by returning FALSE no messages are being processed; the //user can add code here to appropriately handle messages. //WARNING: Not processing WM_PAINT messages will cause the user //        interface to appear to hang and not update until the //        current COM method call returns. return FALSE; } </li></ul>

Then, in the InitInstance of the CWinApp derived class, unregister the IMessageFilter MFC registers for you when calling AfxOleInit. Add this code after the call to AfxOleInit. Then instantiate a class of type CMyMessageFilter and register it: BOOL CmyApp::InitInstance {     // Initialize OLE libraries and registers default message filter. if (!AfxOleInit) {        AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; }

CWinThread* pThread = AfxGetThread; if (pThread != NULL) {        // Destroy message filter, thereby unregistering it. delete pThread->m_pMessageFilter; pThread->m_pMessageFilter = NULL;

// Create the new message filter object. pThread->m_pMessageFilter = new CMyMessageFilter; ASSERT(AfxOleGetMessageFilter != NULL);

// Register the new message filter object. AfxOleGetMessageFilter->Register; }     ...      ...   } For more information on how message filters work, please see the online documentation on IMessageFilter and COleMessageFilter.

<div class="references_section">