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.

453 lines
11 KiB

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