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.

533 lines
9.8 KiB

  1. /*
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. */
  4. #ifndef __SDP_SAFEARRAY__
  5. #define __SDP_SAFEARRAY__
  6. #include <afxdisp.h>
  7. #include "sdpcommo.h"
  8. #include "sdpdef.h"
  9. inline BOOL
  10. ValidateSafeArray(
  11. IN VARTYPE VarType,
  12. IN VARIANT *Variant
  13. )
  14. {
  15. ASSERT(NULL != Variant);
  16. // check if its a safearray and the type of elements in the safe array is whats expected
  17. if ( !(V_VT(Variant) & (VT_ARRAY | VarType)) )
  18. {
  19. return FALSE;
  20. }
  21. // check number of dimensions, cannot handle more than one dimension
  22. if ( V_ARRAY(Variant)->cDims != 1 )
  23. {
  24. return FALSE;
  25. }
  26. return TRUE;
  27. }
  28. class _DllDecl SDP_SAFEARRAY : public COleSafeArray
  29. {
  30. public:
  31. inline SDP_SAFEARRAY();
  32. BOOL CreateAndAttach(
  33. IN ULONG MinSize,
  34. IN VARTYPE VarType,
  35. IN OUT VARIANT &Variant,
  36. OUT HRESULT &HResult
  37. );
  38. inline void Attach(
  39. IN VARIANT &Variant
  40. );
  41. inline void Detach();
  42. inline BOOL Free(
  43. OUT HRESULT &HResult
  44. );
  45. inline BOOL IsAllocated() const;
  46. inline ~SDP_SAFEARRAY();
  47. protected:
  48. VARIANT *m_Variant;
  49. };
  50. inline
  51. SDP_SAFEARRAY::SDP_SAFEARRAY(
  52. )
  53. : m_Variant(NULL)
  54. {
  55. }
  56. inline void
  57. SDP_SAFEARRAY::Attach(
  58. IN VARIANT &Variant
  59. )
  60. {
  61. m_Variant = &Variant;
  62. // because of the way attach is implemented, the variant vt type field is set to VT_EMPTY
  63. // and the ptr is set to null
  64. // if the instance is destroyed without calling free, the vt type and the safe array are assigned
  65. // back to the member variant
  66. COleSafeArray::Attach(Variant);
  67. }
  68. inline void
  69. SDP_SAFEARRAY::Detach(
  70. )
  71. {
  72. ASSERT(NULL != m_Variant);
  73. if ( NULL != m_Variant )
  74. {
  75. *m_Variant = COleSafeArray::Detach();
  76. m_Variant = NULL;
  77. }
  78. }
  79. inline BOOL
  80. SDP_SAFEARRAY::Free(
  81. OUT HRESULT &HResult
  82. )
  83. {
  84. if (NULL == m_Variant)
  85. {
  86. HResult = S_OK;
  87. return TRUE;
  88. }
  89. // destroy the underlying safearray
  90. Clear();
  91. // set the member variant ptr to null so that we are no longer attached to it
  92. m_Variant = NULL;
  93. return TRUE;
  94. }
  95. inline BOOL
  96. SDP_SAFEARRAY::IsAllocated(
  97. ) const
  98. {
  99. return (NULL != m_Variant) ? TRUE : FALSE;
  100. }
  101. inline
  102. SDP_SAFEARRAY::~SDP_SAFEARRAY(
  103. )
  104. {
  105. if ( NULL != m_Variant )
  106. {
  107. *m_Variant = COleSafeArray::Detach();
  108. }
  109. }
  110. template <class T>
  111. class DYNAMIC_ARRAY
  112. {
  113. public:
  114. inline DYNAMIC_ARRAY(
  115. IN ULONG NumElements
  116. );
  117. inline T &operator[](
  118. IN ULONG Index
  119. );
  120. inline T *operator()();
  121. virtual ~DYNAMIC_ARRAY();
  122. protected:
  123. T *m_Array;
  124. };
  125. template <class T>
  126. inline
  127. DYNAMIC_ARRAY<T>::DYNAMIC_ARRAY(
  128. IN ULONG NumElements
  129. )
  130. {
  131. ASSERT(0 != NumElements);
  132. m_Array = new T[NumElements];
  133. }
  134. template <class T>
  135. inline T &
  136. DYNAMIC_ARRAY<T>::operator[](
  137. IN ULONG Index
  138. )
  139. {
  140. return m_Array[Index];
  141. }
  142. template <class T>
  143. inline T *
  144. DYNAMIC_ARRAY<T>::operator ()(
  145. )
  146. {
  147. return m_Array;
  148. }
  149. template <class T>
  150. DYNAMIC_ARRAY<T>::~DYNAMIC_ARRAY(
  151. )
  152. {
  153. ASSERT( NULL != m_Array );
  154. delete[] m_Array;
  155. }
  156. template <class T>
  157. class DYNAMIC_POINTER_ARRAY : public DYNAMIC_ARRAY<T *>
  158. {
  159. public:
  160. inline DYNAMIC_POINTER_ARRAY(
  161. IN ULONG NumElements
  162. );
  163. inline T &operator[](
  164. IN ULONG Index
  165. );
  166. virtual ~DYNAMIC_POINTER_ARRAY();
  167. protected:
  168. ULONG m_NumElements;
  169. // should not be called
  170. inline T *operator()()
  171. {
  172. ASSERT(FALSE);
  173. return NULL;
  174. }
  175. };
  176. template <class T>
  177. inline
  178. DYNAMIC_POINTER_ARRAY<T>::DYNAMIC_POINTER_ARRAY(
  179. IN ULONG NumElements
  180. )
  181. : DYNAMIC_ARRAY<T *>(NumElements),
  182. m_NumElements(NumElements)
  183. {
  184. for (UINT i=0; i < NumElements; i++)
  185. {
  186. m_Array[i] = new T();
  187. }
  188. }
  189. template <class T>
  190. inline T &
  191. DYNAMIC_POINTER_ARRAY<T>::operator[](
  192. IN ULONG Index
  193. )
  194. {
  195. return *m_Array[Index];
  196. }
  197. template <class T>
  198. DYNAMIC_POINTER_ARRAY<T>::~DYNAMIC_POINTER_ARRAY(
  199. )
  200. {
  201. ASSERT( NULL != m_Array );
  202. for (UINT i=0; i < m_NumElements; i++)
  203. {
  204. delete m_Array[i];
  205. }
  206. }
  207. class _DllDecl SDP_SAFEARRAY_WRAP
  208. {
  209. public:
  210. HRESULT GetSafeArrays(
  211. IN const ULONG NumElements,
  212. IN const ULONG NumSafeArrays,
  213. IN VARTYPE VarType[],
  214. OUT VARIANT *Variant[]
  215. );
  216. HRESULT SetSafeArrays(
  217. IN const ULONG NumSafeArrays,
  218. IN VARTYPE VarType[],
  219. IN VARIANT *Variant[]
  220. );
  221. protected:
  222. virtual BOOL GetElement(
  223. IN ULONG Index,
  224. IN ULONG NumEntries,
  225. IN void **Element,
  226. OUT HRESULT &HResult
  227. ) = 0;
  228. virtual BOOL SetElement(
  229. IN ULONG Index,
  230. IN ULONG NumEntries,
  231. IN void ***Element,
  232. OUT HRESULT &HResult
  233. ) = 0;
  234. virtual void RemoveExcessElements(
  235. IN ULONG StartIndex
  236. ) = 0;
  237. };
  238. template <class T, class TLIST>
  239. class _DllDecl SDP_SAFEARRAY_WRAP_EX : public SDP_SAFEARRAY_WRAP
  240. {
  241. public:
  242. inline SDP_SAFEARRAY_WRAP_EX(
  243. IN TLIST &TList
  244. );
  245. protected:
  246. TLIST &m_TList;
  247. T *GetListMember(
  248. IN ULONG Index,
  249. OUT HRESULT &HResult
  250. );
  251. virtual BOOL Get(
  252. IN T &ListMember,
  253. IN ULONG NumEntries,
  254. IN void **Element,
  255. OUT HRESULT &HResult
  256. ) = 0;
  257. virtual BOOL GetElement(
  258. IN ULONG Index,
  259. IN ULONG NumEntries,
  260. IN void **Element,
  261. OUT HRESULT &HResult
  262. );
  263. T *CreateListMemberIfRequired(
  264. IN ULONG Index,
  265. OUT HRESULT &HResult
  266. );
  267. virtual BOOL Set(
  268. IN T &ListMember,
  269. IN ULONG NumEntries,
  270. IN void ***Element,
  271. OUT HRESULT &HResult
  272. ) = 0;
  273. virtual BOOL SetElement(
  274. IN ULONG Index,
  275. IN ULONG NumEntries,
  276. IN void ***Element,
  277. OUT HRESULT &HResult
  278. );
  279. virtual void RemoveExcessElements(
  280. IN ULONG StartIndex
  281. );
  282. };
  283. template <class T, class TLIST>
  284. inline
  285. SDP_SAFEARRAY_WRAP_EX<T, TLIST>::SDP_SAFEARRAY_WRAP_EX(
  286. IN TLIST &TList
  287. )
  288. : m_TList(TList)
  289. {}
  290. template <class T, class TLIST>
  291. T *
  292. SDP_SAFEARRAY_WRAP_EX<T, TLIST>::GetListMember(
  293. IN ULONG Index,
  294. OUT HRESULT &HResult
  295. )
  296. {
  297. T *ToReturn = dynamic_cast<T *>(m_TList[Index]);
  298. if ( NULL == ToReturn )
  299. {
  300. HResult = HRESULT_FROM_ERROR_CODE(SDP_INTERNAL_ERROR);
  301. }
  302. return ToReturn;
  303. }
  304. template <class T, class TLIST>
  305. BOOL
  306. SDP_SAFEARRAY_WRAP_EX<T, TLIST>::GetElement(
  307. IN ULONG Index,
  308. IN ULONG NumEntries,
  309. IN void **Element,
  310. OUT HRESULT &HResult
  311. )
  312. {
  313. T *ListMember = GetListMember(Index, HResult);
  314. if ( NULL == ListMember )
  315. {
  316. return FALSE;
  317. }
  318. ASSERT(ListMember->IsValid());
  319. if ( !Get(*ListMember, NumEntries, Element, HResult) )
  320. {
  321. return FALSE;
  322. }
  323. return TRUE;
  324. }
  325. template <class T, class TLIST>
  326. T *
  327. SDP_SAFEARRAY_WRAP_EX<T, TLIST>::CreateListMemberIfRequired(
  328. IN ULONG Index,
  329. OUT HRESULT &HResult
  330. )
  331. {
  332. // assert that the index is atmost 1 more than the size of the list
  333. ASSERT(0 <= m_TList.GetSize());
  334. ASSERT(Index <= (ULONG)(m_TList.GetSize() + 1));
  335. if ( Index >= (ULONG)m_TList.GetSize() )
  336. {
  337. T *NewElement = dynamic_cast<T *>(m_TList.CreateElement());
  338. if ( NULL == NewElement )
  339. {
  340. HResult = HRESULT_FROM_ERROR_CODE(SDP_INTERNAL_ERROR);
  341. }
  342. return NewElement;
  343. }
  344. else
  345. {
  346. return GetListMember(Index, HResult);
  347. }
  348. // should never reach here
  349. ASSERT(FALSE);
  350. }
  351. template <class T, class TLIST>
  352. BOOL
  353. SDP_SAFEARRAY_WRAP_EX<T, TLIST>::SetElement(
  354. IN ULONG Index,
  355. IN ULONG NumEntries,
  356. IN void ***Element,
  357. OUT HRESULT &HResult
  358. )
  359. {
  360. T *ListMember = CreateListMemberIfRequired(Index, HResult);
  361. if ( NULL == ListMember )
  362. {
  363. return FALSE;
  364. }
  365. if ( !Set(*ListMember, NumEntries, Element, HResult) )
  366. {
  367. return FALSE;
  368. }
  369. ASSERT(ListMember->IsValid());
  370. // if its a newly created instance, make it valid and add it to the list at the appropriate
  371. // index
  372. if ( Index >= (ULONG)m_TList.GetSize() )
  373. {
  374. try
  375. {
  376. m_TList.SetAtGrow(Index, ListMember);
  377. }
  378. catch(...)
  379. {
  380. delete ListMember;
  381. SetLastError(ERROR_OUTOFMEMORY);
  382. return FALSE;
  383. }
  384. }
  385. return TRUE;
  386. }
  387. template <class T, class TLIST>
  388. void
  389. SDP_SAFEARRAY_WRAP_EX<T, TLIST>::RemoveExcessElements(
  390. IN ULONG StartIndex
  391. )
  392. {
  393. ASSERT(0 <= m_TList.GetSize());
  394. // for each list element that is in excess of the safearray members,
  395. // delete and remove them
  396. for ( ULONG i = StartIndex; i < (ULONG)m_TList.GetSize(); i++ )
  397. {
  398. delete m_TList[i];
  399. m_TList.RemoveAt(i);
  400. i++;
  401. }
  402. }
  403. #endif // __SDP_SAFEARRAY__