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.

362 lines
9.8 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: E N U M . C P P
  7. //
  8. // Contents: Enumerator for connection objects.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 21 Sep 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "enum.h"
  18. #include "nccom.h"
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: CConnectionManagerEnumConnection::CreateInstance
  22. //
  23. // Purpose: Creates the connection manager's implementation of
  24. // a connection enumerator.
  25. //
  26. // Arguments:
  27. // Flags [in]
  28. // vecClassManagers [in]
  29. // riid [in]
  30. // ppv [out]
  31. //
  32. // Returns: S_OK or an error code.
  33. //
  34. // Author: shaunco 22 Sep 1997
  35. //
  36. // Notes:
  37. //
  38. HRESULT
  39. CConnectionManagerEnumConnection::CreateInstance (
  40. NETCONMGR_ENUM_FLAGS Flags,
  41. CLASSMANAGERMAP& mapClassManagers,
  42. REFIID riid,
  43. void** ppv)
  44. {
  45. TraceFileFunc(ttidConman);
  46. HRESULT hr = E_OUTOFMEMORY;
  47. CConnectionManagerEnumConnection* pObj;
  48. pObj = new CComObject <CConnectionManagerEnumConnection>;
  49. if (pObj)
  50. {
  51. // Initialize our members.
  52. //
  53. pObj->m_EnumFlags = Flags;
  54. // Copy the array of class managers and AddRef them since
  55. // we will be holding on to them.
  56. //
  57. pObj->m_mapClassManagers = mapClassManagers;
  58. for (CLASSMANAGERMAP::iterator iter = pObj->m_mapClassManagers.begin(); iter != pObj->m_mapClassManagers.end(); iter++)
  59. {
  60. AddRefObj (iter->second);
  61. }
  62. pObj->m_iterCurClassMgr = pObj->m_mapClassManagers.begin();
  63. // Do the standard CComCreator::CreateInstance stuff.
  64. //
  65. pObj->SetVoid (NULL);
  66. pObj->InternalFinalConstructAddRef ();
  67. hr = pObj->FinalConstruct ();
  68. pObj->InternalFinalConstructRelease ();
  69. if (SUCCEEDED(hr))
  70. {
  71. hr = pObj->QueryInterface (riid, ppv);
  72. }
  73. if (FAILED(hr))
  74. {
  75. delete pObj;
  76. }
  77. }
  78. return hr;
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Member: CConnectionManagerEnumConnection::FinalRelease
  83. //
  84. // Purpose: COM Destructor.
  85. //
  86. // Arguments:
  87. // (none)
  88. //
  89. // Returns: nothing
  90. //
  91. // Author: shaunco 22 Sep 1997
  92. //
  93. // Notes:
  94. //
  95. void
  96. CConnectionManagerEnumConnection::FinalRelease ()
  97. {
  98. TraceFileFunc(ttidConman);
  99. // Release the current enumerator if we have one.
  100. //
  101. ReleaseObj (m_penumCurClassMgr);
  102. // Release our class managers.
  103. //
  104. for (CLASSMANAGERMAP::iterator iter = m_mapClassManagers.begin(); iter != m_mapClassManagers.end(); iter++)
  105. {
  106. ReleaseObj (iter->second);
  107. }
  108. }
  109. //+---------------------------------------------------------------------------
  110. // IEnumNetConnection
  111. //
  112. // See documentation in MSDN for any IEnumXXX interface.
  113. //
  114. STDMETHODIMP
  115. CConnectionManagerEnumConnection::Next (
  116. ULONG celt,
  117. INetConnection** rgelt,
  118. ULONG* pceltFetched)
  119. {
  120. TraceFileFunc(ttidConman);
  121. HRESULT hr;
  122. ULONG celtFetched;
  123. // Validate parameters.
  124. //
  125. if (!rgelt || (!pceltFetched && (1 != celt)))
  126. {
  127. hr = E_POINTER;
  128. goto finished;
  129. }
  130. // Important to initialize rgelt so that in case we fail, we can
  131. // release only what we put in rgelt.
  132. //
  133. ZeroMemory (rgelt, sizeof (*rgelt) * celt);
  134. // Ask the current class manager to fulfill the request. If he only
  135. // partially does, move to the next class manager. Do this until
  136. // the request is fulfilled, or we run out of class managers.
  137. //
  138. celtFetched = 0;
  139. hr = S_FALSE;
  140. { // begin lock scope
  141. CExceptionSafeComObjectLock EsLock (this);
  142. while ((S_FALSE == hr) && (celtFetched < celt) &&
  143. (m_iterCurClassMgr != m_mapClassManagers.end()))
  144. {
  145. // Get the connection enumerator from the current class manager
  146. // if neccesary.
  147. //
  148. if (!m_penumCurClassMgr)
  149. {
  150. INetConnectionManager* pConMan = m_iterCurClassMgr->second;
  151. Assert (pConMan);
  152. hr = pConMan->EnumConnections (m_EnumFlags,
  153. &m_penumCurClassMgr);
  154. }
  155. if (SUCCEEDED(hr))
  156. {
  157. Assert (m_penumCurClassMgr);
  158. // Each class manager should request only what was reqeuested
  159. // less what has already been fetched.
  160. //
  161. ULONG celtT;
  162. hr = m_penumCurClassMgr->Next (celt - celtFetched,
  163. rgelt + celtFetched, &celtT);
  164. if (SUCCEEDED(hr))
  165. {
  166. celtFetched += celtT;
  167. // If the current class manager couldn't fill the entire
  168. // request, go to the next one.
  169. //
  170. if (S_FALSE == hr)
  171. {
  172. ReleaseCurrentClassEnumerator ();
  173. Assert (!m_penumCurClassMgr);
  174. m_iterCurClassMgr++;
  175. }
  176. }
  177. }
  178. }
  179. Assert (FImplies (S_OK == hr, (celtFetched == celt)));
  180. } // end lock scope
  181. if (SUCCEEDED(hr))
  182. {
  183. TraceTag (ttidConman, "Enumerated %d total connections", celtFetched);
  184. if (pceltFetched)
  185. {
  186. *pceltFetched = celtFetched;
  187. }
  188. hr = (celtFetched == celt) ? S_OK : S_FALSE;
  189. }
  190. else
  191. {
  192. // For any failures, we need to release what we were about to return.
  193. // Set any output parameters to NULL.
  194. //
  195. for (ULONG ulIndex = 0; ulIndex < celt; ulIndex++)
  196. {
  197. ReleaseObj (rgelt[ulIndex]);
  198. rgelt[ulIndex] = NULL;
  199. }
  200. if (pceltFetched)
  201. {
  202. *pceltFetched = 0;
  203. }
  204. }
  205. finished:
  206. TraceErrorOptional ("CConnectionManagerEnumConnection::Next", hr, (S_FALSE == hr));
  207. return hr;
  208. }
  209. STDMETHODIMP
  210. CConnectionManagerEnumConnection::Skip (
  211. ULONG celt)
  212. {
  213. TraceFileFunc(ttidConman);
  214. // Unfortunately, this method doesn't return the number of objects
  215. // actually skipped. To implement this correctly across the multiple
  216. // class managers, we'd need to know how many they skipped similiar
  217. // to the way we implement Next.
  218. //
  219. // So, we'll cheese out and implement this by actually calling
  220. // Next for the reqested number of elements and just releasing what
  221. // we get back.
  222. //
  223. HRESULT hr = S_OK;
  224. if (celt)
  225. {
  226. INetConnection** rgelt;
  227. CExceptionSafeComObjectLock EsLock (this);
  228. hr = E_OUTOFMEMORY;
  229. rgelt = (INetConnection**)MemAlloc(celt * sizeof(INetConnection*));
  230. if (rgelt)
  231. {
  232. ULONG celtFetched;
  233. hr = Next (celt, rgelt, &celtFetched);
  234. if (SUCCEEDED(hr))
  235. {
  236. ReleaseIUnknownArray (celtFetched, (IUnknown**)rgelt);
  237. }
  238. MemFree (rgelt);
  239. }
  240. }
  241. TraceErrorOptional ("CConnectionManagerEnumConnection::Skip", hr, (S_FALSE == hr));
  242. return hr;
  243. }
  244. STDMETHODIMP
  245. CConnectionManagerEnumConnection::Reset ()
  246. {
  247. TraceFileFunc(ttidConman);
  248. CExceptionSafeComObjectLock EsLock (this);
  249. ReleaseCurrentClassEnumerator ();
  250. m_iterCurClassMgr = m_mapClassManagers.begin();
  251. return S_OK;
  252. }
  253. STDMETHODIMP
  254. CConnectionManagerEnumConnection::Clone (
  255. IEnumNetConnection** ppenum)
  256. {
  257. TraceFileFunc(ttidConman);
  258. HRESULT hr = E_OUTOFMEMORY;
  259. // Validate parameters.
  260. //
  261. if (!ppenum)
  262. {
  263. hr = E_POINTER;
  264. }
  265. else
  266. {
  267. // Initialize output parameter.
  268. //
  269. *ppenum = NULL;
  270. CConnectionManagerEnumConnection* pObj;
  271. pObj = new CComObject <CConnectionManagerEnumConnection>;
  272. if (pObj)
  273. {
  274. hr = S_OK;
  275. CExceptionSafeComObjectLock EsLock (this);
  276. // Initialize our members.
  277. //
  278. pObj->m_EnumFlags = m_EnumFlags;
  279. // Copy the array of class managers and AddRef them since
  280. // we will be holding on to them.
  281. //
  282. pObj->m_mapClassManagers = m_mapClassManagers;
  283. for (CLASSMANAGERMAP::iterator iter = m_mapClassManagers.begin(); iter != m_mapClassManagers.end(); iter++)
  284. {
  285. AddRefObj (iter->second);
  286. }
  287. // The current class manager index need to be copied.
  288. //
  289. pObj->m_iterCurClassMgr = pObj->m_mapClassManagers.find(m_iterCurClassMgr->first);
  290. // Important to clone (not copy) the current class enumerator
  291. // if we have one.
  292. //
  293. if (m_penumCurClassMgr)
  294. {
  295. hr = m_penumCurClassMgr->Clone (&pObj->m_penumCurClassMgr);
  296. }
  297. if (SUCCEEDED(hr))
  298. {
  299. // Return the object with a ref count of 1 on this
  300. // interface.
  301. pObj->m_dwRef = 1;
  302. *ppenum = pObj;
  303. }
  304. if (FAILED(hr))
  305. {
  306. delete pObj;
  307. }
  308. }
  309. }
  310. TraceErrorOptional ("CConnectionManagerEnumConnection::Clone", hr, (S_FALSE == hr));
  311. return hr;
  312. }