Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1051 lines
25 KiB

  1. //***************************************************************************
  2. //
  3. // File:
  4. //
  5. // Module: MS SNMP Provider
  6. //
  7. // Purpose:
  8. //
  9. // Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. /*
  13. * SMIREVT.CPP
  14. *
  15. * Implemenation of a connection point object for the SMIR notify mechanism.
  16. * The methods/objects in this file are accessed by the SMIR API; the API
  17. * provides a user friendly interface to ISMIRNotify.
  18. */
  19. #include <precomp.h>
  20. #include "csmir.h"
  21. #include "smir.h"
  22. #include "handles.h"
  23. #include "classfac.h"
  24. #include <textdef.h>
  25. #include "evtcons.h"
  26. #ifdef ICECAP_PROFILE
  27. #include <icapexp.h>
  28. #endif
  29. // scope guard
  30. #include <autoptr.h>
  31. extern CRITICAL_SECTION g_CriticalSection ;
  32. /**********************************************************************************
  33. * CSmirConnectionPoint
  34. *
  35. * Connectpoint implementation that supports the interface ISMIRNotify.
  36. *
  37. * CSmirConnObject::CSmirConnObject
  38. * CSmirConnObject::~CSmirConnObject
  39. ***********************************************************************************/
  40. /*
  41. * CSmirConnectionPoint::CSmirConnectionPoint
  42. * CSmirConnectionPoint::~CSmirConnectionPoint
  43. *
  44. * Parameters (Constructor):
  45. * pObj PCSmirConnObject of the object we're in. We can
  46. * query this for the IConnectionPointContainer
  47. * interface we might need.
  48. * riid REFIID of the interface we're supporting
  49. ***********************************************************************************/
  50. CSmirConnectionPoint::CSmirConnectionPoint(PCSmirConnObject pObj, REFIID riid, CSmir *pSmir)
  51. {
  52. m_cRef=0;
  53. m_iid=riid;
  54. /*
  55. * Our lifetime is controlled by the connectable object itself,
  56. * although other external clients will call AddRef and Release.
  57. * Since we're nested in the connectable object's lifetime,
  58. * there's no need to call AddRef on pObj.
  59. */
  60. m_pObj=pObj;
  61. m_dwCookieNext=100; //Arbitrary starting cookie value
  62. }
  63. CSmirConnectionPoint::~CSmirConnectionPoint(void)
  64. {
  65. DWORD lKey = 0;
  66. LPUNKNOWN pItem = NULL;
  67. POSITION rNextPosition;
  68. for(rNextPosition=m_Connections.GetStartPosition();NULL!=rNextPosition;)
  69. {
  70. m_Connections.GetNextAssoc(rNextPosition, lKey, pItem );
  71. pItem->Release();
  72. }
  73. m_Connections.RemoveAll();
  74. return;
  75. }
  76. /*
  77. * CSmirConnectionPoint::QueryInterface
  78. * CSmirConnectionPoint::AddRef
  79. * CSmirConnectionPoint::Release
  80. *
  81. * Purpose:
  82. * Non-delegating IUnknown members for CSmirConnectionPoint.
  83. */
  84. STDMETHODIMP CSmirConnectionPoint::QueryInterface(REFIID riid
  85. , LPVOID *ppv)
  86. {
  87. *ppv=NULL;
  88. if ((IID_IUnknown == riid) ||
  89. (IID_IConnectionPoint == riid)||
  90. (IID_ISMIR_Notify == riid))
  91. *ppv=(LPVOID)this;
  92. if (NULL!=*ppv)
  93. {
  94. ((LPUNKNOWN)*ppv)->AddRef();
  95. return NOERROR;
  96. }
  97. return ResultFromScode(E_NOINTERFACE);
  98. }
  99. STDMETHODIMP_(ULONG) CSmirConnectionPoint::AddRef(void)
  100. {
  101. return InterlockedIncrement(&m_cRef);
  102. }
  103. STDMETHODIMP_(ULONG) CSmirConnectionPoint::Release(void)
  104. {
  105. long ret;
  106. if (0!=(ret=InterlockedDecrement(&m_cRef)))
  107. return ret;
  108. delete this;
  109. return 0;
  110. }
  111. /*
  112. * CSmirConnectionPoint::GetConnectionInterface
  113. *
  114. * Purpose:
  115. * Returns the IID of the outgoing interface supported through
  116. * this connection point.
  117. *
  118. * Parameters:
  119. * pIID IID * in which to store the IID.
  120. */
  121. STDMETHODIMP CSmirConnectionPoint::GetConnectionInterface(IID *pIID)
  122. {
  123. if (NULL==pIID)
  124. return ResultFromScode(E_POINTER);
  125. *pIID=m_iid;
  126. return NOERROR;
  127. }
  128. /*
  129. * CSmirConnectionPoint::GetConnectionPointContainer
  130. *
  131. * Purpose:
  132. * Returns a pointer to the IConnectionPointContainer that
  133. * is manageing this connection point.
  134. *
  135. * Parameters:
  136. * ppCPC IConnectionPointContainer ** in which to return
  137. * the pointer after calling AddRef.
  138. */
  139. STDMETHODIMP CSmirConnectionPoint::GetConnectionPointContainer
  140. (IConnectionPointContainer **ppCPC)
  141. {
  142. return m_pObj->QueryInterface(IID_IConnectionPointContainer
  143. , (void **)ppCPC);
  144. }
  145. /*
  146. * CSmirConnectionPoint::Advise
  147. *
  148. * Purpose:
  149. * Provides this connection point with a notification sink to
  150. * call whenever the appropriate outgoing function/event occurs.
  151. *
  152. * Parameters:
  153. * pUnkSink LPUNKNOWN to the sink to notify. The connection
  154. * point must QueryInterface on this pointer to obtain
  155. * the proper interface to call. The connection
  156. * point must also insure that any pointer held has
  157. * a reference count (QueryInterface will do it).
  158. * pdwCookie DWORD * in which to store the connection key for
  159. * later calls to Unadvise.
  160. */
  161. STDMETHODIMP CSmirConnectionPoint::Advise(LPUNKNOWN pUnkSink
  162. , DWORD *pdwCookie)
  163. {
  164. *pdwCookie=0;
  165. if (NULL == pUnkSink)
  166. return E_POINTER;
  167. /*
  168. * Verify that the sink has the interface it's supposed
  169. * to. We don't have to know what it is because we have
  170. * m_iid to describe it. If this works, then we
  171. * have a pointer with an AddRef that we can save.
  172. */
  173. IUnknown *pSink = NULL ;
  174. if (FAILED(pUnkSink->QueryInterface(m_iid, (PPVOID)&pSink)))
  175. {
  176. return CONNECT_E_CANNOTCONNECT;
  177. }
  178. //We got the sink, now store it.
  179. *pdwCookie = InterlockedIncrement(&m_dwCookieNext);
  180. m_Connections.SetAt(*pdwCookie,pSink);
  181. /*Add ref the smir to make sure that this stays in memory for the lifetime of the
  182. *sink. The release is in unadvise.
  183. */
  184. return S_OK;
  185. }
  186. /*
  187. * CSmirConnectionPoint::Unadvise
  188. *
  189. * Purpose:
  190. * Terminates the connection to the notification sink identified
  191. * with dwCookie (that was returned from Advise). The connection
  192. * point has to Release any held pointers for that sink.
  193. *
  194. * Parameters:
  195. * dwCookie DWORD connection key from Advise.
  196. */
  197. STDMETHODIMP CSmirConnectionPoint::Unadvise(DWORD dwCookie)
  198. {
  199. //the only invalid cookie is 0
  200. if (0==dwCookie)
  201. {
  202. //MyTraceEvent.Generate(__FILE__,__LINE__, "CSmirConnectionPoint::Unadvise E_INVALIDARG");
  203. return E_UNEXPECTED;
  204. }
  205. LPUNKNOWN pSink = NULL;
  206. //stop anyone else unadvising with the same cookie
  207. criticalSection.Lock () ;
  208. if(TRUE == m_Connections.Lookup(dwCookie,pSink))
  209. {
  210. m_Connections.RemoveKey(dwCookie);
  211. //having removed the key the look up will fail so we can release the critical section
  212. criticalSection.Unlock () ;
  213. pSink->Release();
  214. /*release the smir. This could cause the smir to unload from memory! Do not do
  215. *anything after this because we are (ultimatly) owned by the smir object
  216. */
  217. return S_OK;
  218. }
  219. criticalSection.Unlock () ;
  220. return CONNECT_E_NOCONNECTION;
  221. }
  222. /*
  223. * CSmirConnectionPoint::EnumConnections
  224. *
  225. * Purpose:
  226. * Creates and returns an enumerator object with the
  227. * IEnumConnections interface that will enumerate the IUnknown
  228. * pointers of each connected sink.
  229. *
  230. * Parameters:
  231. * ppEnum LPENUMCONNECTIONS in which to store the
  232. * IEnumConnections pointer.
  233. */
  234. STDMETHODIMP CSmirConnectionPoint::EnumConnections(LPENUMCONNECTIONS *ppEnum)
  235. {
  236. LPCONNECTDATA pCD = NULL;
  237. PCEnumConnections pEnum = NULL;
  238. //NULL the IN parameter
  239. *ppEnum=NULL;
  240. //check that we have some connections
  241. if (0 == m_Connections.GetCount())
  242. return ResultFromScode(OLE_E_NOCONNECTION);
  243. /*
  244. * Create the array of CONNECTDATA structures to give to the
  245. * enumerator.
  246. */
  247. pCD=new CONNECTDATA[(UINT)m_Connections.GetCount()];
  248. if (NULL==pCD)
  249. return ResultFromScode(E_OUTOFMEMORY);
  250. wmilib::auto_buffer<CONNECTDATA> pCD_Guard ( pCD ) ;
  251. DWORD lKey = 0;
  252. LPUNKNOWN pItem = NULL;
  253. POSITION rNextPosition;
  254. UINT j=0;
  255. for(rNextPosition=m_Connections.GetStartPosition();NULL!=rNextPosition;j++)
  256. {
  257. m_Connections.GetNextAssoc(rNextPosition, lKey, pItem );
  258. pCD[j].pUnk=pItem;
  259. pCD[j].dwCookie=lKey;
  260. }
  261. /*
  262. * If creation works, it makes a copy pCD, so we can
  263. * always delete it regardless of the outcome.
  264. */
  265. pEnum=new CEnumConnections(this, m_Connections.GetCount(), pCD);
  266. if (NULL==pEnum)
  267. return ResultFromScode(E_OUTOFMEMORY);
  268. //This does an AddRef for us.
  269. return pEnum->QueryInterface(IID_IEnumConnections, (PPVOID)ppEnum);
  270. }
  271. //Connection Enumerator follows
  272. /*
  273. * CEnumConnections::CEnumConnections
  274. * CEnumConnections::~CEnumConnections
  275. *
  276. * Parameters (Constructor):
  277. * pUnkRef LPUNKNOWN to use for reference counting.
  278. * cConn ULONG number of connections in prgpConn
  279. * prgConnData LPCONNECTDATA to the array to enumerate.
  280. */
  281. CEnumConnections::CEnumConnections(LPUNKNOWN pUnkRef, ULONG cConn
  282. , LPCONNECTDATA prgConnData) : m_rgConnData ( NULL )
  283. {
  284. UINT i;
  285. m_cRef=0;
  286. m_pUnkRef=pUnkRef;
  287. m_iCur=0;
  288. m_cConn=cConn;
  289. /*
  290. * Copy the passed array. We need to do this because a clone
  291. * has to have its own copy as well.
  292. */
  293. m_rgConnData=new CONNECTDATA[(UINT)cConn];
  294. if (NULL!=m_rgConnData)
  295. {
  296. for (i=0; i < cConn; i++)
  297. {
  298. m_rgConnData[i]=prgConnData[i];
  299. m_rgConnData[i].pUnk=prgConnData[i].pUnk;
  300. m_rgConnData[i].pUnk->AddRef();
  301. }
  302. }
  303. return;
  304. }
  305. CEnumConnections::~CEnumConnections(void)
  306. {
  307. if (NULL!=m_rgConnData)
  308. {
  309. UINT i;
  310. for (i=0; i < m_cConn; i++)
  311. m_rgConnData[i].pUnk->Release();
  312. delete [] m_rgConnData;
  313. }
  314. return;
  315. }
  316. /*
  317. * CEnumConnections::QueryInterface
  318. * CEnumConnections::AddRef
  319. * CEnumConnections::Release
  320. *
  321. * Purpose:
  322. * IUnknown members for CEnumConnections object.
  323. */
  324. STDMETHODIMP CEnumConnections::QueryInterface(REFIID riid
  325. , LPVOID *ppv)
  326. {
  327. *ppv=NULL;
  328. if (IID_IUnknown==riid || IID_IEnumConnections==riid)
  329. *ppv=(LPVOID)this;
  330. if (NULL!=*ppv)
  331. {
  332. ((LPUNKNOWN)*ppv)->AddRef();
  333. return NOERROR;
  334. }
  335. return ResultFromScode(E_NOINTERFACE);
  336. }
  337. STDMETHODIMP_(ULONG) CEnumConnections::AddRef(void)
  338. {
  339. InterlockedIncrement(&m_cRef);
  340. m_pUnkRef->AddRef();
  341. return m_cRef;
  342. }
  343. STDMETHODIMP_(ULONG) CEnumConnections::Release(void)
  344. {
  345. m_pUnkRef->Release();
  346. long ret;
  347. if (0L!=(ret=InterlockedDecrement(&m_cRef)))
  348. return ret;
  349. delete this;
  350. return 0;
  351. }
  352. /*
  353. * CEnumConnections::Next
  354. *
  355. * Purpose:
  356. * Returns the next element in the enumeration.
  357. *
  358. * Parameters:
  359. * cConn ULONG number of connections to return.
  360. * pConnData LPCONNECTDATA in which to store the returned
  361. * structures.
  362. * pulEnum ULONG * in which to return how many we
  363. * enumerated.
  364. *
  365. * Return Value:
  366. * HRESULT NOERROR if successful, S_FALSE otherwise,
  367. */
  368. STDMETHODIMP CEnumConnections::Next(ULONG cConn
  369. , LPCONNECTDATA pConnData, ULONG *pulEnum)
  370. {
  371. ULONG cReturn=0L;
  372. if (NULL==m_rgConnData)
  373. return ResultFromScode(S_FALSE);
  374. if (NULL==pulEnum)
  375. {
  376. if (1L!=cConn)
  377. return ResultFromScode(E_POINTER);
  378. }
  379. else
  380. *pulEnum=0L;
  381. if (NULL==pConnData || m_iCur >= m_cConn)
  382. return ResultFromScode(S_FALSE);
  383. while (m_iCur < m_cConn && cConn > 0)
  384. {
  385. *pConnData++=m_rgConnData[m_iCur];
  386. m_rgConnData[m_iCur++].pUnk->AddRef();
  387. cReturn++;
  388. cConn--;
  389. }
  390. if (NULL!=pulEnum)
  391. *pulEnum=cReturn;
  392. return NOERROR;
  393. }
  394. STDMETHODIMP CEnumConnections::Skip(ULONG cSkip)
  395. {
  396. if (((m_iCur+cSkip) >= m_cConn) || NULL==m_rgConnData)
  397. return ResultFromScode(S_FALSE);
  398. m_iCur+=cSkip;
  399. return NOERROR;
  400. }
  401. STDMETHODIMP CEnumConnections::Reset(void)
  402. {
  403. m_iCur=0;
  404. return NOERROR;
  405. }
  406. STDMETHODIMP CEnumConnections::Clone(LPENUMCONNECTIONS *ppEnum)
  407. {
  408. PCEnumConnections pNew;
  409. *ppEnum=NULL;
  410. //Create the clone
  411. pNew=new CEnumConnections(m_pUnkRef, m_cConn, m_rgConnData);
  412. if (NULL==pNew)
  413. return ResultFromScode(E_OUTOFMEMORY);
  414. pNew->AddRef();
  415. pNew->m_iCur=m_iCur;
  416. *ppEnum=pNew;
  417. return NOERROR;
  418. }
  419. /**********************************************************************************
  420. * CSmirConnObject
  421. *
  422. * Connectable Object implementation that supports the
  423. * interface ISMIRNotify.
  424. *
  425. * CSmirConnObject::CSmirConnObject
  426. * CSmirConnObject::~CSmirConnObject
  427. ***********************************************************************************/
  428. CSmirConnObject::CSmirConnObject(CSmir *pSmir) : m_rgpConnPt ( NULL )
  429. {
  430. // CSMIRClassFactory::objectsInProgress++;
  431. m_cRef=0;
  432. //create SMIR_NUMBER_OF_CONNECTION_POINTS connection points
  433. m_rgpConnPt = new CSmirConnectionPoint*[SMIR_NUMBER_OF_CONNECTION_POINTS];
  434. for(int iLoop=0;iLoop<SMIR_NUMBER_OF_CONNECTION_POINTS;iLoop++)
  435. m_rgpConnPt[iLoop] = NULL;
  436. try
  437. {
  438. Init(pSmir);
  439. }
  440. catch(...)
  441. {
  442. if (m_rgpConnPt)
  443. {
  444. //free the connection points
  445. for(int iLoop=0;iLoop<SMIR_NUMBER_OF_CONNECTION_POINTS;iLoop++)
  446. {
  447. if (NULL!=m_rgpConnPt[iLoop])
  448. {
  449. //release all of the connected objects
  450. //while(m_rgpConnPt[iLoop]->Release());
  451. m_rgpConnPt[iLoop]->Release();
  452. }
  453. }
  454. //and delete the connection point
  455. delete[] m_rgpConnPt;
  456. m_rgpConnPt = NULL;
  457. }
  458. throw;
  459. }
  460. }
  461. CSmirConnObject::~CSmirConnObject(void)
  462. {
  463. if (m_rgpConnPt)
  464. {
  465. //free the connection points
  466. for(int iLoop=0;iLoop<SMIR_NUMBER_OF_CONNECTION_POINTS;iLoop++)
  467. {
  468. if (NULL!=m_rgpConnPt[iLoop])
  469. {
  470. //release all of the connected objects
  471. //while(m_rgpConnPt[iLoop]->Release());
  472. m_rgpConnPt[iLoop]->Release();
  473. }
  474. }
  475. //and delete the connection point
  476. delete[] m_rgpConnPt;
  477. }
  478. // CSMIRClassFactory::objectsInProgress--;
  479. }
  480. /*
  481. * CSmirConnObject::Init
  482. *
  483. * Purpose:
  484. * Instantiates the interface implementations for this object.
  485. *
  486. * Parameters:
  487. * None
  488. *
  489. * Return Value:
  490. * BOOL TRUE if initialization succeeds, FALSE otherwise.
  491. */
  492. BOOL CSmirConnObject::Init(CSmir *pSmir)
  493. {
  494. //Create our connection points
  495. //the smir change CP
  496. m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT]=
  497. new CSmirNotifyCP(this,
  498. IID_ISMIR_Notify, pSmir);
  499. if (NULL==m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT])
  500. return FALSE;
  501. m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT]->AddRef();
  502. return TRUE;
  503. }
  504. /*
  505. * CSmirConnObject::QueryInterface
  506. *
  507. * Purpose:
  508. * Manages the interfaces for this object which supports the
  509. * IUnknown, ISampleOne, and ISampleTwo interfaces.
  510. *
  511. * Parameters:
  512. * riid REFIID of the interface to return.
  513. * ppv PPVOID in which to store the pointer.
  514. *
  515. * Return Value:
  516. * HRESULT NOERROR on success, E_NOINTERFACE if the
  517. * interface is not supported.
  518. */
  519. STDMETHODIMP CSmirConnObject::QueryInterface(REFIID riid, PPVOID ppv)
  520. {
  521. if (ppv)
  522. *ppv = NULL;
  523. else
  524. return E_INVALIDARG;
  525. if((IID_IConnectionPointContainer == riid)||(IID_ISMIR_Notify == riid))
  526. *ppv = this;
  527. else
  528. return E_NOINTERFACE;
  529. return S_OK;
  530. }
  531. /*
  532. * CSmirConnObject::AddRef
  533. * CSmirConnObject::Release
  534. *
  535. * Reference counting members. When Release sees a zero count
  536. * the object destroys itself.
  537. */
  538. DWORD CSmirConnObject::AddRef(void)
  539. {
  540. return InterlockedIncrement(&m_cRef);
  541. }
  542. DWORD CSmirConnObject::Release(void)
  543. {
  544. long ret;
  545. if (0!=(ret=InterlockedDecrement(&m_cRef)))
  546. {
  547. return ret;
  548. }
  549. delete this;
  550. return 0;
  551. }
  552. /*
  553. * CSmirConnObject::EnumConnectionPoints
  554. *
  555. * Purpose:
  556. * Creates and returns an enumerator object with the
  557. * IEnumConnectionPoints interface that will enumerate the
  558. * individual connection points supported in this object.
  559. *
  560. * Parameters:
  561. * ppEnum LPENUMCONNECTIONPOINTS in which to store the
  562. * IEnumConnectionPoints pointer.
  563. *
  564. * Return Value:
  565. * HRESULT NOERROR on success, E_OUTOFMEMORY on failure or
  566. * other error code.
  567. */
  568. STDMETHODIMP CSmirConnObject :: EnumConnectionPoints
  569. (LPENUMCONNECTIONPOINTS *ppEnum)
  570. {
  571. IConnectionPoint **rgCP = NULL ;
  572. CEnumConnectionPoints * pEnum = NULL ;
  573. *ppEnum=NULL;
  574. rgCP=(IConnectionPoint **)m_rgpConnPt;
  575. //Create the enumerator: we have two connection points
  576. pEnum=new CEnumConnectionPoints(this, SMIR_NUMBER_OF_CONNECTION_POINTS, rgCP);
  577. if (NULL==pEnum)
  578. return ResultFromScode(E_OUTOFMEMORY);
  579. pEnum->AddRef();
  580. *ppEnum=pEnum;
  581. return NOERROR;
  582. }
  583. /*
  584. * CSmirConnObject::FindConnectionPoint
  585. *
  586. * Purpose:
  587. * Returns a pointer to the IConnectionPoint for a given
  588. * outgoing IID.
  589. *
  590. * Parameters:
  591. * riid REFIID of the outgoing interface for which
  592. * a connection point is desired.
  593. * ppCP IConnectionPoint ** in which to return
  594. * the pointer after calling AddRef.
  595. *
  596. * Return Value:
  597. * HRESULT NOERROR if the connection point is found,
  598. * E_NOINTERFACE if it's not supported.
  599. */
  600. STDMETHODIMP CSmirConnObject::FindConnectionPoint(REFIID riid
  601. , IConnectionPoint **ppCP)
  602. {
  603. *ppCP=NULL;
  604. HRESULT result;
  605. if (IID_ISMIR_Notify==riid)
  606. {
  607. result = m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT]
  608. ->QueryInterface(IID_IConnectionPoint, (PPVOID)ppCP);
  609. if (NULL != ppCP)
  610. return result;
  611. }
  612. return ResultFromScode(E_NOINTERFACE);
  613. }
  614. //Connection Point Enumerator follows
  615. /*
  616. * CEnumConnectionPoints::CEnumConnectionPoints
  617. * CEnumConnectionPoints::~CEnumConnectionPoints
  618. *
  619. * Parameters (Constructor):
  620. * pUnkRef LPUNKNOWN to use for reference counting.
  621. * cPoints ULONG number of connection points in prgpCP
  622. * rgpCP IConnectionPoint** to the array to enumerate.
  623. */
  624. CEnumConnectionPoints::CEnumConnectionPoints(LPUNKNOWN pUnkRef
  625. , ULONG cPoints, IConnectionPoint **rgpCP) : m_rgpCP ( NULL )
  626. {
  627. UINT i;
  628. m_cRef=0;
  629. m_pUnkRef=pUnkRef;
  630. m_iCur=0;
  631. m_cPoints=cPoints;
  632. m_rgpCP=new IConnectionPoint *[(UINT)cPoints];
  633. if (NULL!=m_rgpCP)
  634. {
  635. for (i=0; i < cPoints; i++)
  636. {
  637. m_rgpCP[i]=rgpCP[i];
  638. m_rgpCP[i]->AddRef();
  639. }
  640. }
  641. return;
  642. }
  643. CEnumConnectionPoints::~CEnumConnectionPoints(void)
  644. {
  645. if (NULL!=m_rgpCP)
  646. {
  647. UINT i;
  648. for (i=0; i < m_cPoints; i++)
  649. m_rgpCP[i]->Release();
  650. delete [] m_rgpCP;
  651. }
  652. return;
  653. }
  654. /*
  655. * CEnumConnectionPoints::QueryInterface
  656. * CEnumConnectionPoints::AddRef
  657. * CEnumConnectionPoints::Release
  658. *
  659. * Purpose:
  660. * IUnknown members for CEnumConnectionPoints object.
  661. */
  662. STDMETHODIMP CEnumConnectionPoints::QueryInterface(REFIID riid
  663. , LPVOID *ppv)
  664. {
  665. *ppv=NULL;
  666. if (IID_IUnknown==riid || IID_IEnumConnectionPoints==riid)
  667. *ppv=(LPVOID)this;
  668. if (NULL!=*ppv)
  669. {
  670. ((LPUNKNOWN)*ppv)->AddRef();
  671. return NOERROR;
  672. }
  673. return ResultFromScode(E_NOINTERFACE);
  674. }
  675. STDMETHODIMP_(ULONG) CEnumConnectionPoints::AddRef(void)
  676. {
  677. InterlockedIncrement(&m_cRef);
  678. m_pUnkRef->AddRef();
  679. return m_cRef;
  680. }
  681. STDMETHODIMP_(ULONG) CEnumConnectionPoints::Release(void)
  682. {
  683. m_pUnkRef->Release();
  684. long ret;
  685. if (0L!=(ret=InterlockedDecrement(&m_cRef)))
  686. return ret;
  687. delete this;
  688. return 0;
  689. }
  690. /*
  691. * CEnumConnectionPoints::Next
  692. *
  693. * Purpose:
  694. * Returns the next element in the enumeration.
  695. *
  696. * Parameters:
  697. * cPoints ULONG number of connection points to return.
  698. * ppCP IConnectionPoint** in which to store the returned
  699. * pointers.
  700. * pulEnum ULONG * in which to return how many we
  701. * enumerated.
  702. *
  703. * Return Value:
  704. * HRESULT NOERROR if successful, S_FALSE otherwise,
  705. */
  706. STDMETHODIMP CEnumConnectionPoints::Next(ULONG cPoints
  707. , IConnectionPoint **ppCP, ULONG *pulEnum)
  708. {
  709. ULONG cReturn=0L;
  710. if (NULL==m_rgpCP)
  711. return ResultFromScode(S_FALSE);
  712. if (NULL==ppCP)
  713. return ResultFromScode(E_POINTER);
  714. if (NULL==pulEnum)
  715. {
  716. if (1L!=cPoints)
  717. return ResultFromScode(E_POINTER);
  718. }
  719. else
  720. *pulEnum=0L;
  721. if (NULL==*ppCP || m_iCur >= m_cPoints)
  722. return ResultFromScode(S_FALSE);
  723. while (m_iCur < m_cPoints && cPoints > 0)
  724. {
  725. *ppCP=m_rgpCP[m_iCur++];
  726. if (NULL!=*ppCP)
  727. (*ppCP)->AddRef();
  728. ppCP++;
  729. cReturn++;
  730. cPoints--;
  731. }
  732. if (NULL!=pulEnum)
  733. *pulEnum=cReturn;
  734. return NOERROR;
  735. }
  736. STDMETHODIMP CEnumConnectionPoints::Skip(ULONG cSkip)
  737. {
  738. if (((m_iCur+cSkip) >= m_cPoints) || NULL==m_rgpCP)
  739. return ResultFromScode(S_FALSE);
  740. m_iCur+=cSkip;
  741. return NOERROR;
  742. }
  743. STDMETHODIMP CEnumConnectionPoints::Reset(void)
  744. {
  745. m_iCur=0;
  746. return NOERROR;
  747. }
  748. STDMETHODIMP CEnumConnectionPoints::Clone
  749. (LPENUMCONNECTIONPOINTS *ppEnum)
  750. {
  751. PCEnumConnectionPoints pNew = NULL ;
  752. *ppEnum=NULL;
  753. //Create the clone
  754. pNew=new CEnumConnectionPoints(m_pUnkRef, m_cPoints, m_rgpCP);
  755. if (NULL==pNew)
  756. return ResultFromScode(E_OUTOFMEMORY);
  757. pNew->AddRef();
  758. pNew->m_iCur=m_iCur;
  759. *ppEnum=pNew;
  760. return NOERROR;
  761. }
  762. /*
  763. * CSmirEnumClassCP/CSmirNotifyCP::
  764. *
  765. * Purpose:
  766. * Provides the notify connection point advise, unadvise constructor and destructor.
  767. *
  768. * Parameters:
  769. * pUnkSink LPUNKNOWN to the sink to notify. The connection
  770. * point must QueryInterface on this pointer to obtain
  771. * the proper interface to call. The connection
  772. * point must also insure that any pointer held has
  773. * a reference count (QueryInterface will do it).
  774. * pdwCookie DWORD * in which to store the connection key for
  775. * later calls to Unadvise.
  776. */
  777. CSmirNotifyCP :: CSmirNotifyCP(PCSmirConnObject pCO, REFIID riid, CSmir *pSmir):
  778. CSmirConnectionPoint(pCO,riid,pSmir), m_evtConsumer (NULL)
  779. {
  780. // CSMIRClassFactory::objectsInProgress++;
  781. m_bRegistered = FALSE;
  782. m_evtConsumer = new CSmirWbemEventConsumer(pSmir);
  783. void* tmp = NULL;
  784. if (FAILED(m_evtConsumer->QueryInterface(IID_ISMIR_WbemEventConsumer, &tmp)))
  785. {
  786. delete m_evtConsumer;
  787. m_evtConsumer = NULL;
  788. }
  789. }
  790. CSmirNotifyCP :: ~CSmirNotifyCP()
  791. {
  792. if (NULL != m_evtConsumer)
  793. {
  794. m_evtConsumer->Release();
  795. }
  796. // CSMIRClassFactory::objectsInProgress--;
  797. }
  798. /*
  799. * CSmirConnObject::TriggerEvent
  800. *
  801. * Purpose:
  802. * Functions to make each connection point generate calls
  803. * to any connected sinks. Since these functions are specific
  804. * to IDuckEvents, they only deal with the connection point
  805. * for that one interface
  806. *
  807. * Parameters:
  808. * iEvent UINT of the event to trigger, either
  809. * EVENT_QUACK, EVENT_FLAP, or EVENT_PADDLE.
  810. *
  811. * Return Value:
  812. * BOOL TRUE events are triggered, FALSE if there
  813. * are no connected sinks.
  814. */
  815. BOOL CSmirNotifyCP::TriggerEvent()
  816. {
  817. IEnumConnections *pEnum = NULL ;
  818. CONNECTDATA cd ;
  819. if (FAILED(EnumConnections(&pEnum)))
  820. return FALSE;
  821. while (NOERROR == pEnum->Next(1, &cd, NULL))
  822. {
  823. //a promise fulfilled - Andrew Sinclair just in case anyone thinks otherwise!
  824. ISMIRNotify *pJudith;
  825. if (SUCCEEDED(cd.pUnk->QueryInterface(IID_ISMIR_Notify, (PPVOID)&pJudith)))
  826. {
  827. pJudith->ChangeNotify();
  828. pJudith->Release();
  829. }
  830. cd.pUnk->Release();
  831. }
  832. pEnum->Release();
  833. return TRUE;
  834. }
  835. STDMETHODIMP CSmirNotifyCP::Advise(CSmir* pSmir, LPUNKNOWN pUnkSink
  836. , DWORD *pdwCookie)
  837. {
  838. if (NULL == m_evtConsumer)
  839. {
  840. return WBEM_E_FAILED;
  841. }
  842. //if this is the first person to connect
  843. if(m_Connections.IsEmpty())
  844. {
  845. //register for WBEM Events for Smir Namespace changes
  846. if (SUCCEEDED(m_evtConsumer->Register(pSmir)))
  847. {
  848. m_bRegistered = TRUE;
  849. }
  850. }
  851. return CSmirConnectionPoint::Advise(pUnkSink, pdwCookie);
  852. }
  853. STDMETHODIMP CSmirNotifyCP::Unadvise(CSmir* pSmir, DWORD dwCookie)
  854. {
  855. EnterCriticalSection ( & g_CriticalSection ) ;
  856. HRESULT hr = CSmirConnectionPoint::Unadvise(dwCookie);
  857. IWbemServices *t_pServ = NULL;
  858. if(S_OK== hr)
  859. {
  860. //if this is the last connection unregister for WBEM Events
  861. if(m_Connections.IsEmpty())
  862. {
  863. if (NULL == m_evtConsumer)
  864. {
  865. return WBEM_E_FAILED;
  866. }
  867. else if (m_bRegistered)
  868. {
  869. hr = m_evtConsumer->GetUnRegisterParams(&t_pServ);
  870. }
  871. }
  872. }
  873. LeaveCriticalSection ( & g_CriticalSection ) ;
  874. if (SUCCEEDED(hr) && (t_pServ != NULL))
  875. {
  876. hr = m_evtConsumer->UnRegister(pSmir, t_pServ);
  877. t_pServ->Release();
  878. t_pServ = NULL;
  879. //guarantees only one query at a time with the event consumer (sink)....
  880. EnterCriticalSection ( & g_CriticalSection ) ;
  881. m_bRegistered = FALSE;
  882. LeaveCriticalSection ( & g_CriticalSection ) ;
  883. }
  884. return hr;
  885. }