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 >
C/C++ Source or Header  |  1998-06-16  |  6KB  |  223 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFXCTL_CORE2_SEG
  14. #pragma code_seg(AFXCTL_CORE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CCmdTarget::EnableTypeLib - locks the typelib cache for this class
  26.  
  27. void CCmdTarget::EnableTypeLib()
  28. {
  29.     AfxLockGlobals(CRIT_TYPELIBCACHE);
  30.  
  31.     CTypeLibCache* pTypeLibCache = GetTypeLibCache();
  32.     ASSERT(pTypeLibCache != NULL);  // must override GetTypeLibCache
  33.  
  34.     if (pTypeLibCache != NULL)
  35.         pTypeLibCache->Lock();      // will be unlocked in OnFinalRelease
  36.  
  37.     AfxUnlockGlobals(CRIT_TYPELIBCACHE);
  38. }
  39.  
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CCmdTarget::GetTypeInfoOfGuid - Returns typeinfo
  42.  
  43. HRESULT CCmdTarget::GetTypeInfoOfGuid(LCID lcid, REFGUID guid,
  44.     LPTYPEINFO* ppTypeInfo)
  45. {
  46.     USES_CONVERSION;
  47.  
  48.     AfxLockGlobals(CRIT_TYPELIBCACHE);
  49.  
  50.     HRESULT hr = TYPE_E_CANTLOADLIBRARY;
  51.     CTypeLibCache* pTypeLibCache = GetTypeLibCache();
  52.     LPTYPELIB pTypeLib = NULL;
  53.  
  54.     // If type info is already cached, just return it.
  55.     if (pTypeLibCache->LookupTypeInfo(lcid, guid, ppTypeInfo))
  56.     {
  57.         hr = S_OK;
  58.     }
  59.     else
  60.     {
  61.         // If type library isn't already cached, try to locate it.
  62.         if (!pTypeLibCache->Lookup(lcid, &pTypeLib))
  63.         {
  64.             // First, try getting the subclass to load the type library
  65.             // (normally this goes through LoadRegTypeLib).
  66.  
  67.             if (FAILED(GetTypeLib(lcid, &pTypeLib)))
  68.             {
  69.                 AFX_MANAGE_STATE(m_pModuleState);
  70.  
  71.                 // If that failed, try loading the type library from our own
  72.                 // resources.
  73.  
  74.                 TCHAR szPath[_MAX_PATH];
  75.                 GetModuleFileName(AfxGetInstanceHandle(), szPath, _MAX_PATH);
  76.  
  77.                 if (FAILED(LoadTypeLib(T2COLE(szPath), &pTypeLib)))
  78.                     pTypeLib = NULL;
  79.             }
  80.  
  81.             pTypeLibCache->Cache(lcid, pTypeLib);
  82.         }
  83.  
  84.         // If we got a type library, extract the requested type info.
  85.         if (pTypeLib != NULL)
  86.         {
  87.             hr = pTypeLib->GetTypeInfoOfGuid(guid, ppTypeInfo);
  88.             pTypeLib->Release();
  89.             pTypeLibCache->CacheTypeInfo(lcid, guid, *ppTypeInfo);
  90.         }
  91.     }
  92.  
  93.     AfxUnlockGlobals(CRIT_TYPELIBCACHE);
  94.  
  95.     return hr;
  96. }
  97.  
  98. /////////////////////////////////////////////////////////////////////////////
  99. // AfxGetTypeLibCache
  100.  
  101. CTypeLibCache* AFXAPI AfxGetTypeLibCache(const GUID* pTypeLibID)
  102. {
  103.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  104.     ASSERT(pModuleState != NULL);
  105.  
  106.     if (pModuleState->m_pTypeLibCacheMap == NULL)
  107.     {
  108.         const GUID* pCachedTypeLibID = pModuleState->m_typeLibCache.m_pTypeLibID;
  109.  
  110.         if (pCachedTypeLibID == NULL)
  111.         {
  112.             // Cache not initialized yet; initialize it now
  113.             pModuleState->m_typeLibCache.m_pTypeLibID = pTypeLibID;
  114.             return &pModuleState->m_typeLibCache;
  115.         }
  116.         else if (pCachedTypeLibID == pTypeLibID)
  117.         {
  118.             // This is the cache we need; return it
  119.             return &pModuleState->m_typeLibCache;
  120.         }
  121.         else
  122.         {
  123.             // Another cache is needed; initialize the map
  124.             pModuleState->m_pTypeLibCacheMap = new CTypeLibCacheMap;
  125.             pModuleState->m_pTypeLibCacheMap->SetAt(
  126.                 (void*)(const void*)pModuleState->m_typeLibCache.m_pTypeLibID,
  127.                 &pModuleState->m_typeLibCache);
  128.  
  129.             // FALL THRU
  130.         }
  131.     }
  132.  
  133.     ASSERT(pModuleState->m_pTypeLibCacheMap != NULL);
  134.  
  135.     // Try to locate cache in the map
  136.     CTypeLibCache* pCache;
  137.     if (!pModuleState->m_pTypeLibCacheMap->Lookup((void*)(const void*)pTypeLibID,
  138.         (void*&)pCache))
  139.     {
  140.         // Create new cache and add it to the map
  141.         pCache = new CTypeLibCache;
  142.         pCache->m_pTypeLibID = pTypeLibID;
  143.         pModuleState->m_pTypeLibCacheMap->SetAt((void*)(const void*)pTypeLibID, pCache);
  144.     }
  145.  
  146.     ASSERT(pCache != NULL);
  147.     ASSERT(pCache->m_pTypeLibID == pTypeLibID);
  148.     return pCache;
  149. }
  150.  
  151. /////////////////////////////////////////////////////////////////////////////
  152. // CTypeLibCache
  153. // (Note: CTypeLibCache::Unlock is implemented in afxstate.cpp)
  154.  
  155. void CTypeLibCache::Lock()
  156. {
  157.     ASSERT(m_cRef >= 0);
  158.  
  159.     if (m_cRef == 0)
  160.         m_lcid = (LCID)-1;
  161.  
  162.     InterlockedIncrement(&m_cRef);
  163. }
  164.  
  165. BOOL CTypeLibCache::Lookup(LCID lcid, LPTYPELIB* pptlib)
  166. {
  167.     if ((m_lcid != -1) && (m_lcid == lcid))
  168.     {
  169.         ASSERT(m_ptlib != NULL);
  170.         *pptlib = m_ptlib;
  171.         m_ptlib->AddRef();
  172.         return TRUE;
  173.     }
  174.     else
  175.     {
  176.         *pptlib = NULL;
  177.         return FALSE;
  178.     }
  179. }
  180.  
  181. void CTypeLibCache::Cache(LCID lcid, LPTYPELIB ptlib)
  182. {
  183.     if (ptlib != NULL)
  184.     {
  185.         m_lcid = lcid;
  186.         m_guidInfo = GUID_NULL;
  187.         RELEASE(m_ptinfo);
  188.         RELEASE(m_ptlib);
  189.         m_ptlib = ptlib;
  190.         m_ptlib->AddRef();
  191.     }
  192. }
  193.  
  194. BOOL CTypeLibCache::LookupTypeInfo(LCID lcid, REFGUID guid,
  195.     LPTYPEINFO* pptinfo)
  196. {
  197.     if ((m_lcid != -1) && (m_lcid == lcid) && (m_ptinfo != NULL) &&
  198.         IsEqualGUID(m_guidInfo, guid))
  199.     {
  200.         ASSERT(m_ptlib != NULL);
  201.         ASSERT(m_ptinfo != NULL);
  202.         *pptinfo = m_ptinfo;
  203.         m_ptinfo->AddRef();
  204.         return TRUE;
  205.     }
  206.     else
  207.     {
  208.         *pptinfo = NULL;
  209.         return FALSE;
  210.     }
  211. }
  212.  
  213. void CTypeLibCache::CacheTypeInfo(LCID lcid, REFGUID guid, LPTYPEINFO ptinfo)
  214. {
  215.     if ((ptinfo != NULL) && (m_lcid == lcid))
  216.     {
  217.         m_guidInfo = guid;
  218.         RELEASE(m_ptinfo);
  219.         m_ptinfo = ptinfo;
  220.         m_ptinfo->AddRef();
  221.     }
  222. }
  223.