hxpluginmanager.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:32k
源码类别:

Symbian

开发平台:

Visual C++

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