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.

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