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

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