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.

440 lines
10 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. */
  4. #ifndef _MSPCOLL_H_
  5. #define _MSPCOLL_H_
  6. ////////////////////////////////////////////////////////////////////////
  7. // CTapiIfCollection -- adapted from tapi3 code
  8. // Collection template for collections of IDispatch interfaces
  9. //
  10. ////////////////////////////////////////////////////////////////////////
  11. template <class T> class CTapiIfCollection :
  12. public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
  13. public CComObjectRootEx<CComMultiThreadModelNoCS>
  14. {
  15. public:
  16. typedef CTapiIfCollection<T> _CTapiCollectionBase;
  17. BEGIN_COM_MAP(_CTapiCollectionBase)
  18. COM_INTERFACE_ENTRY(IDispatch)
  19. COM_INTERFACE_ENTRY(ITCollection)
  20. END_COM_MAP()
  21. private:
  22. int m_nSize;
  23. CComVariant * m_Var;
  24. public:
  25. CTapiIfCollection(void) : m_nSize(0), m_Var(NULL) { }
  26. // initialize
  27. HRESULT STDMETHODCALLTYPE Initialize(
  28. DWORD dwSize,
  29. T * pBegin,
  30. T * pEnd
  31. )
  32. {
  33. int i;
  34. HRESULT hr;
  35. T * iter;
  36. LOG((MSP_TRACE, "CTapiCollection::Initialize - enter"));
  37. // create variant array
  38. m_nSize = dwSize;
  39. m_Var = new CComVariant[m_nSize];
  40. if (m_Var == NULL)
  41. {
  42. // debug output
  43. return E_OUTOFMEMORY;
  44. }
  45. i = 0;
  46. for (iter = pBegin; iter != pEnd; iter++)
  47. {
  48. // get IDispatch pointer
  49. IDispatch * pDisp = NULL;
  50. hr = (*iter)->QueryInterface(IID_IDispatch, (void**)&pDisp);
  51. if (hr != S_OK)
  52. {
  53. return hr;
  54. }
  55. // create a variant and add it to the collection
  56. CComVariant& var = m_Var[i];
  57. VariantInit(&var);
  58. var.vt = VT_DISPATCH;
  59. var.pdispVal = pDisp;
  60. i++;
  61. }
  62. LOG((MSP_TRACE, "CTapiCollection::Initialize - exit"));
  63. return S_OK;
  64. }
  65. void FinalRelease()
  66. {
  67. LOG((MSP_TRACE, "CTapiCollection::FinalRelease - enter"));
  68. //
  69. // We "new"ed an array of objects. Delete each object in the array. The
  70. // destructor for each object calls VariantClear to release the pointer
  71. // in that object, based on the variant's tag.
  72. //
  73. delete [] m_Var;
  74. LOG((MSP_TRACE, "CTapiCollection::FinalRelease - exit"));
  75. }
  76. STDMETHOD(get_Count)(
  77. long* retval
  78. )
  79. {
  80. HRESULT hr = S_OK;
  81. LOG((MSP_TRACE, "CTapiCollection::get_Count - enter"));
  82. try
  83. {
  84. *retval = m_nSize;
  85. }
  86. catch(...)
  87. {
  88. hr = E_INVALIDARG;
  89. }
  90. LOG((MSP_TRACE, "CTapiCollection::get_Count - exit"));
  91. return hr;
  92. }
  93. STDMETHOD(get_Item)(
  94. long Index,
  95. VARIANT* retval
  96. )
  97. {
  98. HRESULT hr = S_OK;
  99. LOG((MSP_TRACE, "CTapiCollection::get_Item - enter"));
  100. if (retval == NULL)
  101. {
  102. return E_POINTER;
  103. }
  104. try
  105. {
  106. VariantInit(retval);
  107. }
  108. catch(...)
  109. {
  110. hr = E_INVALIDARG;
  111. }
  112. if (hr != S_OK)
  113. {
  114. return hr;
  115. }
  116. retval->vt = VT_UNKNOWN;
  117. retval->punkVal = NULL;
  118. // use 1-based index, VB like
  119. if ((Index < 1) || (Index > m_nSize))
  120. {
  121. return E_INVALIDARG;
  122. }
  123. hr = VariantCopy(retval, &m_Var[Index-1]);
  124. if (FAILED(hr))
  125. {
  126. LOG((MSP_ERROR,
  127. "CTapiCollection::get_Item - VariantCopy failed. hr = %lx",
  128. hr));
  129. return hr;
  130. }
  131. LOG((MSP_TRACE, "CTapiCollection::get_Item - exit"));
  132. return S_OK;
  133. }
  134. HRESULT STDMETHODCALLTYPE get__NewEnum(
  135. IUnknown** retval
  136. )
  137. {
  138. HRESULT hr;
  139. LOG((MSP_TRACE, "CTapiCollection::new__Enum - enter"));
  140. if (retval == NULL)
  141. {
  142. return E_POINTER;
  143. }
  144. *retval = NULL;
  145. typedef CComObject<CSafeComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
  146. enumvar* p; // = new enumvar;
  147. hr = enumvar::CreateInstance( &p );
  148. if ( FAILED(hr) )
  149. {
  150. // debug output
  151. return hr;
  152. }
  153. hr = p->Init(&m_Var[0], &m_Var[m_nSize], NULL, AtlFlagCopy);
  154. if (SUCCEEDED(hr))
  155. {
  156. hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
  157. }
  158. if (FAILED(hr))
  159. {
  160. delete p;
  161. }
  162. LOG((MSP_TRACE, "CTapiCollection::new__Enum - exit"));
  163. return hr;
  164. }
  165. };
  166. ////////////////////////////////////////////////////////////////////////
  167. // CTapiBstrCollection -- adapted from tapi3 code
  168. // Collection of BSTRs.
  169. ////////////////////////////////////////////////////////////////////////
  170. class CTapiBstrCollection :
  171. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  172. public IDispatchImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>,
  173. public CMSPObjectSafetyImpl
  174. {
  175. public:
  176. BEGIN_COM_MAP(CTapiBstrCollection)
  177. COM_INTERFACE_ENTRY(IDispatch)
  178. COM_INTERFACE_ENTRY(ITCollection)
  179. COM_INTERFACE_ENTRY(IObjectSafety)
  180. END_COM_MAP()
  181. private:
  182. DWORD m_dwSize;
  183. CComVariant * m_Var;
  184. public:
  185. CTapiBstrCollection(void) : m_dwSize(0), m_Var(NULL) { }
  186. // initialize
  187. HRESULT STDMETHODCALLTYPE Initialize(
  188. DWORD dwSize,
  189. BSTR * pBegin,
  190. BSTR * pEnd
  191. )
  192. {
  193. BSTR * i;
  194. DWORD dw = 0;
  195. LOG((MSP_TRACE, "CTapiBstrCollection::Initialize - enter"));
  196. // create variant array
  197. m_dwSize = dwSize;
  198. m_Var = new CComVariant[m_dwSize];
  199. if (m_Var == NULL)
  200. {
  201. // debug output
  202. return E_OUTOFMEMORY;
  203. }
  204. for (i = pBegin; i != pEnd; i++)
  205. {
  206. // create a variant and add it to the collection
  207. CComVariant& var = m_Var[dw];
  208. var.vt = VT_BSTR;
  209. var.bstrVal = *i;
  210. dw++;
  211. }
  212. LOG((MSP_TRACE, "CTapiBstrCollection::Initialize - exit"));
  213. return S_OK;
  214. }
  215. STDMETHOD(get_Count)(
  216. long* retval
  217. )
  218. {
  219. HRESULT hr = S_OK;
  220. LOG((MSP_TRACE, "CTapiBstrCollection::get_Count - enter"));
  221. try
  222. {
  223. *retval = m_dwSize;
  224. }
  225. catch(...)
  226. {
  227. hr = E_INVALIDARG;
  228. }
  229. LOG((MSP_TRACE, "CTapiBstrCollection::get_Count - exit"));
  230. return hr;
  231. }
  232. STDMETHOD(get_Item)(
  233. long Index,
  234. VARIANT* retval
  235. )
  236. {
  237. HRESULT hr = S_OK;
  238. LOG((MSP_TRACE, "CTapiBstrCollection::get_Item - enter"));
  239. if (retval == NULL)
  240. {
  241. return E_POINTER;
  242. }
  243. try
  244. {
  245. VariantInit(retval);
  246. }
  247. catch(...)
  248. {
  249. hr = E_INVALIDARG;
  250. }
  251. if (hr != S_OK)
  252. {
  253. return hr;
  254. }
  255. retval->vt = VT_BSTR;
  256. retval->bstrVal = NULL;
  257. // use 1-based index, VB like
  258. // no problem with signed/unsigned, since
  259. // if Index < 0 then first clause is true, making it
  260. // irrelevant if the second clause is correct or not.
  261. if ((Index < 1) || ( (DWORD) Index > m_dwSize))
  262. {
  263. return E_INVALIDARG;
  264. }
  265. //
  266. // This copies the string, not just the pointer.
  267. //
  268. hr = VariantCopy(retval, &m_Var[Index-1]);
  269. if (FAILED(hr))
  270. {
  271. LOG((MSP_ERROR,
  272. "CTapiBstrCollection::get_Item - VariantCopy failed. hr = %lx",
  273. hr));
  274. return hr;
  275. }
  276. LOG((MSP_TRACE, "CTapiBstrCollection::get_Item - exit"));
  277. return S_OK;
  278. }
  279. HRESULT STDMETHODCALLTYPE get__NewEnum(
  280. IUnknown** retval
  281. )
  282. {
  283. HRESULT hr;
  284. LOG((MSP_TRACE, "CTapiBstrCollection::get__NumEnum - enter"));
  285. if (retval == NULL)
  286. {
  287. return E_POINTER;
  288. }
  289. *retval = NULL;
  290. typedef CComObject<CSafeComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
  291. enumvar* p = new enumvar;
  292. if ( p == NULL)
  293. {
  294. // debug output
  295. return E_OUTOFMEMORY;
  296. }
  297. hr = p->Init(&m_Var[0], &m_Var[m_dwSize], NULL, AtlFlagCopy);
  298. if (SUCCEEDED(hr))
  299. {
  300. hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval);
  301. }
  302. if (FAILED(hr))
  303. {
  304. delete p;
  305. }
  306. LOG((MSP_TRACE, "CTapiBstrCollection::get__NewEnum - exit"));
  307. return hr;
  308. }
  309. void FinalRelease()
  310. {
  311. LOG((MSP_TRACE, "CTapiBstrCollection::FinalRelease() - enter"));
  312. //
  313. // We "new"ed an array of objects. Delete each object in the array. The
  314. // destructor for each object calls VariantClear to release the pointer
  315. // in that object, based on the variant's tag.
  316. //
  317. delete [] m_Var;
  318. LOG((MSP_TRACE, "CTapiBstrCollection::FinalRelease() - exit"));
  319. }
  320. };
  321. #endif // _MSPCOLL_H_
  322. // eof