BUG: IDispatch:GetIDsOfNames function may return E_FAIL even when the call succeeds (266713)
The information in this article applies to:
- The Microsoft Active Template Library (ATL) 3.0, when used with:
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
This article was previously published under Q266713 SYMPTOMS
The way that ATL implements the IDispatch::GetIDsOfNames function may result in E_FAIL being returned, even when the call succeeds.
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.
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 "ADD" and "END ADD"):
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)
&& "Did you forget to pass the LIBID to CComModule::Init?");
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>
#include "FixAtlCom.h"
STATUSMicrosoft has confirmed that this is a bug in the Microsoft products that are listed in the "Applies to" section.
Modification Type: | Minor | Last Reviewed: | 9/26/2005 |
---|
Keywords: | kbHotfixServer kbQFE kbBug kbpending KB266713 kbAudDeveloper |
---|
|