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.

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