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.

409 lines
8.3 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. rndcoll.h
  5. Abstract:
  6. Definitions for CRendezvous collection template class.
  7. --*/
  8. #ifndef __RENDCOLL_H
  9. #define __RENDCOLL_H
  10. #include "tapi3if.h"
  11. #include "rndobjsf.h"
  12. EXTERN_C const IID LIBID_TAPI3Lib;
  13. template <class T>
  14. class ATL_NO_VTABLE TInterfaceCollection :
  15. public CComObjectRootEx<CComMultiThreadModel>,
  16. public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
  17. public CObjectSafeImpl
  18. {
  19. public:
  20. TInterfaceCollection()
  21. : m_Var(NULL), m_nSize(0), m_pFTM(NULL) {}
  22. ~TInterfaceCollection()
  23. {
  24. delete [] m_Var;
  25. if ( m_pFTM )
  26. {
  27. m_pFTM->Release();
  28. }
  29. }
  30. typedef TInterfaceCollection<T> _TCollection;
  31. DECLARE_GET_CONTROLLING_UNKNOWN()
  32. BEGIN_COM_MAP(_TCollection)
  33. COM_INTERFACE_ENTRY(IDispatch)
  34. COM_INTERFACE_ENTRY(ITCollection)
  35. COM_INTERFACE_ENTRY(IObjectSafety)
  36. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  37. END_COM_MAP()
  38. private:
  39. // Array of Dispatch pointers.
  40. CComVariant* m_Var ;
  41. long m_nSize;
  42. IUnknown * m_pFTM; // pointer to the free threaded marshaler
  43. public:
  44. HRESULT Initialize (long nSize, T* begin, T* end);
  45. // ICollection methods
  46. STDMETHOD (get_Count) (OUT long* retval);
  47. STDMETHOD (get_Item) (IN long Index, OUT VARIANT* retval);
  48. STDMETHOD (get__NewEnum)(IUnknown** retval);
  49. };
  50. template <class T>
  51. HRESULT
  52. TInterfaceCollection<T>::Initialize (long nSize, T* begin, T* end)
  53. {
  54. if ( nSize < 0 )
  55. {
  56. return E_INVALIDARG;
  57. }
  58. HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
  59. & m_pFTM );
  60. if ( FAILED(hr) )
  61. {
  62. LOG((MSP_INFO, "CTInterfaceCollection::Initialize - "
  63. "create FTM returned 0x%08x; exit", hr));
  64. return hr;
  65. }
  66. if (NULL == (m_Var = new CComVariant[nSize]))
  67. {
  68. return E_OUTOFMEMORY;
  69. }
  70. m_nSize = nSize;
  71. DWORD i = 0;
  72. for (T *iter = begin; iter != end; iter ++, i ++)
  73. {
  74. // get IDispatch pointer
  75. IDispatch * pDisp;
  76. hr = (*iter)->QueryInterface(IID_IDispatch, (void**)&pDisp);
  77. if (S_OK != hr) return hr;
  78. V_VT(&m_Var[i]) = VT_DISPATCH;
  79. V_DISPATCH(&m_Var[i]) = pDisp;
  80. }
  81. return S_OK;
  82. }
  83. template <class T>
  84. STDMETHODIMP
  85. TInterfaceCollection<T>::get_Count(OUT long* retval)
  86. {
  87. if ( IsBadWritePtr(retval, sizeof(long) ) )
  88. {
  89. return E_POINTER;
  90. }
  91. *retval = m_nSize;
  92. return S_OK;
  93. }
  94. template <class T>
  95. STDMETHODIMP
  96. TInterfaceCollection<T>::get_Item(IN long Index, OUT VARIANT* retval)
  97. {
  98. if ( IsBadWritePtr(retval, sizeof(VARIANT) ) )
  99. {
  100. return E_POINTER;
  101. }
  102. retval->vt = VT_UNKNOWN;
  103. retval->punkVal = NULL;
  104. // use 1-based index, VB like
  105. if ((Index < 1) || (Index > m_nSize))
  106. {
  107. return E_INVALIDARG;
  108. }
  109. VariantCopy(retval, &m_Var[Index-1]);
  110. return S_OK;
  111. }
  112. template <class T>
  113. STDMETHODIMP
  114. TInterfaceCollection<T>::get__NewEnum(IUnknown** retval)
  115. {
  116. if ( IsBadWritePtr(retval, sizeof( IUnknown * ) ) )
  117. {
  118. return E_POINTER;
  119. }
  120. *retval = NULL;
  121. typedef CComObject<CSafeComEnum<IEnumVARIANT,
  122. &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
  123. enumvar* p; // = new enumvar;
  124. enumvar::CreateInstance( &p );
  125. if (p == NULL)
  126. {
  127. return E_OUTOFMEMORY;
  128. }
  129. HRESULT hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy);
  130. if (SUCCEEDED(hr))
  131. {
  132. hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
  133. }
  134. else
  135. {
  136. delete p;
  137. }
  138. return hr;
  139. }
  140. class ATL_NO_VTABLE TBstrCollection :
  141. public CComObjectRootEx<CComMultiThreadModel>,
  142. public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
  143. public CObjectSafeImpl
  144. {
  145. public:
  146. TBstrCollection()
  147. : m_Var(NULL), m_nSize(0), m_pFTM(NULL) {}
  148. ~TBstrCollection()
  149. {
  150. delete [] m_Var;
  151. if ( m_pFTM )
  152. {
  153. m_pFTM->Release();
  154. }
  155. }
  156. DECLARE_GET_CONTROLLING_UNKNOWN()
  157. BEGIN_COM_MAP(TBstrCollection)
  158. COM_INTERFACE_ENTRY(IDispatch)
  159. COM_INTERFACE_ENTRY(ITCollection)
  160. COM_INTERFACE_ENTRY(IObjectSafety)
  161. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  162. END_COM_MAP()
  163. private:
  164. // Array of Dispatch pointers.
  165. CComVariant* m_Var ;
  166. long m_nSize;
  167. IUnknown * m_pFTM; // pointer to the free threaded marshaler
  168. public:
  169. inline HRESULT Initialize (long nSize, BSTR* begin, BSTR* end, CComEnumFlags flags);
  170. // ITCollection methods
  171. inline STDMETHOD (get_Count) (OUT long* retval);
  172. inline STDMETHOD (get_Item) (IN long Index, OUT VARIANT* retval);
  173. inline STDMETHOD (get__NewEnum)(IUnknown** retval);
  174. };
  175. inline
  176. HRESULT
  177. TBstrCollection::Initialize (long nSize, BSTR * begin, BSTR * end, CComEnumFlags flags)
  178. {
  179. if ( nSize < 0 )
  180. {
  181. return E_INVALIDARG;
  182. }
  183. HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
  184. & m_pFTM );
  185. if ( FAILED(hr) )
  186. {
  187. LOG((MSP_INFO, "TCollectionCollection::Initialize - "
  188. "create FTM returned 0x%08x; exit", hr));
  189. return hr;
  190. }
  191. if (NULL == (m_Var = new CComVariant[nSize]))
  192. {
  193. return E_OUTOFMEMORY;
  194. }
  195. m_nSize = nSize;
  196. DWORD i = 0;
  197. for (BSTR * iter = begin; iter != end; iter ++, i ++)
  198. {
  199. m_Var[i].vt = VT_BSTR;
  200. switch (flags)
  201. {
  202. case AtlFlagNoCopy:
  203. case AtlFlagTakeOwnership :
  204. m_Var[i].bstrVal = (*iter);
  205. break;
  206. case AtlFlagCopy:
  207. m_Var[i].bstrVal = SysAllocString(*iter);
  208. if (m_Var[i].bstrVal == NULL)
  209. {
  210. return E_OUTOFMEMORY;
  211. }
  212. break;
  213. }
  214. }
  215. if (AtlFlagTakeOwnership) delete begin;
  216. return S_OK;
  217. }
  218. inline
  219. STDMETHODIMP
  220. TBstrCollection::get_Count(OUT long* retval)
  221. {
  222. if ( IsBadWritePtr(retval, sizeof(long) ) )
  223. {
  224. return E_POINTER;
  225. }
  226. *retval = m_nSize;
  227. return S_OK;
  228. }
  229. inline
  230. STDMETHODIMP
  231. TBstrCollection::get_Item(IN long Index, OUT VARIANT* retval)
  232. {
  233. if ( IsBadWritePtr(retval, sizeof(VARIANT) ) )
  234. {
  235. return E_POINTER;
  236. }
  237. retval->vt = VT_UNKNOWN;
  238. retval->punkVal = NULL;
  239. // use 1-based index, VB like
  240. if ((Index < 1) || (Index > m_nSize))
  241. {
  242. return E_INVALIDARG;
  243. }
  244. VariantCopy(retval, &m_Var[Index-1]);
  245. return S_OK;
  246. }
  247. inline
  248. STDMETHODIMP
  249. TBstrCollection::get__NewEnum(IUnknown** retval)
  250. {
  251. if ( IsBadWritePtr(retval, sizeof( IUnknown * ) ) )
  252. {
  253. return E_POINTER;
  254. }
  255. *retval = NULL;
  256. typedef CComObject<CSafeComEnum<IEnumVARIANT,
  257. &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
  258. enumvar* p; // = new enumvar;
  259. enumvar::CreateInstance( &p );
  260. if (p == NULL)
  261. {
  262. return E_OUTOFMEMORY;
  263. }
  264. HRESULT hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy);
  265. if (SUCCEEDED(hr))
  266. {
  267. hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
  268. }
  269. else
  270. {
  271. delete p;
  272. }
  273. return hr;
  274. }
  275. template <class T>
  276. HRESULT CreateInterfaceCollection(
  277. IN long nSize,
  278. IN T * begin,
  279. IN T * end,
  280. OUT VARIANT * pVariant
  281. )
  282. {
  283. // create the collection object
  284. typedef TInterfaceCollection<T> CCollection;
  285. CComObject<CCollection> * p;
  286. HRESULT hr = CComObject<CCollection>::CreateInstance( &p );
  287. if (NULL == p)
  288. {
  289. LOG((MSP_ERROR, "Could not create Collection object, %x",hr));
  290. return hr;
  291. }
  292. hr = p->Initialize(nSize, begin, end);
  293. if (S_OK != hr)
  294. {
  295. LOG((MSP_ERROR, "Could not initialize Collection object, %x", hr));
  296. delete p;
  297. return hr;
  298. }
  299. IDispatch *pDisp;
  300. // get the IDispatch interface
  301. hr = p->_InternalQueryInterface(IID_IDispatch, (void **)&pDisp);
  302. if (S_OK != hr)
  303. {
  304. LOG((MSP_ERROR, "QI for IDispatch in CreateCollection, %x", hr));
  305. delete p;
  306. return hr;
  307. }
  308. // put it in the variant
  309. VariantInit(pVariant);
  310. V_VT(pVariant) = VT_DISPATCH;
  311. V_DISPATCH(pVariant) = pDisp;
  312. return S_OK;
  313. }
  314. #endif