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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: chxphook.cpp,v 1.4.20.1 2004/07/09 02:07:59 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 "hlxclib/stdio.h"
  50. #include "hlxclib/string.h"
  51. #include "hxtypes.h"
  52. #include "hxcom.h"
  53. #include "hxcomm.h"
  54. #include "hxbuffer.h"
  55. #include "chxpckts.h"
  56. #include "hxmap.h"
  57. #include "ihxpckts.h"
  58. #include "hxfiles.h"
  59. #include "plghand2.h"
  60. #include "hxcore.h"
  61. #include "hxengin.h"
  62. #include "hxrendr.h"
  63. #include "chxphook.h"
  64. #include "hxheap.h"
  65. #ifdef _DEBUG
  66. #undef HX_THIS_FILE
  67. static const char HX_THIS_FILE[] = __FILE__;
  68. #endif
  69. PacketHookManager::PacketHookManager(IHXPlayer* pPlayer)
  70. : m_lRefCount(0)
  71. , m_pPlayer(NULL)
  72. , m_pPacketHook(NULL)
  73. , m_ulTotalStreams(0)
  74. , m_ulRecordableStreams(0)
  75. {
  76.     if (pPlayer)
  77.     {
  78. m_pPlayer = pPlayer;
  79. m_pPlayer->AddRef();
  80.     }
  81. }
  82. PacketHookManager::~PacketHookManager()
  83. {
  84.     HX_RELEASE(m_pPacketHook);
  85.     HX_RELEASE(m_pPlayer);
  86. }
  87. STDMETHODIMP
  88. PacketHookManager::QueryInterface(REFIID riid, void**ppvObj)
  89. {
  90.     QInterfaceList qiList[] =
  91.         {
  92.             { GET_IIDHANDLE(IID_IHXPacketHookManager), (IHXPacketHookManager*)this },
  93.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPacketHookManager*)this },
  94.         };
  95.     
  96.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  97. }
  98. /////////////////////////////////////////////////////////////////////////
  99. //  Method:
  100. // IUnknown::AddRef
  101. //  Purpose:
  102. // Everyone usually implements this the same... feel free to use
  103. // this implementation.
  104. //
  105. STDMETHODIMP_(ULONG32) 
  106. PacketHookManager::AddRef()
  107. {
  108.     return InterlockedIncrement(&m_lRefCount);
  109. }
  110. /////////////////////////////////////////////////////////////////////////
  111. //  Method:
  112. // IUnknown::Release
  113. //  Purpose:
  114. // Everyone usually implements this the same... feel free to use
  115. // this implementation.
  116. //
  117. STDMETHODIMP_(ULONG32) 
  118. PacketHookManager::Release()
  119. {
  120.     if (InterlockedDecrement(&m_lRefCount) > 0)
  121.     {
  122.         return m_lRefCount;
  123.     }
  124.     delete this;
  125.     return 0;
  126. }
  127.     
  128. /*
  129.  * IHXPacketHookManager methods
  130.  */
  131. /************************************************************************
  132.  * Method:
  133.  *     IHXPacketHookManager::InitHook
  134.  * Purpose:
  135.  *     called by the top level client to pass the IHXPacketHook object
  136.  */
  137. STDMETHODIMP 
  138. PacketHookManager::InitHook (IHXPacketHook* pPacketHook)
  139. {
  140.     HX_RESULT hr = HXR_OK;
  141.      
  142.     if (!m_pPlayer || !pPacketHook)
  143.     {
  144. return HXR_FAILED;
  145.     }
  146.     m_pPacketHook = pPacketHook;
  147.     m_pPacketHook->AddRef();
  148.     BOOL bRecordAllowed = FALSE;
  149.     UINT16 ulSources = 0;
  150.     UINT16 ulStreams = 0;
  151.     IUnknown* pUnknown = NULL;
  152.     IHXStreamSource* pSource = NULL;
  153.     IHXPrivateStreamSource *pPrivateSource = NULL; // for IsSaveAllowed, take this out; XXXCP
  154.     // caculate the total number of streams + TAC info.
  155.     if (!(ulSources = m_pPlayer->GetSourceCount()))
  156.     {
  157. return HXR_FAILED;
  158.     }
  159.     for (UINT16 i = 0; i < ulSources; i++)
  160.     {
  161. if (m_pPlayer->GetSource(i, pUnknown) != HXR_OK)
  162. {
  163.     continue;
  164. }
  165. BOOL bIsSaveAllowed = FALSE;
  166. if (pUnknown->QueryInterface(IID_IHXPrivateStreamSource, (void**)&pPrivateSource) == HXR_OK)
  167. {
  168.     bIsSaveAllowed = pPrivateSource->IsSaveAllowed();
  169.     HX_RELEASE(pPrivateSource);
  170.     if (!bIsSaveAllowed)
  171.     {
  172. HX_RELEASE(pUnknown);
  173. continue;
  174.     }
  175. }
  176. if(bIsSaveAllowed)
  177.     bRecordAllowed = TRUE;
  178. hr = pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource);
  179. HX_RELEASE(pUnknown);
  180. if (hr != HXR_OK)
  181. {
  182.     break;
  183. }
  184. ulStreams = pSource->GetStreamCount();
  185. for (UINT16 j = 0; j < ulStreams; j++)
  186. {
  187.     IHXStream* pStream = NULL;
  188.     pSource->GetStream(j, (IUnknown*&)pStream);
  189.   
  190.     UINT16 ulRenderers = pStream->GetRendererCount();
  191.     for (UINT16 k = 0; k < ulRenderers; k++)
  192.     {
  193. IHXRenderer* pRenderer = NULL;
  194. IHXPacketHookSink* pSink = NULL;
  195. pStream->GetRenderer(k, (IUnknown*&)pRenderer);
  196. if (HXR_OK == pRenderer->QueryInterface(IID_IHXPacketHookSink,
  197.                                         (void**)&pSink))
  198. {
  199.     pSink->StartSink();
  200.     HX_RELEASE(pSink);
  201. }
  202. HX_RELEASE(pRenderer);
  203.     }
  204.     
  205.     HX_RELEASE(pStream);
  206. }
  207. HX_RELEASE(pSource);
  208.     }
  209.     if (!bRecordAllowed)
  210.     {
  211. hr = HXR_NO_DATA;
  212.     }
  213.     return hr;
  214. }
  215. /************************************************************************
  216.  * Method:
  217.  *     IHXPacketHookManager::CloseHook
  218.  * Purpose:
  219.  *     called by the top level client to close the hook connection
  220.  */
  221. STDMETHODIMP 
  222. PacketHookManager::CloseHook ()
  223. {
  224.      HX_RESULT hr = HXR_OK;
  225.      HX_RELEASE(m_pPacketHook);
  226.      return hr;
  227. }
  228. /************************************************************************
  229.  * Method:
  230.  *     IHXPacketHookManager::StartHook
  231.  * Purpose:
  232.  *     called by the top level client to start recording
  233.  */
  234. STDMETHODIMP 
  235. PacketHookManager::StartHook ()
  236. {
  237.     HX_RESULT hr =  HXR_OK;
  238.     UINT16 i = 0;
  239.     UINT16 j = 0;
  240.     UINT16 k = 0;
  241.     UINT16 ulSources = 0;
  242.     UINT16 ulStreams = 0;
  243.     UINT16 ulStreamIndex = 0;
  244.     CHXBuffer* pTitle = NULL;
  245.     CHXBuffer* pAuthor = NULL;
  246.     CHXBuffer* pCopyright = NULL;
  247.     CHXHeader* pFileHeader = NULL;
  248.     CHXHeader* pStreamHeader = NULL;
  249.     IUnknown* pUnknown = NULL;
  250.     IHXPrivateStreamSource *pPrivateSource = NULL; // for IsSaveAllowed, take this out; XXXCP
  251.     IHXStreamSource* pSource = NULL;
  252.     IHXInfoLogger* pInfoLogger = NULL;
  253.     
  254.     // make sure everything has been initialized
  255.     if (!m_pPlayer || !m_pPacketHook)
  256.     {
  257. hr = HXR_FAILED;
  258. goto cleanup;
  259.     }
  260.     // caculate the total number of streams + TAC info.
  261.     if (!(ulSources = m_pPlayer->GetSourceCount()))
  262.     {
  263. hr = HXR_FAILED;
  264. goto cleanup;
  265.     }
  266.     m_ulTotalStreams = 0;    
  267.     for (i = 0; i < ulSources; i++)
  268.     {
  269. if (HXR_OK != m_pPlayer->GetSource(i, pUnknown))
  270. {
  271.     continue;
  272. }
  273. if (HXR_OK != pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource))
  274. {
  275.     HX_RELEASE(pUnknown);
  276.     continue;
  277. }
  278. if (HXR_OK == pUnknown->QueryInterface(IID_IHXPrivateStreamSource, (void**)&pPrivateSource))
  279. {
  280.     if (!(pPrivateSource->IsSaveAllowed()))
  281.     {
  282. pPrivateSource->Release();
  283. continue;
  284.     }
  285.     pPrivateSource->Release();
  286. }
  287. m_ulTotalStreams += pSource->GetStreamCount();
  288. HX_RELEASE(pSource);
  289. HX_RELEASE(pUnknown);
  290.     }
  291.     if (!m_ulTotalStreams)
  292.     {
  293.         hr = HXR_FAILED;
  294.         goto cleanup;
  295.     }
  296.     // prepare the file header
  297.     pTitle = new CHXBuffer();
  298.     pAuthor = new CHXBuffer();
  299.     pCopyright = new CHXBuffer();
  300.     pTitle->AddRef();
  301.     pAuthor->AddRef();
  302.     pCopyright->AddRef();
  303.     // XXX HP: find better way to collect TAC info
  304. #define szTitle     "title"
  305. #define szAuthor    "author"
  306. #define szCopyright "copyright"
  307.     pTitle->Set((const unsigned char*)szTitle, strlen(szTitle)+1);
  308.     pAuthor->Set((const unsigned char*)szAuthor, strlen(szAuthor)+1);
  309.     pCopyright->Set((const unsigned char*)szCopyright, strlen(szCopyright)+1);
  310.     pFileHeader = new CHXHeader();
  311.     pFileHeader->AddRef();
  312.     // set attributes(i.e. num. of streams + TAC)
  313.     pFileHeader->SetPropertyBuffer("Title", pTitle);
  314.     pFileHeader->SetPropertyBuffer("Author", pAuthor);
  315.     pFileHeader->SetPropertyBuffer("Copyright", pCopyright);
  316.     pFileHeader->SetPropertyULONG32("StreamCount", m_ulTotalStreams);
  317.     
  318.     // signal the top level client of upcoming content
  319.     m_pPacketHook->OnStart();
  320.     // send file header to its top level client
  321.     hr = m_pPacketHook->OnFileHeader(pFileHeader);
  322.     if (hr != HXR_OK)
  323.     {
  324. HX_RELEASE(m_pPacketHook);
  325.         goto cleanup;
  326.     }
  327.     // prepare the stream headers
  328.     m_ulRecordableStreams = 0;
  329.     ulStreamIndex = 0;
  330.     for (i = 0; i < ulSources; i++)
  331.     {
  332. if (HXR_OK != m_pPlayer->GetSource(i, pUnknown))
  333. {
  334.     HX_RELEASE(pUnknown);
  335.     continue;
  336. }
  337. if (HXR_OK != pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource))
  338. {
  339.     HX_RELEASE(pSource);
  340.     continue;
  341. }
  342. if (HXR_OK == pUnknown->QueryInterface(IID_IHXPrivateStreamSource, (void**)&pPrivateSource))
  343. {
  344.     if (!(pPrivateSource->IsSaveAllowed()))
  345.     {
  346. pPrivateSource->Release();
  347. continue;
  348.     }
  349.     pPrivateSource->Release();
  350. }
  351. if (HXR_OK == pUnknown->QueryInterface(IID_IHXInfoLogger, (void**)&pInfoLogger))
  352. {
  353.     pInfoLogger->LogInformation("RECSTART", NULL);
  354. }
  355. HX_RELEASE(pInfoLogger);
  356. ulStreams = pSource->GetStreamCount();
  357. for (j = 0; j < ulStreams; j++)
  358. {
  359.     const char*     pszPropName = NULL;
  360.     UINT16     ulRenderers = 0;
  361.     ULONG32     ulPropValue = 0;
  362.     BOOL     bRecordable = FALSE;
  363.     CHXHeader*     pHeader = NULL;
  364.     CHXBuffer*     pPropValueSource = NULL;
  365.     CHXBuffer*     pPropValueTarget = NULL;
  366.     IHXStream*     pStream = NULL;
  367.     // retrieve the stream info
  368.     pSource->GetStream(j, (IUnknown*&)pStream);
  369.     pHeader = (CHXHeader*)pStream->GetHeader();
  370.     // make a copy of this stream header 
  371.     // XXX HP: this could be wrapped up into one method in CHXHeader
  372.     pStreamHeader = new CHXHeader();
  373.     pStreamHeader->AddRef();
  374.     // copy all the ULONG32 attributes
  375.     if (HXR_OK == pHeader->GetFirstPropertyULONG32(pszPropName, ulPropValue))
  376.     {
  377. pStreamHeader->SetPropertyULONG32(pszPropName, ulPropValue);
  378. while (HXR_OK == pHeader->GetNextPropertyULONG32(pszPropName, ulPropValue))
  379. {
  380.     pStreamHeader->SetPropertyULONG32(pszPropName, ulPropValue);
  381. }
  382.     }
  383.     // copy all the buffer attributes
  384.     if (HXR_OK == pHeader->GetFirstPropertyBuffer(pszPropName, (IHXBuffer*&)pPropValueSource))
  385.     {
  386. pPropValueTarget = new CHXBuffer();
  387. pPropValueTarget->AddRef();
  388. pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize());
  389. pStreamHeader->SetPropertyBuffer(pszPropName, pPropValueTarget);
  390. HX_RELEASE(pPropValueTarget);
  391. HX_RELEASE(pPropValueSource);
  392. while (HXR_OK == pHeader->GetNextPropertyBuffer(pszPropName, (IHXBuffer*&)pPropValueSource))
  393. {
  394.     pPropValueTarget = new CHXBuffer();
  395.     pPropValueTarget->AddRef();
  396.     pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize());
  397.     pStreamHeader->SetPropertyBuffer(pszPropName, pPropValueTarget);
  398.     HX_RELEASE(pPropValueTarget);
  399.     HX_RELEASE(pPropValueSource);
  400. }
  401.     }
  402.     // copy all the CString attributes
  403.     if (HXR_OK == pHeader->GetFirstPropertyCString(pszPropName, (IHXBuffer*&)pPropValueSource))
  404.     {
  405. pPropValueTarget = new CHXBuffer();
  406. pPropValueTarget->AddRef();
  407. pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize());
  408. pStreamHeader->SetPropertyCString(pszPropName, pPropValueTarget);
  409. HX_RELEASE(pPropValueTarget);
  410. HX_RELEASE(pPropValueSource);
  411. while (HXR_OK == pHeader->GetNextPropertyCString(pszPropName, (IHXBuffer*&)pPropValueSource))
  412. {
  413.     pPropValueTarget = new CHXBuffer();
  414.     pPropValueTarget->AddRef();
  415.     pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize());
  416.     pStreamHeader->SetPropertyCString(pszPropName, pPropValueTarget);
  417.     HX_RELEASE(pPropValueTarget);
  418.     HX_RELEASE(pPropValueSource);
  419. }
  420.     }
  421.     HX_RELEASE(pHeader);
  422.     // modify some values
  423.     pStreamHeader->SetPropertyULONG32("StreamNumber", ulStreamIndex);
  424.     
  425.     // the stream is recordable as long as there is one renderer supports
  426.     // IHXPacketHookHelper. Multiple renderers can serve the packets with 
  427.     // the same stream number on it, One solution for this is to choose the 
  428.     // first renderer which supports IHXPacketHookHelper as the only source
  429.     ulRenderers = pStream->GetRendererCount();
  430.     for (k = 0; k < ulRenderers; k++)
  431.     {
  432. IUnknown* pUnknown = NULL;
  433. IHXPacketHookHelper* pPacketHookHelper = NULL;
  434. pStream->GetRenderer(k, pUnknown);
  435. if (HXR_OK == pUnknown->QueryInterface(IID_IHXPacketHookHelper, (void**)&pPacketHookHelper))
  436. {
  437.     bRecordable = TRUE;
  438.     
  439.     pPacketHookHelper->StartHook(ulStreamIndex, 0, new PacketHookHelperResponse(this, ulStreamIndex));
  440. }
  441. HX_RELEASE(pPacketHookHelper);
  442. HX_RELEASE(pUnknown);
  443.     }
  444.     
  445.     if (bRecordable)
  446.     {
  447. m_ulRecordableStreams++;
  448.     }
  449.     pStreamHeader->SetPropertyULONG32("Recordable", (ULONG32)bRecordable);
  450.     /*
  451.      * It's possible that StartHook will cause the m_pPacketHook to
  452.      * be released
  453.      */
  454.     if (!m_pPacketHook)
  455.     {
  456. hr = HXR_UNEXPECTED;
  457.         goto cleanup;
  458.     }
  459.     // send stream header to its top level client
  460.     hr = m_pPacketHook->OnStreamHeader(pStreamHeader);
  461.     if (hr != HXR_OK)
  462.     {
  463. HX_RELEASE(m_pPacketHook);
  464.         goto cleanup;
  465.     }
  466.     ulStreamIndex++;
  467.     HX_RELEASE(pStreamHeader);
  468.     HX_RELEASE(pStream);
  469. }
  470. HX_RELEASE(pSource);
  471. HX_RELEASE(pUnknown);
  472.     }
  473.          
  474. cleanup:
  475.     
  476.     HX_RELEASE(pTitle);
  477.     HX_RELEASE(pAuthor);
  478.     HX_RELEASE(pCopyright);
  479.     HX_RELEASE(pFileHeader);
  480.  
  481.     return hr;
  482. }
  483.   
  484. /************************************************************************
  485.  * Method:
  486.  *     IHXPacketHookManager::StopHook
  487.  * Purpose:
  488.  *     called by the top level client to stop recording
  489.  */
  490. STDMETHODIMP 
  491. PacketHookManager::StopHook ()
  492. {
  493.     HX_RESULT hr = HXR_OK;
  494.     UINT16 i = 0;
  495.     UINT16 j = 0;
  496.     UINT16 k = 0;
  497.     UINT16 ulSources = 0;
  498.     UINT16 ulStreams = 0;
  499.     IUnknown* pUnknown = NULL;
  500.     IHXStreamSource* pSource = NULL;
  501.     IHXInfoLogger* pInfoLogger = NULL;
  502.   
  503.     if (!m_pPlayer || !m_pPacketHook)
  504.     {
  505. hr = HXR_FAILED;
  506. goto cleanup;
  507.     }
  508.     // prepare the stream headers
  509.     ulSources = m_pPlayer->GetSourceCount();
  510.     for (i = 0; i < ulSources; i++)
  511.     {
  512. if (m_pPlayer->GetSource(i, pUnknown) != HXR_OK)
  513.     continue;
  514. if (HXR_OK != pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource))
  515. {
  516.     break;
  517. }
  518. if (HXR_OK == pUnknown->QueryInterface(IID_IHXInfoLogger, (void**)&pInfoLogger))
  519. {
  520.     pInfoLogger->LogInformation("RECEND", NULL);
  521. }
  522. HX_RELEASE(pInfoLogger);
  523. ulStreams = pSource->GetStreamCount();
  524. for (j = 0; j < ulStreams; j++)
  525. {
  526.     UINT16     ulRenderers = 0;  
  527.     IHXStream*     pStream = NULL;
  528.     // retrieve the stream info
  529.     pSource->GetStream(j, (IUnknown*&)pStream);
  530.   
  531.     ulRenderers = pStream->GetRendererCount();
  532.     for (k = 0; k < ulRenderers; k++)
  533.     {
  534. IHXRenderer* pRenderer = NULL;
  535. IHXPacketHookHelper* pPacketHookHelper = NULL;
  536. IHXPacketHookSink* pSink = NULL;
  537. pStream->GetRenderer(k, (IUnknown*&)pRenderer);
  538. if (HXR_OK == pRenderer->QueryInterface(IID_IHXPacketHookSink,
  539.                                         (void**)&pSink))
  540. {
  541.     pSink->StopSink();
  542.     HX_RELEASE(pSink);
  543. }
  544. if (HXR_OK == pRenderer->QueryInterface(IID_IHXPacketHookHelper, (void**)&pPacketHookHelper))
  545. {   
  546.     pPacketHookHelper->StopHook();
  547. }
  548. HX_RELEASE(pSink);
  549. HX_RELEASE(pPacketHookHelper);
  550. HX_RELEASE(pRenderer);
  551.     }
  552.     
  553.     HX_RELEASE(pStream);
  554. }
  555. HX_RELEASE(pSource);
  556. HX_RELEASE(pUnknown);
  557.     }
  558. cleanup:
  559.    
  560.     return hr;
  561. }
  562. STDMETHODIMP 
  563. PacketHookManager::OnPacket (IHXPacket* pPacket)
  564. {
  565.     HX_RESULT hr = HXR_OK;
  566.     if (!m_pPacketHook)
  567.     {
  568. hr = HXR_FAILED;
  569. goto cleanup;
  570.     }
  571.     // pass packet back to the top-level client
  572.     hr = m_pPacketHook->OnPacket(pPacket);
  573.     if (hr != HXR_OK)
  574.     {
  575. HX_RELEASE(m_pPacketHook);
  576.     }
  577. cleanup:
  578.     return hr;
  579. }
  580. STDMETHODIMP 
  581. PacketHookManager::OnEndOfPackets (ULONG32 ulStreamID)
  582. {
  583.     HX_RESULT hr = HXR_OK;
  584.     if (!m_pPacketHook)
  585.     {
  586. hr = HXR_FAILED;
  587. goto cleanup;
  588.     }
  589.     // this is the last stream
  590.     if (!--m_ulRecordableStreams)
  591.     {
  592. m_pPacketHook->OnEnd();
  593. HX_RELEASE(m_pPacketHook);
  594.     }
  595. cleanup:
  596.     return hr;
  597. }
  598. PacketHookHelperResponse::PacketHookHelperResponse(PacketHookManager* pPacketHookManager,
  599.    ULONG32 ulStreamID)
  600.     : m_lRefCount (0)
  601.     , m_pPacketHookManager (NULL)
  602.     , m_ulStreamID (0)
  603. {
  604.     m_pPacketHookManager = pPacketHookManager;
  605.     m_pPacketHookManager->AddRef();
  606.     m_ulStreamID = ulStreamID;
  607. }
  608. PacketHookHelperResponse::~PacketHookHelperResponse()
  609. {
  610.    HX_RELEASE(m_pPacketHookManager);
  611. }
  612. /////////////////////////////////////////////////////////////////////////
  613. // Method:
  614. // IUnknown::QueryInterface
  615. // Purpose:
  616. // Implement this to export the interfaces supported by your 
  617. // object.
  618. //
  619. STDMETHODIMP 
  620. PacketHookHelperResponse::QueryInterface(REFIID riid, void** ppvObj)
  621. {
  622.     QInterfaceList qiList[] =
  623.         {
  624.             { GET_IIDHANDLE(IID_IHXPacketHookHelperResponse), (IHXPacketHookHelperResponse*)this },
  625.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPacketHookHelperResponse*)this },
  626.         };
  627.     
  628.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  629. }
  630. /////////////////////////////////////////////////////////////////////////
  631. // Method:
  632. // IUnknown::AddRef
  633. // Purpose:
  634. // Everyone usually implements this the same... feel free to use
  635. // this implementation.
  636. //
  637. STDMETHODIMP_(ULONG32) 
  638. PacketHookHelperResponse::AddRef()
  639. {
  640.     return InterlockedIncrement(&m_lRefCount);
  641. }
  642. /////////////////////////////////////////////////////////////////////////
  643. // Method:
  644. // IUnknown::Release
  645. // Purpose:
  646. // Everyone usually implements this the same... feel free to use
  647. // this implementation.
  648. //
  649. STDMETHODIMP_(ULONG32) 
  650. PacketHookHelperResponse::Release()
  651. {
  652.     if (InterlockedDecrement(&m_lRefCount) > 0)
  653.     {
  654. return m_lRefCount;
  655.     }
  656.     delete this;
  657.     return 0;
  658. }
  659. /*
  660.  * IHXPacketHookHelperResponse methods
  661.  */
  662. /************************************************************************
  663.  * Method:
  664.  *     IHXPacketHookHelperResponse::OnPacket
  665.  * Purpose:
  666.  *     called by the renderer to pass the packet for recording
  667.  */
  668. STDMETHODIMP 
  669. PacketHookHelperResponse::OnPacket (IHXPacket* pPacket)
  670. {
  671.     HX_RESULT hr = HXR_OK;
  672.     if (!m_pPacketHookManager)
  673.     {
  674. hr = HXR_FAILED;
  675. goto cleanup;
  676.     }
  677.     // pass packet back to the top-level client
  678.     hr = m_pPacketHookManager->OnPacket(pPacket);
  679.     if (hr != HXR_OK)
  680.     {
  681. HX_RELEASE(m_pPacketHookManager);
  682.     }
  683. cleanup:
  684.     return hr;
  685. }
  686. /************************************************************************
  687.  * Method:
  688.  *     IHXPacketHookManager::OnEndOfPackets
  689.  * Purpose:
  690.  *     called by the renderer to notify the end of this stream
  691.  */
  692. STDMETHODIMP 
  693. PacketHookHelperResponse::OnEndOfPackets ()
  694. {
  695.     HX_RESULT hr = HXR_OK;
  696.     if (!m_pPacketHookManager)
  697.     {
  698. hr = HXR_FAILED;
  699. goto cleanup;
  700.     }
  701.     m_pPacketHookManager->OnEndOfPackets(m_ulStreamID);
  702. cleanup:
  703.     return hr;
  704. }