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.

1290 lines
33 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2001.
  5. //
  6. // File: R A S C O N O B . C P P
  7. //
  8. // Contents: Implements the base class used to implement the Dialup,
  9. // Direct, and Vpn connection objects. Also includes
  10. // RAS-related utility functions used only within netman.exe.
  11. //
  12. // Notes:
  13. //
  14. // Author: shaunco 23 Sep 1997
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "pch.h"
  18. #pragma hdrstop
  19. #include "nmbase.h"
  20. #include "nccom.h"
  21. #include "ncperms.h"
  22. #include "ncras.h"
  23. #include "rasconob.h"
  24. #include <raserror.h>
  25. #include "gpnla.h"
  26. extern CGroupPolicyNetworkLocationAwareness* g_pGPNLA;
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Function: HrRasConnectionNameFromGuid
  30. //
  31. // Purpose: Exported API used by iphlpapi et. al. to get the connection
  32. // of a RAS connection given its GUID.
  33. //
  34. // Arguments:
  35. // guid [in] The guid id representing the connection.
  36. // pszwName [out] Pointer to a buffer to store the name.
  37. // pcchMax [inout] On input, the length, in characters, of the buffer
  38. // including the null terminator. On output, the
  39. // length of the string including the null terminator
  40. // (if it was written) or the length of the buffer
  41. // required.
  42. //
  43. // Returns: HRESULT_FROM_WIN32(ERROR_NOT_FOUND) if the entry was not found.
  44. // HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
  45. // S_OK
  46. //
  47. // Author: shaunco 23 Sep 1998
  48. //
  49. // Notes:
  50. //
  51. EXTERN_C
  52. HRESULT
  53. WINAPI
  54. HrRasConnectionNameFromGuid (
  55. IN REFGUID guid,
  56. OUT PWSTR pszwName,
  57. IN OUT DWORD* pcchMax)
  58. {
  59. Assert (pszwName);
  60. Assert (pcchMax);
  61. // Initialize the output parameter.
  62. //
  63. *pszwName = NULL;
  64. // We now need to enumerate all entries in this phonebook and
  65. // find our details record with the matching guidId.
  66. //
  67. RASENUMENTRYDETAILS* aRasEntryDetails;
  68. DWORD cRasEntryDetails;
  69. HRESULT hr;
  70. hr = HrRasEnumAllEntriesWithDetails (
  71. NULL,
  72. &aRasEntryDetails,
  73. &cRasEntryDetails);
  74. if (SUCCEEDED(hr))
  75. {
  76. RASENUMENTRYDETAILS* pDetails;
  77. // Assume we don't find the entry.
  78. //
  79. hr = HRESULT_FROM_WIN32 (ERROR_NOT_FOUND);
  80. for (DWORD i = 0; i < cRasEntryDetails; i++)
  81. {
  82. pDetails = &aRasEntryDetails[i];
  83. if (pDetails->guidId == guid)
  84. {
  85. // Only copy the string if the caller has enough room in
  86. // the output buffer.
  87. //
  88. hr = HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER);
  89. DWORD cchRequired = wcslen(pDetails->szEntryName) + 1;
  90. if (cchRequired <= *pcchMax)
  91. {
  92. wcscpy (pszwName, pDetails->szEntryName);
  93. hr = S_OK;
  94. }
  95. *pcchMax = cchRequired;
  96. break;
  97. }
  98. }
  99. MemFree (aRasEntryDetails);
  100. }
  101. else if (HRESULT_FROM_WIN32(ERROR_CANNOT_OPEN_PHONEBOOK) == hr)
  102. {
  103. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  104. }
  105. TraceError ("HrRasConnectionNameFromGuid", hr);
  106. return hr;
  107. }
  108. //+---------------------------------------------------------------------------
  109. //
  110. // Member: CRasConnectionBase::CacheProperties
  111. //
  112. // Purpose:
  113. //
  114. // Arguments:
  115. //
  116. // Returns: nothing.
  117. //
  118. // Author: shaunco 2 Feb 1998
  119. //
  120. // Notes:
  121. //
  122. VOID
  123. CRasConnectionBase::CacheProperties (
  124. const RASENUMENTRYDETAILS* pDetails)
  125. {
  126. Assert (pDetails);
  127. AssertSz(pDetails->dwSize >= sizeof(RASENUMENTRYDETAILS), "RASENUMENTRYDETAILS too small");
  128. m_fEntryPropertiesCached = TRUE;
  129. m_lRasEntryModifiedVersionEra = g_lRasEntryModifiedVersionEra;
  130. m_guidId = pDetails->guidId;
  131. SetEntryName (pDetails->szEntryName);
  132. m_fForAllUsers = !!(pDetails->dwFlags & REN_AllUsers);
  133. m_fShowMonitorIconInTaskBar = pDetails->fShowMonitorIconInTaskBar;
  134. m_strDeviceName = pDetails->szDeviceName;
  135. m_dwFlagsPriv = pDetails->dwFlagsPriv;
  136. m_strPhoneNumber = pDetails->szPhoneNumber;
  137. TraceTag(ttidWanCon, "PhoneNumber: %S", m_strPhoneNumber);
  138. m_fBranded = (RASET_Internet == pDetails->dwType);
  139. TraceTag (ttidWanCon, "rdt:0x%08x, dwType:0x%08x",
  140. pDetails->rdt,
  141. pDetails->dwType);
  142. switch (LOWORD(pDetails->rdt))
  143. {
  144. case RDT_PPPoE:
  145. m_MediaType = NCM_PPPOE;
  146. break;
  147. case RDT_Modem:
  148. case RDT_X25:
  149. m_MediaType = NCM_PHONE;
  150. break;
  151. case RDT_Isdn:
  152. m_MediaType = NCM_ISDN;
  153. break;
  154. case RDT_Serial:
  155. case RDT_FrameRelay:
  156. case RDT_Atm:
  157. case RDT_Sonet:
  158. case RDT_Sw56:
  159. m_MediaType = NCM_PHONE;
  160. break;
  161. case RDT_Tunnel_Pptp:
  162. case RDT_Tunnel_L2tp:
  163. m_MediaType = NCM_TUNNEL;
  164. break;
  165. case RDT_Irda:
  166. case RDT_Parallel:
  167. m_MediaType = NCM_DIRECT;
  168. break;
  169. case RDT_Other:
  170. default:
  171. if (RASET_Vpn == pDetails->dwType)
  172. {
  173. m_MediaType = NCM_TUNNEL;
  174. }
  175. else if (RASET_Direct == pDetails->dwType)
  176. {
  177. m_MediaType = NCM_DIRECT;
  178. }
  179. else
  180. {
  181. m_MediaType = NCM_PHONE;
  182. }
  183. break;
  184. }
  185. if (pDetails->rdt & RDT_Tunnel)
  186. {
  187. m_MediaType = NCM_TUNNEL;
  188. }
  189. else if (pDetails->rdt & (RDT_Direct | RDT_Null_Modem))
  190. {
  191. m_MediaType = NCM_DIRECT;
  192. }
  193. }
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Member: CRasConnectionBase::FAllowRemoval
  197. //
  198. // Purpose: Returns TRUE if the connection is in a state where we
  199. // can validly remove it.
  200. //
  201. // Arguments:
  202. // phrReason [out] If FALSE is returned, this is the reason. It is
  203. // either E_ACCESSDENIED or E_UNEXPECTED.
  204. //
  205. // Returns: TRUE or FALSE.
  206. //
  207. // Author: shaunco 17 Jul 1998
  208. //
  209. // Notes:
  210. //
  211. BOOL
  212. CRasConnectionBase::FAllowRemoval (
  213. HRESULT* phrReason)
  214. {
  215. Assert (phrReason);
  216. Assert (m_fEntryPropertiesCached);
  217. // If this connection is for all users, the user must be
  218. // an administrator or power user.
  219. //
  220. if (m_fForAllUsers && !FIsUserAdmin())
  221. {
  222. *phrReason = E_ACCESSDENIED;
  223. return FALSE;
  224. }
  225. // $$NOTE (jeffspr) -- moved the test for connection state to the
  226. // delete function because we don't want it to affect our loading
  227. // of characteristics
  228. //
  229. // If we passed all tests above, we're okay to remove.
  230. //
  231. *phrReason = S_OK;
  232. return TRUE;
  233. }
  234. //+---------------------------------------------------------------------------
  235. //
  236. // Member: CRasConnectionBase::HrGetCharacteristics
  237. //
  238. // Purpose: Get the characteristics of the connection.
  239. //
  240. // Arguments:
  241. // pdwFlags [out]
  242. //
  243. // Returns: S_OK or an error code
  244. //
  245. // Author: shaunco 17 Jul 1998
  246. //
  247. // Notes:
  248. //
  249. HRESULT
  250. CRasConnectionBase::HrGetCharacteristics (
  251. DWORD* pdwFlags)
  252. {
  253. Assert (pdwFlags);
  254. DWORD dwFlags = NCCF_OUTGOING_ONLY;
  255. HRESULT hr = HrEnsureEntryPropertiesCached ();
  256. if (SUCCEEDED(hr))
  257. {
  258. if (FIsBranded ())
  259. {
  260. dwFlags |= NCCF_BRANDED;
  261. }
  262. else
  263. {
  264. dwFlags |= (NCCF_ALLOW_RENAME | NCCF_ALLOW_DUPLICATION);
  265. }
  266. if (m_fForAllUsers)
  267. {
  268. dwFlags |= NCCF_ALL_USERS;
  269. }
  270. if (m_dwFlagsPriv & REED_F_Default)
  271. {
  272. dwFlags |= NCCF_DEFAULT;
  273. }
  274. HRESULT hrReason;
  275. if (FAllowRemoval (&hrReason))
  276. {
  277. dwFlags |= NCCF_ALLOW_REMOVAL;
  278. }
  279. if (FShowIcon ())
  280. {
  281. dwFlags |= NCCF_SHOW_ICON;
  282. }
  283. if (S_OK == HrEnsureHNetPropertiesCached())
  284. {
  285. if (m_HNetProperties.fIcsPublic)
  286. {
  287. dwFlags |= NCCF_SHARED;
  288. }
  289. BOOL fIsFirewalled = FALSE;
  290. hr = HrIsConnectionFirewalled(&fIsFirewalled);
  291. if (fIsFirewalled)
  292. {
  293. dwFlags |= NCCF_FIREWALLED;
  294. }
  295. }
  296. }
  297. *pdwFlags = dwFlags;
  298. TraceError ("CRasConnectionBase::HrGetCharacteristics", hr);
  299. return hr;
  300. }
  301. //+---------------------------------------------------------------------------
  302. //
  303. // Member: CRasConnectionBase::HrGetStatus
  304. //
  305. // Purpose: Get the stauts of the connection.
  306. //
  307. // Arguments:
  308. // pStatus [out] NETCON_STATUS
  309. //
  310. // Returns: S_OK or an error code
  311. //
  312. // Author: shaunco 17 Jul 1998
  313. //
  314. // Notes:
  315. //
  316. HRESULT
  317. CRasConnectionBase::HrGetStatus (
  318. NETCON_STATUS* pStatus)
  319. {
  320. Assert (pStatus);
  321. // Initialize output parameters.
  322. //
  323. *pStatus = NCS_DISCONNECTED;
  324. // Find the active RAS connection corresponding to this object if
  325. // it exists.
  326. //
  327. HRASCONN hRasConn;
  328. HRESULT hr = HrFindRasConn (&hRasConn, NULL);
  329. if (S_OK == hr)
  330. {
  331. hr = HrRasGetNetconStatusFromRasConnectStatus (
  332. hRasConn, pStatus);
  333. // When the connection becomes disconnected between HrFindRas
  334. // and HrRasGet calls above, ERROR_INVALID_HANLDE is returned
  335. // this simply means that the connection has been disconnected.
  336. //
  337. if (HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) == hr)
  338. {
  339. Assert (NCS_DISCONNECTED == *pStatus);
  340. hr = S_OK;
  341. }
  342. }
  343. else if (S_FALSE == hr)
  344. {
  345. hr = S_OK;
  346. if (!PszwDeviceName())
  347. {
  348. *pStatus = NCS_HARDWARE_NOT_PRESENT;
  349. }
  350. // NCS_HARDWARE_DISABLED ?
  351. // NCS_HARDWARE_MALFUNCTION ?
  352. }
  353. TraceError ("CRasConnectionBase::HrGetStatus", hr);
  354. return hr;
  355. }
  356. //+---------------------------------------------------------------------------
  357. //
  358. // Member: CRasConnectionBase::HrEnsureEntryPropertiesCached
  359. //
  360. // Purpose: Ensures that the member's corresponding to entry properties
  361. // are cached by calling RasGetEntryProperties if needed.
  362. //
  363. // Arguments:
  364. // (none)
  365. //
  366. // Returns: S_OK or an error code.
  367. //
  368. // Author: shaunco 17 Dec 1997
  369. //
  370. // Notes:
  371. //
  372. HRESULT
  373. CRasConnectionBase::HrEnsureEntryPropertiesCached ()
  374. {
  375. HRESULT hr = S_OK;
  376. // If we're not yet cached, or the cache is possibly out of date, we
  377. // need to update ourselves. g_lRasEntryModifiedVersionEra is the global
  378. // version indicator for RAS phonebook entry modifications. Our local
  379. // version indicator is set in CacheProperties.
  380. //
  381. if (!m_fEntryPropertiesCached ||
  382. (m_lRasEntryModifiedVersionEra != g_lRasEntryModifiedVersionEra))
  383. {
  384. // We now need to enumerate all entries in this phonebook and
  385. // find our details record with the matching guidId.
  386. //
  387. RASENUMENTRYDETAILS* aRasEntryDetails;
  388. DWORD cRasEntryDetails;
  389. // Impersonate the client.
  390. //
  391. HRESULT hrT = CoImpersonateClient ();
  392. TraceHr (ttidError, FAL, hrT, FALSE, "CoImpersonateClient");
  393. // We need to continue if we're called in-proc (ie. if RPC_E_CALL_COMPLETE is returned).
  394. if (SUCCEEDED(hrT) || (RPC_E_CALL_COMPLETE == hrT))
  395. {
  396. hr = HrRasEnumAllEntriesWithDetails (
  397. PszwPbkFile(),
  398. &aRasEntryDetails,
  399. &cRasEntryDetails);
  400. }
  401. if (SUCCEEDED(hrT))
  402. {
  403. hrT = CoRevertToSelf ();
  404. TraceHr (ttidError, FAL, hrT, FALSE, "CoRevertToSelf");
  405. }
  406. if (SUCCEEDED(hr))
  407. {
  408. BOOL fNoGuidYet = (m_guidId == GUID_NULL);
  409. RASENUMENTRYDETAILS* pDetails;
  410. // Assume we don't find the entry.
  411. //
  412. hr = HRESULT_FROM_WIN32 (ERROR_NOT_FOUND);
  413. for (DWORD i = 0; i < cRasEntryDetails; i++)
  414. {
  415. pDetails = &aRasEntryDetails[i];
  416. if (pDetails->guidId == m_guidId)
  417. {
  418. CacheProperties (pDetails);
  419. hr = S_OK;
  420. TraceTag (ttidWanCon,
  421. "HrRasEnumAllEntriesWithDetails found entry "
  422. "via guid (%S)",
  423. PszwEntryName());
  424. break;
  425. }
  426. else if (fNoGuidYet &&
  427. !lstrcmpW (PszwEntryName(), pDetails->szEntryName))
  428. {
  429. CacheProperties (pDetails);
  430. hr = S_OK;
  431. TraceTag (ttidWanCon,
  432. "HrRasEnumAllEntriesWithDetails found entry "
  433. "via entryname (%S)",
  434. PszwEntryName());
  435. break;
  436. }
  437. }
  438. MemFree (aRasEntryDetails);
  439. }
  440. else if (HRESULT_FROM_WIN32(ERROR_CANNOT_OPEN_PHONEBOOK) == hr)
  441. {
  442. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  443. }
  444. }
  445. TraceError ("CRasConnectionBase::HrEnsureEntryPropertiesCached", hr);
  446. return hr;
  447. }
  448. //+---------------------------------------------------------------------------
  449. //
  450. // Member: CRasConnectionBase::HrFindRasConn
  451. //
  452. // Purpose: Searches for the active RAS connection that corresponds to
  453. // this phone book and entry.
  454. //
  455. // Arguments:
  456. // phRasConn [out] The returned handle to the RAS connection if it
  457. // was found. NULL otherwise.
  458. // pRasConn [out] Optional pointer to returned RASCONN structure
  459. // if found.
  460. //
  461. // Returns: S_OK if found, S_FALSE if not, or an error code.
  462. //
  463. // Author: shaunco 29 Sep 1997
  464. //
  465. // Notes:
  466. //
  467. HRESULT
  468. CRasConnectionBase::HrFindRasConn (
  469. OUT HRASCONN* phRasConn,
  470. OUT RASCONN* pRasConn OPTIONAL)
  471. {
  472. Assert (phRasConn);
  473. Assert (m_fInitialized);
  474. HRESULT hr = S_OK;
  475. // Initialize the output parameter.
  476. //
  477. *phRasConn = NULL;
  478. // We need m_guidId to be valid. If it is GUID_NULL, it means
  479. // we have an entry name with with to look it up.
  480. //
  481. if (GUID_NULL == m_guidId)
  482. {
  483. hr = HrEnsureEntryPropertiesCached ();
  484. }
  485. if (SUCCEEDED(hr))
  486. {
  487. hr = HrFindRasConnFromGuidId (&m_guidId, phRasConn, pRasConn);
  488. }
  489. TraceError ("CRasConnectionBase::HrFindRasConn",
  490. (S_FALSE == hr) ? S_OK : hr);
  491. return hr;
  492. }
  493. //+---------------------------------------------------------------------------
  494. //
  495. // Member: CRasConnectionBase::HrLockAndRenameEntry
  496. //
  497. // Purpose: Renames the phone book entry and updates our entry name
  498. // member atomically.
  499. //
  500. // Arguments:
  501. // pszwNewName [in] The new name.
  502. // pObj [in] Used to Lock the operation.
  503. //
  504. // Returns: S_OK or an error code.
  505. //
  506. // Author: shaunco 23 Sep 1997
  507. //
  508. // Notes:
  509. //
  510. HRESULT
  511. CRasConnectionBase::HrLockAndRenameEntry (
  512. PCWSTR pszwNewName,
  513. CComObjectRootEx <CComMultiThreadModel>* pObj)
  514. {
  515. // Make sure the name is valid in the same phone book.
  516. //
  517. DWORD dwErr = RasValidateEntryName (PszwPbkFile (), pszwNewName);
  518. HRESULT hr = HRESULT_FROM_WIN32 (dwErr);
  519. TraceHr (ttidError, FAL, hr,
  520. HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr,
  521. "RasValidateEntryName", hr);
  522. // We can ignore ERROR_ALREADY_EXISTS as it will happen when a user
  523. // tries to change the case of the entry name.
  524. //
  525. if (SUCCEEDED(hr) || (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr))
  526. {
  527. hr = HrEnsureEntryPropertiesCached ();
  528. if (SUCCEEDED(hr))
  529. {
  530. // Lock the object and rename it.
  531. //
  532. CExceptionSafeComObjectLock EsLock (pObj);
  533. dwErr = RasRenameEntry (
  534. PszwPbkFile (),
  535. PszwEntryName (),
  536. pszwNewName);
  537. hr = HRESULT_FROM_WIN32 (dwErr);
  538. TraceHr (ttidError, FAL, hr, FALSE, "RasRenameEntry");
  539. if (SUCCEEDED(hr))
  540. {
  541. SetEntryName (pszwNewName);
  542. }
  543. }
  544. }
  545. TraceHr (ttidError, FAL, hr, FALSE,
  546. "CRasConnectionBase::HrLockAndRenameEntry");
  547. return hr;
  548. }
  549. //+---------------------------------------------------------------------------
  550. //
  551. // Member: CRasConnectionBase::HrGetRasConnectionInfo
  552. //
  553. // Purpose: Implementation of INetRasConnection::GetRasConnectionInfo
  554. //
  555. // Arguments:
  556. // pRasConInfo [out] pointer to returned info
  557. //
  558. // Returns: S_OK or E_OUTOFMEMORY.
  559. //
  560. // Author: shaunco 20 Oct 1997
  561. //
  562. // Notes:
  563. //
  564. HRESULT
  565. CRasConnectionBase::HrGetRasConnectionInfo (
  566. RASCON_INFO* pRasConInfo)
  567. {
  568. Assert (m_fInitialized);
  569. HRESULT hr;
  570. // Validate parameters.
  571. //
  572. if (!pRasConInfo)
  573. {
  574. hr = E_POINTER;
  575. }
  576. else
  577. {
  578. hr = HrEnsureEntryPropertiesCached ();
  579. if (SUCCEEDED(hr))
  580. {
  581. ZeroMemory (pRasConInfo, sizeof (*pRasConInfo));
  582. hr = S_OK;
  583. HRESULT hrT;
  584. hrT = HrCoTaskMemAllocAndDupSz (PszwPbkFile(),
  585. &pRasConInfo->pszwPbkFile);
  586. if (FAILED(hrT))
  587. {
  588. hr = hrT;
  589. }
  590. hrT = HrCoTaskMemAllocAndDupSz (PszwEntryName(),
  591. &pRasConInfo->pszwEntryName);
  592. if (FAILED(hrT))
  593. {
  594. hr = hrT;
  595. }
  596. pRasConInfo->guidId = m_guidId;
  597. if (FAILED(hr))
  598. {
  599. RciFree (pRasConInfo);
  600. AssertSz (!pRasConInfo->pszwPbkFile && !pRasConInfo->pszwEntryName,
  601. "RciFree should be zeroing the structure!");
  602. }
  603. }
  604. }
  605. TraceError ("CRasConnectionBase::HrGetRasConnectionInfo", hr);
  606. return hr;
  607. }
  608. //+---------------------------------------------------------------------------
  609. //
  610. // Member: CRasConnectionBase::HrSetRasConnectionInfo
  611. //
  612. // Purpose: Implementation of INetRasConnection::SetRasConnectionInfo
  613. //
  614. // Arguments:
  615. // pRasConInfo [in] info to set
  616. //
  617. // Returns: S_OK
  618. //
  619. // Author: shaunco 20 Oct 1997
  620. //
  621. // Notes:
  622. //
  623. HRESULT
  624. CRasConnectionBase::HrSetRasConnectionInfo (
  625. const RASCON_INFO* pRasConInfo)
  626. {
  627. Assert (!m_fInitialized);
  628. HRESULT hr = S_OK;
  629. // Validate parameters.
  630. //
  631. if (!pRasConInfo)
  632. {
  633. hr = E_POINTER;
  634. }
  635. else if (!pRasConInfo->pszwPbkFile ||
  636. (0 == lstrlenW (pRasConInfo->pszwPbkFile)) ||
  637. !pRasConInfo->pszwEntryName ||
  638. (0 == lstrlenW (pRasConInfo->pszwEntryName)))
  639. {
  640. hr = E_INVALIDARG;
  641. }
  642. else
  643. {
  644. SetPbkFile (pRasConInfo->pszwPbkFile);
  645. SetEntryName (pRasConInfo->pszwEntryName);
  646. m_guidId = pRasConInfo->guidId;
  647. // We are now a full-fledged object.
  648. //
  649. m_fInitialized = TRUE;
  650. }
  651. TraceError ("CRasConnectionBase::HrSetRasConnectionInfo", hr);
  652. return hr;
  653. }
  654. //+---------------------------------------------------------------------------
  655. //
  656. // Member: CRasConnectionBase::HrGetRasConnectionHandle
  657. //
  658. // Purpose: Implementation of INetRasConnection::HrGetRasConnectionHandle
  659. //
  660. // Arguments:
  661. // phRasConn [out] pointer to the returned RAS connection handle
  662. //
  663. // Returns: S_OK if connected, S_FALSE if not, error code otherwise.
  664. //
  665. // Author: CWill 09 Dec 1997
  666. //
  667. // Notes:
  668. //
  669. HRESULT
  670. CRasConnectionBase::HrGetRasConnectionHandle (
  671. HRASCONN* phRasConn)
  672. {
  673. HRESULT hr;
  674. // Validate parameters.
  675. //
  676. if (!phRasConn)
  677. {
  678. hr = E_POINTER;
  679. }
  680. else if (!m_fInitialized)
  681. {
  682. hr = E_UNEXPECTED;
  683. }
  684. else
  685. {
  686. // Initialize the output parameter.
  687. //
  688. *phRasConn = 0;
  689. hr = HrFindRasConn (phRasConn, NULL);
  690. }
  691. TraceError ("CRasConnectionBase::HrGetRasConnectionHandle",
  692. (S_FALSE == hr) ? S_OK : hr);
  693. return hr;
  694. }
  695. //+---------------------------------------------------------------------------
  696. // IPersistNetConnection -
  697. //
  698. // For our persistent (across session) data, we choose to store only the
  699. // the phonebook name and the guid Id of the RAS entry. We explicitly don't
  700. // store the entry name because it can be changed externally. If it were
  701. // we would have an orhpaned connection.
  702. //
  703. // When loading the connection from the persistent store, we need to
  704. // enumerate all of the entries in the given phonebook looking for the one
  705. // with the matching guid Id. Once found, the connection can successfully
  706. // be loaded.
  707. //
  708. // Lead and trail characters for our persistent memory form.
  709. //
  710. static const WCHAR c_chwLead = 0x14;
  711. static const WCHAR c_chwTrail = 0x05;
  712. //+---------------------------------------------------------------------------
  713. //
  714. // Member: CRasConnectionBase::HrPersistGetSizeMax
  715. //
  716. // Purpose: Implementation of IPersistNetConnection::GetSizeMax
  717. //
  718. // Arguments:
  719. // pcbSize []
  720. //
  721. // Returns: S_OK or an error code
  722. //
  723. // Author: shaunco 4 Nov 1997
  724. //
  725. // Notes:
  726. //
  727. HRESULT
  728. CRasConnectionBase::HrPersistGetSizeMax (
  729. ULONG* pcbSize)
  730. {
  731. HRESULT hr = S_OK;
  732. // Validate parameters.
  733. //
  734. if (!pcbSize)
  735. {
  736. hr = E_POINTER;
  737. }
  738. else if (!m_fInitialized)
  739. {
  740. hr = E_UNEXPECTED;
  741. }
  742. else
  743. {
  744. // Size the buffer for the following form:
  745. // +--------------------------------------------+
  746. // |0x14<phonebook file>\0<guid Id>\0<users>0x05|
  747. // +--------------------------------------------+
  748. //
  749. *pcbSize = sizeof (c_chwLead) +
  750. CbOfSzAndTerm (PszwPbkFile()) +
  751. sizeof (m_guidId) +
  752. sizeof (m_fForAllUsers) +
  753. sizeof (c_chwTrail);
  754. }
  755. TraceError ("CRasConnectionBase::HrPersistGetSizeMax", hr);
  756. return hr;
  757. }
  758. //+---------------------------------------------------------------------------
  759. //
  760. // Member: CRasConnectionBase::HrPersistLoad
  761. //
  762. // Purpose: Implementation of IPersistNetConnection::Load
  763. //
  764. // Arguments:
  765. // pbBuf []
  766. // cbSize []
  767. //
  768. // Returns: S_OK or an error code
  769. //
  770. // Author: shaunco 4 Nov 1997
  771. //
  772. // Notes:
  773. //
  774. HRESULT
  775. CRasConnectionBase::HrPersistLoad (
  776. const BYTE* pbBuf,
  777. ULONG cbSize)
  778. {
  779. TraceFileFunc(ttidWanCon);
  780. // The theoretical minimum size for the buffer is:
  781. // (4 characters for a minimal path like 'c:\a')
  782. //
  783. const ULONG c_cbSizeMin = sizeof (c_chwLead) +
  784. (4 + 1) * sizeof(WCHAR) +
  785. sizeof (m_guidId) +
  786. sizeof (m_fForAllUsers) +
  787. sizeof (c_chwTrail);
  788. HRESULT hr = E_INVALIDARG;
  789. // Validate parameters.
  790. //
  791. if (!pbBuf)
  792. {
  793. hr = E_POINTER;
  794. }
  795. else if (cbSize < c_cbSizeMin)
  796. {
  797. hr = E_INVALIDARG;
  798. }
  799. // We can only accept one call on this method and only if we're not
  800. // already initialized.
  801. //
  802. else if (m_fInitialized)
  803. {
  804. hr = E_UNEXPECTED;
  805. }
  806. else
  807. {
  808. // The buffer *should* look like this:
  809. // +--------------------------------------------+
  810. // |0x14<phonebook file>\0<guid Id>\0<users>0x05|
  811. // +--------------------------------------------+
  812. //
  813. const WCHAR* pchw = reinterpret_cast<const WCHAR*>(pbBuf);
  814. const WCHAR* pchwMax;
  815. PCWSTR pszwPhonebook;
  816. GUID guidId;
  817. const GUID* pguidId;
  818. BOOL fForAllUsers;
  819. const BOOL* pfForAllUsers;
  820. // The last valid pointer for the embedded strings.
  821. //
  822. pchwMax = reinterpret_cast<const WCHAR*>(pbBuf + cbSize
  823. - (sizeof (m_guidId) +
  824. sizeof (m_fForAllUsers) +
  825. sizeof (c_chwTrail)));
  826. if (c_chwLead != *pchw)
  827. {
  828. goto finished;
  829. }
  830. // Skip past our lead byte.
  831. //
  832. pchw++;
  833. // Get m_strPbkFile. Search for the terminating null and make sure
  834. // we find it before the end of the buffer. Using lstrlen to skip
  835. // the string can result in an an AV in the event the string is
  836. // not actually null-terminated.
  837. //
  838. for (pszwPhonebook = pchw; ; pchw++)
  839. {
  840. if (pchw >= pchwMax)
  841. {
  842. goto finished;
  843. }
  844. if (0 == *pchw)
  845. {
  846. pchw++;
  847. break;
  848. }
  849. }
  850. // Get m_guidId
  851. //
  852. pguidId = reinterpret_cast<const GUID*>(pchw);
  853. CopyMemory(&guidId, pguidId, sizeof(guidId));
  854. pguidId++;
  855. // Get m_fForAllUsers
  856. //
  857. pfForAllUsers = reinterpret_cast<const BOOL*>(pguidId);
  858. CopyMemory(&fForAllUsers, pfForAllUsers, sizeof(fForAllUsers));
  859. pfForAllUsers++;
  860. // Check our trail byte.
  861. //
  862. pchw = reinterpret_cast<const WCHAR*>(pfForAllUsers);
  863. if (c_chwTrail != *pchw)
  864. {
  865. goto finished;
  866. }
  867. TraceTag (ttidWanCon, "HrPersistLoad for %S", pszwPhonebook);
  868. SetPbkFile (pszwPhonebook);
  869. m_fForAllUsers = fForAllUsers;
  870. m_guidId = guidId;
  871. // We are now a full-fledged object.
  872. //
  873. m_fInitialized = TRUE;
  874. hr = S_OK;
  875. finished:
  876. ;
  877. }
  878. TraceError ("CRasConnectionBase::HrPersistLoad", hr);
  879. return hr;
  880. }
  881. //+---------------------------------------------------------------------------
  882. //
  883. // Member: CRasConnectionBase::HrPersistSave
  884. //
  885. // Purpose: Implementation of IPersistNetConnection::Save
  886. //
  887. // Arguments:
  888. // pbBuf []
  889. // cbSize []
  890. //
  891. // Returns: S_OK or an error code
  892. //
  893. // Author: shaunco 4 Nov 1997
  894. //
  895. // Notes:
  896. //
  897. HRESULT
  898. CRasConnectionBase::HrPersistSave (
  899. BYTE* pbBuf,
  900. ULONG cbSize)
  901. {
  902. HRESULT hr = S_OK;
  903. // Validate parameters.
  904. //
  905. if (!pbBuf)
  906. {
  907. hr = E_POINTER;
  908. }
  909. else if (!m_fInitialized)
  910. {
  911. hr = E_UNEXPECTED;
  912. }
  913. else
  914. {
  915. // Make sure the user's buffer is big enough.
  916. //
  917. ULONG cbSizeRequired;
  918. SideAssert (SUCCEEDED(HrPersistGetSizeMax(&cbSizeRequired)));
  919. if (cbSize < cbSizeRequired)
  920. {
  921. hr = E_INVALIDARG;
  922. }
  923. else
  924. {
  925. TraceTag (ttidWanCon, "HrPersistSave for %S (%S)",
  926. PszwEntryName (),
  927. PszwPbkFile ());
  928. hr = HrEnsureEntryPropertiesCached ();
  929. if (SUCCEEDED(hr))
  930. {
  931. // Make the buffer look like this when we're done:
  932. // +--------------------------------------------+
  933. // |0x14<phonebook file>\0<guid Id>\0<users>0x05|
  934. // +--------------------------------------------+
  935. //
  936. WCHAR* pchw = reinterpret_cast<WCHAR*>(pbBuf);
  937. // Put our lead byte.
  938. //
  939. *pchw = c_chwLead;
  940. pchw++;
  941. // Put m_strPbkFile
  942. //
  943. ULONG cchw = lstrlenW (PszwPbkFile());
  944. lstrcpyW (pchw, PszwPbkFile());
  945. pchw += cchw + 1;
  946. // Put m_guidId
  947. //
  948. GUID* pguidId = reinterpret_cast<GUID*>(pchw);
  949. CopyMemory(pguidId, &GuidId(), sizeof(*pguidId));
  950. pguidId++;
  951. // Put m_fForAllUsers
  952. //
  953. BOOL* pfForAllUsers = reinterpret_cast<BOOL*>(pguidId);
  954. CopyMemory(pfForAllUsers, &m_fForAllUsers, sizeof(*pfForAllUsers));
  955. pfForAllUsers++;
  956. // Put our trail byte.
  957. //
  958. pchw = reinterpret_cast<WCHAR*>(pfForAllUsers);
  959. *pchw = c_chwTrail;
  960. pchw++;
  961. AssertSz (pbBuf + cbSizeRequired == (BYTE*)pchw,
  962. "pch isn't pointing where it should be.");
  963. }
  964. }
  965. }
  966. TraceError ("CRasConnectionBase::HrPersistSave", hr);
  967. return hr;
  968. }
  969. //+---------------------------------------------------------------------------
  970. //
  971. // Member: CRasConnectionBase::HrEnsureHNetPropertiesCached
  972. //
  973. // Purpose: Makes sure home networking properties are up-to-date
  974. //
  975. // Arguments:
  976. // (none)
  977. //
  978. // Returns: S_OK if m_pHNetProperties is now valid (success)
  979. // S_FALSE if it's not currently possible to update the properties
  980. // (e.g., recursive attempt to update)
  981. //
  982. // Author: jonburs 16 August 2000
  983. //
  984. // Notes:
  985. //
  986. HRESULT
  987. CRasConnectionBase::HrEnsureHNetPropertiesCached ()
  988. {
  989. HRESULT hr = S_OK;
  990. if (!m_fHNetPropertiesCached
  991. || m_lHNetModifiedEra != g_lHNetModifiedEra)
  992. {
  993. //
  994. // Our cached properties are possibly out of date. Check
  995. // to see that this is not a recursive entry
  996. //
  997. if (0 == InterlockedExchange(&m_lUpdatingHNetProperties, 1))
  998. {
  999. IHNetConnection *pHNetConn;
  1000. HNET_CONN_PROPERTIES *pProps;
  1001. hr = HrGetIHNetConnection(&pHNetConn);
  1002. if (SUCCEEDED(hr))
  1003. {
  1004. hr = pHNetConn->GetProperties(&pProps);
  1005. ReleaseObj(pHNetConn);
  1006. if (SUCCEEDED(hr))
  1007. {
  1008. //
  1009. // Copy retrieved properties to member structure.
  1010. //
  1011. CopyMemory(
  1012. reinterpret_cast<PVOID>(&m_HNetProperties),
  1013. reinterpret_cast<PVOID>(pProps),
  1014. sizeof(m_HNetProperties)
  1015. );
  1016. CoTaskMemFree(pProps);
  1017. //
  1018. // Update our era, and note that we have valid properties
  1019. //
  1020. InterlockedExchange(&m_lHNetModifiedEra, g_lHNetModifiedEra);
  1021. m_fHNetPropertiesCached = TRUE;
  1022. hr = S_OK;
  1023. }
  1024. }
  1025. else
  1026. {
  1027. //
  1028. // If we don't yet have a record of this connection w/in the
  1029. // home networking store, HrGetIHNetConnection will fail (as
  1030. // we ask it not to create new entries). We therefore convert
  1031. // failure to S_FALSE, which means we can't retrieve this info
  1032. // right now.
  1033. //
  1034. hr = S_FALSE;
  1035. }
  1036. //
  1037. // We're no longer updating our properties
  1038. //
  1039. InterlockedExchange(&m_lUpdatingHNetProperties, 0);
  1040. }
  1041. else
  1042. {
  1043. //
  1044. // Update is alredy going on (possibly an earlier call on
  1045. // the same thread). Return S_FALSE.
  1046. //
  1047. hr = S_FALSE;
  1048. }
  1049. }
  1050. return hr;
  1051. }
  1052. //+---------------------------------------------------------------------------
  1053. //
  1054. // Member: HrGetIHNetConnection
  1055. //
  1056. // Purpose: Retrieves the IHNetConnection for this connection
  1057. //
  1058. // Arguments:
  1059. //
  1060. // Returns: S_OK on success; error otherwise
  1061. //
  1062. // Author: jonburs 16 August 2000
  1063. //
  1064. // Notes:
  1065. //
  1066. HRESULT CRasConnectionBase::HrGetIHNetConnection (
  1067. IHNetConnection **ppHNetConnection)
  1068. {
  1069. HRESULT hr;
  1070. IHNetCfgMgr *pCfgMgr;
  1071. GUID guid;
  1072. Assert(ppHNetConnection);
  1073. hr = HrGetHNetCfgMgr(&pCfgMgr);
  1074. if (SUCCEEDED(hr))
  1075. {
  1076. guid = GuidId();
  1077. hr = pCfgMgr->GetIHNetConnectionForGuid(
  1078. &guid,
  1079. FALSE,
  1080. FALSE,
  1081. ppHNetConnection
  1082. );
  1083. ReleaseObj(pCfgMgr);
  1084. }
  1085. return hr;
  1086. }
  1087. //+---------------------------------------------------------------------------
  1088. //
  1089. // Member: HrGetIHNetConnection
  1090. //
  1091. // Purpose: Retrieves the IHNetConnection for this connection
  1092. //
  1093. // Arguments:
  1094. //
  1095. // Returns: S_OK on success; error otherwise
  1096. //
  1097. // Author: jonburs 16 August 2000
  1098. //
  1099. // Notes:
  1100. //
  1101. HRESULT CRasConnectionBase::HrIsConnectionFirewalled(
  1102. BOOL* pfFirewalled)
  1103. {
  1104. *pfFirewalled = FALSE;
  1105. HRESULT hr = S_OK;
  1106. BOOL fHasPermission = FALSE;
  1107. hr = HrEnsureValidNlaPolicyEngine();
  1108. TraceError("CRasConnectionBase::HrIsConnectionFirewalled calling HrEnsureValidNlaPolicyEngine", hr);
  1109. if (SUCCEEDED(hr))
  1110. {
  1111. // A Connection is only firewalled if the firewall is currently running, so
  1112. // we return FALSE if the permission denies the firewall from running.
  1113. hr = m_pNetMachinePolicies->VerifyPermission(NCPERM_PersonalFirewallConfig, &fHasPermission);
  1114. if (SUCCEEDED(hr) && fHasPermission)
  1115. {
  1116. hr = HrEnsureHNetPropertiesCached();
  1117. if (S_OK == hr)
  1118. {
  1119. *pfFirewalled = m_HNetProperties.fFirewalled;
  1120. }
  1121. }
  1122. }
  1123. return hr;
  1124. }
  1125. HRESULT CRasConnectionBase::HrEnsureValidNlaPolicyEngine()
  1126. {
  1127. HRESULT hr = S_FALSE; // Assume we already have the object
  1128. if (!m_pNetMachinePolicies)
  1129. {
  1130. hr = CoCreateInstance(CLSID_NetGroupPolicies, NULL, CLSCTX_INPROC, IID_INetMachinePolicies, reinterpret_cast<void**>(&m_pNetMachinePolicies));
  1131. }
  1132. return hr;
  1133. }