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

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 "debug.h"
  38. #include "hxtypes.h"
  39. #include "hxcom.h"
  40. #include "hxcomm.h"
  41. #include "db_misc.h"
  42. #include "watchlst.h"
  43. #include "property.h"
  44. #include "commreg.h"
  45. #include "hxmon.h"
  46. #include "watchlst.h"
  47. #include "hxclreg.h"
  48. #include "hxpropwclnt.h"
  49. #include "hxslist.h"
  50. #include "hxheap.h"
  51. #ifdef _DEBUG
  52. #undef HX_THIS_FILE
  53. static const char HX_THIS_FILE[] = __FILE__;
  54. #endif
  55. /////////////////////////////////////////////////////////////////////////
  56. //  Method:
  57. //      HXClientPropWatch::QueryInterface
  58. //  Purpose:
  59. //      Implement this to export the interfaces supported by your
  60. //      object.
  61. //
  62. STDMETHODIMP
  63. HXClientPropWatch::QueryInterface(REFIID riid, void** ppvObj)
  64. {
  65.     QInterfaceList qiList[] =
  66.         {
  67.             { GET_IIDHANDLE(IID_IHXPropWatch), (IHXPropWatch*)this },
  68.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPropWatch*)this },
  69.         };
  70.     
  71.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  72. }   
  73. /////////////////////////////////////////////////////////////////////////
  74. //  Method:
  75. //      HXClientPropWatch::AddRef
  76. //  Purpose:
  77. //      Everyone usually implements this the same... feel free to use
  78. //      this implementation.
  79. //
  80. STDMETHODIMP_(ULONG32)
  81. HXClientPropWatch::AddRef()
  82. {
  83.     return InterlockedIncrement(&m_lRefCount);
  84. }   
  85. /////////////////////////////////////////////////////////////////////////
  86. //  Method:
  87. //      HXClientPropWatch::Release
  88. //  Purpose:
  89. //      Everyone usually implements this the same... feel free to use
  90. //      this implementation.
  91. //
  92. STDMETHODIMP_(ULONG32)
  93. HXClientPropWatch::Release()
  94. {
  95.     if (InterlockedDecrement(&m_lRefCount) > 0)
  96.     {
  97.         return m_lRefCount;
  98.     }
  99.     
  100.     delete this;
  101.     return 0;
  102. }   
  103. HXClientPropWatch::HXClientPropWatch(CommonRegistry* pRegistry, IUnknown* pContext)
  104.    : m_lRefCount(0)
  105.    , m_pResponse(NULL)
  106.    , m_pRegistry(NULL)
  107.    , m_pInterruptSafeResponse(NULL)
  108.    , m_pInterruptState(NULL)
  109.    , m_pScheduler(NULL)
  110.    , m_pInternalResponse(NULL)
  111.    , m_pCallback(NULL)
  112. {
  113.     m_pRegistry = pRegistry;
  114.     /* 
  115.      * Users of HXClientRegistry should call Init and the context should
  116.      * expose IHXInterruptState and IHXScheduler if they want to
  117.      * ensure that watches are fired ONLY at non-interrupt time.
  118.      *
  119.      * Currently, this functionality is ONLY used by the client core
  120.      * since it is multi-threaded and needs to deal with
  121.      * top level clients which are not thread-safe.
  122.      */
  123.     if (pContext)
  124.     {
  125.      pContext->QueryInterface(IID_IHXScheduler, 
  126. (void**) &m_pScheduler);
  127. pContext->QueryInterface(IID_IHXInterruptState, 
  128. (void**) &m_pInterruptState);
  129.     }
  130.     m_pInternalResponse = new PropWatchResponse(this);
  131.     m_pInternalResponse->AddRef();
  132. }
  133. HXClientPropWatch::~HXClientPropWatch()
  134. {
  135.     if (m_pCallback &&
  136. m_pCallback->m_bIsCallbackPending &&
  137. m_pScheduler)
  138.     {
  139. m_pCallback->m_bIsCallbackPending = FALSE;
  140. m_pScheduler->Remove(m_pCallback->m_PendingHandle);
  141.     }
  142.     HX_RELEASE(m_pResponse);
  143.     HX_RELEASE(m_pInterruptSafeResponse);
  144.     HX_RELEASE(m_pInterruptState);
  145.     HX_RELEASE(m_pScheduler);
  146.     HX_RELEASE(m_pInternalResponse);
  147.     HX_RELEASE(m_pCallback);
  148. }
  149. /*
  150.  *  Function Name:   HXClientPropWatch::Init
  151.  *  Input Params:    IHXPropWatchResponse* pResponse, 
  152.  *  Return Value:    STDMETHODIMP
  153.  *  Description:
  154.  *      Initialize with the response object and the registry so that
  155.  *  Watch notifications can be sent back to the respective plugins.
  156.  */
  157. STDMETHODIMP
  158. HXClientPropWatch::Init(IHXPropWatchResponse* pResponse)
  159. {
  160.     if (pResponse)
  161.     {
  162. m_pResponse = pResponse;
  163. m_pResponse->AddRef();
  164. m_pResponse->QueryInterface(IID_IHXInterruptSafe, 
  165. (void**)&m_pInterruptSafeResponse);
  166. return HXR_OK;
  167.     }
  168.     return HXR_FAIL;
  169. }
  170. /*
  171.  *  Function Name:   SetWatchOnRoot
  172.  *  Input Params:
  173.  *  Return Value:    UINT32
  174.  *  Description:
  175.  *   set a watch point at the root of the registry hierarchy.
  176.  *  to be notified if any property at this level gets added/modified/deleted.
  177.  */
  178. STDMETHODIMP_(UINT32)
  179. HXClientPropWatch::SetWatchOnRoot()
  180. {
  181.     PropWatch* pPropWatch = new PropWatch;
  182.     pPropWatch->m_pResponse = m_pInternalResponse;
  183.     
  184.     return m_pRegistry->SetWatch(pPropWatch);
  185. }
  186. /*
  187.  *  Function Name:   SetWatchByName
  188.  *  Input Params:    const char* prop_name
  189.  *  Return Value:    UINT32
  190.  *  Description:
  191.  *   set a watch point on any Property. if the Property gets
  192.  *  modified/deleted a notification will be sent by the registry.
  193.  */
  194. STDMETHODIMP_(UINT32)
  195. HXClientPropWatch::SetWatchByName(const char* prop_name)
  196. {
  197.     UINT32 uiret = 0;
  198.     PropWatch* pPropWatch = new PropWatch;
  199.     pPropWatch->m_pResponse = m_pInternalResponse;
  200.     
  201.     uiret = m_pRegistry->SetWatch(prop_name, pPropWatch);
  202.     if ( uiret == 0 )
  203.     {
  204.         //Failed to add watch.
  205.         HX_DELETE( pPropWatch );
  206.     }
  207.     return uiret;
  208. }
  209. /*
  210.  *  Function Name:   SetWatchById
  211.  *  Input Params:    const UINT32 id
  212.  *  Return Value:    UINT32
  213.  *  Description:
  214.  *   set a watch point on any Property. if the Property gets
  215.  *  modified/deleted a notification will be sent by the registry.
  216.  */
  217. STDMETHODIMP_(UINT32)
  218. HXClientPropWatch::SetWatchById(const UINT32 id)
  219. {
  220.     UINT32 uiret = 0;
  221.     PropWatch* pPropWatch = new PropWatch;
  222.     pPropWatch->m_pResponse = m_pInternalResponse;
  223.     uiret = m_pRegistry->SetWatch(id, pPropWatch);
  224.     if ( uiret == 0 )
  225.     {
  226.         //Failed to add watch.
  227.         HX_DELETE( pPropWatch );
  228.     }
  229.     return uiret;
  230. }
  231. /*
  232.  *  Function Name:   ClearWatchOnRoot
  233.  *  Input Params:
  234.  *  Return Value:    HX_RESULT
  235.  *  Description:
  236.  *   clear a watch point from the root of the DB hierarchy
  237.  */
  238. STDMETHODIMP
  239. HXClientPropWatch::ClearWatchOnRoot()
  240. {
  241.     return m_pRegistry->ClearWatch(m_pInternalResponse);
  242. }
  243. /*
  244.  *  Function Name:   ClearWatchByName
  245.  *  Input Params:    const char* prop_name
  246.  *  Return Value:    HX_RESULT
  247.  *  Description:
  248.  *   clear a watch point on a property.
  249.  */
  250. STDMETHODIMP
  251. HXClientPropWatch::ClearWatchByName(const char* prop_name)
  252. {
  253.     return m_pRegistry->ClearWatch(prop_name, m_pInternalResponse);
  254. }
  255. /*
  256.  *  Function Name:   ClearWatchById
  257.  *  Input Params:    const UINT32 id
  258.  *  Return Value:    HX_RESULT
  259.  *  Description:
  260.  *   clear a watch point on a property.
  261.  */
  262. STDMETHODIMP
  263. HXClientPropWatch::ClearWatchById(const UINT32 id)
  264. {
  265.     return m_pRegistry->ClearWatch(id, m_pInternalResponse);
  266. }
  267. // PropWatchCallback
  268. HXClientPropWatch::PropWatchCallback::PropWatchCallback(HXClientPropWatch* pClientPropWatch) :
  269.      m_lRefCount (0)
  270.     ,m_PendingHandle (0)
  271.     ,m_pPropWatch(pClientPropWatch)
  272.     ,m_bIsCallbackPending (FALSE)
  273. {
  274. }
  275. HXClientPropWatch::PropWatchCallback::~PropWatchCallback()
  276. {
  277. }
  278. /*
  279.  * IUnknown methods
  280.  */
  281. /////////////////////////////////////////////////////////////////////////
  282. //      Method:
  283. //              IUnknown::QueryInterface
  284. //      Purpose:
  285. //              Implement this to export the interfaces supported by your
  286. //              object.
  287. //
  288. STDMETHODIMP HXClientPropWatch::PropWatchCallback::QueryInterface(REFIID riid, void** ppvObj)
  289. {
  290.     QInterfaceList qiList[] =
  291.         {
  292.             { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this },
  293.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXCallback*)this },
  294.         };
  295.     
  296.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  297. }
  298. /////////////////////////////////////////////////////////////////////////
  299. //      Method:
  300. //              IUnknown::AddRef
  301. //      Purpose:
  302. //              Everyone usually implements this the same... feel free to use
  303. //              this implementation.
  304. //
  305. STDMETHODIMP_(ULONG32) HXClientPropWatch::PropWatchCallback::AddRef()
  306. {
  307.     return InterlockedIncrement(&m_lRefCount);
  308. }
  309. /////////////////////////////////////////////////////////////////////////
  310. //      Method:
  311. //              IUnknown::Release
  312. //      Purpose:
  313. //              Everyone usually implements this the same... feel free to use
  314. //              this implementation.
  315. //
  316. STDMETHODIMP_(ULONG32) HXClientPropWatch::PropWatchCallback::Release()
  317. {
  318.     if (InterlockedDecrement(&m_lRefCount) > 0)
  319.     {
  320. return m_lRefCount;
  321.     }
  322.     delete this;
  323.     return 0;
  324. }
  325. /*
  326.  *      IHXCallback methods
  327.  */
  328. STDMETHODIMP HXClientPropWatch::PropWatchCallback::Func(void)
  329. {
  330.     m_PendingHandle         = 0;
  331.     m_bIsCallbackPending    = FALSE;
  332.     if (m_pPropWatch && m_pPropWatch->m_pInternalResponse)
  333.     {
  334. m_pPropWatch->m_pInternalResponse->ProcessPendingResponses();
  335.     }
  336.     return HXR_OK;
  337. }
  338. // PropWatchResponse
  339. HXClientPropWatch::PropWatchResponse::PropWatchResponse(HXClientPropWatch* pClientPropWatch) :
  340.      m_lRefCount (0)
  341.     ,m_pPropWatch(pClientPropWatch)
  342.     ,m_pPendingResponseList (NULL)
  343. {
  344. }
  345. HXClientPropWatch::PropWatchResponse::~PropWatchResponse()
  346. {
  347.     while (m_pPendingResponseList && m_pPendingResponseList->GetCount() > 0)
  348.     {
  349. PropResponseValues* pValues = (PropResponseValues*) 
  350. m_pPendingResponseList->RemoveHead();
  351. delete pValues;
  352.     }
  353.     HX_DELETE(m_pPendingResponseList);
  354. }
  355. /*
  356.  * IUnknown methods
  357.  */
  358. /////////////////////////////////////////////////////////////////////////
  359. //      Method:
  360. //              IUnknown::QueryInterface
  361. //      Purpose:
  362. //              Implement this to export the interfaces supported by your
  363. //              object.
  364. //
  365. STDMETHODIMP HXClientPropWatch::PropWatchResponse::QueryInterface(REFIID riid, void** ppvObj)
  366. {
  367.     QInterfaceList qiList[] =
  368.         {
  369.             { GET_IIDHANDLE(IID_IHXPropWatchResponse), (IHXPropWatchResponse*)this },
  370.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPropWatchResponse*)this },
  371.         };
  372.     
  373.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  374. }
  375. /////////////////////////////////////////////////////////////////////////
  376. //      Method:
  377. //              IUnknown::AddRef
  378. //      Purpose:
  379. //              Everyone usually implements this the same... feel free to use
  380. //              this implementation.
  381. //
  382. STDMETHODIMP_(ULONG32) HXClientPropWatch::PropWatchResponse::AddRef()
  383. {
  384.     return InterlockedIncrement(&m_lRefCount);
  385. }
  386. /////////////////////////////////////////////////////////////////////////
  387. //      Method:
  388. //              IUnknown::Release
  389. //      Purpose:
  390. //              Everyone usually implements this the same... feel free to use
  391. //              this implementation.
  392. //
  393. STDMETHODIMP_(ULONG32) HXClientPropWatch::PropWatchResponse::Release()
  394. {
  395.     if (InterlockedDecrement(&m_lRefCount) > 0)
  396.     {
  397. return m_lRefCount;
  398.     }
  399.     delete this;
  400.     return 0;
  401. }
  402. /*
  403.  * IHXPropWatchResponse methods
  404.  */
  405. STDMETHODIMP
  406. HXClientPropWatch::PropWatchResponse::AddedProp(const UINT32 id,
  407.      const HXPropType    propType,
  408.      const UINT32 ulParentID)
  409. {
  410.     /* If we are at interrupt time, make sure that the 
  411.      * response is interrupt safe
  412.      */
  413.     if (m_pPropWatch->m_pInterruptState &&
  414. m_pPropWatch->m_pInterruptState->AtInterruptTime() &&
  415. (!m_pPropWatch->m_pInterruptSafeResponse ||
  416. !m_pPropWatch->m_pInterruptSafeResponse->IsInterruptSafe()))
  417.     {
  418. ScheduleCallback(ADDEDPROP, id, propType, ulParentID);
  419.     }
  420.     else
  421.     {
  422. ProcessPendingResponses();
  423. m_pPropWatch->m_pResponse->AddedProp(id, propType, ulParentID);
  424.     }
  425.     return HXR_OK;
  426. }
  427. STDMETHODIMP
  428. HXClientPropWatch::PropWatchResponse::ModifiedProp(const UINT32 id,
  429.      const HXPropType    propType,
  430.      const UINT32 ulParentID)
  431. {
  432.     /* If we are at interrupt time, make sure that the 
  433.      * response is interrupt safe
  434.      */
  435.     if (m_pPropWatch->m_pInterruptState &&
  436. m_pPropWatch->m_pInterruptState->AtInterruptTime() &&
  437. (!m_pPropWatch->m_pInterruptSafeResponse ||
  438. !m_pPropWatch->m_pInterruptSafeResponse->IsInterruptSafe()))
  439.     {
  440. ScheduleCallback(MODIFIEDPROP, id, propType, ulParentID);
  441.     }
  442.     else
  443.     {
  444. ProcessPendingResponses();
  445. m_pPropWatch->m_pResponse->ModifiedProp(id, propType, ulParentID);
  446.     }
  447.     return HXR_OK;
  448. }
  449. STDMETHODIMP
  450. HXClientPropWatch::PropWatchResponse::DeletedProp(const UINT32 id,
  451.      const UINT32 ulParentID)
  452. {
  453.     /* If we are at interrupt time, make sure that the 
  454.      * response is interrupt safe
  455.      */
  456.     if (m_pPropWatch->m_pInterruptState &&
  457. m_pPropWatch->m_pInterruptState->AtInterruptTime() &&
  458. (!m_pPropWatch->m_pInterruptSafeResponse ||
  459. !m_pPropWatch->m_pInterruptSafeResponse->IsInterruptSafe()))
  460.     {
  461. ScheduleCallback(DELETEDPROP, id, (HXPropType) 0, ulParentID);
  462.     }
  463.     else
  464.     {
  465. ProcessPendingResponses();
  466. m_pPropWatch->m_pResponse->DeletedProp(id, ulParentID);
  467.     }
  468.     return HXR_OK;
  469. }
  470. void
  471. HXClientPropWatch::PropWatchResponse::ScheduleCallback(ResponseType uResponseType,
  472.     const UINT32 id,
  473.     const HXPropType    propType,
  474.     const UINT32 ulParentID)
  475. {
  476.     if (!m_pPendingResponseList)
  477.     {
  478. m_pPendingResponseList = new CHXSimpleList;
  479.     }
  480.     PropResponseValues* pValues = new PropResponseValues(uResponseType, id, 
  481.     propType, ulParentID);
  482.     m_pPendingResponseList->AddTail((void*) pValues);
  483.     if (!m_pPropWatch->m_pCallback)
  484.     {
  485. m_pPropWatch->m_pCallback = new PropWatchCallback(m_pPropWatch);
  486. m_pPropWatch->m_pCallback->AddRef();
  487.     }
  488.     if (!m_pPropWatch->m_pCallback->m_bIsCallbackPending &&
  489. m_pPropWatch->m_pScheduler)
  490.     {
  491. m_pPropWatch->m_pCallback->m_bIsCallbackPending = TRUE;
  492. m_pPropWatch->m_pCallback->m_PendingHandle = 
  493.     m_pPropWatch->m_pScheduler->RelativeEnter(
  494.     m_pPropWatch->m_pCallback, 0);
  495.     }
  496. }
  497. void
  498. HXClientPropWatch::PropWatchResponse::ProcessPendingResponses()
  499. {
  500.     /* remove any pending callback */
  501.     if (m_pPropWatch->m_pCallback &&
  502. m_pPropWatch->m_pCallback->m_bIsCallbackPending &&
  503. m_pPropWatch->m_pScheduler)
  504.     {
  505. m_pPropWatch->m_pCallback->m_bIsCallbackPending = FALSE;
  506. m_pPropWatch->m_pScheduler->Remove(
  507. m_pPropWatch->m_pCallback->m_PendingHandle);
  508.     }
  509.     while (m_pPendingResponseList && m_pPendingResponseList->GetCount() > 0)
  510.     {
  511. PropResponseValues* pValues = (PropResponseValues*) 
  512. m_pPendingResponseList->RemoveHead();
  513. switch (pValues->m_uResponseType)
  514. {
  515.     case ADDEDPROP:
  516. m_pPropWatch->m_pResponse->AddedProp(pValues->m_ulId, 
  517.      pValues->m_propType,
  518.      pValues->m_ulParentID);
  519.      break;
  520.     case MODIFIEDPROP:
  521. m_pPropWatch->m_pResponse->ModifiedProp(pValues->m_ulId, 
  522.       pValues->m_propType,
  523.       pValues->m_ulParentID);
  524. break;
  525.     case DELETEDPROP:
  526. m_pPropWatch->m_pResponse->DeletedProp(pValues->m_ulId, 
  527.        pValues->m_ulParentID);
  528. break;
  529.     default:
  530. HX_ASSERT(0);
  531. break;
  532. }
  533. delete pValues;
  534.     }
  535. }