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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: basehand.cpp,v 1.18.8.1 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. #ifdef _WINDOWS
  51. #if defined(_WINCE)
  52. #include <stdlib.h>
  53. #define itoa _itoa
  54. #endif
  55. #include <windows.h>
  56. #include <ctype.h>
  57. #endif
  58. #ifdef _MACINTOSH
  59. #include <ctype.h>
  60. #include "filespec.h"
  61. #include "filespecutils.h"
  62. #endif
  63. #if defined _UNIX
  64. #include <stdlib.h>
  65. #include <sys/param.h>
  66. #define _MAX_PATH MAXPATHLEN
  67. #elif defined (__MWERKS__)
  68. #include <stdlib.h>
  69. #include "fullpathname.h"
  70. #include "chxdataf.h"
  71. #include <stat.h>
  72. #include <fcntl.h>
  73. #else
  74. #include "hlxclib/sys/stat.h"
  75. #endif
  76. #include "hlxclib/stdio.h"
  77. #include "hxresult.h"
  78. #include "hxassert.h"
  79. #include "hxcom.h"
  80. #include "ihxpckts.h"
  81. #include "hxfiles.h"
  82. #include "hxformt.h"
  83. #include "hxfwrtr.h"
  84. #include "hxrendr.h"
  85. #include "hxprefs.h"
  86. #include "hxplugn.h"
  87. #include "hxdtcvt.h"
  88. #include "hxphand.h"
  89. #include "hxmeta.h"
  90. #include "hxsdesc.h"
  91. #include "hxauth.h"
  92. #include "hxallow.h"
  93. #include "hxerror.h"
  94. #include "hxcomm.h"
  95. #include "hxengin.h"
  96. #include "hxshtdn.h"
  97. #include "hxplgns.h"
  98. #include "hxmon.h"
  99. #include "chxpckts.h"
  100. #include "hxstring.h"
  101. #include "hxslist.h"
  102. #include "hxmap.h"
  103. #include "hxstrutl.h"
  104. #include "hxdir.h"
  105. #include "findfile.h"
  106. #include "dbcs.h"
  107. #include "hxbdwdth.h"
  108. #include "basehand.h"
  109. #include "chxuuid.h"
  110. #include "md5.h"
  111. #include "dllacces.h"
  112. #include "dllpath.h"
  113. #include "hxperf.h"
  114. #include "rtsputil.h"
  115. #include "hxver.h"
  116. #include "hxheap.h"
  117. #ifdef _DEBUG
  118. #undef HX_THIS_FILE
  119. static const char HX_THIS_FILE[] = __FILE__;
  120. #endif
  121. #ifdef _WINCE
  122. #include <wincestr.h>
  123. #endif
  124. #if defined(_STATICALLY_LINKED)
  125. #include "staticff.h"
  126. #endif
  127. /*
  128.  * XXXND These are also defined in geminc/gemplatformdata.h
  129.  */
  130. #define NAMESPACE_SEPARATOR ':'
  131. /*
  132.  *  Win98 does not allow reg keys that are larger than 16k a pop. we used this value to break up into more manageable bites
  133.  */
  134. #define PREF_CACHE_SIZE 10000
  135. /*
  136.     Load each plug-in, read info, store in memory and update prefs
  137.     This is only done if the plugin hash within the registery is not the same
  138.     as the plugin hash of the plugins directory.
  139. */
  140. const char* const BaseHandler::zm_pszValueSeperator = "|";
  141. const char* const BaseHandler::zm_pszListStart = "{";
  142. const char* const BaseHandler::zm_pszListEnd = "}";
  143. const char* const BaseHandler::zm_pszValueSeperator2= ",";
  144. const char* const BaseHandler::zm_pszKeyNameRegKey = "~KeyNames~";
  145. const char* const BaseHandler::zm_pszRegKeySeperator = "\";
  146. const char* const BaseHandler::zm_pszFileExtension = OS_DLL_PATTERN_STRING;
  147. const char* const BaseHandler::zm_pszDirectorySeperator = OS_SEPARATOR_STRING;
  148. const char BaseHandler::zm_cDirectorySeperator = OS_SEPARATOR_CHAR;
  149. IMPLEMENT_COM_CREATE_FUNCS( BaseHandler )
  150. BEGIN_INTERFACE_LIST_NOCREATE( BaseHandler )
  151.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginEnumerator )
  152.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPlugin2Handler )
  153.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginHandler3 )
  154. END_INTERFACE_LIST
  155. BaseHandler::BaseHandler() :
  156.          m_pContext(NULL)
  157. {
  158. }
  159. BaseHandler::~BaseHandler()
  160. {
  161.     // Make sure Close() got called
  162.     if( m_pContext )
  163.     {
  164. Close();
  165.     }
  166. }
  167. STDMETHODIMP BaseHandler::Init(IUnknown* pContext)
  168. {
  169.     HX_RESULT result = HXR_FAIL;
  170.     if( SUCCEEDED( result = RegisterContext( pContext ) ) )
  171.     {
  172. result = ReadFromRegistry();
  173.     }
  174.     return result;
  175. }
  176. STDMETHODIMP_(ULONG32) BaseHandler::GetNumOfPlugins2()
  177. {
  178.     return m_PluginList.GetCount();
  179. }
  180. STDMETHODIMP
  181. BaseHandler::GetPluginInfo(UINT32 unIndex,
  182.    REF(IHXValues*) /*OUT*/ pValues)
  183. {
  184.     return HXR_NOTIMPL;
  185. }
  186. BaseHandler::Errors
  187. BaseHandler::LoadDLL(char* pszDllName,
  188.      PluginMountPoint* pMountPoint )
  189. {
  190.     Errors result     = NO_ERRORS;
  191.     UINT32 i     = 0;
  192.     struct stat stat_stuct;
  193.     // Make sure there is no path in the pszDllName
  194.     HX_ASSERT( !strrchr(pszDllName, BaseHandler::zm_cDirectorySeperator) );
  195.     BaseHandler::PluginDLL* pPluginDll  = NULL;
  196.     if( !( pPluginDll = new BaseHandler::PluginDLL( pszDllName, pMountPoint, this ) ) )
  197.     {
  198. return MEMORY_ERROR;
  199.     }
  200.     pPluginDll->AddRef();
  201.     CHXString sFileWithPath = pszDllName;
  202.     if (NO_ERRORS==Stat(sFileWithPath, &stat_stuct))
  203.     {
  204.         pPluginDll->SetFileSize((INT32)stat_stuct.st_size);
  205.     }
  206.     result = pPluginDll->Load(m_pContext);
  207.     if (NO_ERRORS != result )
  208.     {
  209. goto cleanup;
  210.     }
  211.     for(i=0;i<pPluginDll->GetNumPlugins();i++)
  212.     {
  213. Plugin* pPlugin = NULL;
  214.      // create a new plugin object
  215. if (!(pPlugin = new Plugin(m_pContext)))
  216. {
  217.     return MEMORY_ERROR;
  218. }
  219. // Setup plugin information
  220. pPlugin->AddRef();
  221. pPlugin->SetDLL(pPluginDll);
  222. pPlugin->SetIndex((UINT16)i);
  223. pPlugin->SetInfoNeedsRefresh(TRUE);
  224. IUnknown* pUnk = NULL;
  225. if( NO_ERRORS != pPlugin->GetPlugin( pUnk ) )
  226. {
  227.     // This plugin doesn't work.  Delete it.
  228.     HX_RELEASE( pPlugin );
  229. }
  230. else
  231. {
  232.     IHXPluginNamespace* pPluginNamespace = NULL;
  233.     if (SUCCEEDED(pUnk->QueryInterface(IID_IHXPluginNamespace, (void**) &pPluginNamespace)))
  234.     {
  235. /*
  236.  * Memory for the IHXBuffer is allocated in the plugin
  237.  */
  238. IHXBuffer* pBuffer = NULL;
  239. if (SUCCEEDED(pPluginNamespace->GetPluginNamespace(pBuffer)))
  240. {
  241.     pPluginDll->SetNamespace(pBuffer);
  242.     HX_RELEASE(pBuffer);
  243. }
  244. HX_RELEASE(pPluginNamespace);
  245.     }
  246.     IHXComponentPlugin* pIIterator = NULL;
  247.     if( SUCCEEDED( pUnk->QueryInterface( IID_IHXComponentPlugin, (void**) &pIIterator ) ) )
  248.     {
  249. // We don't need this.
  250. HX_RELEASE( pPlugin );
  251. LoadPluginsFromComponentDLL( pPluginDll, pIIterator );
  252. HX_RELEASE( pIIterator );
  253.     }
  254.     else
  255.     {
  256. IHXPlugin* pIHXPlugin;
  257. if( SUCCEEDED( pUnk->QueryInterface(IID_IHXPlugin, (void**)&pIHXPlugin ) ) )
  258. {
  259.     pPlugin->GetValuesFromDLL(pIHXPlugin);
  260.     m_PluginList.AddTail(pPlugin);
  261.     pIHXPlugin->Release();
  262. }
  263.     }
  264. }
  265. HX_RELEASE( pUnk );
  266.     }
  267. cleanup:
  268.     HX_RELEASE( pPluginDll );
  269.     return result;
  270. }
  271. void BaseHandler::LoadPluginsFromComponentDLL( BaseHandler::PluginDLL* pPluginDll,
  272.     IHXComponentPlugin* pIIterator )
  273. {
  274.     IHXPlugin* pIHXPlugin = NULL;
  275.     if( SUCCEEDED( pIIterator->QueryInterface(IID_IHXPlugin, (void**)&pIHXPlugin ) ) )
  276.     {
  277. for( UINT32 index = 0; index < pIIterator->GetNumComponents(); index++ )
  278. {
  279.     IHXValues* pIValues = NULL;
  280.     if( SUCCEEDED( pIIterator->GetComponentInfoAtIndex( index, pIValues ) ) )
  281.     {
  282. IHXBuffer* pBuffer = NULL;
  283. if (SUCCEEDED(pIValues->GetPropertyCString(PLUGIN_COMPONENT_NAME, pBuffer)))
  284. {
  285.     IHXBuffer* pNamespace = pPluginDll->GetNamespace();
  286.     if (pNamespace)
  287.     {
  288. CHXString TempNamespace = pNamespace->GetBuffer();
  289. TempNamespace += NAMESPACE_SEPARATOR;
  290. TempNamespace += pBuffer->GetBuffer();
  291. IHXBuffer* pTempBuffer = new CHXBuffer();
  292. pTempBuffer->AddRef();
  293. pTempBuffer->Set((BYTE*)(const char*)TempNamespace, TempNamespace.GetLength()+1);
  294. pIValues->SetPropertyCString(PLUGIN_COMPONENT_NAME, pTempBuffer);
  295. HX_RELEASE(pTempBuffer);
  296. HX_RELEASE(pNamespace);
  297.     }
  298.     HX_RELEASE(pBuffer);
  299. }
  300. // create a new plugin object
  301. Plugin* pPlugin = new Plugin( m_pContext );
  302. HX_ASSERT( pPlugin );
  303. // Setup plugin object
  304. pPlugin->AddRef();
  305. pPlugin->SetDLL( pPluginDll );
  306. pPlugin->SetInfoNeedsRefresh( TRUE );
  307. pPlugin->InitializeComponentPlugin( pIHXPlugin, pIValues );
  308. // Put in plugin list
  309. m_PluginList.AddTail(pPlugin);
  310. HX_RELEASE( pIValues );
  311.     }
  312. }
  313. HX_RELEASE (pIHXPlugin);
  314.     }
  315. }
  316. ///////////////////////////////////////////////////////////////////////////////
  317. //  These functions will find all plugins which are different
  318. //  then those loaded into the registry.
  319. //  It will then load them into memory, get their data, and unload them.
  320. //  It will return HXR_FAIL if some DLL has different values within the
  321. //  registry, and is presently in memory (how could this happen??)
  322. //  If anyone was keeping an index to a loaded DLL and assuming that it
  323. //  would remain constant ... that's not going to work!!!
  324. HX_RESULT BaseHandler::ReloadPluginsNoPropagate()
  325. {
  326.     HX_LOG_BLOCK( "BaseHandler::ReloadPluginsNoPropagate" );
  327.     HX_RESULT result = HXR_OK;
  328.     // Reload them all.
  329.     for(CHXMapStringToOb::Iterator mp = m_MountPoints.Begin(); mp!=m_MountPoints.End(); ++mp)
  330.     {
  331. PluginMountPoint* pMountPoint = (PluginMountPoint*) *mp;
  332. if( FAILED( ReloadPluginsNoPropagate( pMountPoint ) ) )
  333. {
  334.     result = HXR_FAIL;
  335. }
  336.     }
  337.     return result;
  338. }
  339. HX_RESULT BaseHandler::ReloadPluginsNoPropagateWithFindFile(
  340.                PluginMountPoint* pMountPoint, CFindFile* pFileFinder,
  341.                IHXBuffer* pPathBuffer, char* pszPluginDir)
  342. {
  343.     HX_LOG_BLOCK( "BaseHandler::ReloadPluginsNoPropagateWithFindFile" );
  344.     char*     pszDllName     = 0;
  345.     IHXBuffer*     pNewChecksum    = 0;
  346.     // if we have no context do not proceed.
  347.     if (!m_pContext)
  348.     {
  349. return INVALID_CONTEXT;
  350.     }
  351.     // If this is the 1st time, load everything into the registry.
  352.     pszDllName = pFileFinder->FindFirst();
  353.     while (pszDllName)
  354.     {
  355. BaseHandler::Errors loadResult;
  356. loadResult = LoadDLL( pszDllName, pMountPoint );
  357. if (loadResult!= NO_ERRORS)
  358. {
  359.     // The DLL had one of the following problems:
  360.     // (1) the DLL was unloadable
  361.     // (2) the DLL did not have an HXCreateInstance
  362.     // (3) an instance could not be created.
  363.     // (4) It did not implement the PLUGIN interface
  364.     // if it was case 2,3,4 then we can safely never attempt to
  365.     // load the DLL again. However if it was (1) then we must attempt
  366.     // to load the DLL ever time through since it was possibly unloadable due
  367.     // to an imp-lib that will be satisfied lated (without modifing the
  368.     // dll). Jeeze. That comment is UNREADABLE. I have to take effective written
  369.     // english again!
  370.     if (loadResult!=CANT_OPEN_DLL)
  371.     {
  372. BaseHandler::OtherDLL* pDLLData = new BaseHandler::OtherDLL;
  373. pDLLData->m_filename = pszDllName;
  374. pDLLData->m_pMountPoint = pMountPoint;
  375. pNewChecksum = ChecksumFile(pszDllName, pPathBuffer);
  376. if (pNewChecksum)
  377. {
  378.     pDLLData->m_fileChecksum = (char*)pNewChecksum->GetBuffer();
  379.     HX_RELEASE(pNewChecksum);
  380.     m_MiscDLLList.AddTail(pDLLData);
  381. }
  382. else
  383. {
  384.     HX_DELETE(pDLLData);
  385. }
  386.     }
  387. }
  388. pszDllName = pFileFinder->FindNext();
  389.     }
  390.     return HXR_OK;
  391. }
  392. HX_RESULT BaseHandler::ReloadPluginsNoPropagate( PluginMountPoint* pMountPoint )
  393. {
  394.     CFindFile* pFileFinder = NULL;
  395.     IHXBuffer* pPathBuffer = NULL;
  396.     char* pszPluginDir = NULL;
  397.     ULONG32 nPluginDirLen = NULL;
  398.     if (!m_pContext)
  399.     {
  400.         return INVALID_CONTEXT;
  401.     }
  402.     HX_RESULT retVal = HXR_FAIL;
  403. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  404.     pPathBuffer = pMountPoint->Path();
  405.     if (pPathBuffer)
  406.     {
  407.         pPathBuffer->Get((UCHAR*&)pszPluginDir, nPluginDirLen);
  408.         if (nPluginDirLen)
  409.         {
  410.             pFileFinder = CFindFile::CreateFindFile(pszPluginDir,
  411.                         0, BaseHandler::zm_pszFileExtension);
  412.             if (pFileFinder)
  413.             {
  414.                 retVal = ReloadPluginsNoPropagateWithFindFile(pMountPoint,
  415.                         pFileFinder, pPathBuffer, pszPluginDir);
  416.                 HX_DELETE(pFileFinder);
  417.             }
  418.         }
  419.     }
  420. #endif
  421. #if defined(_STATICALLY_LINKED)
  422. pszPluginDir="";
  423.         pFileFinder = CStaticFindFile::CreateFindFile(pszPluginDir,
  424.                 0, BaseHandler::zm_pszFileExtension);
  425.         if (pFileFinder)
  426.         {
  427.             retVal = ReloadPluginsNoPropagateWithFindFile(pMountPoint,
  428.                     pFileFinder, pPathBuffer, pszPluginDir);
  429.             HX_DELETE(pFileFinder);
  430.         }
  431. #endif
  432. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  433.     HX_RELEASE(pPathBuffer);
  434. #endif
  435.     return retVal;
  436. }
  437. STDMETHODIMP BaseHandler::FindIndexUsingValues (IHXValues* pValues,
  438. REF(UINT32) unIndex)
  439. {
  440.     return HXR_NOTIMPL;
  441. }
  442. STDMETHODIMP BaseHandler::GetInstance (UINT32 index, REF(IUnknown*) pUnknown)
  443. {
  444.     pUnknown = NULL;
  445.     LISTPOSITION pPos = m_PluginList.FindIndex(index);
  446.     if (pPos)
  447.     {
  448. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) m_PluginList.GetAt(pPos);
  449. if (pPlugin)
  450. {
  451.     Errors retVal = pPlugin->GetInstance(pUnknown);
  452.     if (retVal== NO_ERRORS)
  453.     {
  454. return HXR_OK;
  455.     }
  456. }
  457.     }
  458.     return HXR_FAIL;
  459. }
  460. STDMETHODIMP BaseHandler::FindIndexUsingStrings (char* PropName1,
  461.     char* PropVal1,
  462.     char* PropName2,
  463.     char* PropVal2,
  464.     char* PropName3,
  465.     char* PropVal3,
  466.     REF(UINT32) unIndex)
  467. {
  468.     return HXR_NOTIMPL;
  469. }
  470. STDMETHODIMP BaseHandler::FindPluginUsingValues (IHXValues* pValues,
  471. REF(IUnknown*) pUnk)
  472. {
  473.     return FindPluginUsingValues( pValues, pUnk, NULL );
  474. }
  475. HX_RESULT BaseHandler::FindGroupOfPluginsUsingStrings(char* PropName1,
  476.     char* PropVal1,
  477.     char* PropName2,
  478.     char* PropVal2,
  479.     char* PropName3,
  480.     char* PropVal3,
  481.     REF(CPluginEnumerator*) pEnumerator)
  482. {
  483.     // PropName and PropVal have to to valid tuple
  484.     if ((PropName1 && !PropVal1)    ||
  485. (PropName2 && !PropVal2)    ||
  486. (PropName3 && !PropVal3)    ||
  487. (!PropName1 && PropVal1)    ||
  488. (!PropName2 && PropVal2)    ||
  489. (!PropName3 && PropVal3))
  490. return HXR_FAIL;
  491.     IHXValues* pValues;
  492.     HX_RESULT   retVal = HXR_FAIL;
  493.     CHXHeader* pHeader = new CHXHeader;
  494.     pHeader->QueryInterface(IID_IHXValues,  (void**)&pValues);
  495.     AddToValues(pValues, PropName1, PropVal1, eString);
  496.     AddToValues(pValues, PropName2, PropVal2, eString);
  497.     AddToValues(pValues, PropName3, PropVal3, eString);
  498.     retVal = FindGroupOfPluginsUsingValues(pValues, pEnumerator);
  499.     pValues->Release();
  500.     return retVal;
  501. }
  502. HX_RESULT BaseHandler::FindGroupOfPluginsUsingValues(IHXValues* pValues,
  503. REF(CPluginEnumerator*) pEnumerator)
  504. {
  505.     CHXSimpleList::Iterator i = m_PluginList.Begin();
  506.     pEnumerator = NULL;
  507.     for(; i!= m_PluginList.End(); ++i)
  508.     {
  509. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) *i;
  510. if (pPlugin->DoesMatch(pValues))
  511. {
  512.     if (!pEnumerator)
  513.     {
  514. pEnumerator = new CPluginEnumerator();
  515.     }
  516.     pEnumerator->Add(pPlugin);
  517. }
  518.     }
  519.     if (!pEnumerator)
  520.     {
  521. return HXR_FAIL;
  522.     }
  523.     return HXR_OK;
  524. }
  525. /********************************************************************
  526. *
  527. * IHXPluginHandler3
  528. *
  529. ********************************************************************/
  530. STDMETHODIMP
  531. BaseHandler::RegisterContext( IUnknown* pContext )
  532. {
  533.     if( !pContext )
  534.     {
  535. return INVALID_CONTEXT;
  536.     }
  537.     if( m_pContext )
  538.     {
  539. return HXR_UNEXPECTED;
  540.     }
  541.     m_pContext = pContext;
  542.     m_pContext->AddRef();
  543.     return HXR_OK;
  544. }
  545. STDMETHODIMP
  546. BaseHandler::AddPluginMountPoint( const char* pName, UINT32 majorVersion, UINT32 minorVersion, IHXBuffer* pPath )
  547. {
  548.     HX_LOG_BLOCK( "BaseHandler::AddPluginMountPoint" );
  549.     const char* pMPKey = pName ? pName : (const char*) pPath->GetBuffer();
  550.     // Make sure this mount point is in the list
  551.     PluginMountPoint* pMountPoint = NULL;
  552.     if( !m_MountPoints.Lookup( pMPKey, (void*&) pMountPoint ) )
  553.     {
  554. // Create new mount point
  555. pMountPoint = new PluginMountPoint( this, pName, majorVersion, minorVersion, pPath );
  556. pMountPoint->AddRef();
  557. // Put new mount point in list
  558. m_MountPoints.SetAt( pMPKey, pMountPoint );
  559.     }
  560.     // Load information from registry, and sync DLLs that aren't up to date
  561.     return RefreshPluginInfo( pMountPoint );
  562. }
  563. STDMETHODIMP
  564. BaseHandler::RefreshPluginMountPoint( const char* pName )
  565. {
  566.     HX_RESULT result = HXR_FAIL;
  567.     // If this mount point is in the list, refresh it
  568.     PluginMountPoint* pMountPoint = NULL;
  569.     if( m_MountPoints.Lookup( pName, (void*&) pMountPoint ) )
  570.     {
  571. result = RefreshPluginInfo( pMountPoint );
  572.     }
  573.     return result;
  574. }
  575. STDMETHODIMP
  576. BaseHandler::RemovePluginMountPoint( const char* pName )
  577. {
  578.     HX_RESULT result = HXR_FAIL;
  579.     // Make sure this is a valid mount point
  580.     PluginMountPoint* pMountPoint = NULL;
  581.     if( m_MountPoints.Lookup( pName, (void*&) pMountPoint ) )
  582.     {
  583. // Clean up plugins
  584. if( m_PluginList.GetCount() )
  585. {
  586.     LISTPOSITION listPos = m_PluginList.GetHeadPosition();
  587.     while( listPos )
  588.     {
  589. // Save off current position for delete
  590. LISTPOSITION posAt = listPos;
  591. // Get current item, and increment position
  592. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) m_PluginList.GetNext( listPos );
  593. // If this plugin belongs to the mountpoint, remove it.
  594. if( pPlugin && ( pPlugin->GetDLL()->GetMountPoint() == pMountPoint ) )
  595. {
  596.     // Delete from the saved position
  597.     m_PluginList.RemoveAt( posAt );
  598.     HX_RELEASE( pPlugin );
  599. }
  600.     }
  601. }
  602. // Remove mount point from list
  603. m_MountPoints.RemoveKey( pName );
  604. HX_RELEASE( pMountPoint );
  605.     }
  606.     return result;
  607. }
  608. STDMETHODIMP
  609. BaseHandler::FindImplementationFromClassID( REFGUID GUIDClassID, REF(IUnknown*) pIUnknownInstance,
  610.     IUnknown* pIUnkOuter, IUnknown* pContext )
  611. {
  612.     HX_RESULT     rc = HXR_OK;
  613.     IUnknown*     pUnknown = NULL;
  614.     IHXPlugin*     pPlugin = NULL;
  615.     IHXCommonClassFactory*     pFactory = NULL;
  616.     IHXPluginSearchEnumerator*     pPluginEnumerator = NULL;
  617.     // a much simpler version than Plugin2Handler, it's not as efficient as Plugin2Handler but it
  618.     // should be good enough for static build.
  619.     // Initialize out params
  620.     pIUnknownInstance = NULL;
  621.     rc = FindGroupOfPluginsUsingStrings(PLUGIN_CLASS, PLUGIN_CLASS_FACTORY_TYPE,
  622. NULL, NULL, NULL, NULL, pPluginEnumerator);
  623.     if (HXR_OK != rc)
  624.     {
  625. rc = HXR_FAILED;
  626. goto cleanup;
  627.     }
  628.     while (HXR_OK == pPluginEnumerator->GetNextPlugin(pUnknown, NULL) && pUnknown)
  629.     {
  630. if (HXR_OK == pUnknown->QueryInterface(IID_IHXPlugin, (void**)&pPlugin))
  631. {
  632.     pPlugin->InitPlugin(pContext);
  633.     if (HXR_OK == pUnknown->QueryInterface(IID_IHXCommonClassFactory, (void**)&pFactory))
  634.     {
  635. if (HXR_OK == pFactory->CreateInstance(GUIDClassID, (void**)&pIUnknownInstance) &&
  636.     pIUnknownInstance)
  637. {
  638.     break;
  639. }
  640. HX_RELEASE(pIUnknownInstance);
  641.     }
  642.     HX_RELEASE(pFactory);
  643. }
  644. HX_RELEASE(pPlugin);
  645. HX_RELEASE(pUnknown);
  646.     }
  647.     if (!pIUnknownInstance)
  648.     {
  649. rc = HXR_FAILED;
  650.     }
  651. cleanup:
  652.     HX_RELEASE(pFactory);
  653.     HX_RELEASE(pPlugin);
  654.     HX_RELEASE(pUnknown);
  655.     HX_RELEASE(pPluginEnumerator);
  656.     return rc;
  657. }
  658. HX_RESULT
  659. BaseHandler::RefreshPluginInfo( PluginMountPoint* pMountPoint )
  660. {
  661.     return ReloadPluginsNoPropagate( pMountPoint );
  662. }
  663. STDMETHODIMP
  664. BaseHandler::FindCLSIDFromName( const char* pName, REF(IHXBuffer*) pCLSID )
  665. {
  666.     return HXR_NOTIMPL;
  667. }
  668. STDMETHODIMP
  669. BaseHandler::FindGroupOfPluginsUsingValues( IHXValues* pValues,
  670. REF(IHXPluginSearchEnumerator*) pIEnumerator)
  671. {
  672.     return HXR_NOTIMPL;
  673. }
  674. STDMETHODIMP
  675. BaseHandler::FindGroupOfPluginsUsingStrings( char* PropName1, char* PropVal1,
  676. char* PropName2, char* PropVal2,
  677. char* PropName3, char* PropVal3,
  678. REF(IHXPluginSearchEnumerator*) pIEnumerator)
  679. {
  680.     // Regardless of how the API can be used, the reality is that this function
  681.     // is essentially the highest level point of access for the core when
  682.     // starting playback of a new stream, so this is a great time to unload
  683.     // all our dead dlls.
  684.     // But the memory efficiency of DLL unloading comes at the expense of
  685.     // setup time, so we probably only want to do this on platforms where
  686.     // memory optimization is our highest priority.
  687. #if defined(HELIX_CONFIG_UNLOAD_DEAD_DLLS)
  688.     UnloadDeadDLLs();
  689. #endif
  690.     // Initialize out params
  691.     pIEnumerator = NULL;
  692.     // Use the internal function to build up an enumerator object
  693.     CPluginEnumerator* pEnumerator = NULL;
  694.     HX_RESULT result = FindGroupOfPluginsUsingStrings( PropName1, PropVal1,
  695.     PropName2, PropVal2, PropName3, PropVal3, pEnumerator );
  696.     // If we have our enumerator, get the appropriate interface
  697.     if( SUCCEEDED( result ) )
  698.     {
  699. result = pEnumerator->QueryInterface( IID_IHXPluginSearchEnumerator,
  700. (void**) &pIEnumerator );
  701.     }
  702.     return result;
  703. }
  704. void BaseHandler::ReportError( UINT8 severity, const char* pDLLName, const char* pDesc )
  705. {
  706. }
  707. STDMETHODIMP
  708. BaseHandler::FindPluginUsingValues( IHXValues* pCriteria,
  709. REF(IUnknown*) pIUnkResult,
  710. IUnknown* pIUnkOuter )
  711. {
  712.     HX_SETUP_CHECKPOINTLIST( "BaseHandler::FindPluginUsingValues()" );
  713.     HX_PRIME_ACCUMULATOR( 'fpuv', "Plugin lookup with IHXValues" );
  714.     // Initialize out params
  715.     pIUnkResult = NULL;
  716.     CHXSimpleList   PossibleValues;
  717.     IHXValues*     pPluginValues = NULL;
  718.     IHXBuffer*     pBuffer = NULL;
  719.     CHXSimpleList::Iterator i = m_PluginList.Begin();
  720.     for(; i!= m_PluginList.End(); ++i)
  721.     {
  722. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) *i;
  723. if (pPlugin->DoesMatch(pCriteria))
  724. {
  725.     PossibleValues.AddTail(pPlugin);
  726. }
  727.     }
  728.     HX_UPDATE_ACCUMULATOR( 'fpuv' );
  729.     if (PossibleValues.Begin() == PossibleValues.End())
  730.     {
  731. pIUnkResult = 0;
  732. return HXR_FAIL;
  733.     }
  734.     /****************************************************************
  735.     ** Presently when we arrive at this spot with more than one
  736.     ** plugin which matches the search criteria, we simply take
  737.     ** the first one found. If this is not satisfactory then
  738.     ** some method can be added which will process the list based
  739.     ** upon some criteria.
  740.     ****************************************************************/
  741.     // if there are multiple plugins found, we will pick the one whose
  742.     // plugin description contains "RealNetworks"
  743.     if (PossibleValues.GetCount() > 1)
  744.     {
  745. for(i = PossibleValues.Begin(); i!= PossibleValues.End(); ++i)
  746. {
  747.     BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) *i;
  748.     if (HXR_OK == pPlugin->GetPluginInfo(pPluginValues) && pPluginValues)
  749.     {
  750. if (HXR_OK == pPluginValues->GetPropertyCString(PLUGIN_DESCRIPTION2, pBuffer) &&
  751.     pBuffer)
  752. {
  753.     if (strstr((const char*)pBuffer->GetBuffer(), "RealNetworks"))
  754.     {
  755. HX_RELEASE(pBuffer);
  756. if ( NO_ERRORS == pPlugin->GetInstance( pIUnkResult, pIUnkOuter ))
  757. {
  758.     return HXR_OK;
  759. }
  760. else
  761. {
  762.     return HXR_FAIL;
  763. }
  764.     }
  765. }
  766. HX_RELEASE(pBuffer);
  767.     }
  768. }
  769.     }
  770.     BaseHandler::Plugin* pPlug = (BaseHandler::Plugin*) *(PossibleValues.Begin());
  771.     Errors retVal = pPlug->GetInstance( pIUnkResult, pIUnkOuter );
  772.     return ( retVal == NO_ERRORS ) ? HXR_OK : HXR_FAIL;
  773. }
  774. STDMETHODIMP
  775. BaseHandler::FindPluginUsingStrings( char* PropName1, char* PropVal1,
  776. char* PropName2, char* PropVal2,
  777. char* PropName3, char* PropVal3,
  778. REF(IUnknown*) pIUnkResult,
  779. IUnknown* pIUnkOuter )
  780. {
  781.     // Initialize out params
  782.     pIUnkResult = NULL;
  783.     // PropName and PropVal have to to valid tuple
  784.     if ((PropName1 && !PropVal1)    ||
  785. (PropName2 && !PropVal2)    ||
  786. (PropName3 && !PropVal3)    ||
  787. (!PropName1 && PropVal1)    ||
  788. (!PropName2 && PropVal2)    ||
  789. (!PropName3 && PropVal3))
  790. return HXR_FAIL;
  791.     IHXValues* pValues;
  792.     HX_RESULT   retVal = HXR_FAIL;
  793.     CHXHeader* pHeader = new CHXHeader();
  794.     pHeader->QueryInterface(IID_IHXValues,  (void**)&pValues);
  795.     AddToValues(pValues, PropName1, PropVal1, eString);
  796.     AddToValues(pValues, PropName2, PropVal2, eString);
  797.     AddToValues(pValues, PropName3, PropVal3, eString);
  798.     retVal = FindPluginUsingValues( pValues, pIUnkResult, pIUnkOuter );
  799.     pValues->Release();
  800.     return retVal;
  801. }
  802. void
  803. BaseHandler::UnloadDeadDLLs()
  804. {
  805.     LISTPOSITION pos = m_PluginList.GetHeadPosition();
  806.     while( pos )
  807.     {
  808.         BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) m_PluginList.GetNext( pos );
  809.         if( pPlugin )
  810.         {
  811.             PluginDLL * pPluginDll = pPlugin->GetDLL();
  812.             if( pPluginDll )
  813.             {
  814.                 pPluginDll->Unload();
  815.             }
  816.         }
  817.     }
  818. }
  819. STDMETHODIMP
  820. BaseHandler::GetPlugin( ULONG32 ulIndex, REF(IUnknown*) pIUnkResult,
  821.     IUnknown* pIUnkOuter )
  822. {
  823.     if( ulIndex <= (ULONG32)(m_PluginList.GetCount()-1) && m_PluginList.GetCount() )
  824.     {
  825. LISTPOSITION pPos = m_PluginList.FindIndex( ulIndex );
  826. if (pPos)
  827. {
  828.     BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) m_PluginList.GetAt( pPos );
  829.     if( pPlugin )
  830.     {
  831. if (NO_ERRORS == pPlugin->GetInstance( pIUnkResult, pIUnkOuter ))
  832. {
  833.     return HXR_OK;
  834. }
  835. else
  836. {
  837.     return HXR_FAIL;
  838. }
  839.     }
  840. }
  841.     }
  842.     return HXR_FAIL;
  843. }
  844. STDMETHODIMP
  845. BaseHandler::UnloadPluginFromClassID(REFGUID GUIDClassID)
  846. {
  847.     return HXR_NOTIMPL;
  848. }
  849. STDMETHODIMP
  850. BaseHandler::UnloadPackageByName(const char* pName)
  851. {
  852.     return HXR_NOTIMPL;
  853. }
  854. //------------------------------------ Class Methods
  855. STDMETHODIMP BaseHandler::FindPluginUsingStrings (char* PropName1,
  856.     char* PropVal1,
  857.     char* PropName2,
  858.     char* PropVal2,
  859.     char* PropName3,
  860.     char* PropVal3,
  861.     REF(IUnknown*) pRetUnk)
  862. {
  863.     return FindPluginUsingStrings( PropName1, PropVal1, PropName2, PropVal2,
  864.    PropName3, PropVal3, pRetUnk, NULL );
  865. }
  866. STDMETHODIMP
  867. BaseHandler::FindImplementationFromClassID
  868. (
  869.     REFGUID GUIDClassID,
  870.     REF(IUnknown*) pIUnknownInstance
  871. )
  872. {
  873.     // Defer to the new version
  874.     return FindImplementationFromClassID( GUIDClassID, pIUnknownInstance, NULL, m_pContext );
  875. }
  876. STDMETHODIMP BaseHandler::Close ()
  877. {
  878.     CHXSimpleList::Iterator i = m_PluginList.Begin();
  879.     // Release all Plugins and Their Associated DLLs
  880.     for(; i!=m_PluginList.End(); ++i)
  881.     {
  882. BaseHandler::Plugin* pPlug = (BaseHandler::Plugin*) *i;
  883. pPlug->Release();
  884.     }
  885.     m_PluginList.RemoveAll();
  886.     for(i = m_PluginDLLList.Begin(); i!=m_PluginDLLList.End(); ++i)
  887.     {
  888. BaseHandler::PluginDLL* pPlugDLL = (BaseHandler::PluginDLL*) *i;
  889. pPlugDLL->Release();
  890.     }
  891.     m_PluginDLLList.RemoveAll();
  892.     for(i = m_MiscDLLList.Begin(); i!=m_MiscDLLList.End(); ++i)
  893.     {
  894. BaseHandler::OtherDLL* pOtherDLL = (BaseHandler::OtherDLL*) *i;
  895. delete pOtherDLL;
  896.     }
  897.     m_MiscDLLList.RemoveAll();
  898.     for(CHXMapStringToOb::Iterator mp = m_MountPoints.Begin(); mp!=m_MountPoints.End(); ++mp)
  899.     {
  900. BaseHandler::PluginMountPoint* pMountPoint = (BaseHandler::PluginMountPoint*) *mp;
  901. pMountPoint->Release();
  902.     }
  903.     m_MountPoints.RemoveAll();
  904.     // release all of the CORE stuff...
  905.     HX_RELEASE(m_pContext);
  906.     return HXR_OK;
  907. }
  908. STDMETHODIMP BaseHandler::SetRequiredPlugins (const char** ppszRequiredPlugins)
  909. {
  910.     return HXR_OK;
  911. }
  912. HX_RESULT BaseHandler::AddToValues(IHXValues* pValues, char* pPropName, char* pPropVal, eValueTypes eValueType)
  913. {
  914.     if (!pPropName || !pPropVal)
  915. return HXR_FAIL;
  916.     // 1st make into a cstrig and to trim the buffer...
  917.     CHXString theValue = (pPropVal);
  918.     theValue.TrimLeft();
  919.     theValue.TrimRight();
  920.     switch (eValueType)
  921.     {
  922. case eString:
  923. {
  924.     IHXBuffer* pBuffer;
  925.     CHXBuffer* pCHXBuffer;
  926.     pCHXBuffer = new CHXBuffer;
  927.     pCHXBuffer->QueryInterface(IID_IHXBuffer, (void**) &pBuffer);
  928.     pBuffer->Set((const unsigned char*)(const char*)theValue, strlen(theValue)+1);
  929.     pValues->SetPropertyCString(pPropName, pBuffer);
  930.     pBuffer->Release();
  931.     return HXR_OK;
  932. }
  933. case eInt:
  934. {
  935.     int val = atoi(theValue);
  936.     pValues->SetPropertyULONG32(pPropName, (ULONG32)val);
  937.     return HXR_OK;
  938. }
  939.     }
  940.     return HXR_NOTIMPL;
  941. }
  942. STDMETHODIMP_(ULONG32) BaseHandler::GetNumOfPlugins()
  943. {
  944.     return m_PluginList.GetCount();
  945. }
  946. STDMETHODIMP BaseHandler::GetPlugin(ULONG32 ulIndex, REF(IUnknown*)  /*OUT*/ pInstance)
  947. {
  948.     return GetPlugin( ulIndex, pInstance, NULL );
  949. }
  950. STDMETHODIMP BaseHandler::FlushCache()
  951. {
  952.     return HXR_OK;
  953. }
  954. STDMETHODIMP BaseHandler::SetCacheSize(ULONG32 nSizeKB)
  955. {
  956.     return HXR_OK;
  957. }
  958. STDMETHODIMP BaseHandler::ReadFromRegistry()
  959. {
  960.     HX_RESULT result;
  961.     IHXBuffer* pBuffer = NULL;
  962. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  963.     const char* pPath = GetDLLAccessPath()->GetPath(DLLTYPE_PLUGIN);
  964.     if (pPath && *pPath)
  965.     {
  966. pBuffer = new CHXBuffer;
  967. if (pBuffer)
  968. {
  969.     pBuffer->AddRef();
  970.     HX_VERIFY(SUCCEEDED(pBuffer->Set((UCHAR*)pPath,
  971.      strlen(pPath) + 1)));
  972. }
  973.     }
  974. #endif
  975.     // Set up a mount point with the default plugin location
  976.     result = AddPluginMountPoint(HXVER_SDK_PRODUCT, 0, 0, pBuffer);
  977.     HX_RELEASE(pBuffer);
  978.     return result;
  979. }
  980. BOOL BaseHandler::FindPlugin(const char* pFileName, UINT32 nDLLIndex, REF(UINT32) nIndex)
  981. {
  982.     UINT32 nTempIndex = 0;
  983.     for(CHXSimpleList::Iterator i = m_PluginList.Begin(); i!=m_PluginList.End(); ++i)
  984.     {
  985. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) *i;
  986. IHXBuffer* pBuffer = pPlugin->GetFileName();
  987. char* pPluginFileName = (char*) pBuffer->GetBuffer();
  988. if (!strcasecmp(pPluginFileName, pFileName))
  989. {
  990.     if (pPlugin->GetIndex() == nDLLIndex)
  991.     {
  992. nIndex = nTempIndex;
  993. HX_RELEASE(pBuffer);
  994. return TRUE;
  995.     }
  996. }
  997. HX_RELEASE(pBuffer);
  998. nTempIndex++;
  999.     }
  1000.     return FALSE;
  1001. }
  1002. /**********************************************************************************
  1003. ***     BaseHandler::Plugin ***
  1004. ***********************************************************************************/
  1005. BaseHandler::Plugin::Plugin(IUnknown* pContext) :
  1006. m_lRefCount(0)
  1007.     , m_pValues(0)
  1008.     , m_pPluginDLL(0)
  1009.     , m_pContext(pContext)
  1010.     ,  m_bInfoNeedsRefresh(FALSE)
  1011.     , m_nPluginIndex(0)
  1012.     , m_pClassFactory(NULL)
  1013. {
  1014.     m_pValues = new CHXHeader();
  1015.     m_pValues->AddRef();
  1016.     m_pContext->AddRef();
  1017.     m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  1018.      (void**)&m_pClassFactory);
  1019. }
  1020. BaseHandler::Plugin::~Plugin()
  1021. {
  1022.     HX_RELEASE(m_pValues);
  1023.     HX_RELEASE(m_pPluginDLL);
  1024.     HX_RELEASE(m_pClassFactory);
  1025.     HX_RELEASE(m_pContext);
  1026.     //HX_RELEASE(m_pPluginWatcher);
  1027. }
  1028. void BaseHandler::Plugin::SetPluginProperty(const char* pszPluginType)
  1029. {
  1030.     IHXBuffer* pBuffer = NULL;
  1031.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1032.     pBuffer->Set((UCHAR*)pszPluginType, strlen(pszPluginType)+1);
  1033.     m_pValues->SetPropertyCString(PLUGIN_CLASS, pBuffer);
  1034.     pBuffer->Release();
  1035. }
  1036. BOOL BaseHandler::Plugin::DoesMatch(IHXValues* pValues)
  1037. {
  1038.     CHXSimpleList   PossibleValues1;
  1039.     CHXSimpleList   PossibleValues2;
  1040.     const char*     pPropName = NULL;
  1041.     ULONG32     nInValue;
  1042.     ULONG32     nOutValue;
  1043.     IHXBuffer*     pInBuffer = NULL;
  1044.     IHXBuffer*     pOutBuffer = NULL;
  1045.     // Check ULONGS 1st
  1046.     if (HXR_OK == pValues->GetFirstPropertyULONG32(pPropName, nInValue))
  1047.     {
  1048. if (HXR_OK==m_pValues->GetPropertyULONG32(pPropName, nOutValue))
  1049. {
  1050.     if (nInValue != nOutValue)
  1051.     {
  1052. goto notFoundexit;
  1053.     }
  1054. }
  1055. else
  1056. {
  1057.     goto notFoundexit;
  1058. }
  1059. while (HXR_OK == pValues->GetNextPropertyULONG32(pPropName, nInValue))
  1060. {
  1061.     if (HXR_OK == m_pValues->GetPropertyULONG32(pPropName, nOutValue))
  1062.     {
  1063. if (nInValue != nOutValue)
  1064. {
  1065.     goto notFoundexit;
  1066. }
  1067.     }
  1068.     else
  1069.     {
  1070. goto notFoundexit;
  1071.     }
  1072. }
  1073.     }
  1074.     // Test code to look at all of the data in the map.
  1075. #ifdef _DEBUG
  1076.     HX_RESULT tempresult;
  1077.     tempresult = HXR_OK;
  1078.     tempresult = m_pValues->GetFirstPropertyCString(pPropName, pInBuffer);
  1079.     HX_RELEASE(pInBuffer);
  1080.     while (tempresult == HXR_OK)
  1081.     {
  1082. tempresult = m_pValues->GetNextPropertyCString(pPropName, pInBuffer);
  1083. if (tempresult == HXR_OK)
  1084. {
  1085.     HX_RELEASE(pInBuffer);
  1086. }
  1087.     }
  1088. #endif /*_DEBUG*/
  1089.     // Check String Props.
  1090.     if (HXR_OK == pValues->GetFirstPropertyCString(pPropName, pInBuffer))
  1091.     {
  1092. if (HXR_OK == m_pValues->GetPropertyCString(pPropName, pOutBuffer))
  1093. {
  1094.     if (!AreBufferEqual(pOutBuffer, pInBuffer))
  1095.     {
  1096. goto notFoundexit;
  1097.     }
  1098. }
  1099. else
  1100. {
  1101.     goto notFoundexit;
  1102. }
  1103. HX_RELEASE(pInBuffer);
  1104. HX_RELEASE(pOutBuffer);
  1105. while (HXR_OK == pValues->GetNextPropertyCString(pPropName, pInBuffer))
  1106. {
  1107.     if (HXR_OK == m_pValues->GetPropertyCString(pPropName, pOutBuffer))
  1108.     {
  1109. if ( !AreBufferEqual(pOutBuffer, pInBuffer))
  1110. {
  1111.     goto notFoundexit;
  1112. }
  1113.     }
  1114.     else
  1115.     {
  1116. goto notFoundexit;
  1117.     }
  1118.     HX_RELEASE(pInBuffer);
  1119.     HX_RELEASE(pOutBuffer);
  1120. }
  1121.     }
  1122.      // Check Buffer Properties
  1123.     if (HXR_OK == pValues->GetFirstPropertyBuffer(pPropName, pInBuffer))
  1124.     {
  1125. // XXXND  Make some utility functions for doing this...
  1126. if (HXR_OK == m_pValues->GetPropertyBuffer(pPropName, pOutBuffer))
  1127. {
  1128.     if( pOutBuffer->GetSize() == pInBuffer->GetSize() )
  1129.     {
  1130. if( ::memcmp( pOutBuffer->GetBuffer(), pInBuffer->GetBuffer(), pOutBuffer->GetSize() ) )
  1131. {
  1132.     goto notFoundexit;
  1133. }
  1134.     }
  1135. }
  1136. else
  1137. {
  1138.     goto notFoundexit;
  1139. }
  1140. HX_RELEASE(pInBuffer);
  1141. HX_RELEASE(pOutBuffer);
  1142. while (HXR_OK == pValues->GetNextPropertyBuffer(pPropName, pInBuffer))
  1143. {
  1144.     if (HXR_OK == m_pValues->GetPropertyBuffer(pPropName, pOutBuffer))
  1145.     {
  1146. // XXXND  Make some utility functions for doing this...
  1147. if( pOutBuffer->GetSize() == pInBuffer->GetSize() )
  1148. {
  1149.     if( ::memcmp( pOutBuffer->GetBuffer(), pInBuffer->GetBuffer(), pOutBuffer->GetSize() ) )
  1150.     {
  1151. goto notFoundexit;
  1152.     }
  1153. }
  1154.     }
  1155.     else
  1156.     {
  1157. goto notFoundexit;
  1158.     }
  1159.     HX_RELEASE(pInBuffer);
  1160.     HX_RELEASE(pOutBuffer);
  1161. }
  1162.     }
  1163.     return TRUE;    // we made it!
  1164. notFoundexit:
  1165.     HX_RELEASE(pInBuffer);
  1166.     HX_RELEASE(pOutBuffer);
  1167.     return FALSE;
  1168. }
  1169. void BaseHandler::Plugin::SetDLL(PluginDLL * pPluginDll)
  1170. {
  1171.     m_pPluginDLL = pPluginDll;
  1172.     m_pPluginDLL->AddRef();
  1173.     IHXBuffer* pBuffer = pPluginDll->GetFileName();
  1174.     HX_ASSERT(pBuffer);
  1175.     m_pValues->SetPropertyCString(PLUGIN_FILENAME, pBuffer);
  1176.     HX_RELEASE(pBuffer);
  1177. }
  1178. void BaseHandler::Plugin::SetIndex(UINT16 nIndex)
  1179. {
  1180.     m_nPluginIndex = nIndex;
  1181.     m_pValues->SetPropertyULONG32(PLUGIN_INDEX, nIndex);
  1182. }
  1183. void BaseHandler::Plugin::SetPropertyULONG32(char* pName, char* pValue)
  1184. {
  1185.     if (m_pValues)
  1186.     {
  1187. m_pValues->SetPropertyULONG32(pName, atoi(pValue));
  1188.     }
  1189. }
  1190. void BaseHandler::Plugin::SetPropertyCString(char* pName, char* pValue)
  1191. {
  1192.     if (m_pValues)
  1193.     {
  1194. IHXBuffer* pTempBuffer = new CHXBuffer();
  1195. pTempBuffer->AddRef();
  1196. pTempBuffer->Set((UCHAR*)pValue, strlen(pValue)+1);
  1197. m_pValues->SetPropertyCString(pName, pTempBuffer);
  1198. HX_RELEASE(pTempBuffer);
  1199.     }
  1200. }
  1201. void BaseHandler::Plugin::SetPropertyBuffer(char* pName, BYTE* pData, UINT32 size )
  1202. {
  1203.     if (m_pValues)
  1204.     {
  1205. // XXXND  FIX  THis really shouldn't have to do this copy
  1206. IHXBuffer* pTempBuffer = new CHXBuffer();
  1207. pTempBuffer->AddRef();
  1208. pTempBuffer->Set( pData, size );
  1209. m_pValues->SetPropertyBuffer(pName, pTempBuffer);
  1210. HX_RELEASE(pTempBuffer);
  1211.     }
  1212. }
  1213. BOOL BaseHandler::Plugin::AreBufferEqual(IHXBuffer* pBigBuff,
  1214.    IHXBuffer* pSmallBuff)
  1215. {
  1216.     char*   pTemp;
  1217.     BOOL    bRetVal = FALSE;
  1218.     pTemp = new char[pBigBuff->GetSize()];
  1219.     strcpy(pTemp, (char*)pBigBuff->GetBuffer()); /* Flawfinder: ignore */
  1220.     char* token;
  1221.     token = strtok(pTemp, zm_pszValueSeperator);
  1222.     while (token)
  1223.     {
  1224. CHXString tokenCHXstring;
  1225. CHXString smallCHXstring;
  1226. tokenCHXstring = token;
  1227. smallCHXstring = (char*)pSmallBuff->GetBuffer();
  1228. tokenCHXstring.TrimLeft();
  1229. tokenCHXstring.TrimRight();
  1230. smallCHXstring.TrimLeft();
  1231. smallCHXstring.TrimRight();
  1232. if (!strcasecmp(tokenCHXstring, smallCHXstring))
  1233. {
  1234.     bRetVal = TRUE;
  1235.     break;
  1236. }
  1237. token = strtok(NULL, zm_pszValueSeperator);
  1238.     }
  1239.     delete[] pTemp;
  1240.     return bRetVal;
  1241. }
  1242. BaseHandler::Errors BaseHandler::Plugin::GetValuesFromDLL(IHXPlugin* pHXPlugin)
  1243. {
  1244.     BaseHandler::Errors  retVal;
  1245.     retVal = GetBasicValues(pHXPlugin);
  1246.     if (retVal == NO_ERRORS)
  1247.     {
  1248. retVal = GetExtendedValues(pHXPlugin);
  1249.     }
  1250.     return retVal;
  1251. }
  1252. BaseHandler::Errors BaseHandler::Plugin::GetPlugin(REF(IUnknown*) pUnknown )
  1253. {
  1254.     pUnknown = NULL;
  1255.     BaseHandler::Errors retVal = NO_ERRORS;
  1256.     if (!m_pPluginDLL)
  1257.     {
  1258. return PLUGIN_NOT_FOUND;
  1259.     }
  1260.     if (!m_pPluginDLL->IsLoaded())
  1261.     {
  1262. if (NO_ERRORS != (retVal = m_pPluginDLL->Load(m_pContext)))
  1263. {
  1264.     return retVal;
  1265. }
  1266.     }
  1267.     if (HXR_OK != m_pPluginDLL->CreateInstance(&pUnknown, m_nPluginIndex))
  1268.     {
  1269. return CREATE_INSTANCHXR_FAILURE;
  1270.     }
  1271.     return retVal;
  1272. }
  1273. BaseHandler::Errors BaseHandler::Plugin::GetInstance(REF(IUnknown*) pUnknown, IUnknown* pIUnkOuter )
  1274. {
  1275.     // Initialize out parameter
  1276.     pUnknown = NULL;
  1277.     IUnknown* pIUnkPlugin = NULL;
  1278.     BaseHandler::Errors retVal = GetPlugin( pIUnkPlugin );
  1279.     if( retVal == NO_ERRORS )
  1280.     {
  1281. IHXComponentPlugin* pIComp = NULL;
  1282. if( SUCCEEDED( pIUnkPlugin->QueryInterface( IID_IHXComponentPlugin, (void**) &pIComp ) ) )
  1283. {
  1284.     // Ask for the correct object by CLSID
  1285.     IHXBuffer* pCLSID = NULL;
  1286.     if( SUCCEEDED( m_pValues->GetPropertyBuffer( PLUGIN_COMPONENT_CLSID, pCLSID ) ) )
  1287.     {
  1288. if( FAILED( pIComp->CreateComponentInstance( *(GUID*) pCLSID->GetBuffer(), pUnknown, pIUnkOuter ) ) )
  1289. {
  1290.     retVal = CREATE_INSTANCHXR_FAILURE;
  1291. }
  1292. HX_RELEASE( pCLSID );
  1293.     }
  1294.     else
  1295.     {
  1296. // Hmmm...we have a component plugin without a CLSID.  Serious internal error
  1297. retVal = BAD_PLUGIN;
  1298.     }
  1299.     // Release the interface, and destroy the plugin
  1300.     HX_RELEASE( pIComp );
  1301.     HX_RELEASE( pIUnkPlugin );
  1302. }
  1303. else
  1304. {
  1305.     // If this isn't a component plugin, then we can't aggregate anything
  1306.     if( pIUnkOuter )
  1307.     {
  1308. HX_RELEASE( pIUnkPlugin );
  1309. retVal = AGGREGATION_NOT_SUPPORTED;
  1310.     }
  1311.     else
  1312.     {
  1313. pUnknown = pIUnkPlugin;
  1314.     }
  1315. }
  1316.     }
  1317.     return retVal;
  1318. }
  1319. BOOL BaseHandler::Plugin::IsLoaded()
  1320. {
  1321.     if (!m_pPluginDLL)
  1322. return FALSE;
  1323.     return m_pPluginDLL->IsLoaded();
  1324. }
  1325. HX_RESULT BaseHandler::Plugin::GetPluginInfo(REF(IHXValues*) pVals)
  1326. {
  1327.     if (m_pValues)
  1328.     {
  1329. pVals = m_pValues;
  1330. return HXR_OK;
  1331.     }
  1332.     pVals = NULL;
  1333.     return HXR_FAIL;
  1334. }
  1335. IHXBuffer* BaseHandler::Plugin::GetFileName()
  1336. {
  1337.     IHXBuffer* retVal = NULL;
  1338.     // Get the filename from m_pValues.  We can't get it from the DLL,
  1339.     // because we may be in the process of loading, and we just got it
  1340.     // from the preferences
  1341.     if( m_pValues )
  1342.     {
  1343. m_pValues->GetPropertyCString( PLUGIN_FILENAME, retVal );
  1344.     }
  1345.     return retVal;
  1346. }
  1347. BaseHandler::Errors
  1348. BaseHandler::Plugin::GetBasicValues(IHXPlugin* pHXPlugin)
  1349. {
  1350.     return NO_ERRORS;
  1351.     const char* pszDescription = NULL;
  1352.     const char* pszCopyright = NULL;
  1353.     const char* pszMoreInfoUrl = NULL;
  1354.     ULONG32 ulVersionNumber = 0;
  1355.     BOOL nload_multiple = 0;
  1356.     if (HXR_OK != pHXPlugin->GetPluginInfo(nload_multiple, pszDescription,
  1357.        pszCopyright, pszMoreInfoUrl, ulVersionNumber))
  1358.     {
  1359.         return BAD_PLUGIN;
  1360.     }
  1361.     IHXBuffer* pBuffer = NULL;
  1362.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1363.     if (pszDescription)
  1364.     {
  1365. pBuffer->Set((UCHAR*)pszDescription, strlen(pszDescription)+1);
  1366.     }
  1367.     m_pValues->SetPropertyCString(PLUGIN_DESCRIPTION2, pBuffer);
  1368.     pBuffer->Release();
  1369.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1370.     if (pszCopyright)
  1371.     {
  1372. pBuffer->Set((UCHAR*)pszCopyright, strlen(pszCopyright)+1);
  1373.     }
  1374.     m_pValues->SetPropertyCString(PLUGIN_COPYRIGHT2, pBuffer);
  1375.     pBuffer->Release();
  1376.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1377.     if (pszMoreInfoUrl)
  1378.     {
  1379. pBuffer->Set((UCHAR*)pszMoreInfoUrl, strlen(pszMoreInfoUrl)+1);
  1380.     }
  1381.     m_pValues->SetPropertyCString(PLUGIN_COPYRIGHT, pBuffer);
  1382.     pBuffer->Release();
  1383.     m_pValues->SetPropertyULONG32(PLUGIN_LOADMULTIPLE, nload_multiple);
  1384.     m_pValues->SetPropertyULONG32(PLUGIN_VERSION, ulVersionNumber);
  1385.     return NO_ERRORS;
  1386. }
  1387. BaseHandler::Errors
  1388. BaseHandler::Plugin::GetExtendedValues(IHXPlugin* pHXPlugin)
  1389. {
  1390. //    Errors result     = NO_ERRORS;
  1391.     IHXFileFormatObject* pFileFormat     = NULL;
  1392. //    IHXMetaFileFormatObject* pMetaFileFormat     = NULL;
  1393.     IHXFileWriter* pFileWriter     = NULL;
  1394.     IHXBroadcastFormatObject* pBroadcastFormat    = NULL;
  1395.     IHXFileSystemObject* pFileSystem     = NULL;
  1396.     IHXRenderer* pRenderer     = NULL;
  1397.     IHXDataRevert* pDataRevert     = NULL;
  1398.     IHXStreamDescription* pStreamDescription  = NULL;
  1399.     IHXPlayerConnectionAdviseSink* pAllowanceFormat    = NULL;
  1400.     IHXCommonClassFactory* pClassFactory       = NULL;
  1401.     IHXPluginProperties* pIHXPluginPropertiesThis = NULL;
  1402.     UINT32 nCountInterfaces    = 0;
  1403.     // file system
  1404.     if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXFileSystemObject, (void**) &pFileSystem))
  1405.     {
  1406. const char* pszShortName;
  1407. const char* pszProtocol;
  1408. if (HXR_OK != pFileSystem->GetFileSystemInfo(pszShortName, pszProtocol))
  1409. {
  1410.     HX_RELEASE (pFileSystem);
  1411.     return  CANT_GET_RENDERER_INFO; //XXXAH Cleanup?
  1412. }
  1413. SetPluginProperty(PLUGIN_FILESYSTEM_TYPE);
  1414. IHXBuffer* pBuffer = NULL;
  1415. m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1416. if (pszShortName)
  1417. {
  1418.     pBuffer->Set((UCHAR*)pszShortName, strlen(pszShortName)+1);
  1419. }
  1420. m_pValues->SetPropertyCString(PLUGIN_FILESYSTEMSHORT, pBuffer);
  1421. pBuffer->Release();
  1422. m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1423. if (pszProtocol)
  1424. {
  1425.     pBuffer->Set((UCHAR*)pszProtocol, strlen(pszProtocol)+1);
  1426. }
  1427. m_pValues->SetPropertyCString(PLUGIN_FILESYSTEMPROTOCOL, pBuffer);
  1428. pBuffer->Release();
  1429. pFileSystem->Release();
  1430. nCountInterfaces++;
  1431.     }
  1432.     // file format
  1433.     if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXFileFormatObject, (void**)&pFileFormat) ||
  1434. HXR_OK == pHXPlugin->QueryInterface(IID_IHXMetaFileFormatObject, (void**)&pFileFormat) ||
  1435. HXR_OK == pHXPlugin->QueryInterface(IID_IHXFileWriter, (void**)&pFileWriter))
  1436.     {
  1437. // fine we are in now we will get the correct type.
  1438. if (pFileFormat)
  1439. {
  1440.     pFileFormat->Release();
  1441. }
  1442. else
  1443. {
  1444.     pFileWriter->Release();
  1445. }
  1446. IHXMetaFileFormatObject* pMetaFileFormat;
  1447. const char** ppszMimeTypes = NULL;
  1448. const char** ppszExtensions = NULL;
  1449. const char** ppszOpenNames = NULL;
  1450. if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXFileFormatObject, (void**)&pFileFormat))
  1451. {
  1452.     pFileFormat->GetFileFormatInfo( ppszMimeTypes,
  1453.     ppszExtensions,
  1454.     ppszOpenNames);
  1455.     pFileFormat->Release();
  1456.     SetPluginProperty(PLUGIN_FILEFORMAT_TYPE);
  1457. }
  1458. if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXMetaFileFormatObject, (void**)&pMetaFileFormat))
  1459. {
  1460.     pMetaFileFormat->GetMetaFileFormatInfo( ppszMimeTypes,
  1461.     ppszExtensions,
  1462.     ppszOpenNames);
  1463.     pMetaFileFormat->Release();
  1464.     SetPluginProperty(PLUGIN_METAFILEFORMAT_TYPE);
  1465. }
  1466. if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXFileWriter, (void**)&pFileWriter))
  1467. {
  1468.     pFileWriter->GetFileFormatInfo( ppszMimeTypes,
  1469.     ppszExtensions,
  1470.     ppszOpenNames);
  1471.     pFileWriter->Release();
  1472.     SetPluginProperty(PLUGIN_FILEWRITER_TYPE);
  1473. }
  1474. IHXBuffer* pBuffer = NULL;
  1475. if (ppszMimeTypes)
  1476. {
  1477.     CatStrings((char**)ppszMimeTypes, pBuffer);     //XXXAH this had better be const in reality!
  1478.     m_pValues->SetPropertyCString(PLUGIN_FILEMIMETYPES, pBuffer);
  1479.     pBuffer->Release();
  1480. }
  1481. if (ppszExtensions)
  1482. {
  1483.     CatStrings((char**)ppszExtensions, pBuffer); //XXXAH this had better be const in reality!
  1484.     m_pValues->SetPropertyCString(PLUGIN_FILEEXTENSIONS, pBuffer);
  1485.     pBuffer->Release();
  1486. }
  1487. if (ppszOpenNames)
  1488. {
  1489.     CatStrings((char**)ppszOpenNames, pBuffer); //XXXAH this had better be const in reality!
  1490.     m_pValues->SetPropertyCString(PLUGIN_FILEOPENNAMES, pBuffer);
  1491.     pBuffer->Release();
  1492. }
  1493. nCountInterfaces++;
  1494.     }
  1495.     // renderer
  1496.     if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXRenderer, (void**)&pRenderer))
  1497.     {
  1498. char** ppszMimeTypes;
  1499.         UINT32 initial_granularity = 0;
  1500. // get the basic info
  1501. if (HXR_OK == pRenderer->GetRendererInfo((const char**&)ppszMimeTypes, initial_granularity))
  1502. {
  1503.     IHXBuffer* pBuffer;
  1504.     if (ppszMimeTypes)
  1505.     {
  1506. CatStrings(ppszMimeTypes, pBuffer);
  1507.     }
  1508.     m_pValues->SetPropertyCString(PLUGIN_RENDERER_MIME, pBuffer);
  1509.     pBuffer->Release();
  1510.     m_pValues->SetPropertyULONG32(PLUGIN_RENDERER_GRANULARITY, initial_granularity);
  1511.     SetPluginProperty(PLUGIN_RENDERER_TYPE);
  1512. }
  1513. HX_RELEASE(pRenderer);
  1514. nCountInterfaces++;
  1515.     }
  1516.     // stream description
  1517.     if (HXR_OK == pHXPlugin->QueryInterface(IID_IHXStreamDescription, (void**)&pStreamDescription))
  1518.     {
  1519. const char* pszMimeType;
  1520. IHXBuffer* pBuffer;
  1521. if (HXR_OK != pStreamDescription->GetStreamDescriptionInfo(pszMimeType))
  1522. {
  1523.     HX_RELEASE (pStreamDescription);
  1524.     return CANT_GET_FILE_FORMAT_INFO; // XXXAH Cleanup?
  1525. }
  1526. pStreamDescription->Release();
  1527. m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pBuffer);
  1528. if (pszMimeType)
  1529. {
  1530.     pBuffer->Set((UCHAR*)pszMimeType, strlen(pszMimeType)+1);
  1531. }
  1532. m_pValues->SetPropertyCString(PLUGIN_STREAMDESCRIPTION, pBuffer);
  1533. pBuffer->Release();
  1534. SetPluginProperty(PLUGIN_STREAM_DESC_TYPE);
  1535. nCountInterfaces++;
  1536.     }
  1537.     // common class factory
  1538.     if(HXR_OK == pHXPlugin->QueryInterface(IID_IHXCommonClassFactory,
  1539. (void**)&pClassFactory))
  1540.     {
  1541. SetPluginProperty(PLUGIN_CLASS_FACTORY_TYPE);
  1542. HX_RELEASE (pClassFactory);
  1543. nCountInterfaces++;
  1544.     }
  1545.     // NO MORE NEW PLUGIN INFORMATION INTERFACES!!!!
  1546.     //
  1547.     // THIS IS THE LAST ONE!!!!!
  1548.     if( SUCCEEDED( pHXPlugin->QueryInterface( IID_IHXPluginProperties, (void**)&pIHXPluginPropertiesThis ) ) )
  1549.     {
  1550. IHXValues* pIHXValuesProperties = NULL;
  1551. pHXPlugin->InitPlugin(m_pContext);
  1552. if( SUCCEEDED( pIHXPluginPropertiesThis->GetProperties( pIHXValuesProperties ) ) && pIHXValuesProperties )
  1553. {
  1554.     CHXHeader::mergeHeaders( m_pValues, pIHXValuesProperties );
  1555. }
  1556. HX_RELEASE(pIHXValuesProperties);
  1557. // XXXkshoop Let this coincide with other interfaces.. for now..
  1558. //nCountInterfaces++;
  1559.     }
  1560.     HX_RELEASE(pIHXPluginPropertiesThis);
  1561.     HX_ASSERT(nCountInterfaces<2);
  1562.     return NO_ERRORS;
  1563. }
  1564. void BaseHandler::Plugin::InitializeComponentPlugin( IHXPlugin* pIPlugin, IHXValues* pIValues )
  1565. {
  1566.     // Setup basic data
  1567.     // XXXHP - this is unnecessary information as it is stored on a PER COMPONENT not PER PLUGIN basis in this case.
  1568.     // GetBasicValues( pIPlugin );
  1569.     // Copy data from pIValues
  1570.     CHXHeader::mergeHeaders( m_pValues, pIValues );
  1571. }
  1572. HX_RESULT BaseHandler::Plugin::CatStrings(char** pInStrings,
  1573.     REF(IHXBuffer*) pOutBuffer)
  1574. {
  1575.     ULONG32 nAllocedSpace   = 100;
  1576.     char*   ptemp     = new char[nAllocedSpace];
  1577.     char*   ptemp2     = NULL;
  1578.     ULONG32 nStrLen     = 0;
  1579.     ULONG32 nNewStrLen     = 0;
  1580.     *ptemp = 0;
  1581.     pOutBuffer = 0;
  1582.     for(; *pInStrings; pInStrings++)
  1583.     {
  1584. nNewStrLen = strlen(*pInStrings);
  1585. if (nNewStrLen+ nStrLen >= nAllocedSpace)
  1586. {
  1587.     // double if the new string is less than the new space
  1588.     // or add double what it required.
  1589.     if (nNewStrLen< nAllocedSpace)
  1590.     {
  1591. nAllocedSpace*=2;
  1592.     }
  1593.     else
  1594.     {
  1595. nAllocedSpace+=nNewStrLen*2;
  1596.     }
  1597.     ptemp2 = new char[nAllocedSpace];
  1598.     memcpy(ptemp2, ptemp, nStrLen+1); /* Flawfinder: ignore */
  1599.     delete [] ptemp;
  1600.     ptemp = ptemp2;
  1601. }
  1602. // XXXAH I must trim the strings before I add them to this string.
  1603. // the find function DEPENDS UPON THIS.
  1604. SafeStrCat(ptemp,  *pInStrings, nAllocedSpace);
  1605. if (*(pInStrings+1))
  1606. {
  1607.     SafeStrCat(ptemp,  BaseHandler::zm_pszValueSeperator, nAllocedSpace); // XXXAH Perhaps a define?
  1608. }
  1609. nStrLen+=nNewStrLen+1;
  1610.     }
  1611.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer,(void**)&pOutBuffer);
  1612.     pOutBuffer->Set((UCHAR*)ptemp, strlen(ptemp)+1);
  1613.     delete[] ptemp;
  1614.     return HXR_OK;
  1615. }
  1616. /////////////////////////////////////////////////////////////////////////
  1617. //  Method:
  1618. //      BaseHandler::Plugin::QueryInterface
  1619. //  Purpose:
  1620. //      Implement this to export the interfaces supported by your
  1621. //      object.
  1622. //
  1623. STDMETHODIMP
  1624. BaseHandler::Plugin::QueryInterface(REFIID riid, void** ppvObj)
  1625. {
  1626.     if (IsEqualIID(riid, IID_IUnknown))
  1627.     {
  1628.         AddRef();
  1629.         *ppvObj = (IUnknown*)this;
  1630.         return HXR_OK;
  1631.     }
  1632.     *ppvObj = NULL;
  1633.     return HXR_NOINTERFACE;
  1634. }
  1635. /////////////////////////////////////////////////////////////////////////
  1636. //  Method:
  1637. //      BaseHandler::Plugin::AddRef
  1638. //  Purpose:
  1639. //      Everyone usually implements this the same... feel free to use
  1640. //      this implementation.
  1641. //
  1642. STDMETHODIMP_(ULONG32)
  1643. BaseHandler::Plugin::AddRef()
  1644. {
  1645.     return InterlockedIncrement(&m_lRefCount);
  1646. }
  1647. /////////////////////////////////////////////////////////////////////////
  1648. //  Method:
  1649. //      BaseHandler::Plugin::Release
  1650. //  Purpose:
  1651. //      Everyone usually implements this the same... feel free to use
  1652. //      this implementation.
  1653. //
  1654. STDMETHODIMP_(ULONG32)
  1655. BaseHandler::Plugin::Release()
  1656. {
  1657.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1658.     {
  1659.         return m_lRefCount;
  1660.     }
  1661.     delete this;
  1662.     return 0;
  1663. }
  1664. /**********************************************************************************
  1665. ***     BaseHandler::PluginDLL ***
  1666. ***********************************************************************************/
  1667. BaseHandler::PluginDLL::PluginDLL( const char* pszFileName, PluginMountPoint* pMountPoint,
  1668. BaseHandler* pBaseHandler )
  1669.     : m_fpCreateInstance(NULL)
  1670.     , m_fpShutdown(NULL)
  1671.     , m_fCanUnload(NULL)
  1672.     , m_pMountPoint( pMountPoint )
  1673.     , m_pFileName( NULL )
  1674.     , m_pNamespace( NULL )
  1675.     , m_nSizeBites(0)
  1676.     , m_lRefCount(0)
  1677.     , m_NumOfPlugins(0)
  1678.     , m_pDLLAccess(NULL)
  1679.     , m_bHas_factory(FALSE)
  1680.     , m_bLoaded(FALSE)
  1681.     , m_nActiveReferences(0)
  1682.     , m_pBaseHandler(pBaseHandler)
  1683.     , m_bDoesExist(TRUE)
  1684. {
  1685.     // Always create an IHXBuffer and store the filename there
  1686.     CHXBuffer* pCHXBuffer = new CHXBuffer();
  1687.     if( SUCCEEDED( pCHXBuffer->QueryInterface( IID_IHXBuffer,(void**) &m_pFileName ) ) )
  1688.     {
  1689. if (pszFileName)
  1690. {
  1691.     // Make sure there are no path components in the filename
  1692.     HX_ASSERT( !strrchr( pszFileName, BaseHandler::zm_cDirectorySeperator ) );
  1693.     m_pFileName->Set( (BYTE*) pszFileName, ::strlen( pszFileName ) + 1 );
  1694. }
  1695.     }
  1696.     m_pDLLAccess = new DLLAccess();
  1697. }
  1698. BaseHandler::PluginDLL::~PluginDLL()
  1699. {
  1700.     HX_RELEASE( m_pFileName );
  1701.     HX_RELEASE( m_pNamespace );
  1702.     if (m_pDLLAccess)
  1703.     {
  1704.         if (m_bLoaded)
  1705. {
  1706.     if (m_fpShutdown)
  1707.     {
  1708. m_fpShutdown();
  1709. m_fpShutdown = NULL;
  1710.     }
  1711.     m_pDLLAccess->close();
  1712. }
  1713. delete m_pDLLAccess;
  1714. m_pDLLAccess = 0;
  1715.     }
  1716. }
  1717. BaseHandler::Errors
  1718. BaseHandler::PluginDLL::Load(IUnknown* pContext)
  1719. {
  1720.     HX_LOG_BLOCK( "BaseHandler::PluginDLL::Load()" );
  1721.     Errors result     = NO_ERRORS;
  1722.     IUnknown* pInstance   = NULL;
  1723.     IHXPlugin* pPlugin = NULL;
  1724.     IHXPluginFactory* pIFactory = NULL;
  1725.     if (m_bLoaded)
  1726.     {
  1727. return PLUGIN_ALREADY_HAS_MOUNT_POINT; //XXXAH Huh?
  1728.     }
  1729.     if( m_pFileName->GetSize() <= 1 )
  1730.     {
  1731. return PLUGIN_NOT_FOUND;
  1732.     }
  1733.     // Build complete path for DLL
  1734.     CHXString fileNameWithPath;
  1735. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  1736.     // we're not statically linked so we must use the mount point path
  1737.     IHXBuffer* pBuffer = m_pMountPoint->Path();
  1738.     if (pBuffer)
  1739.     {
  1740. fileNameWithPath = (char*)pBuffer->GetBuffer();
  1741. UINT32 len = fileNameWithPath.GetLength();
  1742. if (len && fileNameWithPath.GetAt(len - 1) != BaseHandler::zm_cDirectorySeperator)
  1743. {
  1744.     fileNameWithPath += BaseHandler::zm_pszDirectorySeperator;
  1745. }
  1746. HX_RELEASE(pBuffer);
  1747.     }
  1748. #endif
  1749.     fileNameWithPath += (char*) m_pFileName->GetBuffer();
  1750.     // 1st load the DLL into memory
  1751.     HX_PRIME_ACCUMULATOR( 'pdll', "Total DLL Load Time" );
  1752.     int dllLoadResult = m_pDLLAccess->open(fileNameWithPath);
  1753.     HX_UPDATE_ACCUMULATOR( 'pdll' );
  1754.     if( dllLoadResult != DLLAccess::DLL_OK )
  1755.     {
  1756. m_pBaseHandler->ReportError( HXLOG_DEBUG, (char *) m_pFileName->GetBuffer(), m_pDLLAccess->getErrorString() );
  1757. return CANT_OPEN_DLL;
  1758.     }
  1759.     HX_LOG_CHECKPOINT( "DLL Loaded" );
  1760.     // Now look for the HXCreateInstance exported function
  1761.     m_fpCreateInstance = (FPCREATEINSTANCE) m_pDLLAccess->getSymbol(HXCREATEINSTANCESTR);
  1762.     if (NULL == m_fpCreateInstance)
  1763.     {
  1764. m_pBaseHandler->ReportError( HXLOG_DEBUG, "NO HXCreateInstance", NULL );
  1765. return NO_HX_CREATE_INSTANCE;
  1766.     }
  1767.     // And look for HXShutdown exported function... not required.
  1768.     m_fpShutdown    = (FPSHUTDOWN) m_pDLLAccess->getSymbol(HXSHUTDOWNSTR);
  1769.     // and look for CanUnload2 exported function
  1770.     //JE 3/26/01: look for CanUnload2 instead of CanUnload. This way we will
  1771.     //not try and unload any DLLs that may have incorrectly implemented the old
  1772.     // CanUnload. If you implement CanUnload2, you better get it right ;)
  1773.     m_fCanUnload    = (FPSHUTDOWN) m_pDLLAccess->getSymbol("CanUnload2");
  1774.     HX_LOG_CHECKPOINT( "Exported symbols found" );
  1775.     // Does this thing support the IHXPlugin Interface
  1776.     // Now we will test to see if the DLL contains multiple Plugins.
  1777.     HX_PRIME_ACCUMULATOR( 'plmk', "Total Plugin Allocation time" );
  1778.     HX_RESULT createResult = m_fpCreateInstance( &pInstance );
  1779.     HX_UPDATE_ACCUMULATOR( 'plmk' );
  1780.     if( HXR_OK != createResult )
  1781.     {
  1782. m_pBaseHandler->ReportError( HXLOG_DEBUG, "HXCreateInstance Failure", NULL );
  1783. result = CREATE_INSTANCHXR_FAILURE;
  1784. goto cleanup;
  1785.     }
  1786.     HX_LOG_CHECKPOINT( "Plugin instance created" );
  1787.     // To be a valid plugin a DLL must support IHXPlugin
  1788.     // In addition, it may support IHXPluginFactory
  1789.     if( SUCCEEDED( pInstance->QueryInterface( IID_IHXPluginFactory, (void**) &pIFactory ) ) )
  1790.     {
  1791. m_bHas_factory = TRUE;
  1792. m_NumOfPlugins = pIFactory->GetNumPlugins();
  1793. HX_RELEASE( pIFactory );
  1794.     }
  1795.     else if( SUCCEEDED( pInstance->QueryInterface( IID_IHXPlugin, (void**) &pPlugin ) ) )
  1796.     {
  1797. m_bHas_factory = FALSE;
  1798. m_NumOfPlugins = 1;
  1799. IHXComponentPlugin* pIPackage = NULL;
  1800. if (SUCCEEDED (pInstance->QueryInterface (IID_IHXComponentPlugin, (void**) &pIPackage)))
  1801. {
  1802. #ifndef _WINDOWS // XXXHP TEMPORARY - viper team has requested that this shouldn't assert for now on windows.
  1803.     HX_ASSERT (m_fpShutdown);
  1804. #endif
  1805.     pPlugin->InitPlugin (pContext);
  1806.     m_packageName = pIPackage->GetPackageName ();
  1807.     HX_RELEASE (pIPackage);
  1808. }
  1809. HX_RELEASE( pPlugin );
  1810.     }
  1811.     else
  1812.     {
  1813. result = BAD_PLUGIN;
  1814. goto cleanup;
  1815.     }
  1816.     // We are now loaded.
  1817.     HX_RELEASE(pInstance);
  1818.     m_bLoaded = TRUE;
  1819. cleanup:
  1820.     HX_LOG_CHECKPOINT( "BaseHandler::PluginDLL::Load() exiting" );
  1821.     return result;
  1822. }
  1823. HX_RESULT BaseHandler::PluginDLL::Unload(BOOL safe)
  1824. {
  1825.     if (m_bLoaded)
  1826.     {
  1827. if (!safe || ( m_fCanUnload && m_fCanUnload()==HXR_OK ) )
  1828. {
  1829.     if (m_fpShutdown)
  1830.     {
  1831. if (FAILED (m_fpShutdown ())) return HXR_FAIL;
  1832. m_fpShutdown = NULL;
  1833.     }
  1834.             if (DLLAccess::DLL_OK == m_pDLLAccess->close())
  1835.     {
  1836. m_bLoaded = FALSE;
  1837. return HXR_OK;
  1838.     }
  1839. }
  1840.     }
  1841.     return HXR_FAIL;
  1842. }
  1843. BOOL BaseHandler::PluginDLL::IsLoaded()
  1844. {
  1845.     return m_bLoaded;
  1846. }
  1847. BaseHandler::Errors BaseHandler::PluginDLL::CreateInstance(IUnknown** ppUnk,
  1848.  UINT32 uIndex)
  1849. {
  1850.     if (!m_bLoaded)
  1851. return PLUGIN_NOT_FOUND;
  1852.     if (!m_bHas_factory)
  1853.     {
  1854. if (HXR_OK != m_fpCreateInstance(ppUnk))
  1855. {
  1856.     return CREATE_INSTANCHXR_FAILURE;
  1857. }
  1858.     }
  1859.     else
  1860.     {
  1861. if (uIndex > (ULONG32)(m_NumOfPlugins-1) && m_NumOfPlugins)
  1862. {
  1863.     return CANT_LOAD_INTERFACE;
  1864. }
  1865. IUnknown* pUnk;
  1866. IHXPluginFactory* pPluginFactory;
  1867. m_fpCreateInstance(&pUnk);
  1868. if (HXR_OK != pUnk->QueryInterface
  1869. (IID_IHXPluginFactory, (void**) &pPluginFactory))
  1870. {
  1871.     HX_RELEASE(pUnk);
  1872.     return CREATE_INSTANCHXR_FAILURE;
  1873. }
  1874. else
  1875. {
  1876.     HX_RELEASE(pUnk);
  1877.     if (HXR_OK != pPluginFactory->GetPlugin((UINT16)uIndex, ppUnk))
  1878.     {
  1879. HX_RELEASE(pPluginFactory);
  1880. return CREATE_INSTANCHXR_FAILURE;
  1881.     }
  1882.     HX_RELEASE(pPluginFactory);
  1883. }
  1884.     }
  1885.     //m_pPlugin2Handler->AddtoLRU(this);
  1886.     //m_pPlugin2Handler->UpdateCache();
  1887.     return NO_ERRORS;
  1888. }
  1889. IHXBuffer* BaseHandler::PluginDLL::GetFileName()
  1890. {
  1891.     m_pFileName->AddRef();
  1892.     return m_pFileName;
  1893. }
  1894. IHXBuffer* BaseHandler::PluginDLL::GetNamespace()
  1895. {
  1896.     if (m_pNamespace)
  1897.     {
  1898. m_pNamespace->AddRef();
  1899.     }
  1900.     return m_pNamespace;
  1901. }
  1902. void BaseHandler::PluginDLL::SetNamespace(IHXBuffer* pNamespace)
  1903. {
  1904.     m_pNamespace = pNamespace;
  1905.     if (m_pNamespace)
  1906.     {
  1907. m_pNamespace->AddRef();
  1908.     }
  1909. }
  1910. UINT32 BaseHandler::PluginDLL::AddDLLReference()
  1911. {
  1912.     return ++m_nActiveReferences;
  1913. }
  1914. UINT32 BaseHandler::PluginDLL::ReleaseDLLReference()
  1915. {
  1916.     --m_nActiveReferences;
  1917.     Unload();     //XXXAH this should only happen if we have set DLL unloading to true.
  1918.     return 0;
  1919. }
  1920. /////////////////////////////////////////////////////////////////////////
  1921. //  Method:
  1922. //      BaseHandler::PluginDLL::QueryInterface
  1923. //  Purpose:
  1924. //      Implement this to export the interfaces supported by your
  1925. //      object.
  1926. //
  1927. STDMETHODIMP
  1928. BaseHandler::PluginDLL::QueryInterface(REFIID riid, void** ppvObj)
  1929. {
  1930.     if (IsEqualIID(riid, IID_IUnknown))
  1931.     {
  1932.         AddRef();
  1933.         *ppvObj = (IUnknown*)this;
  1934.         return HXR_OK;
  1935.     }
  1936.     *ppvObj = NULL;
  1937.     return HXR_NOINTERFACE;
  1938. }
  1939. /////////////////////////////////////////////////////////////////////////
  1940. //  Method:
  1941. //      BaseHandler::PluginDLL::AddRef
  1942. //  Purpose:
  1943. //      Everyone usually implements this the same... feel free to use
  1944. //      this implementation.
  1945. //
  1946. STDMETHODIMP_(ULONG32)
  1947. BaseHandler::PluginDLL::AddRef()
  1948. {
  1949.     return InterlockedIncrement(&m_lRefCount);
  1950. }
  1951. /////////////////////////////////////////////////////////////////////////
  1952. //  Method:
  1953. //      BaseHandler::PluginDLL::Release
  1954. //  Purpose:
  1955. //      Everyone usually implements this the same... feel free to use
  1956. //      this implementation.
  1957. //
  1958. STDMETHODIMP_(ULONG32)
  1959. BaseHandler::PluginDLL::Release()
  1960. {
  1961.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1962.     {
  1963.         return m_lRefCount;
  1964.     }
  1965.     delete this;
  1966.     return 0;
  1967. }
  1968. /**********************************************************************************
  1969. ***     BaseHandler::PluginMountPoint ***
  1970. ***********************************************************************************/
  1971. BaseHandler::PluginMountPoint::PluginMountPoint( BaseHandler* pContext, const char* pName,
  1972.  UINT32 majorVersion, UINT32 minorVersion, IHXBuffer* pPath ) :
  1973.     m_lRefCount( 0 )
  1974. {
  1975. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  1976.     m_pPath = pPath;
  1977.     if (m_pPath)
  1978.     {
  1979. m_pPath->AddRef();
  1980.     }
  1981. #endif
  1982. }
  1983. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  1984. IHXBuffer*
  1985. BaseHandler::PluginMountPoint::Path()
  1986. {
  1987.     if (m_pPath)
  1988.     {
  1989. m_pPath->AddRef();
  1990.     }
  1991.     return m_pPath;
  1992. }
  1993. #endif
  1994. BaseHandler::PluginMountPoint::~PluginMountPoint()
  1995. {
  1996. #if !defined(_STATICALLY_LINKED) || defined(HELIX_CONFIG_CONSOLIDATED_CORE)
  1997.     HX_RELEASE(m_pPath);
  1998. #endif
  1999. }
  2000. STDMETHODIMP_(ULONG32)
  2001. BaseHandler::PluginMountPoint::AddRef()
  2002. {
  2003.     return InterlockedIncrement(&m_lRefCount);
  2004. }
  2005. STDMETHODIMP_(ULONG32)
  2006. BaseHandler::PluginMountPoint::Release()
  2007. {
  2008.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2009.     {
  2010.         return m_lRefCount;
  2011.     }
  2012.     delete this;
  2013.     return 0;
  2014. }
  2015. ///////////////////////////////////////////////////////////////////////////////
  2016. //
  2017. // BaseHandler::CheckDirectory
  2018. //
  2019. ///////////////////////////////////////////////////////////////////////////////
  2020. BaseHandler::Errors BaseHandler::Stat(const char* pszFilename, struct stat* pStatBuffer)
  2021. {
  2022.     CHXString strFileName;
  2023.     memset(pStatBuffer,0,sizeof(*pStatBuffer));
  2024. #if !defined(_STATICALLY_LINKED)
  2025.     if(stat(pszFilename, pStatBuffer) < 0)
  2026. return CANT_OPEN_DLL;
  2027. #endif
  2028.     pStatBuffer->st_atime = 0;
  2029.     return NO_ERRORS ;
  2030. }
  2031. IHXBuffer* BaseHandler::ConvertToAsciiString(char* pBuffer, UINT32 nBuffLen)
  2032. {
  2033.     char* pszOut = new char[nBuffLen*2+1];
  2034.     char* pszStartOut = pszOut;
  2035.     char Nibble;
  2036.     IHXBuffer* pOutBuffer = new CHXBuffer(); // This is the ONLY place where this is done!
  2037.     pOutBuffer->AddRef();
  2038.     for (int i = 0; i<(int)nBuffLen; i++)
  2039.     {
  2040. Nibble = (*pBuffer >> 4) & 15;
  2041. *pszOut= (Nibble > 9 ) ? Nibble+55 : Nibble +48;
  2042. pszOut++;
  2043. Nibble = *pBuffer & 15;
  2044. *pszOut= (Nibble> 9 ) ? Nibble+ 55 : Nibble+48;
  2045. pszOut++;
  2046. pBuffer++;
  2047.     }
  2048.     *pszOut = 0;
  2049.     pOutBuffer->Set((UCHAR*)pszStartOut, strlen(pszStartOut)+1);
  2050.     delete[] pszStartOut;
  2051.     return pOutBuffer;
  2052. }
  2053. IHXBuffer* BaseHandler::ChecksumFile(char* pszFileName, IHXBuffer* pPathBuffer)
  2054. {
  2055.     return ConvertToAsciiString("abc", 3);
  2056. }
  2057. /********************************************************************
  2058. *
  2059. * Plugin Enumeration
  2060. *
  2061. ********************************************************************/
  2062. BEGIN_INTERFACE_LIST_NOCREATE( CPluginEnumerator )
  2063.     INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginSearchEnumerator )
  2064. END_INTERFACE_LIST
  2065. CPluginEnumerator::CPluginEnumerator() :
  2066.     m_nIndex(0)
  2067. {
  2068. }
  2069. CPluginEnumerator::~CPluginEnumerator()
  2070. {
  2071. }
  2072. STDMETHODIMP_( UINT32 )
  2073. CPluginEnumerator::GetNumPlugins()
  2074. {
  2075.     return m_ListOfPlugins.GetCount();
  2076. }
  2077. STDMETHODIMP_( void )
  2078. CPluginEnumerator::GoHead()
  2079. {
  2080.     m_nIndex = 0;
  2081. }
  2082. STDMETHODIMP
  2083. CPluginEnumerator::GetNextPlugin( REF(IUnknown*) pIUnkResult, IUnknown* pIUnkOuter )
  2084. {
  2085.     // Initialize out params
  2086.     pIUnkResult = NULL;
  2087.     HX_RESULT res = GetPluginAt( m_nIndex, pIUnkResult, pIUnkOuter );
  2088.     m_nIndex++;
  2089.     return res;
  2090. }
  2091. STDMETHODIMP
  2092. CPluginEnumerator::GetNextPluginInfo( REF(IHXValues*) pRetValues )
  2093. {
  2094.     // Initialize out params
  2095.     pRetValues = NULL;
  2096.     HX_RESULT res = GetPluginInfoAt( m_nIndex, pRetValues );
  2097.     m_nIndex++;
  2098.     return res;
  2099. }
  2100. STDMETHODIMP
  2101. CPluginEnumerator::GetPluginAt( UINT32 index, REF(IUnknown*) pIUnkResult, IUnknown* pIUnkOuter )
  2102. {
  2103.     // Initialize out params
  2104.     pIUnkResult = NULL;
  2105.     HX_RESULT res = HXR_FAIL;
  2106.     LISTPOSITION pos = m_ListOfPlugins.FindIndex(index);
  2107.     if (pos)
  2108.     {
  2109. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) m_ListOfPlugins.GetAt(pos);
  2110. if (pPlugin)
  2111. {
  2112.     if (BaseHandler::NO_ERRORS == pPlugin->GetInstance( pIUnkResult, pIUnkOuter ))
  2113.     {
  2114. res = HXR_OK;
  2115.     }
  2116. }
  2117.     }
  2118.     return res;
  2119. }
  2120. STDMETHODIMP
  2121. CPluginEnumerator::GetPluginInfoAt( UINT32 index, REF(IHXValues*) pRetValues )
  2122. {
  2123.     // Initialize out params
  2124.     pRetValues = NULL;
  2125.     HX_RESULT res = HXR_FAIL;
  2126.     LISTPOSITION pos = m_ListOfPlugins.FindIndex(m_nIndex);
  2127.     m_nIndex++;
  2128.     if (pos)
  2129.     {
  2130. BaseHandler::Plugin* pPlugin = (BaseHandler::Plugin*) m_ListOfPlugins.GetAt(pos);
  2131. if (pPlugin)
  2132. {
  2133.     res = pPlugin->GetPluginInfo( pRetValues );
  2134. }
  2135.     }
  2136.     return res;
  2137. }
  2138. void CPluginEnumerator::Add(BaseHandler::Plugin* pPlugin)
  2139. {
  2140.     IHXValues*     pPluginValues   = NULL;
  2141.     IHXBuffer*     pBuffer     = NULL;
  2142.     BOOL     bAdded     = FALSE;
  2143.     if (HXR_OK == pPlugin->GetPluginInfo(pPluginValues) && pPluginValues)
  2144.     {
  2145. if (HXR_OK == pPluginValues->GetPropertyCString(PLUGIN_DESCRIPTION2, pBuffer) &&
  2146.     pBuffer)
  2147. {
  2148.     if (strstr((const char*)pBuffer->GetBuffer(), "RealNetworks"))
  2149.     {
  2150. m_ListOfPlugins.AddHead(pPlugin);
  2151. bAdded = TRUE;
  2152.     }
  2153. }
  2154. HX_RELEASE(pBuffer);
  2155.     }
  2156.     if (!bAdded)
  2157.     {
  2158. m_ListOfPlugins.AddTail(pPlugin);
  2159.     }
  2160. }
  2161. HX_RESULT CPluginEnumerator::GetNext(REF(IUnknown*) pRetUnk)
  2162. {
  2163.     pRetUnk = NULL;
  2164.     return GetNextPlugin( pRetUnk, NULL );
  2165. }