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.

269 lines
7.0 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  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 "ncdefine.h" // for NOTHROW
  19. #include "ncstlstr.h"
  20. HRESULT
  21. HrCoTaskMemAlloc (
  22. ULONG cb,
  23. VOID** ppv);
  24. HRESULT
  25. HrCoTaskMemAllocAndDupSzLen (
  26. IN PCWSTR pszwSrc,
  27. IN ULONG cchSrc,
  28. OUT PWSTR* ppszwDst);
  29. HRESULT
  30. HrCoTaskMemAllocAndDupSz (
  31. IN PCWSTR pszwSrc,
  32. OUT PWSTR* ppszwDst);
  33. VOID
  34. NcSetProxyBlanket (
  35. IN IUnknown* pUnk);
  36. //+---------------------------------------------------------------------------
  37. //
  38. // Function: ReleaseIUnknownArray
  39. //
  40. // Purpose: Releases an array of IUnknown pointers.
  41. //
  42. // Arguments:
  43. // cpunk [in] count of pointers to release
  44. // apunk [in] array of pointers to release
  45. //
  46. // Returns: Nothing
  47. //
  48. // Author: shaunco 23 Mar 1997
  49. //
  50. // Notes: Any of the pointers in the array can be NULL.
  51. //
  52. inline
  53. NOTHROW
  54. VOID
  55. ReleaseIUnknownArray (
  56. ULONG cpunk,
  57. IUnknown** apunk)
  58. {
  59. AssertH (apunk);
  60. while (cpunk--)
  61. {
  62. ReleaseObj (*apunk);
  63. apunk++;
  64. }
  65. }
  66. //------------------------------------------------------------------------
  67. // CIEnumIter - template iterator for IEnumIUnknown
  68. //
  69. // Tenum is of type IEnumXXX (the enumeration interface)
  70. // Telt is of type XXX (the type of the element being enumerated)
  71. //
  72. // HrNext(Telt* pelt) retreives next interface pointer and returns S_OK
  73. // if it is non-null. S_FALSE is returned if *pelt is null (at end of list).
  74. // An error code will be returned for other failures (and *pelt will be
  75. // null of course.)
  76. //
  77. template <class Tenum, class Telt>
  78. class CIEnumIter
  79. {
  80. public:
  81. NOTHROW CIEnumIter (Tenum* penum);
  82. NOTHROW ~CIEnumIter () { ReleaseRemainingBatch (); }
  83. NOTHROW HRESULT HrNext(Telt* pelt);
  84. NOTHROW VOID SetEnumerator(Tenum* penum)
  85. { AssertSzH(!m_penum, "Enumerator already set.");
  86. m_penum = penum;
  87. AssertSzH(m_penum, "Can't use a null enumerator."); }
  88. protected:
  89. NOTHROW VOID ReleaseRemainingBatch ();
  90. Tenum* m_penum; // pointer to the enumerator. not addref'd.
  91. Telt* m_aelt; // array of enumerated types.
  92. Telt* m_peltNext; // pointer to next type to be returned.
  93. ULONG m_celtFetched; // number of elements fetched.
  94. HRESULT m_hrLast; // last error
  95. };
  96. //------------------------------------------------------------------------
  97. // CIEnumIter - template iterator for IEnumXXX
  98. //
  99. template <class Tenum, class Telt>
  100. inline CIEnumIter<Tenum, Telt>::CIEnumIter(Tenum* penum)
  101. {
  102. m_penum = penum;
  103. m_aelt = NULL;
  104. m_peltNext = NULL;
  105. m_celtFetched = NULL;
  106. m_hrLast = S_OK;
  107. }
  108. //+---------------------------------------------------------------------------
  109. //
  110. // Member: CIEnumIter<Tenum, Telt>::HrNext
  111. //
  112. // Purpose: Returns the next item in the enumeration.
  113. //
  114. // Arguments:
  115. // pelt [out] Pointer to the returned elemnt. Null if not available.
  116. //
  117. // Returns: S_OK if *pelt is valid. S_FALSE if it is NULL. Error
  118. // otherwise.
  119. //
  120. // Author: shaunco 24 Mar 1997
  121. //
  122. // Notes:
  123. //
  124. template <class Tenum, class Telt>
  125. inline NOTHROW HRESULT CIEnumIter<Tenum, Telt>::HrNext(Telt* pelt)
  126. {
  127. AssertH(pelt);
  128. const ULONG c_celtBatch = 256;
  129. // If we failed for any reason before, return that failure.
  130. //
  131. if (FAILED(m_hrLast))
  132. {
  133. *pelt = NULL;
  134. goto error;
  135. }
  136. AssertSzH(m_penum, "m_penum is null. Did you forget to call SetEnumerator()?");
  137. AssertSzH(c_celtBatch, "c_celtBatch can't be zero.");
  138. // If we already have the next interface pointer, and we're
  139. // not at the end of the batch, return it and advance.
  140. // This if should be caught most of the time.
  141. //
  142. if (m_peltNext && (m_peltNext < m_aelt + m_celtFetched))
  143. {
  144. *pelt = *m_peltNext;
  145. m_peltNext++;
  146. }
  147. // Otherwise, if we don't have the next interface pointer (first time),
  148. // or we're at the end of the batch, get the next batch and return
  149. // the first pointer in it.
  150. // This if should be caught the first time through.
  151. //
  152. else if (!m_peltNext || (m_celtFetched == c_celtBatch))
  153. {
  154. // Indicate that m_peltNext is invalid.
  155. //
  156. m_peltNext = NULL;
  157. // Free the old block of pointers
  158. MemFree(m_aelt);
  159. // Allocate the next block of pointers
  160. m_aelt = reinterpret_cast<Telt *>(MemAlloc(c_celtBatch * sizeof(Telt *)));
  161. if (!m_aelt)
  162. {
  163. *pelt = NULL;
  164. m_hrLast = E_OUTOFMEMORY;
  165. goto error;
  166. }
  167. AssertH (m_aelt);
  168. // Get the next batch.
  169. //
  170. m_hrLast = m_penum->Next(c_celtBatch, m_aelt, &m_celtFetched);
  171. // Make sure the implementor of Next is obeying the rules.
  172. AssertH (FImplies((S_OK == m_hrLast), (m_celtFetched == c_celtBatch)));
  173. AssertH (FImplies((SUCCEEDED(m_hrLast) && (0 == m_celtFetched)), (NULL == *m_aelt)));
  174. // If we were successful, set the next pointer and return
  175. // S_OK if we returned a valid pointer or S_FALSE if we
  176. // returned NULL.
  177. //
  178. if (SUCCEEDED(m_hrLast))
  179. {
  180. m_peltNext = m_aelt + 1;
  181. if (m_celtFetched)
  182. {
  183. *pelt = *m_aelt;
  184. m_hrLast = S_OK;
  185. }
  186. else
  187. {
  188. *pelt = NULL;
  189. m_hrLast = S_FALSE;
  190. }
  191. }
  192. else
  193. {
  194. *pelt = NULL;
  195. }
  196. }
  197. // Otherwise we've completely iterated the last batch and there are
  198. // no more batches.
  199. //
  200. else
  201. {
  202. AssertH(m_peltNext >= m_aelt + m_celtFetched);
  203. AssertH(m_celtFetched != c_celtBatch);
  204. *pelt = NULL;
  205. m_hrLast = S_FALSE;
  206. }
  207. error:
  208. AssertH(FIff(S_OK == m_hrLast, NULL != *pelt));
  209. AssertH(FImplies(S_FALSE == m_hrLast, NULL == *pelt));
  210. TraceError("CIEnumIter<Tenum, Telt>::HrNext(Telt* pelt)",
  211. (S_FALSE == m_hrLast) ? S_OK : m_hrLast);
  212. return m_hrLast;
  213. }
  214. template <class Tenum, class Telt>
  215. inline NOTHROW VOID CIEnumIter<Tenum, Telt>::ReleaseRemainingBatch ()
  216. {
  217. // This needs to be run if the user doesn't completely iterate the
  218. // batch. Finish releasing the interface pointers and free the batch.
  219. //
  220. if (m_peltNext && m_aelt)
  221. {
  222. while (m_peltNext < m_aelt + m_celtFetched)
  223. {
  224. ReleaseObj (*m_peltNext);
  225. m_peltNext++;
  226. }
  227. MemFree (m_aelt);
  228. }
  229. // If this method is ever called from anywhere other than just
  230. // the destructor, uncomment the following lines.
  231. // m_peltNext = NULL;
  232. // m_aelt = NULL;
  233. }
  234. #endif // _NCCOM_H_