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.

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