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.

1217 lines
28 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. enum.h
  5. Abstract:
  6. Template classes for enumerations in TAPI3
  7. Author:
  8. mquinton 06-12-97
  9. Notes:
  10. Revision History:
  11. --*/
  12. #ifndef __ENUM_H_
  13. #define __ENUM_H_
  14. #include "resource.h" // main symbols
  15. #include <mspenum.h> // for CSafeComEnum
  16. //////////////////////////////////////////////////////////////////////
  17. // CTapiEnum
  18. // Template class for enumerations in TAPI3.
  19. //////////////////////////////////////////////////////////////////////
  20. template <class Base, class T, const IID* piid> class CTapiEnum :
  21. public Base,
  22. public CTAPIComObjectRoot<Base>
  23. {
  24. public:
  25. typedef CTapiEnum<Base, T, piid> _CTapiEnumBase;
  26. DECLARE_MARSHALQI(CTapiEnum)
  27. DECLARE_TRACELOG_CLASS(CTapiEnum)
  28. BEGIN_COM_MAP(_CTapiEnumBase)
  29. COM_INTERFACE_ENTRY_IID(*piid, _CTapiEnumBase)
  30. COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI)
  31. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  32. END_COM_MAP()
  33. protected:
  34. CTObjectArray<T*> m_Array;
  35. int m_iCurrentLocation;
  36. public:
  37. // initialize the enumerator with a list<T*>
  38. HRESULT Initialize(
  39. CTObjectArray<T*> array
  40. )
  41. {
  42. int iSize, iCount;
  43. iSize = array.GetSize();
  44. for( iCount = 0; iCount < iSize; iCount++ )
  45. {
  46. m_Array.Add(array[iCount]);
  47. }
  48. m_iCurrentLocation = 0;
  49. this->AddRef();
  50. return S_OK;
  51. }
  52. // overloaded
  53. HRESULT Initialize(
  54. CTArray<T*> array
  55. )
  56. {
  57. int iSize, iCount;
  58. iSize = array.GetSize();
  59. for( iCount = 0; iCount < iSize; iCount++ )
  60. {
  61. m_Array.Add(array[iCount]);
  62. }
  63. m_iCurrentLocation = 0;
  64. this->AddRef();
  65. return S_OK;
  66. }
  67. // Overloaded function, used with Add to build enum list manually
  68. HRESULT Initialize( )
  69. {
  70. m_iCurrentLocation = 0;
  71. this->AddRef();
  72. return S_OK;
  73. }
  74. // Add - used with non-parameterized initialize() to build enum list manually
  75. HRESULT Add( T* t)
  76. {
  77. m_Array.Add( t );
  78. return S_OK;
  79. }
  80. // FinalRelease - release the objects that were addreffed in
  81. // initialize
  82. void FinalRelease()
  83. {
  84. m_Array.Shutdown();
  85. }
  86. // standard Next method
  87. HRESULT STDMETHODCALLTYPE Next(
  88. ULONG celt,
  89. T ** ppElements,
  90. ULONG* pceltFetched
  91. )
  92. {
  93. DWORD dwCount = 0;
  94. HRESULT hr = S_OK;
  95. if ((NULL == ppElements) || (NULL == pceltFetched && celt > 1))
  96. {
  97. return E_POINTER;
  98. }
  99. // special case
  100. if (celt == 0)
  101. {
  102. return E_INVALIDARG;
  103. }
  104. if (TAPIIsBadWritePtr( ppElements, celt * sizeof(T*)) )
  105. {
  106. return E_POINTER;
  107. }
  108. if ( ( NULL != pceltFetched) &&
  109. TAPIIsBadWritePtr( pceltFetched, sizeof (ULONG) ) )
  110. {
  111. return E_POINTER;
  112. }
  113. // iterator over elements
  114. while ((m_iCurrentLocation != m_Array.GetSize()) && (dwCount < celt))
  115. {
  116. ppElements[dwCount] = m_Array[m_iCurrentLocation];
  117. ppElements[dwCount]->AddRef();
  118. m_iCurrentLocation++;
  119. dwCount++;
  120. }
  121. if (NULL != pceltFetched)
  122. {
  123. *pceltFetched = dwCount;
  124. }
  125. // indicate that we've reached the end
  126. // of the enumeration.
  127. if (dwCount < celt)
  128. {
  129. return S_FALSE;
  130. }
  131. return S_OK;
  132. }
  133. // standard Reset method
  134. HRESULT STDMETHODCALLTYPE Reset( void )
  135. {
  136. m_iCurrentLocation = 0;
  137. return S_OK;
  138. }
  139. // standard Skip method
  140. HRESULT STDMETHODCALLTYPE Skip(
  141. ULONG celt
  142. )
  143. {
  144. long lCount = 0;
  145. while ( (lCount < celt) && (m_iCurrentLocation < m_Array.GetSize() ) )
  146. {
  147. m_iCurrentLocation++;
  148. lCount++;
  149. }
  150. return S_OK;
  151. }
  152. // standard Clone method
  153. HRESULT STDMETHODCALLTYPE Clone(
  154. Base ** ppEnum
  155. )
  156. {
  157. HRESULT hr = S_OK;
  158. CComObject< _CTapiEnumBase > * pNewEnum;
  159. if (TAPIIsBadWritePtr( ppEnum, sizeof (Base *) ) )
  160. {
  161. return E_POINTER;
  162. }
  163. CComObject< _CTapiEnumBase >::CreateInstance(&pNewEnum);
  164. if (pNewEnum == NULL)
  165. {
  166. hr = E_OUTOFMEMORY;
  167. }
  168. else
  169. {
  170. pNewEnum->Initialize(m_Array);
  171. pNewEnum->m_iCurrentLocation = m_iCurrentLocation;
  172. *ppEnum = pNewEnum;
  173. }
  174. return hr;
  175. }
  176. };
  177. ////////////////////////////////////////////////////////////////////////
  178. // CTapiCollection
  179. // Collection template for TAPI3.0 collections
  180. ////////////////////////////////////////////////////////////////////////
  181. template <class T> class CTapiCollection :
  182. public CComDualImpl<ITCollection2, &IID_ITCollection2, &LIBID_TAPI3Lib>,
  183. public CTAPIComObjectRoot<T>,
  184. public CObjectSafeImpl
  185. {
  186. public:
  187. typedef CTapiCollection<T> _CTapiCollectionBase;
  188. DECLARE_MARSHALQI(CTapiCollection)
  189. DECLARE_TRACELOG_CLASS(CTapiCollection)
  190. BEGIN_COM_MAP(_CTapiCollectionBase)
  191. COM_INTERFACE_ENTRY(IDispatch)
  192. COM_INTERFACE_ENTRY(ITCollection)
  193. COM_INTERFACE_ENTRY(ITCollection2)
  194. COM_INTERFACE_ENTRY(IObjectSafety)
  195. COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI)
  196. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  197. END_COM_MAP()
  198. private:
  199. int m_nSize;
  200. CComVariant * m_Var;
  201. public:
  202. CTapiCollection() : m_nSize(0),
  203. m_Var(NULL)
  204. {}
  205. // initialize
  206. HRESULT STDMETHODCALLTYPE Initialize(
  207. CTObjectArray<T *> array
  208. )
  209. {
  210. int i;
  211. HRESULT hr;
  212. LOG((TL_TRACE, "Initialize - enter"));
  213. // create variant array
  214. m_nSize = array.GetSize();
  215. m_Var = new CComVariant[m_nSize];
  216. if (m_Var == NULL)
  217. {
  218. LOG((TL_ERROR, "Initialize - out of memory"));
  219. return E_OUTOFMEMORY;
  220. }
  221. for (i = 0; i < array.GetSize(); i++)
  222. {
  223. // get IDispatch pointer
  224. IDispatch * pDisp = NULL;
  225. hr = array[i]->QueryInterface(IID_IDispatch, (void**)&pDisp);
  226. if (S_OK != hr)
  227. {
  228. return hr;
  229. }
  230. // create a variant and add it to the collection
  231. CComVariant& var = m_Var[i];
  232. VariantInit(&var);
  233. var.vt = VT_DISPATCH;
  234. var.pdispVal = pDisp;
  235. }
  236. LOG((TL_TRACE, "Initialize - exit"));
  237. return S_OK;
  238. }
  239. // initialize
  240. HRESULT STDMETHODCALLTYPE Initialize(
  241. CTArray<T *> array
  242. )
  243. {
  244. int i;
  245. HRESULT hr;
  246. LOG((TL_TRACE, "Initialize - enter"));
  247. // create variant array
  248. m_nSize = array.GetSize();
  249. m_Var = new CComVariant[m_nSize];
  250. if (m_Var == NULL)
  251. {
  252. LOG((TL_ERROR, "Initialize - out of memory"));
  253. return E_OUTOFMEMORY;
  254. }
  255. for (i = 0; i < array.GetSize(); i++)
  256. {
  257. // get IDispatch pointer
  258. IDispatch * pDisp = NULL;
  259. hr = array[i]->QueryInterface(IID_IDispatch, (void**)&pDisp);
  260. if (S_OK != hr)
  261. {
  262. return hr;
  263. }
  264. // create a variant and add it to the collection
  265. CComVariant& var = m_Var[i];
  266. VariantInit(&var);
  267. var.vt = VT_DISPATCH;
  268. var.pdispVal = pDisp;
  269. }
  270. LOG((TL_TRACE, "Initialize - exit"));
  271. return S_OK;
  272. }
  273. void FinalRelease()
  274. {
  275. //
  276. // We "new"ed an array of objects -- delete the array and call
  277. // each object's destructor. Each destructor calls VariantClear,
  278. // which calls Release on each pointer.
  279. //
  280. if(m_Var != NULL)
  281. {
  282. delete [] m_Var;
  283. }
  284. }
  285. STDMETHOD(get_Count)(
  286. long* retval
  287. )
  288. {
  289. LOG((TL_TRACE, "get_Count - enter"));
  290. if ( TAPIIsBadWritePtr( retval, sizeof(long) ) )
  291. {
  292. return E_POINTER;
  293. }
  294. *retval = m_nSize;
  295. LOG((TL_TRACE, "get_Count - exit"));
  296. return S_OK;
  297. }
  298. STDMETHOD(get_Item)(
  299. long Index,
  300. VARIANT* retval
  301. )
  302. {
  303. LOG((TL_TRACE, "get_Item - enter"));
  304. if ( TAPIIsBadWritePtr (retval, sizeof(VARIANT) ) )
  305. {
  306. return E_POINTER;
  307. }
  308. VariantInit(retval);
  309. retval->vt = VT_UNKNOWN;
  310. retval->punkVal = NULL;
  311. // use 1-based index, VB like
  312. if ((Index < 1) || (Index > m_nSize))
  313. {
  314. return E_INVALIDARG;
  315. }
  316. VariantCopy(retval, &m_Var[Index-1]);
  317. LOG((TL_TRACE, "get_Item - exit"));
  318. return S_OK;
  319. }
  320. HRESULT STDMETHODCALLTYPE get__NewEnum(
  321. IUnknown** retval
  322. )
  323. {
  324. HRESULT hr;
  325. LOG((TL_TRACE, "new__Enum - enter"));
  326. if ( TAPIIsBadWritePtr( retval, sizeof( IUnknown * ) ) )
  327. {
  328. return E_POINTER;
  329. }
  330. *retval = NULL;
  331. typedef CComObject<CSafeComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
  332. enumvar* p; // = new enumvar;
  333. enumvar::CreateInstance( &p );
  334. _ASSERTE(p);
  335. if (p == NULL)
  336. {
  337. hr = E_OUTOFMEMORY;
  338. }
  339. else
  340. {
  341. hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy);
  342. if (SUCCEEDED(hr))
  343. {
  344. hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
  345. }
  346. if (FAILED(hr))
  347. {
  348. delete p;
  349. }
  350. }
  351. LOG((TL_TRACE, "new__Enum - exit"));
  352. return hr;
  353. }
  354. STDMETHOD(Add)(
  355. long Index,
  356. VARIANT* pVariant
  357. )
  358. {
  359. LOG((TL_TRACE, "Add - enter"));
  360. if ( IsBadReadPtr (pVariant, sizeof(VARIANT) ) )
  361. {
  362. return E_POINTER;
  363. }
  364. // use 1-based index, VB like
  365. if ( (Index < 1) || (Index > (m_nSize + 1)) )
  366. {
  367. return E_INVALIDARG;
  368. }
  369. CComVariant * newVar = NULL;
  370. newVar = new CComVariant[m_nSize + 1];
  371. if ( NULL == newVar )
  372. {
  373. LOG((TL_ERROR, "Add - out of memory"));
  374. return E_OUTOFMEMORY;
  375. }
  376. HRESULT hr;
  377. int i;
  378. // fill in the new array
  379. for ( i = 0; i < (m_nSize + 1); i++ )
  380. {
  381. VariantInit(&newVar[i]);
  382. if ( i < (Index - 1) )
  383. {
  384. // shouldn't reach this case unless there was an old array
  385. _ASSERTE(m_Var != NULL);
  386. hr = VariantCopy(&newVar[i], &m_Var[i]);
  387. }
  388. else if ( i == (Index - 1) )
  389. {
  390. // copy the new element
  391. hr = VariantCopy(&newVar[i], pVariant);
  392. }
  393. else
  394. {
  395. // shouldn't reach this case unless there was an old array
  396. _ASSERTE(m_Var != NULL);
  397. hr = VariantCopy(&newVar[i], &m_Var[i-1]);
  398. }
  399. if ( FAILED(hr) )
  400. {
  401. LOG((TL_ERROR, "Add - VariantCopy failed - %lx", hr));
  402. delete [] newVar;
  403. return hr;
  404. }
  405. }
  406. if ( m_Var != NULL)
  407. {
  408. // Delete the old array
  409. delete [] m_Var;
  410. }
  411. m_Var = newVar;
  412. m_nSize++;
  413. LOG((TL_TRACE, "Add - exit"));
  414. return S_OK;
  415. }
  416. STDMETHOD(Remove)(
  417. long Index
  418. )
  419. {
  420. LOG((TL_TRACE, "Remove - enter"));
  421. // use 1-based index, VB like
  422. if ( (Index < 1) || (Index > m_nSize) )
  423. {
  424. return E_INVALIDARG;
  425. }
  426. CComVariant * newVar = NULL;
  427. // if there is only one element in the array we don't need to do
  428. // any copying
  429. if (m_nSize > 1)
  430. {
  431. newVar = new CComVariant[m_nSize - 1];
  432. if ( NULL == newVar )
  433. {
  434. LOG((TL_ERROR, "Remove - out of memory"));
  435. return E_OUTOFMEMORY;
  436. }
  437. HRESULT hr;
  438. int i;
  439. // fill in the new array
  440. for ( i = 0; i < (m_nSize - 1); i++ )
  441. {
  442. VariantInit(&newVar[i]);
  443. if ( i < (Index - 1) )
  444. {
  445. // shouldn't reach this case unless there was an old array
  446. _ASSERTE(m_Var != NULL);
  447. hr = VariantCopy(&newVar[i], &m_Var[i]);
  448. }
  449. else
  450. {
  451. // shouldn't reach this case unless there was an old array
  452. _ASSERTE(m_Var != NULL);
  453. hr = VariantCopy(&newVar[i], &m_Var[i+1]);
  454. }
  455. if ( FAILED(hr) )
  456. {
  457. LOG((TL_ERROR, "Remove - VariantCopy failed - %lx", hr));
  458. delete [] newVar;
  459. return hr;
  460. }
  461. }
  462. }
  463. if ( m_Var != NULL)
  464. {
  465. // Delete the old array
  466. delete [] m_Var;
  467. }
  468. m_Var = newVar;
  469. m_nSize--;
  470. LOG((TL_TRACE, "Remove - exit"));
  471. return S_OK;
  472. }
  473. };
  474. ////////////////////////////////////////////////////////////////////////
  475. // CTapiBstrCollection
  476. // Collection of BSTRs.
  477. ////////////////////////////////////////////////////////////////////////
  478. class CTapiBstrCollection :
  479. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  480. public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
  481. public CObjectSafeImpl
  482. {
  483. public:
  484. DECLARE_TRACELOG_CLASS(CTapiBstrCollection)
  485. BEGIN_COM_MAP(CTapiBstrCollection)
  486. COM_INTERFACE_ENTRY(IDispatch)
  487. COM_INTERFACE_ENTRY(ITCollection)
  488. COM_INTERFACE_ENTRY(IObjectSafety)
  489. END_COM_MAP()
  490. private:
  491. DWORD m_dwSize;
  492. CComVariant * m_Var;
  493. public:
  494. CTapiBstrCollection(void) : m_dwSize(0), m_Var(NULL) { }
  495. // initialize
  496. HRESULT STDMETHODCALLTYPE Initialize(
  497. DWORD dwSize,
  498. BSTR * pBegin,
  499. BSTR * pEnd
  500. )
  501. {
  502. BSTR * i;
  503. DWORD dw = 0;
  504. LOG((TL_TRACE, "Initialize - enter"));
  505. // create variant array
  506. m_dwSize = dwSize;
  507. m_Var = new CComVariant[m_dwSize];
  508. if (m_Var == NULL)
  509. {
  510. // debug output
  511. return E_OUTOFMEMORY;
  512. }
  513. for (i = pBegin; i != pEnd; i++)
  514. {
  515. // create a variant and add it to the collection
  516. CComVariant& var = m_Var[dw];
  517. var.vt = VT_BSTR;
  518. var.bstrVal = *i;
  519. dw++;
  520. }
  521. LOG((TL_TRACE, "Initialize - exit"));
  522. return S_OK;
  523. }
  524. STDMETHOD(get_Count)(
  525. long* retval
  526. )
  527. {
  528. HRESULT hr = S_OK;
  529. LOG((TL_TRACE, "get_Count - enter"));
  530. try
  531. {
  532. *retval = m_dwSize;
  533. }
  534. catch(...)
  535. {
  536. hr = E_INVALIDARG;
  537. }
  538. LOG((TL_TRACE, "get_Count - exit"));
  539. return hr;
  540. }
  541. STDMETHOD(get_Item)(
  542. long Index,
  543. VARIANT* retval
  544. )
  545. {
  546. HRESULT hr = S_OK;
  547. LOG((TL_TRACE, "get_Item - enter"));
  548. if (retval == NULL)
  549. {
  550. return E_POINTER;
  551. }
  552. try
  553. {
  554. VariantInit(retval);
  555. }
  556. catch(...)
  557. {
  558. hr = E_INVALIDARG;
  559. }
  560. if (hr != S_OK)
  561. {
  562. return hr;
  563. }
  564. retval->vt = VT_BSTR;
  565. retval->bstrVal = NULL;
  566. // use 1-based index, VB like
  567. // no problem with signed/unsigned, since
  568. // if Index < 0 then first clause is true, making it
  569. // irrelevant if the second clause is correct or not.
  570. if ((Index < 1) || ( (DWORD) Index > m_dwSize))
  571. {
  572. return E_INVALIDARG;
  573. }
  574. //
  575. // This copies the string, not just the pointer.
  576. //
  577. VariantCopy(retval, &m_Var[Index-1]);
  578. LOG((TL_TRACE, "get_Item - exit"));
  579. return S_OK;
  580. }
  581. HRESULT STDMETHODCALLTYPE get__NewEnum(
  582. IUnknown** retval
  583. )
  584. {
  585. HRESULT hr;
  586. LOG((TL_TRACE, "get__NumEnum - enter"));
  587. if (retval == NULL)
  588. {
  589. return E_POINTER;
  590. }
  591. *retval = NULL;
  592. typedef CComObject<CSafeComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
  593. enumvar* p = new enumvar;
  594. if ( p == NULL)
  595. {
  596. // debug output
  597. return E_OUTOFMEMORY;
  598. }
  599. hr = p->Init(&m_Var[0], &m_Var[m_dwSize], NULL, AtlFlagCopy);
  600. if (SUCCEEDED(hr))
  601. {
  602. hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
  603. }
  604. if (FAILED(hr))
  605. {
  606. delete p;
  607. }
  608. LOG((TL_TRACE, "get__NewEnum - exit"));
  609. return hr;
  610. }
  611. void FinalRelease()
  612. {
  613. LOG((TL_TRACE, "FinalRelease() - enter"));
  614. //
  615. // We "new"ed an array of objects. Delete each object in the array. The
  616. // destructor for each object calls VariantClear to release the pointer
  617. // in that object, based on the variant's tag.
  618. //
  619. delete [] m_Var;
  620. LOG((TL_TRACE, "FinalRelease() - exit"));
  621. }
  622. };
  623. ////////////////////////////////////////////////////////////////////////
  624. // CTapiTypeEnum template - enumerate types & structures
  625. ////////////////////////////////////////////////////////////////////////
  626. template <class Base, class T, class Copy, const IID* piid> class CTapiTypeEnum :
  627. public Base,
  628. public CTAPIComObjectRoot<Base>
  629. {
  630. public:
  631. // *piid is the IID of the enumerator class being
  632. // created (like IID_IEnumAddressType)
  633. typedef CTapiTypeEnum<Base, T, Copy, piid> _CTapiTypeEnumBase;
  634. BEGIN_COM_MAP(_CTapiTypeEnumBase)
  635. COM_INTERFACE_ENTRY_IID(*piid, _CTapiTypeEnumBase)
  636. COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI)
  637. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  638. END_COM_MAP()
  639. DECLARE_QI()
  640. DECLARE_MARSHALQI(CTapiTypeEnum)
  641. DECLARE_TRACELOG_CLASS(CTapiTypeEnum)
  642. protected:
  643. CTArray<T> m_Array;
  644. int m_iCurrentLocation;
  645. public:
  646. //
  647. // initialize the enumerator
  648. //
  649. HRESULT Initialize(CTArray<T> array)
  650. {
  651. int iSize, iCount;
  652. iSize = array.GetSize();
  653. for (iCount = 0; iCount < iSize; iCount++ )
  654. {
  655. m_Array.Add(array[iCount]);
  656. }
  657. m_iCurrentLocation = 0;
  658. //
  659. // addref ourself
  660. //
  661. this->AddRef();
  662. return S_OK;
  663. }
  664. //
  665. // FinalRelease
  666. //
  667. void FinalRelease()
  668. {
  669. m_Array.Shutdown();
  670. }
  671. HRESULT STDMETHODCALLTYPE Next(
  672. ULONG celt,
  673. T * pElements,
  674. ULONG* pceltFetched
  675. )
  676. {
  677. DWORD dwCount = 0;
  678. if ((NULL == pElements) || (NULL == pceltFetched && celt > 1))
  679. {
  680. return E_POINTER;
  681. }
  682. //
  683. // special case
  684. //
  685. if (celt == 0)
  686. {
  687. return E_INVALIDARG;
  688. }
  689. if (TAPIIsBadWritePtr( pElements, celt * sizeof(T) ) )
  690. {
  691. return E_POINTER;
  692. }
  693. if ( (NULL != pceltFetched) &&
  694. TAPIIsBadWritePtr( pceltFetched, sizeof(ULONG) ) )
  695. {
  696. return E_POINTER;
  697. }
  698. //
  699. // iterator over elements and copy
  700. //
  701. while ((m_iCurrentLocation != m_Array.GetSize()) && (dwCount < celt))
  702. {
  703. Copy::copy(
  704. &(pElements[dwCount]),
  705. &(m_Array[m_iCurrentLocation])
  706. );
  707. m_iCurrentLocation++;
  708. dwCount++;
  709. }
  710. //
  711. // return number copied
  712. //
  713. if (NULL != pceltFetched)
  714. {
  715. *pceltFetched = dwCount;
  716. }
  717. //
  718. // indicate if we've reached the end
  719. // of the enumeration.
  720. //
  721. if (dwCount < celt)
  722. {
  723. return S_FALSE;
  724. }
  725. return S_OK;
  726. }
  727. HRESULT STDMETHODCALLTYPE Skip(
  728. ULONG celt
  729. )
  730. {
  731. long lCount = 0;
  732. while ( (lCount < celt) && (m_iCurrentLocation < m_Array.GetSize()) )
  733. {
  734. m_iCurrentLocation++;
  735. lCount++;
  736. }
  737. return S_OK;
  738. }
  739. HRESULT STDMETHODCALLTYPE Reset(void)
  740. {
  741. m_iCurrentLocation = 0;
  742. return S_OK;
  743. }
  744. HRESULT STDMETHODCALLTYPE Clone(
  745. Base ** ppEnum
  746. )
  747. {
  748. HRESULT hr = S_OK;
  749. CComObject< _CTapiTypeEnumBase > * pNewEnum;
  750. if (TAPIIsBadWritePtr( ppEnum, sizeof (Base *) ) )
  751. {
  752. return E_POINTER;
  753. }
  754. CComObject< _CTapiTypeEnumBase >::CreateInstance(&pNewEnum);
  755. if (pNewEnum == NULL)
  756. {
  757. hr = E_OUTOFMEMORY;
  758. }
  759. else
  760. {
  761. pNewEnum->Initialize(m_Array);
  762. pNewEnum->m_iCurrentLocation = m_iCurrentLocation;
  763. *ppEnum = pNewEnum;
  764. }
  765. return hr;
  766. }
  767. };
  768. ////////////////////////////////////////////////////////////////////////
  769. // CTerminalClassEnum
  770. ////////////////////////////////////////////////////////////////////////
  771. class CTerminalClassEnum :
  772. public IEnumTerminalClass,
  773. public CTAPIComObjectRoot<CTerminalClassEnum>
  774. {
  775. public:
  776. DECLARE_MARSHALQI(CTerminalClassEnum)
  777. DECLARE_TRACELOG_CLASS(CTerminalClassEnum)
  778. BEGIN_COM_MAP(CTerminalClassEnum)
  779. COM_INTERFACE_ENTRY(IEnumTerminalClass)
  780. COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI)
  781. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  782. END_COM_MAP()
  783. protected:
  784. TerminalClassPtrList m_list;
  785. TerminalClassPtrList::iterator m_iter;
  786. public:
  787. virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) = 0;
  788. virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
  789. virtual ULONG STDMETHODCALLTYPE Release() = 0;
  790. // initialize the enumerator
  791. HRESULT Initialize(
  792. TerminalClassPtrList List
  793. )
  794. {
  795. // copy the array
  796. m_list.clear();
  797. m_list.insert(m_list.begin(), List.begin(), List.end());
  798. m_iter = m_list.begin();
  799. this->AddRef();
  800. return S_OK;
  801. }
  802. // FinalRelease -- added by ZoltanS
  803. void FinalRelease(void)
  804. {
  805. // go through the list
  806. for ( m_iter = m_list.begin(); m_iter != m_list.end(); m_iter++ )
  807. {
  808. SysFreeString(*m_iter); // this is the real way to free a BSTR
  809. *m_iter = NULL; // destructor for list will delete(NULL)
  810. }
  811. }
  812. HRESULT STDMETHODCALLTYPE Next(
  813. ULONG celt,
  814. GUID * pElements,
  815. ULONG* pceltFetched
  816. )
  817. {
  818. DWORD dwCount = 0;
  819. HRESULT hr = S_OK;
  820. if ((NULL == pElements) || (NULL == pceltFetched && celt > 1))
  821. {
  822. return E_POINTER;
  823. }
  824. // special case
  825. if (celt == 0)
  826. {
  827. return E_INVALIDARG;
  828. }
  829. // iterator over elements
  830. try
  831. {
  832. while ( (m_iter != m_list.end()) &&
  833. (dwCount < celt) )
  834. {
  835. hr = IIDFromString( *m_iter, &(pElements[dwCount]) );
  836. if (!SUCCEEDED(hr))
  837. {
  838. break;
  839. }
  840. m_iter++;
  841. dwCount++;
  842. }
  843. }
  844. catch(...)
  845. {
  846. hr = E_INVALIDARG;
  847. }
  848. if (S_OK != hr)
  849. {
  850. return hr;
  851. }
  852. if (NULL != pceltFetched)
  853. {
  854. try
  855. {
  856. *pceltFetched = dwCount;
  857. }
  858. catch(...)
  859. {
  860. hr = E_INVALIDARG;
  861. }
  862. }
  863. if (S_OK != hr)
  864. {
  865. return hr;
  866. }
  867. // indicate that we've reached the end
  868. // of the enumeration.
  869. if (dwCount < celt)
  870. {
  871. return S_FALSE;
  872. }
  873. return S_OK;
  874. }
  875. HRESULT STDMETHODCALLTYPE Skip(
  876. ULONG celt
  877. )
  878. {
  879. long lCount = 0;
  880. while ( (lCount < celt) && (m_iter != m_list.end()) )
  881. {
  882. m_iter++;
  883. lCount++;
  884. }
  885. // check to see if we reached the end
  886. if (lCount != celt)
  887. {
  888. return S_OK;
  889. }
  890. return S_OK;
  891. }
  892. HRESULT STDMETHODCALLTYPE Reset(void)
  893. {
  894. m_iter = m_list.begin();
  895. return S_OK;
  896. }
  897. HRESULT STDMETHODCALLTYPE Clone(
  898. IEnumTerminalClass ** ppEnum
  899. )
  900. {
  901. HRESULT hr = S_OK;
  902. CComObject< CTerminalClassEnum > * pNewEnum;
  903. CComObject< CTerminalClassEnum >::CreateInstance(&pNewEnum);
  904. if (pNewEnum == NULL)
  905. {
  906. hr = E_OUTOFMEMORY;
  907. }
  908. else
  909. {
  910. pNewEnum->Initialize( m_list );
  911. try
  912. {
  913. *ppEnum = pNewEnum;
  914. }
  915. catch(...)
  916. {
  917. hr = E_INVALIDARG;
  918. }
  919. }
  920. return hr;
  921. }
  922. };
  923. #endif // __ENUM_H__