hxpluginmanager.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:31k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: RCSL 1.0/RPSL 1.0
  3.  *
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
  5.  *
  6.  * The contents of this file, and the files included with this file, are
  7.  * subject to the current version of the RealNetworks Public Source License
  8.  * Version 1.0 (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the RealNetworks Community Source License Version 1.0
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
  12.  * in which case the RCSL will apply. You may also obtain the license terms
  13.  * directly from RealNetworks.  You may not use this file except in
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or
  16.  * RCSL for the rights, obligations and limitations governing use of the
  17.  * contents of the file.
  18.  *
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the
  20.  * developer of the Original Code and owns the copyrights in the portions
  21.  * it created.
  22.  *
  23.  * This file, and the files included with this file, is distributed and made
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  28.  *
  29.  * Technology Compatibility Kit Test Suite(s) Location:
  30.  *    http://www.helixcommunity.org/content/tck
  31.  *
  32.  * Contributor(s):
  33.  *
  34.  * ***** END LICENSE BLOCK ***** */
  35. #include "hxtypes.h"
  36. #include "hxassert.h"
  37. #include "debug.h"
  38. #include "hxcom.h"
  39. #include "hxccf.h"      // IHXCommonClassFactory
  40. #include "ihxpckts.h"   // IHXBuffer
  41. #include "hxplugn.h"    // IHXComponentPlugin
  42. #include "hxprefs.h" // IHXPreferences
  43. #include "hxprefutil.h"
  44. #include "findfile.h"
  45. #include "chxpckts.h"   // CHXHeader
  46. #include "dllacces.h"
  47. #include "dllpath.h"
  48. #include "pathutil.h"
  49. #include "hxver.h"
  50. #include "hxheap.h"
  51. #ifdef _DEBUG
  52. #undef HX_THIS_FILE
  53. static const char HX_THIS_FILE[] = __FILE__;
  54. #endif
  55. #if defined(_STATICALLY_LINKED)
  56. #include "staticff.h"
  57. #endif
  58. #include "hxpluginarchive.h"
  59. #include "hxplugindll.h"
  60. #include "hxplugin.h"
  61. #include "hxpluginmanager.h"
  62. #if(0)
  63. // helper
  64. static bool IsRealNetworksPlugin(HXPlugin* pPlugin)
  65. {
  66.     bool isRNPlugin = false;
  67.     HX_ASSERT(pPlugin);
  68.     IHXValues* pval = 0;
  69.     if (SUCCEEDED(pPlugin->GetPluginInfo(pval)))
  70.     {
  71.         IHXBuffer* pbuff = 0;
  72. if (SUCCEEDED(pval->GetPropertyCString(PLUGIN_DESCRIPTION2, pbuff)))
  73. {
  74.     isRNPlugin =  (0 != strstr((const char*)pbuff->GetBuffer(), "RealNetworks"));
  75.             HX_RELEASE(pbuff);
  76.         }
  77.         HX_RELEASE(pval);
  78.     }
  79.     return isRNPlugin;
  80. }
  81. #endif
  82. IMPLEMENT_COM_CREATE_FUNCS( HXPluginManager )
  83. BEGIN_INTERFACE_LIST_NOCREATE( HXPluginManager )
  84.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginEnumerator )
  85.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPlugin2Handler )
  86.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginHandler3 )
  87. END_INTERFACE_LIST
  88. HXPluginManager::HXPluginManager() 
  89. : m_pContext(0)
  90. , m_pClassFactory(0)
  91. {
  92. }
  93. HXPluginManager::~HXPluginManager()
  94. {
  95.     Close();
  96. }
  97. STDMETHODIMP HXPluginManager::Init(IUnknown* pContext)
  98. {
  99.     DPRINTF(D_INFO, ("HXPluginManager::Init()n"));
  100.     HX_RESULT result = HXR_FAIL;
  101.     if( SUCCEEDED( result = RegisterContext( pContext ) ) )
  102.     {
  103. result = ReadFromRegistry();
  104.     }
  105.     return result;
  106. }
  107. STDMETHODIMP_(ULONG32) HXPluginManager::GetNumOfPlugins2()
  108. {
  109.     return m_plugins.GetCount();
  110. }
  111. STDMETHODIMP
  112. HXPluginManager::GetPluginInfo(UINT32 unIndex, REF(IHXValues*) /*OUT*/ pValues)
  113. {
  114.     return HXR_NOTIMPL;
  115. }
  116. ///////////////////////////////////////////////////////////////////////////////
  117. //
  118. HX_RESULT HXPluginManager::ReloadPluginsNoPropagate()
  119. {
  120.     return ReloadPlugins();
  121. }
  122. ///////////////////////////////////////////////////////////////////////////////
  123. //
  124. HX_RESULT HXPluginManager::ReloadPlugins()
  125. {
  126.     DPRINTF(D_INFO, ("HXPluginManager()::ReloadPlugins()n"));
  127.     HX_RESULT result = HXR_OK;
  128.     // reload plugins for all mountpoints
  129.     for(CHXMapStringToString::Iterator iter = m_mountPoints.Begin(); iter != m_mountPoints.End(); ++iter)
  130.     {
  131. const char* pMountPoint = (const char*) *iter;
  132. if( FAILED( ReloadPlugins( pMountPoint ) ) )
  133. {
  134.     result = HXR_FAIL;
  135. }
  136.     }
  137.     return result;
  138. }
  139. /////////////////////////////////
  140. //
  141. // do we already have the given dll in our collection?
  142. //
  143. // we use case insensitive match in all OS/filesystem cases (even if technically inappropriate)
  144. //
  145. bool HXPluginManager::DoesDLLExist(const char* pszName, const char* pszMountPoint)
  146. {
  147.     CHXSimpleList::Iterator iter;
  148.     for(iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
  149.     {
  150. HXPluginDLL* pLib = (HXPluginDLL*) *iter;
  151.         if( !pLib->GetFileName().CompareNoCase(pszName) && !pLib->GetMountPoint().CompareNoCase(pszMountPoint) )
  152.         {
  153.             DPRINTF(D_INFO, ("HXPluginManager::DoesDLLExist(): plugin dll exists '%s'n", (const char*)pLib->GetFileName()));
  154.             return true;
  155.         }
  156.     }
  157.     for(iter = m_otherDlls.Begin(); iter != m_otherDlls.End(); ++iter)
  158.     {
  159. HXOtherDLL* pLib = (HXOtherDLL*) *iter;
  160.         if( !pLib->GetFileName().CompareNoCase(pszName) && !pLib->GetMountPoint().CompareNoCase(pszMountPoint) )
  161.         {
  162.             DPRINTF(D_INFO, ("HXPluginManager::DoesDLLExist(): other dll exists '%s'n", (const char*)pLib->GetFileName()));
  163.             return true;
  164.         }
  165.     }
  166.     return false;
  167. }
  168. HX_RESULT HXPluginManager::SaveToArchive(const char* pszArchiveFile)
  169. {
  170.     DPRINTF(D_INFO, ("SaveToArchive(): writing '%s' (%d plugin dlls; %d other dlls)n", pszArchiveFile, m_pluginDlls.GetCount(), m_otherDlls.GetCount()));
  171.     HXPluginArchiveWriter ar;
  172.     HX_RESULT hr = ar.Open(m_pContext, pszArchiveFile);
  173.     if(SUCCEEDED(hr))
  174.     {
  175.         CHXSimpleList::Iterator iter;
  176.         for(iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
  177.         {
  178.             HXPluginDLL* pLib = (HXPluginDLL*) *iter;
  179.             pLib->Archive(ar);
  180.         }
  181.         for(iter = m_otherDlls.Begin(); iter != m_otherDlls.End(); ++iter)
  182.         {
  183.             HXOtherDLL* pLib = (HXOtherDLL*) *iter;
  184.             pLib->Archive(ar);
  185.         }
  186.     }
  187.     ar.Close();
  188.     return hr;
  189. }
  190. HX_RESULT HXPluginManager::LoadPluginDLLFromArchive(const char* pszMountPoint, HXPluginArchiveReader& ar)
  191. {
  192.     HXPluginDLL* pPluginDLL = new HXPluginDLL(m_pContext, pszMountPoint, ar);
  193.     if( !pPluginDLL )
  194.     {
  195.         return HXR_OUTOFMEMORY;
  196.     }
  197.     pPluginDLL->AddRef();
  198.     HX_ASSERT(!DoesDLLExist(pPluginDLL->GetFileName(), pPluginDLL->GetMountPoint()));
  199.     // no need to load! that's the point of the archive
  200.     HX_ASSERT(pPluginDLL->GetNumPlugins() > 0);
  201.     m_pluginDlls.AddTail(pPluginDLL);
  202.     return HXR_OK;
  203. }
  204. HX_RESULT HXPluginManager::LoadOtherDLLFromArchive(const char* pszMountPoint, HXPluginArchiveReader& ar)
  205. {
  206.     HXOtherDLL* pOtherDLL = new HXOtherDLL(pszMountPoint, ar);
  207.     if( !pOtherDLL )
  208.     {
  209.         return HXR_OUTOFMEMORY;
  210.     }
  211.     pOtherDLL->AddRef();
  212.     HX_ASSERT(!DoesDLLExist(pOtherDLL->GetFileName(), pOtherDLL->GetMountPoint()));
  213.     m_otherDlls.AddTail(pOtherDLL);
  214.     return HXR_OK;
  215. }
  216. //
  217. // Try to re-construct plugin dll and associated plugin objects
  218. // from saved archive for faster plugin discovery
  219. //
  220. // If you want to override this (i.e., after new dlls installed), delete the archive
  221. //
  222. HX_RESULT HXPluginManager::LoadFromArchive(const char* pszArchiveFile, const char* pszMountPoint)
  223. {
  224.     DPRINTF(D_INFO, ("LoadFromArchive(): looking for '%s'n", pszArchiveFile));
  225.     HXPluginArchiveReader ar;
  226.     HX_RESULT hr = ar.Open(m_pContext, pszArchiveFile);
  227.     if(SUCCEEDED(hr))
  228.     {
  229.         while(SUCCEEDED(hr) && !ar.AtEnd())
  230.         {
  231.             UINT32 type;
  232.             ar.Read(type);
  233.             switch(type)
  234.             {
  235.             case ARCHIVE_ID_PLUGIN_DLL:
  236.                 hr = LoadPluginDLLFromArchive(pszMountPoint,ar);
  237.                 break;
  238.             case ARCHIVE_ID_OTHER_DLL:
  239.                 hr = LoadOtherDLLFromArchive(pszMountPoint, ar);
  240.                 break;
  241.             default:
  242.                 hr = HXR_FAIL;
  243.                 break;
  244.             }
  245.         }
  246.     
  247.         ar.Close();
  248.         DPRINTF(D_INFO, ("LoadFromArchive(): found %ld plugin dlls, %ld other dllsn", m_pluginDlls.GetCount(), m_otherDlls.GetCount()));
  249.     }
  250.     else
  251.     {
  252.         DPRINTF(D_INFO, ("LoadFromArchive(): archive missingn"));
  253.     }
  254.     return hr;
  255. }
  256. ///////////////////////////////////////////////////////////////////////////////
  257. //
  258. // 'query plugin dlls'
  259. //
  260. // load all plugin dlls and determine associated plugin attributes
  261. //
  262. // called when:
  263. //
  264. //   1) a mount point is added
  265. //   2) a mount point is removed and re-added (e.g., dynamic re-load)
  266. //
  267. // does nothing if dlls for mount point have already been loaded and queried
  268. //
  269. HX_RESULT HXPluginManager::ReloadPluginsWithFindFile(
  270.                const char* pMountPoint, CFindFile* pFileFinder,
  271.                IHXBuffer* pPathBuffer, const char* pszPluginDir)
  272. {
  273.     DPRINTF(D_INFO, ("HXPluginManager()::ReloadPluginsWithFindFile()n"));
  274.   
  275.     CHXString strArchiveFile;
  276.     IHXPreferences* pPrefs = 0;
  277.     m_pContext->QueryInterface(IID_IHXPreferences, (void**) &pPrefs);
  278.     HX_RESULT hr = ReadPrefCSTRING(pPrefs, "PluginArchiveFileName", strArchiveFile);
  279.     HX_RELEASE(pPrefs);
  280.     if(SUCCEEDED(hr))
  281.     {
  282.         // first try to recreate dll and plugin state from archive
  283.         hr = LoadFromArchive(strArchiveFile, pMountPoint); 
  284.     }
  285.     if(HXR_OUTOFMEMORY == hr)
  286.     {
  287.         return hr;
  288.     }
  289.     
  290.     // iterate files in this plugin directory
  291.     hr = HXR_OK;
  292.     bool bWriteArchive = false;
  293.     const char* pszDllName = pFileFinder->FindFirst();
  294.     for (; pszDllName; pszDllName = pFileFinder->FindNext())
  295.     {
  296.         if( DoesDLLExist(pszDllName, pMountPoint) )
  297.         {
  298.             // we already have info about this dll (perhaps from achive)
  299.             continue;
  300.         }
  301.         // since we found a dll we don't know about yet we need to update the archive
  302.         bWriteArchive = true;
  303.         // create plugin dll wrapper, assuming this is a plugin dll
  304.         HXPluginDLL* pPluginDll  = new HXPluginDLL(m_pContext, pszDllName, pMountPoint);
  305.         if(!pPluginDll)
  306.         {
  307.             // oom
  308.     hr = HXR_OUTOFMEMORY;
  309.             break;
  310.         }
  311.         pPluginDll->AddRef();
  312.         // load dll to force query of supported plugins
  313.         hr = pPluginDll->Load();
  314.         if (SUCCEEDED(hr))
  315.         {
  316.             // add successfully loaded dll to list
  317.             pPluginDll->AddRef();
  318.             m_pluginDlls.AddTail(pPluginDll);
  319.             // Unload the dll. The dll was loaded only to query supported plugin 
  320.             // info. It will be re-loaded only when actually needed, i.e., when
  321.             // an instance of a plugin that it implements is requested.
  322.             pPluginDll->Unload();
  323.         }
  324.         HX_RELEASE(pPluginDll);
  325.         if (FAILED(hr))
  326.         {
  327.             if(HXR_OUTOFMEMORY == hr)
  328.             {
  329.                 break;
  330.             }
  331.             // lib load attempt failed; add this to 'other' dll list (maybe it is a codec dll, e.g.)
  332.             HXOtherDLL* pOtherDll  = new HXOtherDLL(pszDllName, pMountPoint);
  333.             if( !pOtherDll)
  334.             {
  335.                 //oom
  336.                 hr = HXR_OUTOFMEMORY;
  337.                 break;
  338.             }
  339.             pOtherDll->AddRef();
  340.             m_otherDlls.AddTail(pOtherDll);
  341.             bWriteArchive = true;
  342.         }
  343.     }
  344.     RebuildPluginList();
  345.     // write archive now if it needs updating
  346.     if(bWriteArchive)
  347.     {
  348.         SaveToArchive(strArchiveFile);
  349.     }
  350.     return hr;
  351. }
  352. ///////////////////////////////////////////////////////////////////////////////
  353. //
  354. HX_RESULT HXPluginManager::ReloadPlugins( const char* pMountPoint )
  355. {
  356.     CFindFile* pFileFinder = NULL;
  357.     IHXBuffer* pPathBuffer = NULL;
  358.     HX_RESULT hr = HXR_FAIL;
  359.     HX_ASSERT(m_pContext);
  360.     if (m_pContext)
  361.     {
  362. #if defined(_STATICALLY_LINKED) && !defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  363.         const char* const pszPluginDir = "";
  364.         pFileFinder = CStaticFindFile::CreateFindFile(pszPluginDir,0, OS_DLL_PATTERN_STRING);
  365. #else
  366.         const char* const pszPluginDir = pMountPoint;
  367.         pFileFinder = CFindFile::CreateFindFile(pszPluginDir, 0, OS_DLL_PATTERN_STRING);
  368. #endif
  369.         
  370.         if (pFileFinder)
  371.         {
  372.             hr = ReloadPluginsWithFindFile(pMountPoint, pFileFinder, pPathBuffer, pszPluginDir);
  373.             HX_DELETE(pFileFinder);
  374.         }
  375.     }
  376.     return hr;
  377. }
  378. STDMETHODIMP HXPluginManager::FindIndexUsingValues(IHXValues* pValues,REF(UINT32) unIndex)
  379. {
  380.     return HXR_NOTIMPL;
  381. }
  382. STDMETHODIMP HXPluginManager::GetInstance (UINT32 index, REF(IUnknown*) pUnknown)
  383. {
  384.     pUnknown = NULL;
  385.     LISTPOSITION pPos = m_plugins.FindIndex(index);
  386.     if (pPos)
  387.     {
  388. HXPlugin* pPlugin = (HXPlugin*) m_plugins.GetAt(pPos);
  389. if (pPlugin)
  390. {
  391.     return pPlugin->GetInstance(pUnknown);
  392. }
  393.     }
  394.     return HXR_FAIL;
  395. }
  396. STDMETHODIMP HXPluginManager::FindIndexUsingStrings (char* PropName1,
  397.     char* PropVal1,
  398.     char* PropName2,
  399.     char* PropVal2,
  400.     char* PropName3,
  401.     char* PropVal3,
  402.     REF(UINT32) unIndex)
  403. {
  404.     return HXR_NOTIMPL;
  405. }
  406. STDMETHODIMP HXPluginManager::FindPluginUsingValues(IHXValues* pValues,REF(IUnknown*) pUnk)
  407. {
  408.     return FindPluginUsingValues( pValues, pUnk, NULL );
  409. }
  410. HX_RESULT HXPluginManager::FindGroupOfPluginsUsingStrings(char* PropName1,
  411.     char* PropVal1,
  412.     char* PropName2,
  413.     char* PropVal2,
  414.     char* PropName3,
  415.     char* PropVal3,
  416.     REF(HXPluginEnumerator*) pEnumerator)
  417. {
  418.     DPRINTF(D_INFO, ("HXPluginManager()::FindGroupOfPluginsUsingStrings(): '%s' = '%s', etc.n", PropName1, PropVal1));
  419.     // PropName and PropVal have to to valid tuple
  420.     if ((PropName1 && !PropVal1)    ||
  421. (PropName2 && !PropVal2)    ||
  422. (PropName3 && !PropVal3)    ||
  423. (!PropName1 && PropVal1)    ||
  424. (!PropName2 && PropVal2)    ||
  425. (!PropName3 && PropVal3))
  426. return HXR_FAIL;
  427.     IHXValues* pValues;
  428.     HX_RESULT   retVal = HXR_FAIL;
  429.     CHXHeader* pHeader = new CHXHeader;
  430.     pHeader->QueryInterface(IID_IHXValues,  (void**)&pValues);
  431.     AddToValues(pValues, PropName1, PropVal1, eString);
  432.     AddToValues(pValues, PropName2, PropVal2, eString);
  433.     AddToValues(pValues, PropName3, PropVal3, eString);
  434.     retVal = FindGroupOfPluginsUsingValues(pValues, pEnumerator);
  435.     pValues->Release();
  436.     return retVal;
  437. }
  438. HX_RESULT HXPluginManager::FindGroupOfPluginsUsingValues(IHXValues* pValues,
  439. REF(HXPluginEnumerator*) pEnumerator)
  440. {
  441.     
  442.     HX_RESULT hr = HXR_FAIL;
  443.     pEnumerator = NULL;
  444.     for(CHXSimpleList::Iterator iter = m_plugins.Begin();
  445.         iter != m_plugins.End(); ++iter)
  446.     {
  447. HXPlugin* pPlugin = (HXPlugin*) *iter;
  448. if (pPlugin->DoesMatch(pValues))
  449. {
  450.     if (!pEnumerator)
  451.     {
  452. pEnumerator = new HXPluginEnumerator();
  453.                 if(pEnumerator)
  454.                 {
  455.                     hr = HXR_OK;
  456.                 }
  457.                 else
  458.                 {
  459.                     hr = HXR_OUTOFMEMORY;
  460.                     break;
  461.                 }
  462.     }
  463.     
  464.             pEnumerator->Add(pPlugin); 
  465.         }
  466.     }
  467.     return hr;
  468. }
  469. // IHXPluginHandler3
  470. STDMETHODIMP
  471. HXPluginManager::RegisterContext( IUnknown* pContext )
  472. {
  473.     HX_ASSERT(pContext);
  474.     if( !pContext )
  475.     {
  476. return HXR_INVALID_PARAMETER;
  477.     }
  478.     if( m_pContext )
  479.     {
  480. return HXR_UNEXPECTED;
  481.     }
  482.     m_pContext = pContext;
  483.     m_pContext->AddRef();
  484.     m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_pClassFactory);
  485.     return HXR_OK;
  486. }
  487. // IHXPluginHandler3
  488. STDMETHODIMP
  489. HXPluginManager::AddPluginMountPoint( const char* pName, UINT32 majorVersion, UINT32 minorVersion, IHXBuffer* pPath )
  490. {
  491.     DPRINTF(D_INFO, ("HXPluginManager()::AddPluginMountPoint(): name = '%s'n", pName));
  492.     const char* pMPKey = pName ? pName : (const char*) pPath->GetBuffer();
  493.     // Make sure this mount point is in the list
  494.     CHXString strMountPoint;
  495.     if( !m_mountPoints.Lookup(pMPKey, strMountPoint) && pPath )
  496.     {
  497.         strMountPoint = (const char*)pPath->GetBuffer();
  498.         
  499.         // Put new mount point in list
  500.         m_mountPoints.SetAt( pMPKey, strMountPoint );
  501.     }
  502.     // Load information from registry, and sync DLLs that aren't up to date
  503.     return ReloadPlugins( strMountPoint );
  504. }
  505. // IHXPluginHandler3
  506. STDMETHODIMP
  507. HXPluginManager::RefreshPluginMountPoint( const char* pName )
  508. {
  509.     HX_RESULT result = HXR_FAIL;
  510.     CHXString strMountPoint;
  511.     if( m_mountPoints.Lookup( pName, strMountPoint ) )
  512.     {
  513. result = ReloadPlugins( strMountPoint );
  514.     }
  515.     return result;
  516. }
  517. // IHXPluginHandler3
  518. STDMETHODIMP
  519. HXPluginManager::RemovePluginMountPoint( const char* pName )
  520. {
  521.     HX_RESULT hr = HXR_FAIL;
  522.     CHXString strMountPoint;
  523.     if( m_mountPoints.Lookup( pName, strMountPoint ) )
  524.     {
  525. // Clean up plugin dlls associated with mountpoint
  526. LISTPOSITION listPos = m_pluginDlls.GetHeadPosition();
  527. while( listPos )
  528. {
  529.     LISTPOSITION curPos = listPos;
  530.     HXPluginDLL* pLibrary = (HXPluginDLL*) m_pluginDlls.GetNext( listPos );
  531.     if( pLibrary && ( pLibrary->GetMountPoint() == strMountPoint ) )
  532.     {
  533. m_pluginDlls.RemoveAt( curPos ); 
  534.                 pLibrary->Unload(); // just in case; this should be last ref
  535. HX_RELEASE( pLibrary );
  536.     }
  537. }
  538.         
  539.         // Clean up 'other' dlls associated with mountpoint
  540.         listPos = m_otherDlls.GetHeadPosition();
  541. while( listPos )
  542. {
  543.     LISTPOSITION curPos = listPos;
  544.     HXOtherDLL* pLibrary = (HXOtherDLL*) m_otherDlls.GetNext( listPos );
  545.     if( pLibrary && ( pLibrary->GetMountPoint() == strMountPoint ) )
  546.     {
  547. m_otherDlls.RemoveAt( curPos ); 
  548. HX_RELEASE( pLibrary );
  549.     }
  550. }
  551.        
  552. m_mountPoints.RemoveKey( pName );
  553.         // Plugin list must be rebuilt
  554.         RebuildPluginList();
  555.         hr = HXR_OK;
  556.     }
  557.     return hr;
  558. }
  559. //
  560. // called every time dll list has been altered (we could be more efficient in many cases)
  561. //
  562. void HXPluginManager::RebuildPluginList()
  563. {
  564.     DPRINTF(D_INFO, ("HXPluginManager()::RebuildPluginList()n"));
  565.     CHXSimpleList::Iterator iter;
  566.         
  567.     // clean up (now invalid) plugin list
  568.     for(iter = m_plugins.Begin(); iter != m_plugins.End(); ++iter)
  569.     {
  570. HXPlugin* pPlugin = (HXPlugin*) *iter;
  571. pPlugin->Release();
  572.     }
  573.     m_plugins.RemoveAll();
  574.     // rebuild list of plugins we can instanciate
  575.     for(iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
  576.     {
  577. HXPluginDLL* pLibrary = (HXPluginDLL*) *iter;
  578.         pLibrary->AddPlugins(m_plugins);
  579.     }
  580. }
  581. STDMETHODIMP
  582. HXPluginManager::FindImplementationFromClassID( REFGUID GUIDClassID, REF(IUnknown*) pIUnknownInstance,
  583.     IUnknown* pIUnkOuter, IUnknown* pContext )
  584. {
  585.     DPRINTF(D_INFO, ("HXPluginManager()::FindImplementationFromClassID()n"));
  586.     HX_RESULT     rc = HXR_OK;
  587.     IUnknown*     pUnknown = NULL;
  588.     IHXPlugin*     pPlugin = NULL;
  589.     IHXCommonClassFactory*     pFactory = NULL;
  590.     IHXPluginSearchEnumerator*     pPluginEnumerator = NULL;
  591.     // a much simpler version than Plugin2Handler, it's not as efficient as Plugin2Handler but it
  592.     // should be good enough for static build.
  593.     
  594.     pIUnknownInstance = NULL;
  595.     rc = FindGroupOfPluginsUsingStrings(PLUGIN_CLASS, PLUGIN_CLASS_FACTORY_TYPE,
  596. NULL, NULL, NULL, NULL, pPluginEnumerator);
  597.     if (SUCCEEDED(rc))
  598.     {
  599.         while (HXR_OK == pPluginEnumerator->GetNextPlugin(pUnknown, NULL) && pUnknown)
  600.         {
  601.     if (HXR_OK == pUnknown->QueryInterface(IID_IHXPlugin, (void**)&pPlugin))
  602.     {
  603.         pPlugin->InitPlugin(pContext);
  604.         if (HXR_OK == pUnknown->QueryInterface(IID_IHXCommonClassFactory, (void**)&pFactory))
  605.         {
  606.     if (HXR_OK == pFactory->CreateInstance(GUIDClassID, (void**)&pIUnknownInstance) &&
  607.         pIUnknownInstance)
  608.     {
  609.         break;
  610.     }
  611.     HX_RELEASE(pIUnknownInstance);
  612.         }
  613.         HX_RELEASE(pFactory);
  614.     }
  615.     HX_RELEASE(pPlugin);
  616.     HX_RELEASE(pUnknown);
  617.         }
  618.         if (!pIUnknownInstance)
  619.         {
  620.     rc = HXR_FAILED;
  621.         }
  622.     }
  623.     // cleanup
  624.     HX_RELEASE(pFactory);
  625.     HX_RELEASE(pPlugin);
  626.     HX_RELEASE(pUnknown);
  627.     HX_RELEASE(pPluginEnumerator);
  628.     return rc;
  629. }
  630. STDMETHODIMP
  631. HXPluginManager::FindCLSIDFromName( const char* pName, REF(IHXBuffer*) pCLSID )
  632. {
  633.     return HXR_NOTIMPL;
  634. }
  635. STDMETHODIMP
  636. HXPluginManager::FindGroupOfPluginsUsingValues( IHXValues* pValues,
  637. REF(IHXPluginSearchEnumerator*) pIEnumerator)
  638. {
  639.     return HXR_NOTIMPL;
  640. }
  641. STDMETHODIMP
  642. HXPluginManager::FindGroupOfPluginsUsingStrings( char* PropName1, char* PropVal1,
  643. char* PropName2, char* PropVal2,
  644. char* PropName3, char* PropVal3,
  645. REF(IHXPluginSearchEnumerator*) pIEnumerator)
  646. {
  647.     DPRINTF(D_INFO, ("HXPluginManager()::FindGroupOfPluginsUsingStrings()n"));
  648.     // Regardless of how the API can be used, the reality is that this function
  649.     // is essentially the highest level point of access for the core when
  650.     // starting playback of a new stream, so this is a great time to unload
  651.     // all our dead dlls.
  652.     // But the memory efficiency of DLL unloading comes at the expense of
  653.     // setup time, so we probably only want to do this on platforms where
  654.     // memory optimization is our highest priority.
  655. #if defined(HELIX_CONFIG_UNLOAD_DEAD_DLLS)
  656.     UnloadDeadDLLs();
  657. #endif
  658.     // Initialize out params
  659.     pIEnumerator = NULL;
  660.     // Use the internal function to build up an enumerator object
  661.     HXPluginEnumerator* pEnumerator = NULL;
  662.     HX_RESULT result = FindGroupOfPluginsUsingStrings( PropName1, PropVal1,
  663.     PropName2, PropVal2, PropName3, PropVal3, pEnumerator );
  664.     // If we have our enumerator, get the appropriate interface
  665.     if( SUCCEEDED( result ) )
  666.     {
  667. result = pEnumerator->QueryInterface( IID_IHXPluginSearchEnumerator,
  668. (void**) &pIEnumerator );
  669.     }
  670.     return result;
  671. }
  672. STDMETHODIMP
  673. HXPluginManager::FindPluginUsingValues( IHXValues* pCriteria,
  674. REF(IUnknown*) pIUnkResult,
  675. IUnknown* pIUnkOuter )
  676. {
  677.     DPRINTF(D_INFO, ("HXPluginManager()::FindPluginUsingValues()n"));
  678.     // out
  679.     pIUnkResult = NULL;
  680.     CHXSimpleList   matches;
  681.     CHXSimpleList::Iterator iter = m_plugins.Begin();
  682.     for(; iter != m_plugins.End(); ++iter)
  683.     {
  684. HXPlugin* pPlugin = (HXPlugin*) *iter;
  685. if (pPlugin->DoesMatch(pCriteria))
  686. {
  687.     matches.AddTail(pPlugin);
  688. }
  689.     }
  690.     HX_RESULT hr = HXR_FAIL;
  691.     if (matches.GetCount() > 0)
  692.     {
  693.         // return first match by default
  694.         HXPlugin* pPlug = (HXPlugin*) *(matches.Begin());
  695. #if (0)
  696.         if (matches.GetCount() > 1)
  697.         {
  698.             //
  699.             // strategy:
  700.             //
  701.             // with multiple matching plugins, pick first one with description "RealNetworks"
  702.             //
  703.     for(iter = matches.Begin(); iter != matches.End(); ++iter)
  704.     {
  705.                 HXPlugin* pThisPlugin = (HXPlugin*) *iter;
  706.                 if( IsRealNetworksPlugin(pThisPlugin) )
  707.                 {
  708.                     // use this one
  709.                     pPlug = pThisPlugin;
  710.                     break;
  711.             
  712.                 }
  713.     }
  714.         }
  715. #endif
  716.         hr = pPlug->GetInstance( pIUnkResult, pIUnkOuter );
  717.     }
  718.     return hr;
  719. }
  720. STDMETHODIMP
  721. HXPluginManager::FindPluginUsingStrings( char* PropName1, char* PropVal1,
  722. char* PropName2, char* PropVal2,
  723. char* PropName3, char* PropVal3,
  724. REF(IUnknown*) pIUnkResult,
  725. IUnknown* pIUnkOuter )
  726. {
  727.     DPRINTF(D_INFO, ("HXPluginManager()::FindPluginUsingStrings()n"));
  728.     
  729.     // out 
  730.     pIUnkResult = NULL;
  731.     // PropName and PropVal have to to valid tuple
  732.     if ((PropName1 && !PropVal1)    ||
  733. (PropName2 && !PropVal2)    ||
  734. (PropName3 && !PropVal3)    ||
  735. (!PropName1 && PropVal1)    ||
  736. (!PropName2 && PropVal2)    ||
  737. (!PropName3 && PropVal3))
  738. return HXR_FAIL;
  739.     IHXValues* pValues;
  740.     HX_RESULT   retVal = HXR_FAIL;
  741.     CHXHeader* pHeader = new CHXHeader();
  742.     pHeader->QueryInterface(IID_IHXValues,  (void**)&pValues);
  743.     AddToValues(pValues, PropName1, PropVal1, eString);
  744.     AddToValues(pValues, PropName2, PropVal2, eString);
  745.     AddToValues(pValues, PropName3, PropVal3, eString);
  746.     retVal = FindPluginUsingValues( pValues, pIUnkResult, pIUnkOuter );
  747.     pValues->Release();
  748.     return retVal;
  749. }
  750. //
  751. // Call Unload() on each plugins (library unloads only if no plugin references)
  752. //
  753. void
  754. HXPluginManager::UnloadDeadDLLs()
  755. {
  756.     DPRINTF(D_INFO, ("HXPluginManager()::UnloadDeadDLLs()n"));
  757.     
  758.     for(CHXSimpleList::Iterator iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
  759.     {
  760. HXPluginDLL* pPlugDLL = (HXPluginDLL*) *iter;
  761. pPlugDLL->Unload();
  762.     }
  763. }
  764. STDMETHODIMP
  765. HXPluginManager::GetPlugin( ULONG32 ulIndex, REF(IUnknown*) pIUnkResult,
  766.     IUnknown* pIUnkOuter )
  767. {
  768.     if( ulIndex <= (ULONG32)(m_plugins.GetCount()-1) && m_plugins.GetCount() )
  769.     {
  770. LISTPOSITION pPos = m_plugins.FindIndex( ulIndex );
  771. if (pPos)
  772. {
  773.     HXPlugin* pPlugin = (HXPlugin*) m_plugins.GetAt( pPos );
  774.     if( pPlugin )
  775.     {
  776. return pPlugin->GetInstance( pIUnkResult, pIUnkOuter );
  777.     }
  778. }
  779.     }
  780.     return HXR_FAIL;
  781. }
  782. STDMETHODIMP
  783. HXPluginManager::UnloadPluginFromClassID(REFGUID GUIDClassID)
  784. {
  785.     return HXR_NOTIMPL;
  786. }
  787. STDMETHODIMP
  788. HXPluginManager::UnloadPackageByName(const char* pName)
  789. {
  790.     return HXR_NOTIMPL;
  791. }
  792. STDMETHODIMP HXPluginManager::FindPluginUsingStrings (char* PropName1,
  793.     char* PropVal1,
  794.     char* PropName2,
  795.     char* PropVal2,
  796.     char* PropName3,
  797.     char* PropVal3,
  798.     REF(IUnknown*) pRetUnk)
  799. {
  800.     return FindPluginUsingStrings( PropName1, PropVal1, PropName2, PropVal2,
  801.    PropName3, PropVal3, pRetUnk, NULL );
  802. }
  803. STDMETHODIMP
  804. HXPluginManager::FindImplementationFromClassID
  805. (
  806.     REFGUID GUIDClassID,
  807.     REF(IUnknown*) pIUnknownInstance
  808. )
  809. {
  810.     return FindImplementationFromClassID( GUIDClassID, pIUnknownInstance, NULL, m_pContext );
  811. }
  812. STDMETHODIMP HXPluginManager::Close()
  813. {
  814.     DPRINTF(D_INFO, ("HXPluginManager()::Close()n"));
  815.     // Release all dlls and associated plugins
  816.    
  817.     CHXSimpleList::Iterator iter;
  818.        
  819.     //HXPlugin
  820.     for(iter = m_plugins.Begin(); iter != m_plugins.End(); ++iter)
  821.     {
  822. HXPlugin* pPlugin = (HXPlugin*) *iter;
  823. pPlugin->Release();
  824.     }
  825.     m_plugins.RemoveAll();
  826.  
  827.     //HXPluginDLL
  828.     for(iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
  829.     {
  830. HXPluginDLL* pLib = (HXPluginDLL*) *iter;
  831. pLib->Release();
  832.     }
  833.     m_pluginDlls.RemoveAll();
  834.     //HXOtherDLL
  835.     for(iter = m_otherDlls.Begin(); iter != m_otherDlls.End(); ++iter)
  836.     {
  837. HXOtherDLL* pLib = (HXOtherDLL*) *iter;
  838. pLib->Release();
  839.     }
  840.     m_otherDlls.RemoveAll();
  841.     m_mountPoints.RemoveAll();
  842.     HX_RELEASE(m_pContext);
  843.     HX_RELEASE(m_pClassFactory);
  844.     return HXR_OK;
  845. }
  846. STDMETHODIMP HXPluginManager::SetRequiredPlugins (const char** ppszRequiredPlugins)
  847. {
  848.     return HXR_OK;
  849. }
  850. HX_RESULT HXPluginManager::AddToValues(IHXValues* pValues, char* pPropName, char* pPropVal, eValueTypes eValueType)
  851. {
  852.     if (!pPropName || !pPropVal)
  853. return HXR_FAIL;
  854.     // trim value
  855.     CHXString theValue = (pPropVal);
  856.     theValue.TrimLeft();
  857.     theValue.TrimRight();
  858.     HX_RESULT hr = HXR_OK;
  859.     switch (eValueType)
  860.     {
  861. case eString:
  862. {
  863.     IHXBuffer* pBuffer;
  864.     CHXBuffer* pCHXBuffer;
  865.     pCHXBuffer = new CHXBuffer;
  866.     pCHXBuffer->QueryInterface(IID_IHXBuffer, (void**) &pBuffer);
  867.     pBuffer->Set((const unsigned char*)(const char*)theValue, strlen(theValue)+1);
  868.     pValues->SetPropertyCString(pPropName, pBuffer);
  869.     pBuffer->Release();
  870.             break;
  871. }
  872. case eInt:
  873. {
  874.     int val = atoi(theValue);
  875.     pValues->SetPropertyULONG32(pPropName, (ULONG32)val);
  876.     break;
  877. }
  878.         default:
  879.             hr = HXR_NOTIMPL;
  880.             break;
  881.     }
  882.     return hr;
  883. }
  884. STDMETHODIMP_(ULONG32) HXPluginManager::GetNumOfPlugins()
  885. {
  886.     return m_plugins.GetCount();
  887. }
  888. STDMETHODIMP HXPluginManager::GetPlugin(ULONG32 ulIndex, REF(IUnknown*)  /*OUT*/ pInstance)
  889. {
  890.     return GetPlugin( ulIndex, pInstance, NULL );
  891. }
  892. STDMETHODIMP HXPluginManager::FlushCache()
  893. {
  894.     return HXR_OK;
  895. }
  896. STDMETHODIMP HXPluginManager::SetCacheSize(ULONG32 nSizeKB)
  897. {
  898.     return HXR_OK;
  899. }
  900. STDMETHODIMP HXPluginManager::ReadFromRegistry()
  901. {
  902.     DPRINTF(D_INFO, ("HXPluginManager()::ReadFromRegistry()n"));
  903.     HX_RESULT result;
  904.     IHXBuffer* pBuffer = NULL;
  905. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  906.     const char* pPath = GetDLLAccessPath()->GetPath(DLLTYPE_PLUGIN);
  907.     pBuffer = HXBufferUtil::CreateBuffer(m_pClassFactory, pPath);
  908. #endif
  909.     // Set up a mount point with the default plugin location
  910.     result = AddPluginMountPoint(HXVER_SDK_PRODUCT, 0, 0, pBuffer);
  911.     HX_RELEASE(pBuffer);
  912.     return result;
  913. }
  914. /********************************************************************
  915. *
  916. * Plugin Enumeration
  917. *
  918. ********************************************************************/
  919. BEGIN_INTERFACE_LIST_NOCREATE( HXPluginEnumerator )
  920.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginSearchEnumerator )
  921. END_INTERFACE_LIST
  922. HXPluginEnumerator::HXPluginEnumerator() :
  923.     m_nIndex(0)
  924. {
  925. }
  926. HXPluginEnumerator::~HXPluginEnumerator()
  927. {
  928. }
  929. STDMETHODIMP_( UINT32 )
  930. HXPluginEnumerator::GetNumPlugins()
  931. {
  932.     return m_plugins.GetCount();
  933. }
  934. STDMETHODIMP_( void )
  935. HXPluginEnumerator::GoHead()
  936. {
  937.     m_nIndex = 0;
  938. }
  939. STDMETHODIMP
  940. HXPluginEnumerator::GetNextPlugin( REF(IUnknown*) pIUnkResult, IUnknown* pIUnkOuter )
  941. {
  942.     // Initialize out params
  943.     pIUnkResult = NULL;
  944.     HX_RESULT res = GetPluginAt( m_nIndex, pIUnkResult, pIUnkOuter );
  945.     m_nIndex++;
  946.     return res;
  947. }
  948. STDMETHODIMP
  949. HXPluginEnumerator::GetNextPluginInfo( REF(IHXValues*) pRetValues )
  950. {
  951.     pRetValues = NULL;
  952.     HX_RESULT res = GetPluginInfoAt( m_nIndex, pRetValues );
  953.     m_nIndex++;
  954.     return res;
  955. }
  956. STDMETHODIMP
  957. HXPluginEnumerator::GetPluginAt( UINT32 index, REF(IUnknown*) pIUnkResult, IUnknown* pIUnkOuter )
  958. {
  959.     pIUnkResult = NULL;
  960.     HX_RESULT res = HXR_FAIL;
  961.     LISTPOSITION pos = m_plugins.FindIndex(index);
  962.     if (pos)
  963.     {
  964. HXPlugin* pPlugin = (HXPlugin*) m_plugins.GetAt(pos);
  965. if (pPlugin)
  966. {
  967.     res = pPlugin->GetInstance( pIUnkResult, pIUnkOuter );
  968. }
  969.     }
  970.     return res;
  971. }
  972. STDMETHODIMP
  973. HXPluginEnumerator::GetPluginInfoAt( UINT32 index, REF(IHXValues*) pRetValues )
  974. {
  975.     // Initialize out params
  976.     pRetValues = NULL;
  977.     HX_RESULT res = HXR_FAIL;
  978.     LISTPOSITION pos = m_plugins.FindIndex(m_nIndex);
  979.     m_nIndex++;
  980.     if (pos)
  981.     {
  982. HXPlugin* pPlugin = (HXPlugin*) m_plugins.GetAt(pos);
  983. if (pPlugin)
  984. {
  985.     res = pPlugin->GetPluginInfo( pRetValues );
  986. }
  987.     }
  988.     return res;
  989. }
  990. void HXPluginEnumerator::Add(HXPlugin* pPlugin)
  991. {
  992.     HX_ASSERT(pPlugin);
  993.     m_plugins.AddTail(pPlugin);
  994. }