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.

487 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: E N U M I . C P P
  7. //
  8. // Contents: Enumerator for Inbound connection objects.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 12 Nov 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "enumi.h"
  18. #include "inbound.h"
  19. #include "ncras.h"
  20. #include "ncsvc.h"
  21. LONG g_CountIncomingConnectionEnumerators;
  22. extern const WCHAR c_szSvcRemoteAccess[];
  23. extern const GUID GUID_InboundConfigConnectionId;
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Member: CInboundConnectionManagerEnumConnection::CreateInstance
  27. //
  28. // Purpose: Creates the Inbound class manager's implementation of
  29. // a connection enumerator.
  30. //
  31. // Arguments:
  32. // Flags [in]
  33. // riid [in]
  34. // ppv [out]
  35. //
  36. // Returns: S_OK or an error code.
  37. //
  38. // Author: shaunco 12 Nov 1997
  39. //
  40. // Notes:
  41. //
  42. HRESULT
  43. CInboundConnectionManagerEnumConnection::CreateInstance (
  44. NETCONMGR_ENUM_FLAGS Flags,
  45. REFIID riid,
  46. VOID** ppv)
  47. {
  48. HRESULT hr = E_OUTOFMEMORY;
  49. CInboundConnectionManagerEnumConnection* pObj;
  50. pObj = new CComObject <CInboundConnectionManagerEnumConnection>;
  51. if (pObj)
  52. {
  53. // Initialize our members.
  54. //
  55. pObj->m_EnumFlags = Flags;
  56. pObj->m_fReturnedConfig = FALSE;
  57. // Do the standard CComCreator::CreateInstance stuff.
  58. //
  59. pObj->SetVoid (NULL);
  60. pObj->InternalFinalConstructAddRef ();
  61. hr = pObj->FinalConstruct ();
  62. pObj->InternalFinalConstructRelease ();
  63. if (SUCCEEDED(hr))
  64. {
  65. hr = pObj->QueryInterface (riid, ppv);
  66. }
  67. if (FAILED(hr))
  68. {
  69. delete pObj;
  70. }
  71. }
  72. return hr;
  73. }
  74. CInboundConnectionManagerEnumConnection::CInboundConnectionManagerEnumConnection ()
  75. {
  76. InterlockedIncrement (&g_CountIncomingConnectionEnumerators);
  77. m_EnumFlags = NCME_DEFAULT;
  78. m_aRasSrvConn = NULL;
  79. m_cRasSrvConn = 0;
  80. m_iNextRasSrvConn = 0;
  81. m_fFirstTime = TRUE;
  82. m_fDone = FALSE;
  83. }
  84. CInboundConnectionManagerEnumConnection::~CInboundConnectionManagerEnumConnection ()
  85. {
  86. MemFree (m_aRasSrvConn);
  87. InterlockedDecrement (&g_CountIncomingConnectionEnumerators);
  88. }
  89. //+---------------------------------------------------------------------------
  90. //
  91. // Function: HrCreateConfigOrCurrentEnumeratedConnection
  92. //
  93. // Purpose: Parameterize the call to CInboundConnection::CreateInstance
  94. // based on whether we are returning the configuration
  95. // connection or the currently enumerated one.
  96. //
  97. // Arguments:
  98. // fIsConfigConnection [in]
  99. // ppCon [out]
  100. //
  101. // Returns: S_OK or an error code.
  102. //
  103. // Author: shaunco 16 Nov 1997
  104. //
  105. // Notes:
  106. //
  107. HRESULT
  108. CInboundConnectionManagerEnumConnection::
  109. HrCreateConfigOrCurrentEnumeratedConnection (
  110. BOOL fIsConfigConnection,
  111. INetConnection** ppCon)
  112. {
  113. // Parameterize the call to
  114. // CInboundConnection::CreateInstance based on whether
  115. // we are returning the configuration connection or the currently
  116. // enumerated one.
  117. //
  118. HRASSRVCONN hRasSrvConn;
  119. PCWSTR pszName;
  120. PCWSTR pszDeviceName;
  121. DWORD dwType;
  122. const GUID* pguidId;
  123. if (fIsConfigConnection)
  124. {
  125. hRasSrvConn = 0;
  126. pszName = NULL;
  127. pszDeviceName = NULL;
  128. dwType = 0;
  129. pguidId = &GUID_InboundConfigConnectionId;
  130. m_fReturnedConfig = TRUE;
  131. }
  132. else
  133. {
  134. hRasSrvConn = m_aRasSrvConn[m_iNextRasSrvConn].hRasSrvConn;
  135. pszName = m_aRasSrvConn[m_iNextRasSrvConn].szEntryName;
  136. pszDeviceName = m_aRasSrvConn[m_iNextRasSrvConn].szDeviceName;
  137. dwType = m_aRasSrvConn[m_iNextRasSrvConn].dwType;
  138. pguidId = &m_aRasSrvConn[m_iNextRasSrvConn].Guid;
  139. m_iNextRasSrvConn++;
  140. }
  141. HRESULT hr = CInboundConnection::CreateInstance (
  142. fIsConfigConnection,
  143. hRasSrvConn,
  144. pszName,
  145. pszDeviceName,
  146. dwType,
  147. pguidId,
  148. IID_INetConnection,
  149. reinterpret_cast<VOID**>(ppCon));
  150. TraceError ("CInboundConnectionManagerEnumConnection::"
  151. "HrCreateConfigOrCurrentEnumeratedConnection", hr);
  152. return hr;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Member: CInboundConnectionManagerEnumConnection::HrNextOrSkip
  157. //
  158. // Purpose: Common implementation of Next and Skip. rgelt and
  159. // pceltFetched are optional. If provided, the output
  160. // objects are returned (for Next). If not provided, the output
  161. // objects are not returned (for Skip).
  162. //
  163. // Arguments:
  164. // celt [in] Count of elements to fetch or skip.
  165. // rgelt [out]
  166. // pceltFetched [out]
  167. //
  168. // Returns:
  169. //
  170. // Author: shaunco 12 Nov 1997
  171. //
  172. // Notes:
  173. //
  174. HRESULT
  175. CInboundConnectionManagerEnumConnection::HrNextOrSkip (
  176. ULONG celt,
  177. INetConnection** rgelt,
  178. ULONG* pceltFetched)
  179. {
  180. // Important to initialize rgelt so that in case we fail, we can
  181. // release only what we put in rgelt.
  182. //
  183. if (rgelt)
  184. {
  185. ZeroMemory (rgelt, sizeof (*rgelt) * celt);
  186. }
  187. CExceptionSafeComObjectLock EsLock (this);
  188. // Enumerate the requested number of elements or stop short
  189. // if we don't have that many left to enumerate. We don't enumerate
  190. // anything specific to the current user. All elements are for all
  191. // users.
  192. //
  193. HRESULT hr = S_OK;
  194. ULONG celtFetched = 0;
  195. if ((celtFetched < celt) && !m_fDone)
  196. {
  197. // This gets set to TRUE if we are to return the configuration
  198. // connection. This only happens when RAS is running and no
  199. // active connections exist.
  200. //
  201. BOOL fReturnConfigCon = FALSE;
  202. // If this is our first time through, we need to check if the server
  203. // is running and possibly fill up m_aRasSrvConn. This is our
  204. // array of RASSRVCONN handles enumerted from RAS. We need
  205. // to keep this array across calls because RAS doesn't allow us to
  206. // pickup from a previous enumeration. So, we enumerate everything
  207. // in one shot from RAS and hand it out to the caller however they
  208. // they want it.
  209. //
  210. if (m_fFirstTime)
  211. {
  212. m_fFirstTime = FALSE;
  213. // Assert is so that we don't set m_fDone back to FALSE
  214. // in the case where the service is suddenly running again.
  215. // The enumerator is static. Once done, always done.
  216. //
  217. AssertSz (!m_fDone, "How'd we get here if we're done?");
  218. // Use HrSvcQueryStatus instead of RasSrvIsServiceRunning since
  219. // calling the latter could page in all of the RAS DLLs. If
  220. // the service isn't running, we have nothing to enumerate anyway
  221. // so if we were to page in the RAS DLLs only to find that we
  222. // have no further work to do.
  223. //
  224. DWORD dwState;
  225. HRESULT hrT = HrSvcQueryStatus (c_szSvcRemoteAccess, &dwState);
  226. m_fDone = FAILED(hrT) || (SERVICE_RUNNING != dwState);
  227. if (!m_fDone)
  228. {
  229. hr = HrRasEnumAllActiveServerConnections (&m_aRasSrvConn,
  230. &m_cRasSrvConn);
  231. // If no active connections returned, we need to return
  232. // the configuration connection.
  233. //
  234. if (SUCCEEDED(hr) && (!m_aRasSrvConn || !m_cRasSrvConn || !m_fReturnedConfig))
  235. {
  236. // See if RAS allows us to configure incoming
  237. // connections.
  238. //
  239. BOOL fAllowConfig;
  240. DWORD dwErr = RasSrvAllowConnectionsConfig (&fAllowConfig);
  241. TraceError ("RasSrvAllowConnectionsConfig",
  242. HRESULT_FROM_WIN32 (dwErr));
  243. fReturnConfigCon = ((ERROR_SUCCESS == dwErr) &&
  244. fAllowConfig);
  245. // We're done if we're not returning the config connection.
  246. //
  247. m_fDone = !fReturnConfigCon;
  248. }
  249. else if (FAILED(hr))
  250. {
  251. // Return an empty enumeration on any failures.
  252. //
  253. Assert (!m_aRasSrvConn);
  254. Assert (!m_cRasSrvConn);
  255. m_fDone = TRUE;
  256. hr = S_OK;
  257. }
  258. }
  259. }
  260. // If we're not done, and we need to return something, do it.
  261. //
  262. if (SUCCEEDED(hr) && !m_fDone && (m_cRasSrvConn || fReturnConfigCon))
  263. {
  264. // If we're not returning the configuration connection, it means
  265. // we must be returning an active connection.
  266. //
  267. Assert (FImplies (!fReturnConfigCon, m_aRasSrvConn));
  268. Assert (FImplies (!fReturnConfigCon,
  269. m_iNextRasSrvConn < m_cRasSrvConn));
  270. // For each entry returned, create the inbound connection object.
  271. //
  272. while (SUCCEEDED(hr) && (celtFetched < celt) &&
  273. (fReturnConfigCon || (m_iNextRasSrvConn < m_cRasSrvConn)))
  274. {
  275. // Its important that this check for rgelt come inside the
  276. // loop because we still need to loop to update our state
  277. // for the Skip case.
  278. //
  279. if (rgelt)
  280. {
  281. hr = HrCreateConfigOrCurrentEnumeratedConnection (
  282. fReturnConfigCon,
  283. rgelt + celtFetched);
  284. }
  285. if (fReturnConfigCon)
  286. {
  287. // Only return one of these, so set it back to false.
  288. // This let's the loop complete above.
  289. //
  290. fReturnConfigCon = FALSE;
  291. // m_fDone = TRUE;
  292. }
  293. celtFetched++;
  294. }
  295. if (m_iNextRasSrvConn >= m_cRasSrvConn)
  296. {
  297. Assert (S_OK == hr);
  298. m_fDone = TRUE;
  299. MemFree (m_aRasSrvConn);
  300. m_aRasSrvConn = NULL;
  301. m_cRasSrvConn = 0;
  302. }
  303. }
  304. }
  305. if (SUCCEEDED(hr))
  306. {
  307. TraceTag (ttidWanCon, "Enumerated %d incoming connections",
  308. celtFetched);
  309. if (pceltFetched)
  310. {
  311. *pceltFetched = celtFetched;
  312. }
  313. hr = (celtFetched == celt) ? S_OK : S_FALSE;
  314. }
  315. else
  316. {
  317. // For any failures, we need to release what we were about to return.
  318. // Set any output parameters to NULL.
  319. //
  320. if (rgelt)
  321. {
  322. for (ULONG ulIndex = 0; ulIndex < celt; ulIndex++)
  323. {
  324. ReleaseObj (rgelt[ulIndex]);
  325. rgelt[ulIndex] = NULL;
  326. }
  327. }
  328. if (pceltFetched)
  329. {
  330. *pceltFetched = 0;
  331. }
  332. }
  333. TraceError ("CInboundConnectionManagerEnumConnection::HrNextOrSkip",
  334. (S_FALSE == hr) ? S_OK : hr);
  335. return hr;
  336. }
  337. //+---------------------------------------------------------------------------
  338. // IEnumNetConnection
  339. //
  340. STDMETHODIMP
  341. CInboundConnectionManagerEnumConnection::Next (
  342. ULONG celt,
  343. INetConnection** rgelt,
  344. ULONG* pceltFetched)
  345. {
  346. HRESULT hr;
  347. // Validate parameters.
  348. //
  349. if (!rgelt || (!pceltFetched && (1 != celt)))
  350. {
  351. hr = E_POINTER;
  352. }
  353. else
  354. {
  355. hr = HrNextOrSkip (celt, rgelt, pceltFetched);
  356. }
  357. TraceError ("CInboundConnectionManagerEnumConnection::Next",
  358. (S_FALSE == hr) ? S_OK : hr);
  359. return hr;
  360. }
  361. STDMETHODIMP
  362. CInboundConnectionManagerEnumConnection::Skip (
  363. ULONG celt)
  364. {
  365. HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
  366. TraceError ("CInboundConnectionManagerEnumConnection::Skip",
  367. (S_FALSE == hr) ? S_OK : hr);
  368. return hr;
  369. }
  370. STDMETHODIMP
  371. CInboundConnectionManagerEnumConnection::Reset ()
  372. {
  373. CExceptionSafeComObjectLock EsLock (this);
  374. MemFree (m_aRasSrvConn);
  375. m_aRasSrvConn = NULL;
  376. m_cRasSrvConn = 0;
  377. m_iNextRasSrvConn = 0;
  378. m_fFirstTime = TRUE;
  379. m_fDone = FALSE;
  380. return S_OK;
  381. }
  382. STDMETHODIMP
  383. CInboundConnectionManagerEnumConnection::Clone (
  384. IEnumNetConnection** ppenum)
  385. {
  386. HRESULT hr = E_OUTOFMEMORY;
  387. // Validate parameters.
  388. //
  389. if (!ppenum)
  390. {
  391. hr = E_POINTER;
  392. }
  393. else
  394. {
  395. // Initialize output parameter.
  396. //
  397. *ppenum = NULL;
  398. CInboundConnectionManagerEnumConnection* pObj;
  399. pObj = new CComObject <CInboundConnectionManagerEnumConnection>;
  400. if (pObj)
  401. {
  402. hr = S_OK;
  403. CExceptionSafeComObjectLock EsLock (this);
  404. // Copy our internal state.
  405. //
  406. pObj->m_EnumFlags = m_EnumFlags;
  407. ULONG cbBuf = m_cRasSrvConn * sizeof (RASSRVCONN);
  408. hr = HrMalloc (cbBuf, (PVOID*)&pObj->m_aRasSrvConn);
  409. if (SUCCEEDED(hr))
  410. {
  411. CopyMemory (pObj->m_aRasSrvConn, m_aRasSrvConn, cbBuf);
  412. pObj->m_cRasSrvConn = m_cRasSrvConn;
  413. pObj->m_iNextRasSrvConn = m_iNextRasSrvConn;
  414. pObj->m_fFirstTime = m_fFirstTime;
  415. pObj->m_fDone = m_fDone;
  416. // Return the object with a ref count of 1 on this
  417. // interface.
  418. pObj->m_dwRef = 1;
  419. *ppenum = pObj;
  420. }
  421. if (FAILED(hr))
  422. {
  423. delete pObj;
  424. }
  425. }
  426. }
  427. TraceError ("CInboundConnectionManagerEnumConnection::Clone", hr);
  428. return hr;
  429. }