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

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxcom.h"
  36. #include "hlxclib/stdio.h"
  37. #include "hxtypes.h"
  38. #include "hxresult.h"
  39. #include "hxassert.h"
  40. #include "hxcomm.h"
  41. #include "hxplugn.h"
  42. #include "hxfiles.h"
  43. #include "hxmeta.h"
  44. #include "hxcore.h"
  45. #include "hxpends.h"
  46. #include "timeval.h"
  47. #include "pq.h"
  48. #include "hxstring.h"
  49. #include "hxslist.h"
  50. #include "hxrquest.h"
  51. #include "hxbuffer.h"
  52. #include "chxpckts.h"
  53. #include "dbcs.h"
  54. #include "hxmarsh.h"
  55. #include "hxmime.h"
  56. #include "hxstrutl.h"
  57. #include "plghand2.h"
  58. #include "validatr.h"
  59. #include "hxxfile.h"
  60. #include "rmfftype.h"
  61. #include "hxheap.h"
  62. #ifdef _DEBUG
  63. #undef HX_THIS_FILE
  64. static const char HX_THIS_FILE[] = __FILE__;
  65. #endif
  66. #define MAX_URL_STRING 4096
  67. HXValidator::HXValidator(IUnknown* pContext)
  68. : m_lRefCount (0)
  69. , m_pContext (NULL)
  70. , m_bRefresh (TRUE)
  71. {
  72.     if (pContext)
  73.     {
  74. m_pContext = pContext;
  75. m_pContext->AddRef();
  76.     }
  77. }
  78. HXValidator::~HXValidator()
  79. {
  80.     CHXSimpleList::Iterator i;
  81.     // cleanup the protocol list
  82.     i = m_ProtocolList.Begin();
  83.     for (; i != m_ProtocolList.End(); ++i)
  84.     {
  85. CHXString* pProtocol = (CHXString*) (*i);
  86. HX_DELETE(pProtocol);
  87.     }
  88.     m_ProtocolList.RemoveAll();
  89.     HX_RELEASE(m_pContext);
  90. }
  91. STDMETHODIMP
  92. HXValidator::QueryInterface(REFIID riid, void**ppvObj)
  93. {
  94.     QInterfaceList qiList[] =
  95.         {
  96.             { GET_IIDHANDLE(IID_IHXValidator), (IHXValidator*)this },
  97.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXValidator*)this },
  98.         };
  99.     
  100.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  101. }
  102. /////////////////////////////////////////////////////////////////////////
  103. //  Method:
  104. // IUnknown::AddRef
  105. //  Purpose:
  106. // Everyone usually implements this the same... feel free to use
  107. // this implementation.
  108. //
  109. STDMETHODIMP_(ULONG32) 
  110. HXValidator::AddRef()
  111. {
  112.     return InterlockedIncrement(&m_lRefCount);
  113. }
  114. /////////////////////////////////////////////////////////////////////////
  115. //  Method:
  116. // IUnknown::Release
  117. //  Purpose:
  118. // Everyone usually implements this the same... feel free to use
  119. // this implementation.
  120. //
  121. STDMETHODIMP_(ULONG32) 
  122. HXValidator::Release()
  123. {
  124.     if (InterlockedDecrement(&m_lRefCount) > 0)
  125.     {
  126.         return m_lRefCount;
  127.     }
  128.     delete this;
  129.     return 0;
  130. }
  131. /************************************************************************
  132.  * Method:
  133.  *     IHXValidator::ValidateProtocol
  134.  * Purpose:
  135.  *     Find out if the protocol is valid
  136.  *     
  137.  *
  138.  */
  139. STDMETHODIMP_(BOOL)
  140. HXValidator::ValidateProtocol(char* pProtocol)
  141. {
  142.     BOOL bResult = FALSE;
  143.     CHXString* pValue = NULL;
  144.     CHXSimpleList::Iterator i;
  145.     if (!pProtocol)
  146.     {
  147. goto cleanup;
  148.     }
  149.     if (m_bRefresh)
  150.     {
  151. BuildProtocolList();
  152. m_bRefresh = FALSE;
  153.     }
  154.     i = m_ProtocolList.Begin();
  155.     for (; i != m_ProtocolList.End(); ++i)
  156.     {
  157. pValue = (CHXString*) (*i);
  158. if (strcasecmp(pProtocol, (const char*)(*pValue)) == 0)
  159. {
  160.     bResult = TRUE;
  161.     break;
  162. }
  163.     }
  164. cleanup:
  165.     return bResult;
  166. }
  167. /************************************************************************
  168.  * Method:
  169.  *     IHXValidator::ValidateMetaFile
  170.  * Purpose:
  171.  *     Find out if it is a meta file
  172.  *     
  173.  *
  174.  */
  175. STDMETHODIMP
  176. HXValidator::ValidateMetaFile(IHXRequest* pRequest,
  177.        IHXBuffer* pData)
  178. {
  179.     HX_RESULT hr = HXR_OK;    
  180.     BOOL bIsRAM = FALSE;
  181.     BOOL bTrackFound = FALSE;
  182.     BOOL bHeaderToBeSet = FALSE;
  183.     UINT32 ulFileType = 0;
  184.     UINT32 ulSize = 0;
  185.     UINT32 ulMajorVersion = 0;
  186.     int i = 0; 
  187.     int j = 0;
  188.     int iLen = 0;
  189.     int iSize = 0;
  190.     char* pMimeType = NULL;
  191.     char* pFileExt = NULL;
  192.     char* pProtocol = NULL;
  193.     char* pCursor = NULL;
  194.     char* pLine = NULL;
  195.     char* pContent = NULL;
  196.     char* pTemp = NULL;
  197.     char* pURL = NULL;
  198.     const char* pConstTemp = NULL;
  199.     const char* charset = " rnt";
  200.     const char* tokenset = "nr";    
  201.     UINT32 ulProtocol = 0;
  202.     CHXString* pString = NULL;
  203.     IHXBuffer* pValue = NULL;
  204.     IHXValues* pResponseHeaders = NULL;
  205.     
  206.     if (pRequest)
  207.     {
  208. pRequest->AddRef();
  209.     }
  210.     if (pData)
  211.     {
  212.         pData->AddRef();
  213.     }
  214.     else
  215.     {
  216. hr = HXR_FAILED;
  217. goto cleanup;
  218.     }
  219.     if (pRequest)
  220.     {
  221.         pRequest->GetURL(pConstTemp);
  222.         if (HXXFile::IsPlusURL(pConstTemp))
  223.         {
  224.     hr = HXR_FAILED;
  225.     goto cleanup;
  226.         }
  227.     }
  228.     ulSize = pData->GetSize() + 1;
  229.     pContent = new char[ulSize];
  230.     memset(pContent, 0, ulSize);
  231.     memcpy(pContent, (char*)pData->GetBuffer(), pData->GetSize()); /* Flawfinder: ignore */
  232.     // if the first FOURCC is either ".RA " or ".RMF"
  233.     if (pData->GetSize() >= 4)
  234.     {
  235. ulFileType = (UINT32) getlong((UCHAR*) pContent);
  236.     
  237. const char* pContentType = NULL;
  238. switch (ulFileType)
  239. {
  240.     case RM_HEADER_OBJECT:
  241.     case RMS_HEADER_OBJECT:
  242.     case RA_FILE_MAGIC_NUMBER:
  243.     {
  244. pContentType = REALAUDIO_MIME_TYPE;
  245.     }
  246.     break;
  247.     case REDHAT_PACKAGE_MAGIC_NUMBER:
  248.     {
  249. pContentType = REDHAT_PACKAGE_MIME_TYPE;
  250.     }
  251.     break;
  252. }
  253. if (pContentType)
  254. {
  255.     if (pRequest)
  256.     {
  257. pRequest->GetResponseHeaders(pResponseHeaders);
  258. if (!pResponseHeaders)
  259. {
  260.     pResponseHeaders = (IHXValues*) new CHXHeader;
  261.     pResponseHeaders->AddRef();
  262.     bHeaderToBeSet = TRUE;
  263. }
  264. if (HXR_OK !=
  265.     pResponseHeaders->GetPropertyCString("Content-Type",
  266.  pValue) ||
  267.     !pValue)
  268. {
  269.     pValue = (IHXBuffer*) new CHXBuffer;
  270.     pValue->AddRef();
  271.     pValue->Set((UCHAR*)pContentType,
  272. ::strlen(pContentType) + 1);
  273.     pResponseHeaders->SetPropertyCString("Content-Type",
  274.  pValue);
  275.     if (bHeaderToBeSet)
  276.     {
  277. pRequest->SetResponseHeaders(pResponseHeaders);
  278.     }
  279. }
  280.     }
  281.     
  282.     hr = HXR_FAILED;
  283.     goto cleanup;
  284. }
  285.     }
  286.     // retreive the MimeType and FileExt
  287.     if (pRequest)
  288.     {
  289. if (HXR_OK == pRequest->GetResponseHeaders(pResponseHeaders) &&
  290.     pResponseHeaders)
  291. {
  292.     if (HXR_OK == pResponseHeaders->GetPropertyCString("Content-Type", pValue) &&
  293. pValue)
  294.     {
  295. pMimeType = (char*)pValue->GetBuffer();
  296.     }
  297. }
  298. pTemp = (char*)pConstTemp;
  299. if (pTemp)
  300. {
  301.     pURL = new char[strlen(pTemp) + 1];
  302.     strcpy(pURL, pTemp); /* Flawfinder: ignore */
  303.     pTemp = strrchr(pURL, '?');
  304.     if (pTemp)
  305.     {
  306. *pTemp = '';
  307.     }
  308.     pFileExt = strrchr(pURL, '.');
  309. }
  310.     }
  311.     // determine whether it is a RAM file
  312.     if ((pMimeType &&
  313.  ((strcasecmp(pMimeType, "audio/x-pn-realaudio") == 0) ||
  314.   (strcasecmp(pMimeType, "audio/x-pn-realaudio-plugin") == 0))) ||
  315. (pFileExt &&
  316.  ((strcasecmp(pFileExt, ".ram") == 0) ||
  317.   (strcasecmp(pFileExt, ".rpm") == 0) ||
  318.   (strcasecmp(pFileExt, ".rmm") == 0))))
  319.     {
  320. bIsRAM = TRUE;
  321.         iLen = pData->GetSize();
  322. char* ramFile = new char[iLen+1];
  323.     
  324. while( i <= iLen && !bTrackFound)
  325. {
  326. /*
  327.  * XXXJHUG  12/07/00 change to allow unlimitted length ram files.
  328.  *      - we no longer need to check to see if the url
  329.  *        is longer than a fixed value.
  330.     if (j >= MAX_URL_STRING)
  331.     {
  332. // exceeds the max. length of URL
  333. // skip the whole line
  334. while (pContent[i] != 'n' && pContent[i] != 'r' &&
  335.        pContent[i] != 0 && i < iLen)
  336. {
  337.     i++;
  338. }
  339. memset(pUrl, 0, MAX_URL_STRING);
  340. j = 0;
  341. i++;
  342. continue;
  343.     }
  344. */
  345.     ramFile[j] = pContent[i]; 
  346.     
  347.     // Look for line terminators.
  348.     if ( ramFile[j] == 'n' || ramFile[j] == 'r' || ramFile[j] == 0 || i == iLen)
  349.     {
  350. ramFile[j] = 0;
  351. pString = new CHXString(ramFile);
  352. pString->TrimLeft();
  353. pString->TrimRight();
  354. iSize = pString->GetLength();
  355. if (iSize)
  356. {
  357.     memset(ramFile, 0, iLen+1);
  358.     SafeStrCpy(ramFile,  pString->GetBuffer(iSize), iLen+1);
  359.     
  360.     // A URL must have at least 4 chars. for protocol. This will
  361.     // take care of lines with junk or just CR on them.
  362.     
  363.     // detect RAM3.0 syntax
  364.     if (strncasecmp(ramFile, HX_RAM30_START_TAG, HX_RAM30_START_TAGSIZE) == 0)
  365.     {
  366. ulMajorVersion = 3;
  367.     }
  368.     else if (strncasecmp(ramFile, HX_RAM30_END_TAG, HX_RAM30_END_TAGSIZE) == 0)
  369.     {
  370. HX_DELETE(pString);
  371. break;
  372.     }
  373.     // detect RAM2.0 syntax
  374.     else if (strncasecmp(ramFile, HX_RAM20_START_TAG, HX_RAM20_START_TAGSIZE) == 0)
  375.     {
  376. ulMajorVersion = 2;
  377.     }
  378.     else if (strncasecmp(ramFile, HX_RAM20_END_TAG, HX_RAM20_END_TAGSIZE) == 0)
  379.     {
  380. HX_DELETE(pString);
  381. break;
  382.     }
  383.     // handle "--stop--" tag in 6.0
  384.     else if (strncasecmp(ramFile, "--stop--", 8) == 0)
  385.     {
  386. HX_DELETE(pString);
  387. break;
  388.     }
  389.     else 
  390.     {
  391. if (ulMajorVersion == 2 || ulMajorVersion == 3)
  392. {
  393.     if (strncasecmp(ramFile, HX_RAM_ENTRY_TAG, HX_RAM_ENTRY_TAGSIZE) == 0 && 
  394. (iSize >= (HX_RAM_ENTRY_TAGSIZE + 4)))
  395.     {
  396. CHXString* pStringAfterTag = new CHXString(ramFile+2);
  397. pStringAfterTag->TrimLeft();
  398. pStringAfterTag->TrimRight();
  399.     
  400. iSize = pStringAfterTag->GetLength();
  401. if (iSize)
  402. {
  403.     memset(ramFile, 0, iLen);
  404.     SafeStrCpy(ramFile,  pStringAfterTag->GetBuffer(iSize), iLen+1);
  405. }
  406. HX_DELETE(pStringAfterTag);
  407.     }
  408.     else
  409.     {
  410. memset(ramFile, 0, iLen);
  411.     }     
  412. }
  413.     
  414. pCursor = strstr(ramFile, ":");
  415. if (pCursor)
  416. {
  417.     ulProtocol = pCursor - ramFile;
  418.     if (ulProtocol > 0)
  419.     {
  420. pProtocol = new char[ulProtocol+1];
  421. memset(pProtocol, 0, ulProtocol+1);
  422. strncpy(pProtocol, ramFile, ulProtocol); /* Flawfinder: ignore */
  423. if (ValidateProtocol(pProtocol))
  424. {
  425.     bTrackFound = TRUE;
  426. }
  427. HX_VECTOR_DELETE(pProtocol);
  428.     }
  429. }
  430.     }
  431. }
  432. j = 0;
  433. HX_DELETE(pString);
  434.     }
  435.     else
  436.     {
  437. j++; 
  438.     }
  439.     i++;
  440. }
  441. HX_VECTOR_DELETE(ramFile);
  442. if (bTrackFound)
  443. {     
  444.     hr = HXR_OK;
  445.     goto cleanup;
  446. }
  447. else
  448. {
  449.     hr = HXR_INVALID_METAFILE;
  450.     goto cleanup;
  451. }
  452.     }
  453.     // determine if it is a RAM
  454.     else
  455.     {
  456. // Trim off any leading spaces/EOLs/tabs before adding on the pnm protocol...
  457. pLine = strtok(pContent, tokenset);
  458. while (pLine != NULL)
  459. {
  460.     size_t pos = strspn(pLine,charset);
  461.     pLine += pos;
  462.     // handle RAM3.0 syntax
  463.     if (strncasecmp(pLine, HX_RAM30_START_TAG, HX_RAM30_START_TAGSIZE) == 0)
  464.     {
  465. ulMajorVersion = 3;
  466. pLine = strtok(NULL, tokenset);
  467. continue;
  468.     }
  469.     // handle RAM2.0 syntax
  470.     else if (strncasecmp(pLine, HX_RAM20_START_TAG, HX_RAM20_START_TAGSIZE) == 0)
  471.     {
  472. ulMajorVersion = 2;
  473. pLine = strtok(NULL, tokenset);
  474. continue;
  475.     }
  476.     if (ulMajorVersion == 2 && ulMajorVersion == 3)
  477.     {
  478. if (strncasecmp(pLine, HX_RAM_ENTRY_TAG, HX_RAM_ENTRY_TAGSIZE) == 0 &&
  479.     (pCursor = strstr(pLine, ":")))
  480. {
  481.     pLine += 2;     
  482.     // trim off the leading spaces
  483.     while (pLine[0] == ' ')
  484.     {
  485. pLine++;
  486.     }
  487. }
  488. else
  489. {
  490.     pLine = strtok(NULL, tokenset);
  491.     continue;
  492. }     
  493.     }
  494.     else
  495.     {
  496. pString = new CHXString(pLine);
  497. pString->TrimLeft();
  498. pString->TrimRight();
  499. if ((pString->GetLength() == 0)     ||
  500.     (strncasecmp(pLine, "//", 2) == 0)  ||
  501.     (strncasecmp(pLine, "#", 1) == 0))
  502. {
  503.     // comments, skip to next line
  504.     pLine = strtok(NULL, tokenset);
  505.     HX_DELETE(pString);
  506.     continue;
  507. }
  508. HX_DELETE(pString);
  509. pCursor = strstr(pLine, ":");
  510. if (!pCursor)
  511. {
  512.     bIsRAM = FALSE;
  513.     break;
  514. }
  515.     }
  516.     ulProtocol = pCursor - pLine;
  517.     if (ulProtocol > 0)
  518.     {
  519. pProtocol = new char[ulProtocol+1];
  520. memset(pProtocol, 0, ulProtocol+1);
  521. strncpy(pProtocol, pLine, ulProtocol); /* Flawfinder: ignore */
  522. bIsRAM = ValidateProtocol(pProtocol);
  523. HX_VECTOR_DELETE(pProtocol);
  524. break;
  525.     }
  526.     else
  527.     {
  528. bIsRAM = FALSE;
  529. break;
  530.     }
  531. }
  532. if (bIsRAM)
  533. {
  534.     hr = HXR_OK;
  535.     goto cleanup;
  536. }
  537. else
  538. {
  539.     hr = HXR_FAILED;
  540.     goto cleanup;
  541. }
  542.     }
  543.     
  544. cleanup:
  545.     // set the RAMVersion to response header, it will be retrieved by the 
  546.     // RAM file format
  547.     if (pRequest && bIsRAM)
  548.     {
  549. if (!pResponseHeaders)
  550. {
  551.     pResponseHeaders = (IHXValues*) new CHXHeader;
  552.     pResponseHeaders->AddRef();
  553.     bHeaderToBeSet = TRUE;
  554. }
  555. UINT32 ulPersistentVersion = HX_ENCODE_PROD_VERSION(ulMajorVersion, 0, 0, 0);
  556. pResponseHeaders->SetPropertyULONG32("PersistentVersion", ulPersistentVersion);
  557. if (bHeaderToBeSet)
  558. {
  559.     pRequest->SetResponseHeaders(pResponseHeaders); 
  560. }
  561.     }
  562.     HX_VECTOR_DELETE(pURL);
  563.     HX_VECTOR_DELETE(pContent);
  564.     HX_RELEASE(pResponseHeaders);
  565.     HX_RELEASE(pValue);
  566.     HX_RELEASE(pRequest);
  567.     HX_RELEASE(pData);
  568.     return hr;
  569. }
  570. HX_RESULT
  571. HXValidator::BuildProtocolList(void)
  572. {
  573.     HX_RESULT hr = HXR_OK;
  574.     UINT32 j = 0;
  575.     UINT32 ulPlugins = 0;
  576.     IHXValues* pValues = NULL;
  577.     IHXBuffer* pBuffer = NULL;
  578.     IHXCommonClassFactory* pCommonClassFactory = NULL;
  579.     IHXPluginQuery* pPluginQuery = NULL;
  580.     IHXPluginGroupEnumerator* pPluginEnum = NULL;
  581.     CHXString* pProtocol = NULL;
  582.     CHXSimpleList::Iterator i;
  583.     if (HXR_OK != m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCommonClassFactory))
  584.     {
  585. hr = HXR_FAILED;
  586. goto cleanup;
  587.     }
  588.     // reset the list
  589.     i = m_ProtocolList.Begin();
  590.     for (; i != m_ProtocolList.End(); ++i)
  591.     {
  592. pProtocol = (CHXString*) (*i);
  593. HX_DELETE(pProtocol);
  594.     }
  595.     m_ProtocolList.RemoveAll();
  596.     // we always add "pnm" and "rtsp"
  597.     pProtocol = new CHXString("pnm");
  598.     m_ProtocolList.AddTail(pProtocol);
  599.     pProtocol = new CHXString("rtsp");
  600.     m_ProtocolList.AddTail(pProtocol);
  601.     // collect protocol info. from the pluginhandler
  602.     if (HXR_OK != pCommonClassFactory->CreateInstance(IID_IHXPluginGroupEnumerator, 
  603. (void**)&pPluginEnum))
  604.     {
  605. goto cleanup;
  606.     }
  607.     if (HXR_OK != pPluginEnum->QueryInterface(IID_IHXPluginQuery, (void**)&pPluginQuery))
  608.     {
  609. goto cleanup;
  610.     }
  611.     if (HXR_OK != pPluginQuery->GetNumPluginsGivenGroup(IID_IHXFileSystemObject, ulPlugins))
  612.     {
  613. goto cleanup;
  614.     }
  615.     for (j = 0; j < ulPlugins; j++)
  616.     {
  617. HX_RELEASE(pBuffer);
  618. HX_RELEASE(pValues);
  619. if (HXR_OK != pPluginQuery->GetPluginInfo(IID_IHXFileSystemObject, j, pValues) ||
  620.     !pValues)
  621. {
  622.     continue;
  623. }
  624. if (HXR_OK != pValues->GetPropertyCString("FileProtocol", pBuffer) ||
  625.     !pBuffer)
  626. {
  627.     continue;
  628. }
  629. pProtocol = new CHXString((const char*) pBuffer->GetBuffer());
  630. int nPos = pProtocol->Find('|');
  631. while (nPos > 0)
  632. {
  633.     CHXString* pTemp = new CHXString(pProtocol->Left(nPos));
  634.     *pProtocol = pProtocol->Mid(nPos + 1);
  635.     m_ProtocolList.AddTail(pTemp);
  636.     nPos = pProtocol->Find('|');
  637. }
  638. m_ProtocolList.AddTail(pProtocol);
  639. if (pProtocol->CompareNoCase("lice") == 0)
  640. {
  641.     CHXString *pAnother = new CHXString("rnba");
  642.     m_ProtocolList.AddTail(pAnother);
  643. }
  644.     }
  645. cleanup:
  646.     HX_RELEASE(pBuffer);
  647.     HX_RELEASE(pValues);
  648.     HX_RELEASE(pPluginQuery);
  649.     HX_RELEASE(pPluginEnum);
  650.     HX_RELEASE(pCommonClassFactory);
  651.     return hr;
  652. }
  653. void
  654. HXValidator::RefreshProtocols(void)
  655. {
  656.     m_bRefresh = TRUE;
  657. }