Microsoft KB Archive/266713

= BUG: IDispatch:GetIDsOfNames function may return E_FAIL even when the call succeeds =

Article ID: 266713

Article Last Modified on 9/26/2005

-

APPLIES TO

 Microsoft ActiveX Template Library 3.0, when used with:  Microsoft Visual C++ 6.0 Enterprise Edition

 Microsoft Visual C++ 6.0 Professional Edition

 Microsoft Visual C++ 6.0 Standard Edition 

-

<div class="notice_section">

This article was previously published under Q266713

<div class="symptoms_section">

SYMPTOMS
The way that ATL implements the IDispatch::GetIDsOfNames function may result in E_FAIL being returned, even when the call succeeds.

<div class="cause_section">

CAUSE
When multiple threads call into an object's IDispatch::GetIDsOfNames function, the CComTypeInfoHolder::GetTI function is eventually called to load the type library and get the ITypeInfo interface. Because loading the type library and retrieving the interface are protected by a critical section, the second thread waits for the first thread to finish. Once the first thread releases the critical section, the second thread enters the critical section, finds m_pInfo is non-NULL (set by the first thread), and returns the hRes, which is set to E_FAIL. The IDispatch::GetIDsNames function eventually returns this E_FAIL.

<div class="resolution_section">

RESOLUTION
To work around this problem, the CComTypeInfoHolder::GetTI function in the Atlcom.h file must be modified as follows (all changes are marked with the comments &quot;ADD&quot; and &quot;END ADD&quot;): inline HRESULT CComTypeInfoHolder::GetTI(LCID lcid) {  // If this assert occurs, probably didn't initialize properly. ATLASSERT(m_plibid != NULL && m_pguid != NULL); ATLASSERT(!InlineIsEqualGUID(*m_plibid, GUID_NULL)      && &quot;Did you forget to pass the LIBID to CComModule::Init?&quot;);

if (m_pInfo != NULL) return S_OK; HRESULT hRes = E_FAIL; EnterCriticalSection(&_Module.m_csTypeInfoHolder); if (m_pInfo == NULL) {     ITypeLib* pTypeLib; hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib); if (SUCCEEDED(hRes)) {    CComPtr<ITypeInfo> spTypeInfo; hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo); if (SUCCEEDED(hRes)) {       CComPtr<ITypeInfo> spInfo(spTypeInfo); CComPtr<ITypeInfo2> spTypeInfo2; if (SUCCEEDED(spTypeInfo->QueryInterface(&spTypeInfo2))) spInfo = spTypeInfo2;

LoadNameCache(spInfo); m_pInfo = spInfo.Detach; }    pTypeLib->Release; }   }    //ADD else {   hRes = S_OK; }   //END ADD LeaveCriticalSection(&_Module.m_csTypeInfoHolder); _Module.AddTermFunc(Cleanup, (DWORD)this); return hRes; } Make these modifications to a copy of the Atlcom.h file (for example, Fixatlcom.h). Comment out Atlcom.h in the Stdafx.h file, and then use Fixatlcom.h instead, as follows: //#include <atlcom.h>
 * 1) include &quot;FixAtlCom.h&quot;

<div class="status_section">

STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed in the &quot;Applies to&quot; section.

Additional query words: IDispatch Invoke 0x80004005 80004005

Keywords: kbbug kbqfe kbpending kbhotfixserver KB266713

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.