Source code of Windows XP (NT5)
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.

1634 lines
47 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: connect.cpp
  3. Description: Contains class definitions for classes associated with
  4. OLE connection points. These are:
  5. ConnectionPoint ( IConnectionPoint )
  6. ConnectionPointEnum ( IEnumConnectionPoints )
  7. ConnectionEnum ( IEnumConnections )
  8. Revision History:
  9. Date Description Programmer
  10. -------- --------------------------------------------------- ----------
  11. 06/19/96 Initial creation. BrianAu
  12. */
  13. ///////////////////////////////////////////////////////////////////////////////
  14. #include "pch.h" // PCH
  15. #pragma hdrstop
  16. #include "connect.h"
  17. #include "guidsp.h"
  18. //
  19. // Constants for connection point-related objects.
  20. //
  21. const UINT CONNECTION_FIRST_COOKIE = 100; // 1st cookie value given out.
  22. //
  23. // Verify that build is UNICODE.
  24. //
  25. #if !defined(UNICODE)
  26. # error This module must be compiled UNICODE.
  27. #endif
  28. ///////////////////////////////////////////////////////////////////////////////
  29. /* Function: ConnectionPoint::ConnectionPoint
  30. Description: Constructor,
  31. Arguments:
  32. pUnkContainer - Pointer to containing DiskQuotaController object.
  33. riid - Reference to IID that this connection point object supports.
  34. Returns: Nothing.
  35. Exceptions: CAllocException, CSyncException
  36. Revision History:
  37. Date Description Programmer
  38. -------- --------------------------------------------------- ----------
  39. 06/19/96 Initial creation. BrianAu
  40. 09/06/96 Added exception handling. BrianAu
  41. */
  42. ///////////////////////////////////////////////////////////////////////////////
  43. ConnectionPoint::ConnectionPoint(
  44. LPUNKNOWN pUnkContainer,
  45. REFIID riid
  46. ) : m_cRef(0),
  47. m_cConnections(0),
  48. m_dwCookieNext(CONNECTION_FIRST_COOKIE),
  49. m_pUnkContainer(pUnkContainer),
  50. m_riid(riid),
  51. m_hMutex(NULL)
  52. {
  53. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPoint::ConnectionPoint")));
  54. DBGASSERT((NULL != pUnkContainer));
  55. if (NULL == (m_hMutex = CreateMutex(NULL, FALSE, NULL)))
  56. throw CSyncException(CSyncException::mutex, CSyncException::create);
  57. m_Dispatch.Initialize(static_cast<IDispatch *>(this),
  58. LIBID_DiskQuotaTypeLibrary,
  59. IID_DIDiskQuotaControlEvents,
  60. L"DSKQUOTA.DLL");
  61. }
  62. ///////////////////////////////////////////////////////////////////////////////
  63. /* Function: ConnectionPoint::~ConnectionPoint
  64. Description: Destructor.
  65. Arguments: None.
  66. Returns: Nothing.
  67. Revision History:
  68. Date Description Programmer
  69. -------- --------------------------------------------------- ----------
  70. 06/19/96 Initial creation. BrianAu
  71. */
  72. ///////////////////////////////////////////////////////////////////////////////
  73. ConnectionPoint::~ConnectionPoint(
  74. VOID
  75. )
  76. {
  77. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPoint::~ConnectionPoint")));
  78. Lock();
  79. UINT cConnections = m_ConnectionList.Count();
  80. for (UINT i = 0; i < cConnections; i++)
  81. {
  82. if (NULL != m_ConnectionList[i].pUnk)
  83. {
  84. m_ConnectionList[i].pUnk->Release();
  85. }
  86. }
  87. ReleaseLock();
  88. if (NULL != m_hMutex)
  89. CloseHandle(m_hMutex);
  90. }
  91. ///////////////////////////////////////////////////////////////////////////////
  92. /* Function: ConnectionPoint::QueryInterface
  93. Description: Returns an interface pointer to the object's IUnknown or
  94. IConnectionPoint interface. Only IID_IUnknown and
  95. IID_IConnectionPoint are recognized. The object referenced by the
  96. returned interface pointer is uninitialized. The recipient of the
  97. pointer must call Initialize() before the object is usable.
  98. Arguments:
  99. riid - Reference to requested interface ID.
  100. ppvOut - Address of interface pointer variable to accept interface ptr.
  101. Returns:
  102. NOERROR - Success.
  103. E_NOINTERFACE - Requested interface not supported.
  104. E_INVALIDARG - ppvOut argument was NULL.
  105. Revision History:
  106. Date Description Programmer
  107. -------- --------------------------------------------------- ----------
  108. 06/18/96 Initial creation. BrianAu
  109. */
  110. ///////////////////////////////////////////////////////////////////////////////
  111. STDMETHODIMP
  112. ConnectionPoint::QueryInterface(
  113. REFIID riid,
  114. LPVOID *ppvOut
  115. )
  116. {
  117. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPoint::QueryInterface")));
  118. DBGPRINTIID(DM_CONNPT, DL_MID, riid);
  119. HRESULT hr = E_NOINTERFACE;
  120. if (NULL == ppvOut)
  121. return E_INVALIDARG;
  122. *ppvOut = NULL;
  123. if (IID_IUnknown == riid || IID_IConnectionPoint == riid)
  124. {
  125. *ppvOut = static_cast<IConnectionPoint *>(this);
  126. }
  127. else if (IID_IDispatch == riid)
  128. {
  129. *ppvOut = static_cast<IDispatch *>(this);
  130. }
  131. if (NULL != *ppvOut)
  132. {
  133. ((LPUNKNOWN)*ppvOut)->AddRef();
  134. hr = NOERROR;
  135. }
  136. return hr;
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////
  139. /* Function: ConnectionPoint::AddRef
  140. Description: Increments object reference count.
  141. Arguments: None.
  142. Returns: New reference count value.
  143. Revision History:
  144. Date Description Programmer
  145. -------- --------------------------------------------------- ----------
  146. 06/18/96 Initial creation. BrianAu
  147. */
  148. ///////////////////////////////////////////////////////////////////////////////
  149. STDMETHODIMP_(ULONG)
  150. ConnectionPoint::AddRef(
  151. VOID
  152. )
  153. {
  154. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPoint::AddRef")));
  155. DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
  156. this, m_cRef, m_cRef + 1));
  157. ULONG ulReturn = m_cRef + 1;
  158. InterlockedIncrement(&m_cRef);
  159. //
  160. // NOTE: We maintain a pointer to the quota controller (m_pUnkContainer) but
  161. // we DO NOT AddRef it. The controller calls AddRef for connection
  162. // point objects so this would create a circular reference.
  163. //
  164. return ulReturn;
  165. }
  166. ///////////////////////////////////////////////////////////////////////////////
  167. /* Function: ConnectionPoint::Release
  168. Description: Decrements object reference count. If count drops to 0,
  169. object is deleted.
  170. Arguments: None.
  171. Returns: New reference count value.
  172. Revision History:
  173. Date Description Programmer
  174. -------- --------------------------------------------------- ----------
  175. 06/18/96 Initial creation. BrianAu
  176. */
  177. ///////////////////////////////////////////////////////////////////////////////
  178. STDMETHODIMP_(ULONG)
  179. ConnectionPoint::Release(
  180. VOID
  181. )
  182. {
  183. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPoint::Release")));
  184. DBGPRINT((DM_COM, DL_HIGH, TEXT("\t0x%08X %d -> %d\n"),
  185. this, m_cRef, m_cRef - 1));
  186. ULONG ulReturn = m_cRef - 1;
  187. if (InterlockedDecrement(&m_cRef) == 0)
  188. {
  189. delete this;
  190. ulReturn = 0;
  191. }
  192. return ulReturn;
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////
  195. /* Function: ConnectionPoint::GetConnectionInterface
  196. Description: Retrieves a connection point's interface ID.
  197. Arguments:
  198. pIID - Address of IID variable to receive the IID.
  199. Returns:
  200. NOERROR - Success.
  201. E_INVALIDARG - pIID is NULL.
  202. Revision History:
  203. Date Description Programmer
  204. -------- --------------------------------------------------- ----------
  205. 06/18/96 Initial creation. BrianAu
  206. */
  207. ///////////////////////////////////////////////////////////////////////////////
  208. STDMETHODIMP
  209. ConnectionPoint::GetConnectionInterface(
  210. LPIID pIID
  211. )
  212. {
  213. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetConnectionInterface")));
  214. HRESULT hr = E_INVALIDARG;
  215. if (NULL != pIID)
  216. {
  217. *pIID = m_riid;
  218. hr = NOERROR;
  219. }
  220. return hr;
  221. }
  222. ///////////////////////////////////////////////////////////////////////////////
  223. /* Function: ConnectionPoint::GetConnectionPointContainer
  224. Description: Retrieves an interface pointer for the point's parent
  225. container.
  226. Arguments:
  227. ppCPC - Address of variable to receive container's interface pointer
  228. value.
  229. Returns:
  230. NOERROR - Success.
  231. E_INVALIDARG - ppCPC argument was NULL.
  232. Revision History:
  233. Date Description Programmer
  234. -------- --------------------------------------------------- ----------
  235. 06/18/96 Initial creation. BrianAu
  236. */
  237. ///////////////////////////////////////////////////////////////////////////////
  238. STDMETHODIMP
  239. ConnectionPoint::GetConnectionPointContainer(
  240. PCONNECTIONPOINTCONTAINER *ppCPC
  241. )
  242. {
  243. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetConnectionPointContainer")));
  244. return m_pUnkContainer->QueryInterface(IID_IConnectionPointContainer,
  245. (LPVOID *)ppCPC);
  246. }
  247. ///////////////////////////////////////////////////////////////////////////////
  248. /* Function: ConnectionPoint::Advise
  249. Description: Notifies the connection point of an outgoing interface.
  250. Arguments:
  251. pUnkSink - Pointer to outgoing interface provided by Sink.
  252. pdwCookie - Address of variable to receive the "cookie" returned
  253. for this connection. The client uses this "cookie" value to
  254. refer to the connection.
  255. Returns:
  256. NOERROR - Success.
  257. E_INVALIDARG - pUnkSink or pdwCookie were NULL.
  258. CONNECT_E_CANNOTCONNECT - Sink doesn't support our event interface.
  259. E_UNEXPECTED - Exception caught while calling client code.
  260. E_OUTOFMEMORY - Insufficient memory.
  261. Revision History:
  262. Date Description Programmer
  263. -------- --------------------------------------------------- ----------
  264. 07/21/96 Initial creation. BrianAu
  265. 09/06/96 Added exception handling. BrianAu
  266. */
  267. ///////////////////////////////////////////////////////////////////////////////
  268. STDMETHODIMP
  269. ConnectionPoint::Advise(
  270. LPUNKNOWN pUnkSink,
  271. LPDWORD pdwCookie
  272. )
  273. {
  274. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::Advise")));
  275. DBGPRINT((DM_CONNPT, DL_MID, TEXT("\tAdvising connpt 0x%08X of sink 0x%08X"),
  276. this, pUnkSink));
  277. HRESULT hr = NOERROR;
  278. if (NULL == pUnkSink || NULL == pdwCookie)
  279. return E_INVALIDARG;
  280. LPUNKNOWN pSink = NULL;
  281. AutoLockMutex lock(m_hMutex);
  282. //
  283. // Does the sink support our conn pt interface?
  284. //
  285. try
  286. {
  287. //
  288. // QueryInterface() is client code. Must handle exceptions.
  289. //
  290. hr = pUnkSink->QueryInterface(m_riid, (LPVOID *)&pSink);
  291. if (SUCCEEDED(hr))
  292. {
  293. CONNECTDATA cd;
  294. //
  295. // See if there is an unused entry in the list.
  296. // If not, we'll have to extend the list.
  297. //
  298. UINT index = m_cConnections;
  299. for (UINT i = 0; i < m_cConnections; i++)
  300. {
  301. if (NULL == m_ConnectionList[i].pUnk)
  302. {
  303. index = i;
  304. break;
  305. }
  306. }
  307. //
  308. // Fill in the connection info and add to connection list.
  309. //
  310. cd.pUnk = pSink;
  311. *pdwCookie = cd.dwCookie = m_dwCookieNext++;
  312. if (index < m_cConnections)
  313. m_ConnectionList[index] = cd;
  314. else
  315. m_ConnectionList.Append(cd); // This can throw OutOfMemory.
  316. if (SUCCEEDED(hr))
  317. {
  318. m_cConnections++; // Another connection.
  319. DBGPRINT((DM_CONNPT, DL_HIGH,
  320. TEXT("CONNPT - Connection complete. Cookie = %d. %d total connections."),
  321. *pdwCookie, m_cConnections));
  322. }
  323. else
  324. {
  325. DBGERROR((TEXT("ConnPt connection failed with error 0x%08X."), hr));
  326. }
  327. }
  328. else
  329. hr = CONNECT_E_CANNOTCONNECT; // Interface not supported.
  330. }
  331. catch(CAllocException& e)
  332. {
  333. DBGERROR((TEXT("Insufficient memory exception")));
  334. hr = E_OUTOFMEMORY;
  335. }
  336. if (FAILED(hr) && NULL != pSink)
  337. {
  338. //
  339. // Something failed after QueryInterface. Release sink pointer.
  340. //
  341. pSink->Release();
  342. }
  343. return hr;
  344. }
  345. ///////////////////////////////////////////////////////////////////////////////
  346. /* Function: ConnectionPoint::Unadvise
  347. Description: Disconntinues an outgoing communication channel with the
  348. connection point object.
  349. Arguments:
  350. dwCookie - The "channel" identifier returned from Advise().
  351. Returns:
  352. NOERROR - Success.
  353. CONNECT_E_NOCONNECTION - No connection found for this cookie.
  354. E_UNEXPECTED - Exception caught while calling client code.
  355. Revision History:
  356. Date Description Programmer
  357. -------- --------------------------------------------------- ----------
  358. 07/21/96 Initial creation. BrianAu
  359. */
  360. ///////////////////////////////////////////////////////////////////////////////
  361. STDMETHODIMP
  362. ConnectionPoint::Unadvise(
  363. DWORD dwCookie
  364. )
  365. {
  366. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::Unadvise")));
  367. DBGPRINT((DM_CONNPT, DL_MID, TEXT("\tUnadvising connpt 0x%08X of cookie %d"),
  368. this, dwCookie));
  369. HRESULT hr = CONNECT_E_NOCONNECTION;
  370. if (0 != dwCookie)
  371. {
  372. AutoLockMutex lock(m_hMutex);
  373. for (UINT i = 0; i < m_cConnections; i++)
  374. {
  375. if (m_ConnectionList[i].dwCookie == dwCookie)
  376. {
  377. //
  378. // Matching cookie found. Release interface, mark connection
  379. // list entry as unused.
  380. //
  381. hr = NOERROR;
  382. m_ConnectionList[i].pUnk->Release();
  383. m_ConnectionList[i].pUnk = NULL;
  384. m_ConnectionList[i].dwCookie = 0;
  385. m_cConnections--;
  386. DBGPRINT((DM_CONNPT, DL_HIGH, TEXT("CONNPT - Connection terminated for cookie %d. %d total connections"),
  387. dwCookie, m_cConnections));
  388. break;
  389. }
  390. }
  391. }
  392. return hr;
  393. }
  394. ///////////////////////////////////////////////////////////////////////////////
  395. /* Function: ConnectionPoint::EnumConnections
  396. Description: Retrieves in interface pointer to a connection enumerator
  397. which enumerates all connections associated with this connection
  398. point.
  399. Arguments:
  400. ppEnum - Address of interface pointer variable to received address of
  401. the enumerator's IEnumConnection interface.
  402. Returns:
  403. NOERROR - Success.
  404. E_INVALIDARG - ppEnum was NULL.
  405. E_OUTOFMEMORY - Insufficient memory to create enumerator.
  406. E_UNEXPECTED - Unexpected exception.
  407. Revision History:
  408. Date Description Programmer
  409. -------- --------------------------------------------------- ----------
  410. 07/21/96 Initial creation. BrianAu
  411. 09/06/96 Added exception handling. BrianAu
  412. */
  413. ///////////////////////////////////////////////////////////////////////////////
  414. STDMETHODIMP
  415. ConnectionPoint::EnumConnections(
  416. PENUMCONNECTIONS *ppEnum
  417. )
  418. {
  419. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::EnumConnections")));
  420. HRESULT hr = NOERROR;
  421. if (NULL == ppEnum)
  422. return E_INVALIDARG;
  423. ConnectionEnum *pEnum = NULL;
  424. AutoLockMutex lock(m_hMutex);
  425. try
  426. {
  427. array_autoptr<CONNECTDATA> ptrCD;
  428. PCONNECTDATA pcd = NULL;
  429. //
  430. // Build temp array of connection data to initialize enumerator.
  431. // Note: If m_cConnections == 0, we still return an enumerator
  432. // but it's uninitialized. Calls to Next and Skip will always
  433. // return S_FALSE so the enumerator is just viewed as "empty".
  434. //
  435. if (0 != m_cConnections)
  436. {
  437. ptrCD = new CONNECTDATA[m_cConnections];
  438. pcd = ptrCD.get();
  439. //
  440. // Transfer connection info to temp array for initializting
  441. // the enumerator object.
  442. // Remember, the connection list can have unused entries so
  443. // cConnListEntries can be greater than m_cConnections.
  444. //
  445. UINT cConnListEntries = m_ConnectionList.Count();
  446. for (UINT i = 0, j = 0; i < cConnListEntries; i++)
  447. {
  448. DBGASSERT((j < m_cConnections));
  449. *(pcd + j) = m_ConnectionList[i];
  450. if (NULL != pcd[j].pUnk)
  451. j++;
  452. }
  453. }
  454. //
  455. // Create the enumerator object.
  456. // The enumerator keeps a copy of the connection's
  457. // IUnknown pointer. Note that we still create an
  458. // enumerator even if m_cConnections is 0. It's just an
  459. // empty enumerator. If m_cConnections is 0, pcd can be NULL.
  460. //
  461. DBGASSERT((m_cConnections ? NULL != pcd : TRUE));
  462. pEnum = new ConnectionEnum(static_cast<IConnectionPoint *>(this), m_cConnections, pcd);
  463. hr = pEnum->QueryInterface(IID_IEnumConnections,
  464. (LPVOID *)ppEnum);
  465. }
  466. catch(CAllocException& e)
  467. {
  468. DBGERROR((TEXT("Insufficient memory exception")));
  469. delete pEnum;
  470. hr = E_OUTOFMEMORY;
  471. }
  472. return hr;
  473. }
  474. //
  475. // IDispatch::GetIDsOfNames
  476. //
  477. STDMETHODIMP
  478. ConnectionPoint::GetIDsOfNames(
  479. REFIID riid,
  480. OLECHAR **rgszNames,
  481. UINT cNames,
  482. LCID lcid,
  483. DISPID *rgDispId
  484. )
  485. {
  486. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetIDsOfNames")));
  487. //
  488. // Let our dispatch object handle this.
  489. //
  490. return m_Dispatch.GetIDsOfNames(riid,
  491. rgszNames,
  492. cNames,
  493. lcid,
  494. rgDispId);
  495. }
  496. //
  497. // IDispatch::GetTypeInfo
  498. //
  499. STDMETHODIMP
  500. ConnectionPoint::GetTypeInfo(
  501. UINT iTInfo,
  502. LCID lcid,
  503. ITypeInfo **ppTypeInfo
  504. )
  505. {
  506. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetTypeInfo")));
  507. //
  508. // Let our dispatch object handle this.
  509. //
  510. return m_Dispatch.GetTypeInfo(iTInfo, lcid, ppTypeInfo);
  511. }
  512. //
  513. // IDispatch::GetTypeInfoCount
  514. //
  515. STDMETHODIMP
  516. ConnectionPoint::GetTypeInfoCount(
  517. UINT *pctinfo
  518. )
  519. {
  520. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::GetTypeInfoCount")));
  521. //
  522. // Let our dispatch object handle this.
  523. //
  524. return m_Dispatch.GetTypeInfoCount(pctinfo);
  525. }
  526. //
  527. // IDispatch::Invoke
  528. //
  529. STDMETHODIMP
  530. ConnectionPoint::Invoke(
  531. DISPID dispIdMember,
  532. REFIID riid,
  533. LCID lcid,
  534. WORD wFlags,
  535. DISPPARAMS *pDispParams,
  536. VARIANT *pVarResult,
  537. EXCEPINFO *pExcepInfo,
  538. UINT *puArgErr
  539. )
  540. {
  541. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionPoint::Invoke")));
  542. //
  543. // Let our dispatch object handle this.
  544. //
  545. return m_Dispatch.Invoke(dispIdMember,
  546. riid,
  547. lcid,
  548. wFlags,
  549. pDispParams,
  550. pVarResult,
  551. pExcepInfo,
  552. puArgErr);
  553. }
  554. ///////////////////////////////////////////////////////////////////////////////
  555. /* Function: ConnectionEnum::ConnectionEnum
  556. Description: Constructor,
  557. Arguments:
  558. pUnkContainer - Pointer to the IUnknown interface of the containing
  559. object.
  560. cConnections - Number of connections in array pointed to by rgConnections.
  561. rgConnections - Array of connection information used to
  562. initialize the enumerator.
  563. Returns: Nothing.
  564. Exceptions: CAllocException.
  565. Revision History:
  566. Date Description Programmer
  567. -------- --------------------------------------------------- ----------
  568. 06/19/96 Initial creation. BrianAu
  569. 09/06/06 Added copy constructor. BrianAu
  570. */
  571. ///////////////////////////////////////////////////////////////////////////////
  572. ConnectionEnum::ConnectionEnum(
  573. LPUNKNOWN pUnkContainer,
  574. UINT cConnections,
  575. PCONNECTDATA rgConnections
  576. ) : m_cRef(0),
  577. m_iCurrent(0),
  578. m_cConnections(0),
  579. m_rgConnections(NULL),
  580. m_pUnkContainer(pUnkContainer)
  581. {
  582. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::ConnectionEnum")));
  583. DBGASSERT((NULL != pUnkContainer));
  584. if (0 != cConnections)
  585. {
  586. m_rgConnections = new CONNECTDATA[cConnections];
  587. DBGASSERT((NULL != rgConnections));
  588. for (UINT i = 0; i < cConnections; i++)
  589. {
  590. //
  591. // IUnknown::AddRef() is client code. It can generate an exception.
  592. // Caller must catch and handle it.
  593. //
  594. rgConnections[i].pUnk->AddRef();
  595. m_rgConnections[i].pUnk = rgConnections[i].pUnk;
  596. m_rgConnections[i].dwCookie = rgConnections[i].dwCookie;
  597. m_cConnections++;
  598. }
  599. }
  600. }
  601. ConnectionEnum::ConnectionEnum(const ConnectionEnum& refEnum)
  602. : m_cRef(0),
  603. m_iCurrent(0),
  604. m_cConnections(0),
  605. m_rgConnections(NULL),
  606. m_pUnkContainer(m_pUnkContainer)
  607. {
  608. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::ConnectionEnum [copy]")));
  609. if (0 != m_cConnections)
  610. {
  611. m_rgConnections = new CONNECTDATA[m_cConnections];
  612. DBGASSERT((NULL != refEnum.m_rgConnections));
  613. for (UINT i = 0; i < m_cConnections; i++)
  614. {
  615. //
  616. // IUnknown::AddRef() is client code. It can generate an exception.
  617. // Caller must catch and handle it.
  618. //
  619. refEnum.m_rgConnections[i].pUnk->AddRef();
  620. m_rgConnections[i].pUnk = refEnum.m_rgConnections[i].pUnk;
  621. m_rgConnections[i].dwCookie = refEnum.m_rgConnections[i].dwCookie;
  622. m_cConnections++;
  623. }
  624. }
  625. }
  626. ///////////////////////////////////////////////////////////////////////////////
  627. /* Function: ConnectionEnum::~ConnectionEnum
  628. Description: Destructor. Releases all connection sink interface pointers
  629. held in enumerator's array.
  630. Arguments: None.
  631. Returns: Nothing.
  632. Revision History:
  633. Date Description Programmer
  634. -------- --------------------------------------------------- ----------
  635. 06/19/96 Initial creation. BrianAu
  636. */
  637. ///////////////////////////////////////////////////////////////////////////////
  638. ConnectionEnum::~ConnectionEnum(
  639. VOID
  640. )
  641. {
  642. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::~ConnectionEnum")));
  643. if (NULL != m_rgConnections)
  644. {
  645. for (UINT i = 0; i < m_cConnections; i++)
  646. {
  647. if (NULL != m_rgConnections[i].pUnk)
  648. {
  649. m_rgConnections[i].pUnk->Release();
  650. m_rgConnections[i].pUnk = NULL;
  651. }
  652. }
  653. delete[] m_rgConnections;
  654. }
  655. }
  656. ///////////////////////////////////////////////////////////////////////////////
  657. /* Function: ConnectionEnum::QueryInterface
  658. Description: Returns an interface pointer to the object's IUnknown or
  659. IEnumConnections interface. Only IID_IUnknown and
  660. IID_IEnumConnections are recognized. The object referenced by the
  661. returned interface pointer is uninitialized. The recipient of the
  662. pointer must call Initialize() before the object is usable.
  663. Arguments:
  664. riid - Reference to requested interface ID.
  665. ppvOut - Address of interface pointer variable to accept interface ptr.
  666. Returns:
  667. NOERROR - Success.
  668. E_NOINTERFACE - Requested interface not supported.
  669. E_INVALIDARG - ppvOut arg is NULL.
  670. Revision History:
  671. Date Description Programmer
  672. -------- --------------------------------------------------- ----------
  673. 06/18/96 Initial creation. BrianAu
  674. */
  675. ///////////////////////////////////////////////////////////////////////////////
  676. STDMETHODIMP
  677. ConnectionEnum::QueryInterface(
  678. REFIID riid,
  679. LPVOID *ppvOut
  680. )
  681. {
  682. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionEnum::QueryInterface")));
  683. DBGPRINTIID(DM_CONNPT, DL_MID, riid);
  684. HRESULT hr = E_NOINTERFACE;
  685. if (NULL == ppvOut)
  686. return E_INVALIDARG;
  687. *ppvOut = NULL;
  688. if (IID_IUnknown == riid || IID_IEnumConnections == riid)
  689. {
  690. *ppvOut = this;
  691. ((LPUNKNOWN)*ppvOut)->AddRef();
  692. hr = NOERROR;
  693. }
  694. return hr;
  695. }
  696. ///////////////////////////////////////////////////////////////////////////////
  697. /* Function: ConnectionEnum::AddRef
  698. Description: Increments object reference count.
  699. Arguments: None.
  700. Returns: New reference count value.
  701. Revision History:
  702. Date Description Programmer
  703. -------- --------------------------------------------------- ----------
  704. 06/18/96 Initial creation. BrianAu
  705. */
  706. ///////////////////////////////////////////////////////////////////////////////
  707. STDMETHODIMP_(ULONG)
  708. ConnectionEnum::AddRef(
  709. VOID
  710. )
  711. {
  712. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionEnum::AddRef")));
  713. DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
  714. this, m_cRef, m_cRef + 1));
  715. ULONG ulReturn = m_cRef + 1;
  716. InterlockedIncrement(&m_cRef);
  717. //
  718. // Increment ref count of connection point so that it stays around
  719. // while the connection enumerator is alive.
  720. //
  721. m_pUnkContainer->AddRef();
  722. return ulReturn;
  723. }
  724. ///////////////////////////////////////////////////////////////////////////////
  725. /* Function: ConnectionEnum::Release
  726. Description: Decrements object reference count. If count drops to 0,
  727. object is deleted.
  728. Arguments: None.
  729. Returns: New reference count value.
  730. Revision History:
  731. Date Description Programmer
  732. -------- --------------------------------------------------- ----------
  733. 06/18/96 Initial creation. BrianAu
  734. */
  735. ///////////////////////////////////////////////////////////////////////////////
  736. STDMETHODIMP_(ULONG)
  737. ConnectionEnum::Release(
  738. VOID
  739. )
  740. {
  741. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionEnum::Release")));
  742. DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
  743. this, m_cRef, m_cRef - 1));
  744. ULONG ulReturn = m_cRef - 1;
  745. //
  746. // Decrement ref count of connection point. We AddRef'd it
  747. // above.
  748. //
  749. m_pUnkContainer->Release();
  750. if (InterlockedDecrement(&m_cRef) == 0)
  751. {
  752. delete this;
  753. ulReturn = 0;
  754. }
  755. return ulReturn;
  756. }
  757. ///////////////////////////////////////////////////////////////////////////////
  758. /* Function: ConnectionEnum::Next
  759. Description: Retrieve the next cConnections connections supported by
  760. the enumerator.
  761. Arguments:
  762. cConnections - Number of elements in pConnections array.
  763. pConnections - Array to receive CONNECTDATA data records.
  764. pcCreated [optional] - Address of DWORD to accept the count of records
  765. returned in pConnections. Note that any array locations equal to
  766. or beyond the value returned in pcCreated are invalid and set to
  767. NULL.
  768. Returns:
  769. S_OK - Success. Enumerated number of requested connections.
  770. S_FALSE - End of enumeration encountered. Returning less than
  771. cConnections records.
  772. E_INVALIDARG - pConnections arg is NULL.
  773. E_UNEXPECTED - Exception caught.
  774. Revision History:
  775. Date Description Programmer
  776. -------- --------------------------------------------------- ----------
  777. 06/19/96 Initial creation. BrianAu
  778. */
  779. ///////////////////////////////////////////////////////////////////////////////
  780. HRESULT
  781. ConnectionEnum::Next(
  782. DWORD cConnections, // Number of elements in array.
  783. PCONNECTDATA pConnections, // Dest array for connection info.
  784. DWORD *pcCreated // Return number created.
  785. )
  786. {
  787. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Next")));
  788. if (NULL == pConnections)
  789. return E_INVALIDARG;
  790. HRESULT hr = S_OK;
  791. DWORD cCreated = 0;
  792. //
  793. // Transfer data to caller's array.
  794. // Stop when at the end of the enumeration or we've
  795. // returned all that the caller asked for.
  796. //
  797. while(m_iCurrent < m_cConnections && cConnections > 0)
  798. {
  799. DBGASSERT((NULL != m_rgConnections));
  800. *pConnections = m_rgConnections[m_iCurrent++];
  801. if (NULL != pConnections->pUnk)
  802. {
  803. pConnections->pUnk->AddRef();
  804. pConnections++;
  805. cCreated++;
  806. cConnections--;
  807. }
  808. }
  809. //
  810. // If requested, return the count of items enumerated.
  811. //
  812. if (NULL != pcCreated)
  813. *pcCreated = cCreated;
  814. if (cConnections > 0)
  815. {
  816. //
  817. // Less than requested number of connections were retrieved.
  818. //
  819. hr = S_FALSE;
  820. while(cConnections > 0)
  821. {
  822. //
  823. // Set any un-filled array elements to NULL.
  824. //
  825. pConnections->pUnk = NULL;
  826. pConnections->dwCookie = 0;
  827. pConnections++;
  828. cConnections--;
  829. }
  830. }
  831. return hr;
  832. }
  833. ///////////////////////////////////////////////////////////////////////////////
  834. /* Function: ConnectionEnum::Skip
  835. Description: Skips a specified number of connections in the enumeration.
  836. Arguments:
  837. cConnections - Number of connections to skip.
  838. Returns:
  839. S_OK - Success. Skipped number of requested items.
  840. S_FALSE - End of enumeration encountered. Skipped less than
  841. cConnections items.
  842. Revision History:
  843. Date Description Programmer
  844. -------- --------------------------------------------------- ----------
  845. 06/19/96 Initial creation. BrianAu
  846. */
  847. ///////////////////////////////////////////////////////////////////////////////
  848. STDMETHODIMP
  849. ConnectionEnum::Skip(
  850. DWORD cConnections
  851. )
  852. {
  853. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Skip")));
  854. while(m_iCurrent < m_cConnections && cConnections > 0)
  855. {
  856. m_iCurrent++;
  857. cConnections--;
  858. }
  859. return cConnections == 0 ? S_OK : S_FALSE;
  860. }
  861. ///////////////////////////////////////////////////////////////////////////////
  862. /* Function: ConnectionEnum::Reset
  863. Description: Resets the enumerator object so that the next call to Next()
  864. starts enumerating at the beginning of the enumeration.
  865. Arguments: None.
  866. Returns:
  867. S_OK - Success.
  868. Revision History:
  869. Date Description Programmer
  870. -------- --------------------------------------------------- ----------
  871. 06/19/96 Initial creation. BrianAu
  872. */
  873. ///////////////////////////////////////////////////////////////////////////////
  874. STDMETHODIMP
  875. ConnectionEnum::Reset(
  876. VOID
  877. )
  878. {
  879. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Reset")));
  880. m_iCurrent = 0;
  881. return S_OK;
  882. }
  883. ///////////////////////////////////////////////////////////////////////////////
  884. /* Function: ConnectionEnum::Clone
  885. Description: Creates a duplicate of the enumerator object and returns
  886. a pointer to the new object's IEnumConnections interface.
  887. Arguments:
  888. ppEnum - Address of interface pointer variable to accept the pointer
  889. to the new object's IEnumConnections interface.
  890. Returns:
  891. NOERROR - Success.
  892. E_OUTOFMEMORY - Insufficient memory to create new enumerator.
  893. E_INVALIDARG - ppEnum arg was NULL.
  894. E_UNEXPECTED - Exception caught while calling client code.
  895. Revision History:
  896. Date Description Programmer
  897. -------- --------------------------------------------------- ----------
  898. 06/19/96 Initial creation. BrianAu
  899. */
  900. ///////////////////////////////////////////////////////////////////////////////
  901. STDMETHODIMP
  902. ConnectionEnum::Clone(
  903. PENUMCONNECTIONS *ppEnum
  904. )
  905. {
  906. DBGTRACE((DM_CONNPT, DL_HIGH, TEXT("ConnectionEnum::Clone")));
  907. if (NULL == ppEnum)
  908. return E_INVALIDARG;
  909. HRESULT hr = NOERROR;
  910. ConnectionEnum *pEnum = NULL;
  911. *ppEnum = NULL;
  912. try
  913. {
  914. pEnum = new ConnectionEnum((const ConnectionEnum&)*this);
  915. hr = pEnum->QueryInterface(IID_IEnumConnections, (LPVOID *)ppEnum);
  916. }
  917. catch(CAllocException& e)
  918. {
  919. DBGERROR((TEXT("Insufficient memory exception")));
  920. hr = E_OUTOFMEMORY;
  921. }
  922. if (FAILED(hr) && NULL != pEnum)
  923. {
  924. delete pEnum;
  925. *ppEnum = NULL;
  926. }
  927. return hr;
  928. }
  929. ///////////////////////////////////////////////////////////////////////////////
  930. /* Function: ConnectionPointEnum::ConnectionPointEnum
  931. Description: Constructor,
  932. Arguments:
  933. pUnkContainer - Pointer to IUnknown of containing object.
  934. cConnPts - Number of connection points in array pointed to by rgConnPts.
  935. rgConnPts - Array of connection point object pointers used to
  936. initialize the enumerator.
  937. Returns: Nothing.
  938. Revision History:
  939. Date Description Programmer
  940. -------- --------------------------------------------------- ----------
  941. 06/19/96 Initial creation. BrianAu
  942. 09/06/96 Added copy constructor. BrianAu
  943. */
  944. ///////////////////////////////////////////////////////////////////////////////
  945. ConnectionPointEnum::ConnectionPointEnum(
  946. LPUNKNOWN pUnkContainer,
  947. UINT cConnPts,
  948. PCONNECTIONPOINT *rgConnPts
  949. ) : m_cRef(0),
  950. m_iCurrent(0),
  951. m_cConnPts(0),
  952. m_rgConnPts(NULL),
  953. m_pUnkContainer(pUnkContainer)
  954. {
  955. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::ConnectionPointEnum")));
  956. DBGASSERT((NULL != pUnkContainer));
  957. if (0 != cConnPts)
  958. {
  959. m_rgConnPts = new PCONNECTIONPOINT[cConnPts];
  960. m_cConnPts = cConnPts;
  961. for (UINT i = 0; i < m_cConnPts; i++)
  962. {
  963. m_rgConnPts[i] = rgConnPts[i];
  964. m_rgConnPts[i]->AddRef();
  965. }
  966. }
  967. }
  968. ConnectionPointEnum::ConnectionPointEnum(
  969. const ConnectionPointEnum& refEnum
  970. ) : m_cRef(0),
  971. m_iCurrent(0),
  972. m_cConnPts(0),
  973. m_rgConnPts(NULL),
  974. m_pUnkContainer(refEnum.m_pUnkContainer)
  975. {
  976. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::ConnectionPointEnum [copy]")));
  977. if (0 != refEnum.m_cConnPts)
  978. {
  979. m_rgConnPts = new PCONNECTIONPOINT[refEnum.m_cConnPts];
  980. m_cConnPts = refEnum.m_cConnPts;
  981. for (UINT i = 0; i < m_cConnPts; i++)
  982. {
  983. m_rgConnPts[i] = refEnum.m_rgConnPts[i];
  984. m_rgConnPts[i]->AddRef();
  985. }
  986. }
  987. }
  988. ///////////////////////////////////////////////////////////////////////////////
  989. /* Function: ConnectionPointEnum::~ConnectionPointEnum
  990. Description: Destructor. Releases all connection point object pointers
  991. held in enumerator's array.
  992. Arguments: None.
  993. Returns: Nothing.
  994. Revision History:
  995. Date Description Programmer
  996. -------- --------------------------------------------------- ----------
  997. 06/19/96 Initial creation. BrianAu
  998. */
  999. ///////////////////////////////////////////////////////////////////////////////
  1000. ConnectionPointEnum::~ConnectionPointEnum(
  1001. VOID
  1002. )
  1003. {
  1004. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::~ConnectionPointEnum")));
  1005. if (NULL != m_rgConnPts)
  1006. {
  1007. for (UINT i = 0; i < m_cConnPts; i++)
  1008. {
  1009. if (NULL != m_rgConnPts[i])
  1010. {
  1011. m_rgConnPts[i]->Release();
  1012. m_rgConnPts[i] = NULL;
  1013. }
  1014. }
  1015. delete[] m_rgConnPts;
  1016. }
  1017. }
  1018. ///////////////////////////////////////////////////////////////////////////////
  1019. /* Function: ConnectionPointEnum::QueryInterface
  1020. Description: Returns an interface pointer to the object's IUnknown or
  1021. IEnumConnectionPoints interface. Only IID_IUnknown and
  1022. IID_IEnumConnectionPoints are recognized. The object referenced by the
  1023. returned interface pointer is uninitialized. The recipient of the
  1024. pointer must call Initialize() before the object is usable.
  1025. Arguments:
  1026. riid - Reference to requested interface ID.
  1027. ppvOut - Address of interface pointer variable to accept interface ptr.
  1028. Returns:
  1029. NOERROR - Success.
  1030. E_NOINTERFACE - Requested interface not supported.
  1031. E_INVALIDARG - ppvOut argument was NULL.
  1032. Revision History:
  1033. Date Description Programmer
  1034. -------- --------------------------------------------------- ----------
  1035. 06/18/96 Initial creation. BrianAu
  1036. */
  1037. ///////////////////////////////////////////////////////////////////////////////
  1038. STDMETHODIMP
  1039. ConnectionPointEnum::QueryInterface(
  1040. REFIID riid,
  1041. LPVOID *ppvOut
  1042. )
  1043. {
  1044. DBGTRACE((DM_CONNPT, DL_MID, TEXT("ConnectionPointEnum::QueryInterface")));
  1045. DBGPRINTIID(DM_CONNPT, DL_MID, riid);
  1046. HRESULT hr = E_NOINTERFACE;
  1047. if (NULL == ppvOut)
  1048. return E_INVALIDARG;
  1049. *ppvOut = NULL;
  1050. if (IID_IUnknown == riid || IID_IEnumConnectionPoints == riid)
  1051. {
  1052. *ppvOut = this;
  1053. ((LPUNKNOWN)*ppvOut)->AddRef();
  1054. hr = NOERROR;
  1055. }
  1056. return hr;
  1057. }
  1058. ///////////////////////////////////////////////////////////////////////////////
  1059. /* Function: ConnectionPointEnum::AddRef
  1060. Description: Increments object reference count.
  1061. Arguments: None.
  1062. Returns: New reference count value.
  1063. Revision History:
  1064. Date Description Programmer
  1065. -------- --------------------------------------------------- ----------
  1066. 06/18/96 Initial creation. BrianAu
  1067. */
  1068. ///////////////////////////////////////////////////////////////////////////////
  1069. STDMETHODIMP_(ULONG)
  1070. ConnectionPointEnum::AddRef(
  1071. VOID
  1072. )
  1073. {
  1074. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::AddRef")));
  1075. DBGPRINT((DM_CONNPT, DL_LOW, TEXT("\t0x%08X %d -> %d\n"),
  1076. this, m_cRef, m_cRef + 1));
  1077. ULONG ulReturn = m_cRef + 1;
  1078. //
  1079. // Increment ref count of QuotaController so that it stays around
  1080. // while the enumerator is alive.
  1081. //
  1082. m_pUnkContainer->AddRef();
  1083. InterlockedIncrement(&m_cRef);
  1084. return ulReturn;
  1085. }
  1086. ///////////////////////////////////////////////////////////////////////////////
  1087. /* Function: ConnectionPointEnum::Release
  1088. Description: Decrements object reference count. If count drops to 0,
  1089. object is deleted.
  1090. Arguments: None.
  1091. Returns: New reference count value.
  1092. Revision History:
  1093. Date Description Programmer
  1094. -------- --------------------------------------------------- ----------
  1095. 06/18/96 Initial creation. BrianAu
  1096. */
  1097. ///////////////////////////////////////////////////////////////////////////////
  1098. STDMETHODIMP_(ULONG)
  1099. ConnectionPointEnum::Release(
  1100. VOID
  1101. )
  1102. {
  1103. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Release")));
  1104. DBGPRINT((DM_COM, DL_HIGH, TEXT("\t0x%08X %d -> %d\n"),
  1105. this, m_cRef, m_cRef - 1));
  1106. ULONG ulReturn = m_cRef - 1;
  1107. //
  1108. // Decrement ref count of QuotaController. We AddRef'd it above.
  1109. //
  1110. m_pUnkContainer->Release();
  1111. if (InterlockedDecrement(&m_cRef) == 0)
  1112. {
  1113. delete this;
  1114. ulReturn = 0;
  1115. }
  1116. return ulReturn;
  1117. }
  1118. ///////////////////////////////////////////////////////////////////////////////
  1119. /* Function: ConnectionPointEnum::Next
  1120. Description: Retrieve the next cConnPts connections supported by
  1121. the enumerator.
  1122. Arguments:
  1123. cConnPts - Number of elements in pConnPts array.
  1124. pConnPts - Array to receive PCONNECTIONPOINT pointers.
  1125. pcCreated [optional] - Address of DWORD to accept the count of records
  1126. returned in pConnPts. Note that any array locations equal to or
  1127. beyond the value returned in pcCreated are invalid and set to NULL.
  1128. Returns:
  1129. S_OK - Success. Enumerated number of requested connection pts.
  1130. S_FALSE - End of enumeration encountered. Returning less than
  1131. cConnPts records.
  1132. E_INVALIDARG - pConnPts arg is NULL.
  1133. Revision History:
  1134. Date Description Programmer
  1135. -------- --------------------------------------------------- ----------
  1136. 06/19/96 Initial creation. BrianAu
  1137. */
  1138. ///////////////////////////////////////////////////////////////////////////////
  1139. HRESULT
  1140. ConnectionPointEnum::Next(
  1141. DWORD cConnPts, // Number of elements in array.
  1142. PCONNECTIONPOINT *rgpConnPts, // Dest array for connection point ptrs.
  1143. DWORD *pcCreated // Return number created.
  1144. )
  1145. {
  1146. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Next")));
  1147. if (NULL == rgpConnPts)
  1148. return E_INVALIDARG;
  1149. HRESULT hr = S_OK;
  1150. DWORD cCreated = 0;
  1151. //
  1152. // Transfer data to caller's array.
  1153. // Stop when at the end of the enumeration or we've
  1154. // returned all that the caller asked for.
  1155. //
  1156. while(m_iCurrent < m_cConnPts && cConnPts > 0)
  1157. {
  1158. *rgpConnPts = m_rgConnPts[m_iCurrent++];
  1159. if (NULL != *rgpConnPts)
  1160. {
  1161. (*rgpConnPts)->AddRef();
  1162. rgpConnPts++;
  1163. cCreated++;
  1164. cConnPts--;
  1165. }
  1166. else
  1167. DBGASSERT((FALSE)); // Shouldn't hit this.
  1168. }
  1169. //
  1170. // If requested, return the count of items enumerated.
  1171. //
  1172. if (NULL != pcCreated)
  1173. *pcCreated = cCreated;
  1174. if (cConnPts > 0)
  1175. {
  1176. //
  1177. // Less than requested number of connections were retrieved.
  1178. //
  1179. hr = S_FALSE;
  1180. while(cConnPts > 0)
  1181. {
  1182. //
  1183. // Set any un-filled array elements to NULL.
  1184. //
  1185. *rgpConnPts = NULL;
  1186. rgpConnPts++;
  1187. cConnPts--;
  1188. }
  1189. }
  1190. return hr;
  1191. }
  1192. ///////////////////////////////////////////////////////////////////////////////
  1193. /* Function: ConnectionPointEnum::Skip
  1194. Description: Skips a specified number of connection pts in the enumeration.
  1195. Arguments:
  1196. cConnPts - Number of connection points to skip.
  1197. Returns:
  1198. S_OK - Success. Skipped number of requested items.
  1199. S_FALSE - End of enumeration encountered. Skipped less than
  1200. cConnPts items.
  1201. Revision History:
  1202. Date Description Programmer
  1203. -------- --------------------------------------------------- ----------
  1204. 06/19/96 Initial creation. BrianAu
  1205. */
  1206. ///////////////////////////////////////////////////////////////////////////////
  1207. STDMETHODIMP
  1208. ConnectionPointEnum::Skip(
  1209. DWORD cConnPts
  1210. )
  1211. {
  1212. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Skip")));
  1213. while(m_iCurrent < m_cConnPts && cConnPts > 0)
  1214. {
  1215. m_iCurrent++;
  1216. cConnPts--;
  1217. }
  1218. return cConnPts == 0 ? S_OK : S_FALSE;
  1219. }
  1220. ///////////////////////////////////////////////////////////////////////////////
  1221. /* Function: ConnectionPointEnum::Reset
  1222. Description: Resets the enumerator object so that the next call to Next()
  1223. starts enumerating at the start of the enumeration.
  1224. Arguments: None.
  1225. Returns:
  1226. S_OK - Success.
  1227. Revision History:
  1228. Date Description Programmer
  1229. -------- --------------------------------------------------- ----------
  1230. 06/19/96 Initial creation. BrianAu
  1231. */
  1232. ///////////////////////////////////////////////////////////////////////////////
  1233. STDMETHODIMP
  1234. ConnectionPointEnum::Reset(
  1235. VOID
  1236. )
  1237. {
  1238. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Reset")));
  1239. m_iCurrent = 0;
  1240. return S_OK;
  1241. }
  1242. ///////////////////////////////////////////////////////////////////////////////
  1243. /* Function: ConnectionPointEnum::Clone
  1244. Description: Creates a duplicate of the enumerator object and returns
  1245. a pointer to the new object's IEnumConnectionPoints interface.
  1246. Arguments:
  1247. ppEnum - Address of interface pointer variable to accept the pointer
  1248. to the new object's IEnumConnectionPoints interface.
  1249. Returns:
  1250. NOERROR - Success.
  1251. E_OUTOFMEMORY - Insufficient memory to create new enumerator.
  1252. E_INVALIDARG - ppEnum arg was NULL.
  1253. E_UNEXPECTED - Unexpected exception.
  1254. Revision History:
  1255. Date Description Programmer
  1256. -------- --------------------------------------------------- ----------
  1257. 06/19/96 Initial creation. BrianAu
  1258. */
  1259. ///////////////////////////////////////////////////////////////////////////////
  1260. STDMETHODIMP
  1261. ConnectionPointEnum::Clone(
  1262. PENUMCONNECTIONPOINTS *ppEnum
  1263. )
  1264. {
  1265. DBGTRACE((DM_CONNPT, DL_LOW, TEXT("ConnectionPointEnum::Clone")));
  1266. if (NULL == ppEnum)
  1267. return E_INVALIDARG;
  1268. HRESULT hr = NOERROR;
  1269. ConnectionPointEnum *pEnum = NULL;
  1270. try
  1271. {
  1272. *ppEnum = NULL;
  1273. pEnum = new ConnectionPointEnum((const ConnectionPointEnum&)*this);
  1274. hr = pEnum->QueryInterface(IID_IEnumConnectionPoints, (LPVOID *)ppEnum);
  1275. }
  1276. catch(CAllocException& e)
  1277. {
  1278. DBGERROR((TEXT("Insufficient memory exception")));
  1279. hr = E_OUTOFMEMORY;
  1280. }
  1281. if (FAILED(hr) && NULL != pEnum)
  1282. {
  1283. delete pEnum;
  1284. *ppEnum = NULL;
  1285. }
  1286. return hr;
  1287. }