home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
oletyplb.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
6KB
|
223 lines
// 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();
}
}