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.

227 lines
6.2 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 1998
  5. //
  6. // File: N C C O M . H
  7. //
  8. // Contents: Common routines for dealing with COM.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 25 Jan 1998
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #ifndef _NCCOM_H_
  17. #define _NCCOM_H_
  18. #include "ncutil.h"
  19. HRESULT
  20. HrCoTaskMemAlloc (
  21. ULONG cb,
  22. void** ppv);
  23. HRESULT
  24. HrCoTaskMemAllocAndDupSz (
  25. LPCWSTR pszwSrc,
  26. LPWSTR* ppszwDst);
  27. //------------------------------------------------------------------------
  28. // CIEnumIter - template iterator for IEnumIUnknown
  29. //
  30. // Tenum is of type IEnumXXX (the enumeration interface)
  31. // Telt is of type XXX (the type of the element being enumerated)
  32. //
  33. // HrNext(Telt* pelt) retreives next interface pointer and returns S_OK
  34. // if it is non-null. S_FALSE is returned if *pelt is null (at end of list).
  35. // An error code will be returned for other failures (and *pelt will be
  36. // null of course.)
  37. //
  38. template <class Tenum, class Telt>
  39. class CIEnumIter
  40. {
  41. public:
  42. CIEnumIter (Tenum* penum) NOTHROW;
  43. ~CIEnumIter () NOTHROW { ReleaseRemainingBatch (); }
  44. HRESULT HrNext(Telt* pelt) NOTHROW;
  45. void SetEnumerator(Tenum* penum) NOTHROW
  46. { /*AssertSzH(!m_penum, "Enumerator already set."); */
  47. m_penum = penum;
  48. /*AssertSzH(m_penum, "Can't use a null enumerator."); */}
  49. protected:
  50. void ReleaseRemainingBatch () NOTHROW;
  51. Tenum* m_penum; // pointer to the enumerator. not addref'd.
  52. Telt* m_aelt; // array of enumerated types.
  53. Telt* m_peltNext; // pointer to next type to be returned.
  54. ULONG m_celtFetched; // number of elements fetched.
  55. HRESULT m_hrLast; // last error
  56. };
  57. //------------------------------------------------------------------------
  58. // CIEnumIter - template iterator for IEnumXXX
  59. //
  60. template <class Tenum, class Telt>
  61. inline CIEnumIter<Tenum, Telt>::CIEnumIter(Tenum* penum)
  62. {
  63. m_penum = penum;
  64. m_aelt = NULL;
  65. m_peltNext = NULL;
  66. m_celtFetched = NULL;
  67. m_hrLast = S_OK;
  68. }
  69. //+---------------------------------------------------------------------------
  70. //
  71. // Member: CIEnumIter<Tenum, Telt>::HrNext
  72. //
  73. // Purpose: Returns the next item in the enumeration.
  74. //
  75. // Arguments:
  76. // pelt [out] Pointer to the returned elemnt. Null if not available.
  77. //
  78. // Returns: S_OK if *pelt is valid. S_FALSE if it is NULL. Error
  79. // otherwise.
  80. //
  81. // Author: shaunco 24 Mar 1997
  82. //
  83. // Notes:
  84. //
  85. template <class Tenum, class Telt>
  86. inline HRESULT CIEnumIter<Tenum, Telt>::HrNext(Telt* pelt) NOTHROW
  87. {
  88. // AssertH(pelt);
  89. const ULONG c_celtBatch = 512;
  90. // If we failed for any reason before, return that failure.
  91. //
  92. if (FAILED(m_hrLast))
  93. {
  94. *pelt = NULL;
  95. goto error;
  96. }
  97. // AssertSzH(m_penum, "m_penum is null. Did you forget to call SetEnumerator()?");
  98. // AssertSzH(c_celtBatch, "c_celtBatch can't be zero.");
  99. // If we already have the next interface pointer, and we're
  100. // not at the end of the batch, return it and advance.
  101. // This if should be caught most of the time.
  102. //
  103. if (m_peltNext && (m_peltNext < m_aelt + m_celtFetched))
  104. {
  105. *pelt = *m_peltNext;
  106. m_peltNext++;
  107. }
  108. // Otherwise, if we don't have the next interface pointer (first time),
  109. // or we're at the end of the batch, get the next batch and return
  110. // the first pointer in it.
  111. // This if should be caught the first time through.
  112. //
  113. else if (!m_peltNext || (m_celtFetched == c_celtBatch))
  114. {
  115. // Indicate that m_peltNext is invalid.
  116. //
  117. m_peltNext = NULL;
  118. // Free the old block of pointers
  119. free (m_aelt);
  120. // Allocate the next block of pointers
  121. m_aelt = reinterpret_cast<Telt *>(malloc(c_celtBatch * sizeof(Telt *)));
  122. if (!m_aelt)
  123. {
  124. *pelt = NULL;
  125. m_hrLast = E_OUTOFMEMORY;
  126. goto error;
  127. }
  128. // Assert (m_aelt);
  129. // Get the next batch.
  130. //
  131. m_hrLast = m_penum->Next(c_celtBatch, m_aelt, &m_celtFetched);
  132. // Make sure the implementor of Next is obeying the rules.
  133. // AssertH (FImplies((S_OK == m_hrLast), (m_celtFetched == c_celtBatch)));
  134. // AssertH (FImplies((SUCCEEDED(m_hrLast) && (0 == m_celtFetched)), (NULL == *m_aelt)));
  135. // If we were successful, set the next pointer and return
  136. // S_OK if we returned a valid pointer or S_FALSE if we
  137. // returned NULL.
  138. //
  139. if (SUCCEEDED(m_hrLast))
  140. {
  141. m_peltNext = m_aelt + 1;
  142. if (m_celtFetched)
  143. {
  144. *pelt = *m_aelt;
  145. m_hrLast = S_OK;
  146. }
  147. else
  148. {
  149. *pelt = NULL;
  150. m_hrLast = S_FALSE;
  151. }
  152. }
  153. else
  154. {
  155. *pelt = NULL;
  156. }
  157. }
  158. // Otherwise we've completely iterated the last batch and there are
  159. // no more batches.
  160. //
  161. else
  162. {
  163. // AssertH(m_peltNext >= m_aelt + m_celtFetched);
  164. // AssertH(m_celtFetched != c_celtBatch);
  165. *pelt = NULL;
  166. m_hrLast = S_FALSE;
  167. }
  168. error:
  169. // AssertH(FIff(S_OK == m_hrLast, NULL != *pelt));
  170. // AssertH(FImplies(S_FALSE == m_hrLast, NULL == *pelt));
  171. // TraceError("CIEnumIter<Tenum, Telt>::HrNext(Telt* pelt)",
  172. // (S_FALSE == m_hrLast) ? S_OK : m_hrLast);
  173. return m_hrLast;
  174. }
  175. template <class Tenum, class Telt>
  176. inline void CIEnumIter<Tenum, Telt>::ReleaseRemainingBatch () NOTHROW
  177. {
  178. // This needs to be run if the user doesn't completely iterate the
  179. // batch. Finish releasing the interface pointers and free the batch.
  180. //
  181. if (m_peltNext && m_aelt)
  182. {
  183. while (m_peltNext < m_aelt + m_celtFetched)
  184. {
  185. ReleaseObj (*m_peltNext);
  186. m_peltNext++;
  187. }
  188. free (m_aelt);
  189. }
  190. // If this method is ever called from anywhere other than just
  191. // the destructor, uncomment the following lines.
  192. // m_peltNext = NULL;
  193. // m_aelt = NULL;
  194. }
  195. #endif // _NCCOM_H_