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.

397 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: E N U M W . C P P
  7. //
  8. // Contents: Enumerator for RAS connection objects.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 2 Oct 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "enumw.h"
  18. #include "dialup.h"
  19. #include "ncras.h"
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Member: CWanConnectionManagerEnumConnection::CreateInstance
  23. //
  24. // Purpose: Creates the WAN class manager's implementation of
  25. // a connection enumerator.
  26. //
  27. // Arguments:
  28. // Flags [in]
  29. // riid [in]
  30. // ppv [out]
  31. //
  32. // Returns: S_OK or an error code.
  33. //
  34. // Author: shaunco 23 Sep 1997
  35. //
  36. // Notes:
  37. //
  38. HRESULT
  39. CWanConnectionManagerEnumConnection::CreateInstance (
  40. NETCONMGR_ENUM_FLAGS Flags,
  41. REFIID riid,
  42. VOID** ppv)
  43. {
  44. HRESULT hr = E_OUTOFMEMORY;
  45. CWanConnectionManagerEnumConnection* pObj;
  46. pObj = new CComObject <CWanConnectionManagerEnumConnection>;
  47. if (pObj)
  48. {
  49. // Initialize our members.
  50. //
  51. pObj->m_EnumFlags = Flags;
  52. // Do the standard CComCreator::CreateInstance stuff.
  53. //
  54. pObj->SetVoid (NULL);
  55. pObj->InternalFinalConstructAddRef ();
  56. hr = pObj->FinalConstruct ();
  57. pObj->InternalFinalConstructRelease ();
  58. if (SUCCEEDED(hr))
  59. {
  60. hr = pObj->QueryInterface (riid, ppv);
  61. }
  62. if (FAILED(hr))
  63. {
  64. delete pObj;
  65. }
  66. }
  67. return hr;
  68. }
  69. //+---------------------------------------------------------------------------
  70. //
  71. // Member: CWanConnectionManagerEnumConnection::CWanConnectionManagerEnumConnection
  72. //
  73. // Purpose: Constructor
  74. //
  75. // Arguments:
  76. // (none)
  77. //
  78. // Returns: nothing
  79. //
  80. // Author: shaunco 5 Oct 1997
  81. //
  82. // Notes:
  83. //
  84. CWanConnectionManagerEnumConnection::CWanConnectionManagerEnumConnection ()
  85. {
  86. m_EnumFlags = NCME_DEFAULT;
  87. m_aRasEntryName = NULL;
  88. m_cRasEntryName = 0;
  89. m_iNextRasEntryName = 0;
  90. m_fDone = FALSE;
  91. }
  92. //+---------------------------------------------------------------------------
  93. //
  94. // Member: CWanConnectionManagerEnumConnection::~CWanConnectionManagerEnumConnection
  95. //
  96. // Purpose: Destructor
  97. //
  98. // Arguments:
  99. // (none)
  100. //
  101. // Returns: nothing
  102. //
  103. // Author: shaunco 2 Oct 1997
  104. //
  105. // Notes:
  106. //
  107. CWanConnectionManagerEnumConnection::~CWanConnectionManagerEnumConnection ()
  108. {
  109. MemFree (m_aRasEntryName);
  110. }
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Member: CWanConnectionManagerEnumConnection::HrNextOrSkip
  114. //
  115. // Purpose: Common implementation of Next and Skip. rgelt and
  116. // pceltFetched are optional. If provided, the output
  117. // objects are returned (for Next). If not provided, the output
  118. // objects are not returned (for Skip).
  119. //
  120. // Arguments:
  121. // celt [in] Count of elements to fetch or skip.
  122. // rgelt [out]
  123. // pceltFetched [out]
  124. //
  125. // Returns:
  126. //
  127. // Author: shaunco 15 Oct 1997
  128. //
  129. // Notes:
  130. //
  131. HRESULT
  132. CWanConnectionManagerEnumConnection::HrNextOrSkip (
  133. ULONG celt,
  134. INetConnection** rgelt,
  135. ULONG* pceltFetched)
  136. {
  137. // Important to initialize rgelt so that in case we fail, we can
  138. // release only what we put in rgelt.
  139. //
  140. if (rgelt)
  141. {
  142. ZeroMemory (rgelt, sizeof (*rgelt) * celt);
  143. }
  144. CExceptionSafeComObjectLock EsLock (this);
  145. // Enumerate the requested number of elements or stop short
  146. // if we don't have that many left to enumerate.
  147. //
  148. HRESULT hr = S_OK;
  149. ULONG celtFetched = 0;
  150. while (SUCCEEDED(hr) && (celtFetched < celt) && !m_fDone)
  151. {
  152. // See if we need to fill m_aRasEntryName. This is our
  153. // array of RASENTRYNAME structures enumerted from RAS. We need
  154. // to keep this array across calls because RAS doesn't allow us to
  155. // pickup from a previous enumeration. So, we enumerate everything
  156. // in one shot from RAS and hand it out to the caller however they
  157. // they want it.
  158. //
  159. if (!m_aRasEntryName)
  160. {
  161. // Because RasEnumEntries also enumerates per-user entries
  162. // we need to impersonate the client to allow the correct
  163. // per-user entries to be enumerated.
  164. //
  165. // Impersonate the client.
  166. //
  167. HRESULT hrT = CoImpersonateClient ();
  168. TraceHr (ttidError, FAL, hrT, FALSE, "CoImpersonateClient");
  169. // We need to continue if we're called in-proc (ie. if RPC_E_CALL_COMPLETE is returned).
  170. if (SUCCEEDED(hrT) || (RPC_E_CALL_COMPLETE == hrT))
  171. {
  172. hr = HrRasEnumAllEntriesWithDetails (NULL,
  173. &m_aRasEntryName, &m_cRasEntryName);
  174. }
  175. if (SUCCEEDED(hrT))
  176. {
  177. hrT = CoRevertToSelf ();
  178. TraceHr (ttidError, FAL, hrT, FALSE, "CoRevertToSelf");
  179. }
  180. if (!m_cRasEntryName || FAILED(hr))
  181. {
  182. // RAS may not be installed or may otherwise have a problem.
  183. // We catch this here and return an empty enumeration.
  184. //
  185. Assert (!m_aRasEntryName);
  186. Assert (!m_cRasEntryName);
  187. m_fDone = TRUE;
  188. hr = S_OK;
  189. }
  190. }
  191. // Now that we have m_aRasEntryName and m_iNextRasEntryName,
  192. // use them to fill up the output array if we have an output
  193. // array to fill up.
  194. //
  195. if (SUCCEEDED(hr) && !m_fDone)
  196. {
  197. Assert (m_aRasEntryName);
  198. Assert (m_cRasEntryName);
  199. Assert (m_iNextRasEntryName < m_cRasEntryName);
  200. // Create the RAS connection objects.
  201. //
  202. while (SUCCEEDED(hr) && (celtFetched < celt) &&
  203. (m_iNextRasEntryName < m_cRasEntryName))
  204. {
  205. // Its important that this check for rgelt come inside the
  206. // loop because we still need to loop to update our state
  207. // for the Skip case.
  208. //
  209. if (rgelt)
  210. {
  211. hr = CDialupConnection::CreateInstanceFromDetails (
  212. m_aRasEntryName + m_iNextRasEntryName,
  213. IID_INetConnection,
  214. reinterpret_cast<VOID**>(rgelt + celtFetched));
  215. }
  216. celtFetched++;
  217. m_iNextRasEntryName++;
  218. }
  219. if (m_iNextRasEntryName >= m_cRasEntryName)
  220. {
  221. Assert (S_OK == hr);
  222. m_fDone = TRUE;
  223. MemFree (m_aRasEntryName);
  224. m_aRasEntryName = NULL;
  225. m_cRasEntryName = 0;
  226. }
  227. }
  228. }
  229. if (SUCCEEDED(hr))
  230. {
  231. TraceTag (ttidWanCon, "Enumerated %d RAS connections", celtFetched);
  232. if (pceltFetched)
  233. {
  234. *pceltFetched = celtFetched;
  235. }
  236. hr = (celtFetched == celt) ? S_OK : S_FALSE;
  237. }
  238. else
  239. {
  240. // For any failures, we need to release what we were about to return.
  241. // Set any output parameters to NULL.
  242. //
  243. if (rgelt)
  244. {
  245. for (ULONG ulIndex = 0; ulIndex < celt; ulIndex++)
  246. {
  247. ReleaseObj (rgelt[ulIndex]);
  248. rgelt[ulIndex] = NULL;
  249. }
  250. }
  251. if (pceltFetched)
  252. {
  253. *pceltFetched = 0;
  254. }
  255. }
  256. TraceError ("CWanConnectionManagerEnumConnection::HrNextOrSkip",
  257. (S_FALSE == hr) ? S_OK : hr);
  258. return hr;
  259. }
  260. //+---------------------------------------------------------------------------
  261. // IEnumNetConnection
  262. //
  263. STDMETHODIMP
  264. CWanConnectionManagerEnumConnection::Next (
  265. ULONG celt,
  266. INetConnection** rgelt,
  267. ULONG* pceltFetched)
  268. {
  269. HRESULT hr;
  270. // Validate parameters.
  271. //
  272. if (!rgelt || (!pceltFetched && (1 != celt)))
  273. {
  274. hr = E_POINTER;
  275. }
  276. else
  277. {
  278. hr = HrNextOrSkip (celt, rgelt, pceltFetched);
  279. }
  280. TraceError ("CWanConnectionManagerEnumConnection::Next",
  281. (S_FALSE == hr) ? S_OK : hr);
  282. return hr;
  283. }
  284. STDMETHODIMP
  285. CWanConnectionManagerEnumConnection::Skip (
  286. ULONG celt)
  287. {
  288. HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
  289. TraceError ("CWanConnectionManagerEnumConnection::Skip",
  290. (S_FALSE == hr) ? S_OK : hr);
  291. return hr;
  292. }
  293. STDMETHODIMP
  294. CWanConnectionManagerEnumConnection::Reset ()
  295. {
  296. CExceptionSafeComObjectLock EsLock (this);
  297. MemFree (m_aRasEntryName);
  298. m_aRasEntryName = NULL;
  299. m_cRasEntryName = 0;
  300. m_iNextRasEntryName = 0;
  301. m_fDone = FALSE;
  302. return S_OK;
  303. }
  304. STDMETHODIMP
  305. CWanConnectionManagerEnumConnection::Clone (
  306. IEnumNetConnection** ppenum)
  307. {
  308. HRESULT hr = E_OUTOFMEMORY;
  309. // Validate parameters.
  310. //
  311. if (!ppenum)
  312. {
  313. hr = E_POINTER;
  314. }
  315. else
  316. {
  317. // Initialize output parameter.
  318. //
  319. *ppenum = NULL;
  320. CWanConnectionManagerEnumConnection* pObj;
  321. pObj = new CComObject <CWanConnectionManagerEnumConnection>;
  322. if (pObj)
  323. {
  324. hr = S_OK;
  325. CExceptionSafeComObjectLock EsLock (this);
  326. // Copy our internal state.
  327. //
  328. pObj->m_EnumFlags = m_EnumFlags;
  329. ULONG cbBuf = m_cRasEntryName * sizeof (RASENUMENTRYDETAILS);
  330. if (cbBuf && m_aRasEntryName)
  331. {
  332. hr = E_OUTOFMEMORY;
  333. pObj->m_aRasEntryName = (RASENUMENTRYDETAILS*)(MemAlloc (cbBuf));
  334. if (pObj->m_aRasEntryName)
  335. {
  336. hr = S_OK;
  337. CopyMemory (pObj->m_aRasEntryName, m_aRasEntryName, cbBuf);
  338. pObj->m_cRasEntryName = m_cRasEntryName;
  339. }
  340. }
  341. if (S_OK == hr)
  342. {
  343. pObj->m_iNextRasEntryName = m_iNextRasEntryName;
  344. pObj->m_fDone = m_fDone;
  345. // Return the object with a ref count of 1 on this
  346. // interface.
  347. pObj->m_dwRef = 1;
  348. *ppenum = pObj;
  349. }
  350. else
  351. {
  352. delete pObj;
  353. }
  354. }
  355. }
  356. TraceError ("CWanConnectionManagerEnumConnection::Clone", hr);
  357. return hr;
  358. }