// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #ifdef AFXCTL_CORE2_SEG #pragma code_seg(AFXCTL_CORE2_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// // CCmdTarget::EnableTypeLib - locks the typelib cache for this class void CCmdTarget::EnableTypeLib() { AfxLockGlobals(CRIT_TYPELIBCACHE); CTypeLibCache* pTypeLibCache = GetTypeLibCache(); ASSERT(pTypeLibCache != NULL); // must override GetTypeLibCache if (pTypeLibCache != NULL) pTypeLibCache->Lock(); // will be unlocked in OnFinalRelease AfxUnlockGlobals(CRIT_TYPELIBCACHE); } ///////////////////////////////////////////////////////////////////////////// // CCmdTarget::GetTypeInfoOfGuid - Returns typeinfo HRESULT CCmdTarget::GetTypeInfoOfGuid(LCID lcid, REFGUID guid, LPTYPEINFO* ppTypeInfo) { USES_CONVERSION; AfxLockGlobals(CRIT_TYPELIBCACHE); HRESULT hr = TYPE_E_CANTLOADLIBRARY; CTypeLibCache* pTypeLibCache = GetTypeLibCache(); LPTYPELIB pTypeLib = NULL; // If type info is already cached, just return it. if (pTypeLibCache->LookupTypeInfo(lcid, guid, ppTypeInfo)) { hr = S_OK; } else { // If type library isn't already cached, try to locate it. if (!pTypeLibCache->Lookup(lcid, &pTypeLib)) { // First, try getting the subclass to load the type library // (normally this goes through LoadRegTypeLib). if (FAILED(GetTypeLib(lcid, &pTypeLib))) { AFX_MANAGE_STATE(m_pModuleState); // If that failed, try loading the type library from our own // resources. TCHAR szPath[_MAX_PATH]; GetModuleFileName(AfxGetInstanceHandle(), szPath, _MAX_PATH); if (FAILED(LoadTypeLib(T2COLE(szPath), &pTypeLib))) pTypeLib = NULL; } pTypeLibCache->Cache(lcid, pTypeLib); } // If we got a type library, extract the requested type info. if (pTypeLib != NULL) { hr = pTypeLib->GetTypeInfoOfGuid(guid, ppTypeInfo); pTypeLib->Release(); pTypeLibCache->CacheTypeInfo(lcid, guid, *ppTypeInfo); } } AfxUnlockGlobals(CRIT_TYPELIBCACHE); return hr; } ///////////////////////////////////////////////////////////////////////////// // AfxGetTypeLibCache CTypeLibCache* AFXAPI AfxGetTypeLibCache(const GUID* pTypeLibID) { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); ASSERT(pModuleState != NULL); if (pModuleState->m_pTypeLibCacheMap == NULL) { const GUID* pCachedTypeLibID = pModuleState->m_typeLibCache.m_pTypeLibID; if (pCachedTypeLibID == NULL) { // Cache not initialized yet; initialize it now pModuleState->m_typeLibCache.m_pTypeLibID = pTypeLibID; return &pModuleState->m_typeLibCache; } else if (pCachedTypeLibID == pTypeLibID) { // This is the cache we need; return it return &pModuleState->m_typeLibCache; } else { // Another cache is needed; initialize the map pModuleState->m_pTypeLibCacheMap = new CTypeLibCacheMap; pModuleState->m_pTypeLibCacheMap->SetAt( (void*)(const void*)pModuleState->m_typeLibCache.m_pTypeLibID, &pModuleState->m_typeLibCache); // FALL THRU } } ASSERT(pModuleState->m_pTypeLibCacheMap != NULL); // Try to locate cache in the map CTypeLibCache* pCache; if (!pModuleState->m_pTypeLibCacheMap->Lookup((void*)(const void*)pTypeLibID, (void*&)pCache)) { // Create new cache and add it to the map pCache = new CTypeLibCache; pCache->m_pTypeLibID = pTypeLibID; pModuleState->m_pTypeLibCacheMap->SetAt((void*)(const void*)pTypeLibID, pCache); } ASSERT(pCache != NULL); ASSERT(pCache->m_pTypeLibID == pTypeLibID); return pCache; } ///////////////////////////////////////////////////////////////////////////// // CTypeLibCache // (Note: CTypeLibCache::Unlock is implemented in afxstate.cpp) void CTypeLibCache::Lock() { ASSERT(m_cRef >= 0); if (m_cRef == 0) m_lcid = (LCID)-1; InterlockedIncrement(&m_cRef); } BOOL CTypeLibCache::Lookup(LCID lcid, LPTYPELIB* pptlib) { if ((m_lcid != -1) && (m_lcid == lcid)) { ASSERT(m_ptlib != NULL); *pptlib = m_ptlib; m_ptlib->AddRef(); return TRUE; } else { *pptlib = NULL; return FALSE; } } void CTypeLibCache::Cache(LCID lcid, LPTYPELIB ptlib) { if (ptlib != NULL) { m_lcid = lcid; m_guidInfo = GUID_NULL; RELEASE(m_ptinfo); RELEASE(m_ptlib); m_ptlib = ptlib; m_ptlib->AddRef(); } } BOOL CTypeLibCache::LookupTypeInfo(LCID lcid, REFGUID guid, LPTYPEINFO* pptinfo) { if ((m_lcid != -1) && (m_lcid == lcid) && (m_ptinfo != NULL) && IsEqualGUID(m_guidInfo, guid)) { ASSERT(m_ptlib != NULL); ASSERT(m_ptinfo != NULL); *pptinfo = m_ptinfo; m_ptinfo->AddRef(); return TRUE; } else { *pptinfo = NULL; return FALSE; } } void CTypeLibCache::CacheTypeInfo(LCID lcid, REFGUID guid, LPTYPEINFO ptinfo) { if ((ptinfo != NULL) && (m_lcid == lcid)) { m_guidInfo = guid; RELEASE(m_ptinfo); m_ptinfo = ptinfo; m_ptinfo->AddRef(); } }