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.

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