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.

1734 lines
56 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: D I A L U P . C P P
  7. //
  8. // Contents: Implements the dial up connection object.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 23 Sep 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "dialup.h"
  18. #include "nccom.h"
  19. #include "ncnetcon.h"
  20. #include "ncras.h"
  21. #include "ncreg.h"
  22. #include "userenv.h"
  23. #include "cmutil.h"
  24. #include "cobase.h"
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Member: CDialupConnection::CreateInstanceUninitialized
  28. //
  29. // Purpose: Create an uninitialized instance of
  30. // CComObject <CDialupConnection> and return an interface
  31. // pointer as well as a pointer to the CDialupConnection.
  32. //
  33. // Arguments:
  34. // riid [in] IID of desired interface.
  35. // ppv [out] Returned interface pointer.
  36. // ppObj [out] Returned object pointer.
  37. //
  38. // Returns: S_OK or E_OUTOFMEMORY.
  39. //
  40. // Author: shaunco 20 Apr 1998
  41. //
  42. // Notes:
  43. //
  44. //static
  45. HRESULT
  46. CDialupConnection::CreateInstanceUninitialized (
  47. REFIID riid,
  48. VOID** ppv,
  49. CDialupConnection** ppObj)
  50. {
  51. Assert (ppObj);
  52. Assert (ppv);
  53. *ppv = NULL;
  54. *ppObj = NULL;
  55. HRESULT hr = E_OUTOFMEMORY;
  56. CDialupConnection* pObj;
  57. pObj = new CComObject <CDialupConnection>;
  58. if (pObj)
  59. {
  60. // Do the standard CComCreator::CreateInstance stuff.
  61. //
  62. pObj->SetVoid (NULL);
  63. pObj->InternalFinalConstructAddRef ();
  64. hr = pObj->FinalConstruct ();
  65. pObj->InternalFinalConstructRelease ();
  66. if (SUCCEEDED(hr))
  67. {
  68. INetConnection* pCon = static_cast<INetConnection*>(pObj);
  69. hr = pCon->QueryInterface (riid, ppv);
  70. if (SUCCEEDED(hr))
  71. {
  72. *ppObj = pObj;
  73. }
  74. }
  75. if (FAILED(hr))
  76. {
  77. delete pObj;
  78. }
  79. }
  80. TraceError ("CDialupConnection::CreateInstanceFromDetails", hr);
  81. return hr;
  82. }
  83. //+---------------------------------------------------------------------------
  84. //
  85. // Member: CDialupConnection::CreateInstanceFromDetails
  86. //
  87. // Purpose: Create an initialized instance of
  88. // CComObject <CDialupConnection> given RASENUMENTRYDETAILS and
  89. // return an interface pointer on that object.
  90. //
  91. // Arguments:
  92. // pszwPbkFile [in] Path to the phonebook file.
  93. // pszwEntryName [in] Name of the entry in the phonebook.
  94. // fForAllUsers [in] TRUE if this entry is for all users.
  95. // riid [in] IID of desired interface.
  96. // ppv [out] Returned interface pointer.
  97. //
  98. // Returns: S_OK or E_OUTOFMEMORY.
  99. //
  100. // Author: shaunco 23 Sep 1997
  101. //
  102. // Notes:
  103. //
  104. // static
  105. HRESULT
  106. CDialupConnection::CreateInstanceFromDetails (
  107. const RASENUMENTRYDETAILS* pEntryDetails,
  108. REFIID riid,
  109. VOID** ppv)
  110. {
  111. Assert(pEntryDetails);
  112. Assert(pEntryDetails->szPhonebookPath);
  113. CDialupConnection* pObj;
  114. HRESULT hr = CreateInstanceUninitialized (riid, ppv, &pObj);
  115. if (SUCCEEDED(hr))
  116. {
  117. pObj->SetPbkFile (pEntryDetails->szPhonebookPath);
  118. pObj->CacheProperties (pEntryDetails);
  119. // We are now a full-fledged object.
  120. //
  121. pObj->m_fInitialized = TRUE;
  122. }
  123. TraceError ("CDialupConnection::CreateInstanceFromDetails", hr);
  124. return hr;
  125. }
  126. //+---------------------------------------------------------------------------
  127. //
  128. // Member: CDialupConnection::CreateInstanceFromPbkFileAndEntryName
  129. //
  130. // Purpose: Create an initialized instance of
  131. // CComObject <CDialupConnection> given only a phonebook path,
  132. // entry name, and weather it is for all users or not and
  133. // return an interface pointer on that object.
  134. //
  135. // Arguments:
  136. // pszPbkFile [in] Phonebook path.
  137. // pszEntryName [in] Entry name.
  138. // riid [in] IID of desired interface.
  139. // ppv [out] Returned interface pointer.
  140. //
  141. // Returns: S_OK or E_OUTOFMEMORY.
  142. //
  143. // Author: shaunco 20 Apr 1998
  144. //
  145. // Notes: This is called from Duplicate.
  146. //
  147. //static
  148. HRESULT
  149. CDialupConnection::CreateInstanceFromPbkFileAndEntryName (
  150. PCWSTR pszPbkFile,
  151. PCWSTR pszEntryName,
  152. REFIID riid,
  153. VOID** ppv)
  154. {
  155. TraceTag (ttidWanCon,
  156. "CDialupConnection::CreateInstanceFromPbkFileAndEntryName called");
  157. CDialupConnection* pObj;
  158. HRESULT hr = CreateInstanceUninitialized (riid, ppv, &pObj);
  159. if (SUCCEEDED(hr))
  160. {
  161. pObj->SetPbkFile (pszPbkFile);
  162. pObj->SetEntryName (pszEntryName);
  163. pObj->m_guidId = GUID_NULL;
  164. // We are now a full-fledged object.
  165. //
  166. pObj->m_fInitialized = TRUE;
  167. }
  168. TraceError ("CDialupConnection::CreateInstanceFromPbkFileAndEntryName", hr);
  169. return hr;
  170. }
  171. //+---------------------------------------------------------------------------
  172. // INetConnection
  173. //
  174. STDMETHODIMP
  175. CDialupConnection::GetUiObjectClassId (
  176. CLSID* pclsid)
  177. {
  178. HRESULT hr = S_OK;
  179. // Validate parameters.
  180. //
  181. if (!pclsid)
  182. {
  183. hr = E_POINTER;
  184. }
  185. else if (!m_fInitialized)
  186. {
  187. hr = E_UNEXPECTED;
  188. }
  189. else
  190. {
  191. static const CLSID CLSID_DialupConnectionUi =
  192. {0x7007ACC1,0x3202,0x11D1,{0xAA,0xD2,0x00,0x80,0x5F,0xC1,0x27,0x0E}};
  193. static const CLSID CLSID_DirectConnectionUi =
  194. {0x7007ACC2,0x3202,0x11D1,{0xAA,0xD2,0x00,0x80,0x5F,0xC1,0x27,0x0E}};
  195. static const CLSID CLSID_VpnConnectionUi =
  196. {0x7007ACC6,0x3202,0x11D1,{0xAA,0xD2,0x00,0x80,0x5F,0xC1,0x27,0x0E}};
  197. static const CLSID CLSID_PPPoEUi =
  198. {0x7007ACD4,0x3202,0x11D1,{0xAA,0xD2,0x00,0x80,0x5F,0xC1,0x27,0x0E}};
  199. hr = HrEnsureEntryPropertiesCached ();
  200. if (SUCCEEDED(hr))
  201. {
  202. switch (MediaType ())
  203. {
  204. case NCM_DIRECT:
  205. *pclsid = CLSID_DirectConnectionUi;
  206. break;
  207. case NCM_ISDN:
  208. case NCM_PHONE:
  209. *pclsid = CLSID_DialupConnectionUi;
  210. break;
  211. case NCM_TUNNEL:
  212. *pclsid = CLSID_VpnConnectionUi;
  213. break;
  214. case NCM_PPPOE:
  215. *pclsid = CLSID_PPPoEUi;
  216. break;
  217. default:
  218. *pclsid = CLSID_DialupConnectionUi;
  219. TraceTag (ttidWanCon, "GetUiObjectClassId: Unknown media type "
  220. "(%d) treating as CLSID_DialupConnectionUi", MediaType());
  221. }
  222. }
  223. }
  224. TraceError ("CDialupConnection::GetUiObjectClassId", hr);
  225. return hr;
  226. }
  227. STDMETHODIMP
  228. CDialupConnection::Connect ()
  229. {
  230. return E_NOTIMPL;
  231. }
  232. STDMETHODIMP
  233. CDialupConnection::Disconnect ()
  234. {
  235. HRESULT hr;
  236. if (!m_fInitialized)
  237. {
  238. hr = E_UNEXPECTED;
  239. }
  240. else
  241. {
  242. HRASCONN hRasConn;
  243. hr = HrFindRasConn (&hRasConn, NULL);
  244. if (S_OK == hr)
  245. {
  246. // Because RasHangup could call RasCustomHangup
  247. // we need to impersonate the client to allow the correct
  248. // per-user information to be used.
  249. //
  250. // Impersonate the client.
  251. //
  252. HRESULT hrT = CoImpersonateClient ();
  253. TraceErrorOptional ("CDialupConnection::Disconnect -- CoImpersonateClient", hrT, RPC_E_CALL_COMPLETE == hrT);
  254. // We need to continue if we're called in-proc (ie. if RPC_E_CALL_COMPLETE is returned).
  255. if (SUCCEEDED(hrT) || (RPC_E_CALL_COMPLETE == hrT))
  256. {
  257. hr = HrRasHangupUntilDisconnected (hRasConn);
  258. }
  259. if (SUCCEEDED(hrT))
  260. {
  261. hrT = CoRevertToSelf ();
  262. TraceError ("CDialupConnection::Disconnect -- CoRevertToSelf", hrT);
  263. }
  264. }
  265. else if (S_FALSE == hr)
  266. {
  267. hr = S_OK;
  268. }
  269. }
  270. TraceError ("CDialupConnection::Disconnect", hr);
  271. return hr;
  272. }
  273. STDMETHODIMP
  274. CDialupConnection::Delete ()
  275. {
  276. HRESULT hr = E_UNEXPECTED;
  277. if (!m_fInitialized)
  278. {
  279. hr = E_UNEXPECTED;
  280. }
  281. else
  282. {
  283. hr = HrEnsureEntryPropertiesCached ();
  284. if (SUCCEEDED(hr))
  285. {
  286. // If we allow removal (a decision which is based on the
  287. // whether the user is an admin, whether the connection is
  288. // 'for all users', and the connection's current state) then
  289. // proceed. If FAllowRemoval fails, it's output parameter
  290. // is the "reason" in the form of an HRESULT. We can use
  291. // this as our return value in that case.
  292. //
  293. HRESULT hrReason;
  294. if (FAllowRemoval (&hrReason))
  295. {
  296. // If we're active in any way, we can't be removed.
  297. //
  298. NETCON_STATUS status;
  299. hr = HrGetStatus(&status);
  300. if (SUCCEEDED(hr) &&
  301. ((NCS_CONNECTING != status) &&
  302. (NCS_CONNECTED != status) &&
  303. (NCS_DISCONNECTING != status)))
  304. {
  305. // We do an impersonation here in case the connection has a RAS custom delete notification
  306. // setup (CM connections do, for instance). This allows the RasCustomDeleteEntryNotify
  307. // function to interact with the system as the user.
  308. //
  309. HRESULT hrT = CoImpersonateClient ();
  310. TraceError ("HrRemoveCmProfile -- CoImpersonateClient", hrT);
  311. // We need to continue if we're called in-proc (ie. if RPC_E_CALL_COMPLETE is returned).
  312. if (SUCCEEDED(hrT) || (RPC_E_CALL_COMPLETE == hrT))
  313. {
  314. // Delete the RAS entry, note that for branded connections, RAS
  315. // will call RasCustomDeleteEntryNotify after deletion.
  316. //
  317. DWORD dwErr = RasDeleteEntry (PszwPbkFile (), PszwEntryName ());
  318. hr = HRESULT_FROM_WIN32 (dwErr);
  319. TraceError ("RasDeleteEntry", hr);
  320. }
  321. // Revert to ourselves
  322. //
  323. if (SUCCEEDED(hrT))
  324. {
  325. CoRevertToSelf ();
  326. }
  327. }
  328. else
  329. {
  330. // Don't allow deletion unless disconnected
  331. //
  332. TraceTag (ttidWanCon, "Disallowing delete while in connected or"
  333. "partially connected state");
  334. hr = E_UNEXPECTED;
  335. }
  336. }
  337. else
  338. {
  339. hr = hrReason;
  340. }
  341. }
  342. }
  343. TraceError ("CDialupConnection::Delete", hr);
  344. return hr;
  345. }
  346. STDMETHODIMP
  347. CDialupConnection::Duplicate (
  348. PCWSTR pszDuplicateName,
  349. INetConnection** ppCon)
  350. {
  351. HRESULT hr = S_OK;
  352. // Validate parameters.
  353. //
  354. if (!pszDuplicateName || !ppCon)
  355. {
  356. hr = E_POINTER;
  357. }
  358. else if (!m_fInitialized)
  359. {
  360. hr = E_UNEXPECTED;
  361. }
  362. else
  363. {
  364. *ppCon = NULL;
  365. hr = HrEnsureEntryPropertiesCached ();
  366. if (SUCCEEDED(hr))
  367. {
  368. // Make sure the name is valid in the same phone book.
  369. //
  370. DWORD dwErr = RasValidateEntryName (
  371. PszwPbkFile (), pszDuplicateName);
  372. hr = HRESULT_FROM_WIN32 (dwErr);
  373. TraceError ("RasValidateEntryName", hr);
  374. if (SUCCEEDED(hr))
  375. {
  376. dwErr = DwCloneEntry (
  377. PszwPbkFile(),
  378. PszwEntryName(),
  379. pszDuplicateName);
  380. hr = HRESULT_FROM_WIN32 (dwErr);
  381. TraceError ("DwCloneEntry", hr);
  382. if (SUCCEEDED(hr))
  383. {
  384. hr = CreateInstanceFromPbkFileAndEntryName (
  385. PszwPbkFile (),
  386. pszDuplicateName,
  387. IID_INetConnection, (VOID**)ppCon);
  388. if (SUCCEEDED(hr))
  389. {
  390. hr = HrEnsureHNetPropertiesCached();
  391. }
  392. if (SUCCEEDED(hr))
  393. {
  394. if (m_HNetProperties.fFirewalled || m_HNetProperties.fIcsPublic) // lazy eval the hnetcfg stuff
  395. {
  396. IHNetCfgMgr* pHomenetConfigManager;
  397. hr = HrGetHNetCfgMgr(&pHomenetConfigManager);
  398. if(SUCCEEDED(hr))
  399. {
  400. IHNetConnection* pNewHomenetConnection;
  401. hr = pHomenetConfigManager->GetIHNetConnectionForINetConnection(*ppCon, &pNewHomenetConnection);
  402. if(SUCCEEDED(hr))
  403. {
  404. IHNetConnection* pHomenetConnection;
  405. hr = HrGetIHNetConnection(&pHomenetConnection);
  406. if(SUCCEEDED(hr))
  407. {
  408. // copy port bindings
  409. // REVIEW if somethings fails here to we need to nuke the new connection?
  410. IEnumHNetPortMappingBindings* pEnumPortMappingBindings;
  411. hr = pNewHomenetConnection->EnumPortMappings(FALSE, &pEnumPortMappingBindings);
  412. if(SUCCEEDED(hr))
  413. {
  414. ULONG ulFetched;
  415. IHNetPortMappingBinding* pNewPortMappingBinding;
  416. while(S_OK == pEnumPortMappingBindings->Next(1, &pNewPortMappingBinding, &ulFetched))
  417. {
  418. Assert(1 == ulFetched);
  419. IHNetPortMappingProtocol* pPortMappingProtocol;
  420. hr = pNewPortMappingBinding->GetProtocol(&pPortMappingProtocol);
  421. if(SUCCEEDED(hr))
  422. {
  423. // find the original binding by using the protocol field
  424. IHNetPortMappingBinding* pPortMappingBinding;
  425. hr = pHomenetConnection->GetBindingForPortMappingProtocol(pPortMappingProtocol, &pPortMappingBinding);
  426. if(SUCCEEDED(hr))
  427. {
  428. BOOLEAN bEnabled;
  429. hr = pPortMappingBinding->GetEnabled(&bEnabled);
  430. if(SUCCEEDED(hr))
  431. {
  432. if(TRUE == bEnabled)
  433. {
  434. hr = pNewPortMappingBinding->SetEnabled(bEnabled);
  435. }
  436. }
  437. // always set the computer address
  438. if(SUCCEEDED(hr))
  439. {
  440. ULONG ulAddress;
  441. hr = pPortMappingBinding->GetTargetComputerAddress(&ulAddress);
  442. if(SUCCEEDED(hr))
  443. {
  444. if(0 != ulAddress)
  445. {
  446. hr = pNewPortMappingBinding->SetTargetComputerAddress(ulAddress);
  447. }
  448. }
  449. }
  450. // only set the computer name if it is used
  451. if(SUCCEEDED(hr))
  452. {
  453. BOOLEAN bUseName;
  454. hr = pPortMappingBinding->GetCurrentMethod(&bUseName);
  455. if(SUCCEEDED(hr) && TRUE == bUseName)
  456. {
  457. OLECHAR* pszTargetComputerName;
  458. hr = pPortMappingBinding->GetTargetComputerName(&pszTargetComputerName);
  459. if(SUCCEEDED(hr))
  460. {
  461. if(L'\0' != *pszTargetComputerName)
  462. {
  463. hr = pNewPortMappingBinding->SetTargetComputerName(pszTargetComputerName);
  464. }
  465. CoTaskMemFree(pszTargetComputerName);
  466. }
  467. }
  468. }
  469. ReleaseObj(pPortMappingBinding);
  470. }
  471. ReleaseObj(pPortMappingProtocol);
  472. }
  473. ReleaseObj(pNewPortMappingBinding);
  474. }
  475. ReleaseObj(pEnumPortMappingBindings);
  476. }
  477. if(m_HNetProperties.fFirewalled) // copy firewall yes/no and ICMP settings
  478. {
  479. IHNetFirewalledConnection* pFirewalledConnection;
  480. hr = pNewHomenetConnection->Firewall(&pFirewalledConnection);
  481. if(SUCCEEDED(hr))
  482. {
  483. HNET_FW_ICMP_SETTINGS* pICMPSettings;
  484. hr = pHomenetConnection->GetIcmpSettings(&pICMPSettings);
  485. if(SUCCEEDED(hr))
  486. {
  487. hr = pNewHomenetConnection->SetIcmpSettings(pICMPSettings);
  488. CoTaskMemFree(pICMPSettings);
  489. }
  490. ReleaseObj(pFirewalledConnection);
  491. }
  492. }
  493. ReleaseObj(pHomenetConnection);
  494. }
  495. ReleaseObj(pNewHomenetConnection);
  496. }
  497. ReleaseObj(pHomenetConfigManager);
  498. }
  499. }
  500. }
  501. }
  502. }
  503. }
  504. }
  505. TraceError ("CDialupConnection::Duplicate", hr);
  506. return hr;
  507. }
  508. STDMETHODIMP
  509. CDialupConnection::GetProperties (
  510. NETCON_PROPERTIES** ppProps)
  511. {
  512. HRESULT hr = S_OK;
  513. HRESULT hrHiddenCM = S_OK;
  514. CMEntry cm;
  515. // Validate parameters.
  516. //
  517. if (!ppProps)
  518. {
  519. hr = E_POINTER;
  520. }
  521. else if (!m_fInitialized)
  522. {
  523. hr = E_UNEXPECTED;
  524. }
  525. else
  526. {
  527. // Initialize the output parameter.
  528. //
  529. *ppProps = NULL;
  530. hr = HrEnsureEntryPropertiesCached ();
  531. if (SUCCEEDED(hr))
  532. {
  533. NETCON_PROPERTIES* pProps;
  534. hr = HrCoTaskMemAlloc (sizeof (NETCON_PROPERTIES),
  535. reinterpret_cast<VOID**>(&pProps));
  536. if (SUCCEEDED(hr))
  537. {
  538. HRESULT hrT;
  539. ZeroMemory (pProps, sizeof (NETCON_PROPERTIES));
  540. // guidId
  541. //
  542. pProps->guidId = GuidId ();
  543. // pszwName
  544. //
  545. hrT = HrCoTaskMemAllocAndDupSz (
  546. PszwEntryName(),
  547. &pProps->pszwName);
  548. if (FAILED(hrT))
  549. {
  550. hr = hrT;
  551. }
  552. hrT = HrCoTaskMemAllocAndDupSz (
  553. PszwDeviceName(),
  554. &pProps->pszwDeviceName);
  555. if (FAILED(hrT))
  556. {
  557. hr = hrT;
  558. }
  559. // Status
  560. //
  561. hrT = HrGetStatus (&pProps->Status);
  562. if (FAILED(hrT))
  563. {
  564. hr = hrT;
  565. }
  566. // Verify that the status return is accurate. HrGetStatus returns NCS_DISCONNECTED
  567. // if the connectoid is NCS_CONNECTING, which is wrong!!!!.
  568. //
  569. if( pProps->Status == NCS_DISCONNECTED )
  570. {
  571. // CMUtil remebers the Hidden connection (Connection Manager) and the status of
  572. // any ras events (i.e. Connecting, Disconnecting etc). The Data is filled in
  573. // in function RasEventNotify.
  574. //
  575. hrHiddenCM = CCMUtil::Instance().HrGetEntry(pProps->guidId,cm);
  576. if ( S_OK == hrHiddenCM )
  577. {
  578. // Use CCMUtil's status, its more accurate.
  579. //
  580. pProps->Status = cm.m_ncs;
  581. }
  582. }
  583. // Check if this connection has a child connection
  584. //
  585. hrHiddenCM = CCMUtil::Instance().HrGetEntry(PszwEntryName(),cm);
  586. if( hrHiddenCM == S_OK )
  587. {
  588. // It has a child connectoid
  589. // Now we have to determine which one describes the overall status of the connection
  590. //
  591. if( cm.m_ncs == NCS_CONNECTING || cm.m_ncs == NCS_DISCONNECTING ||
  592. cm.m_ncs == NCS_CONNECTED)
  593. {
  594. if( pProps->Status == NCS_DISCONNECTING )
  595. {
  596. // This case happens if the parent is disconnecting
  597. // The parent is disconnecting, so the child will be disconnecting.
  598. // Change the status of the child to disconnecting so that we do not
  599. // get confused later on when the child is connected at the parent is
  600. // disconnected. i.e. are we overall connecting or disconnecting!!!!
  601. //
  602. CCMUtil::Instance().SetEntry(GuidId (), PszwEntryName(),pProps->Status);
  603. }
  604. else
  605. if( cm.m_ncs == NCS_CONNECTED && pProps->Status == NCS_DISCONNECTED )
  606. {
  607. // This case will only happen if the child is connected and the parent is still
  608. // disconnected.
  609. //
  610. pProps->Status = NCS_CONNECTING;
  611. }
  612. else if (!IsEqualGUID(pProps->guidId, cm.m_guid))
  613. {
  614. TraceTag(ttidWanCon, "Overwriting parent connection status: %s with child status: %s", DbgNcs(pProps->Status), DbgNcs(cm.m_ncs));
  615. // When in doubt and the GUID's are different (ie. not a BAP/Multilink connection) take the childs status =)
  616. //
  617. pProps->Status = cm.m_ncs;
  618. }
  619. }
  620. }
  621. // Type
  622. //
  623. pProps->MediaType = MediaType ();
  624. // dwCharacter
  625. //
  626. hrT = HrGetCharacteristics (&pProps->dwCharacter);
  627. if (FAILED(hrT))
  628. {
  629. hr = hrT;
  630. }
  631. // clsidThisObject
  632. //
  633. pProps->clsidThisObject = CLSID_DialupConnection;
  634. // clsidUiObject
  635. //
  636. hrT = GetUiObjectClassId (&pProps->clsidUiObject);
  637. if (FAILED(hrT))
  638. {
  639. hr = hrT;
  640. }
  641. // Assign the output parameter or cleanup if we had any failures.
  642. //
  643. if (SUCCEEDED(hr))
  644. {
  645. *ppProps = pProps;
  646. }
  647. else
  648. {
  649. Assert (NULL == *ppProps);
  650. FreeNetconProperties (pProps);
  651. }
  652. }
  653. }
  654. }
  655. TraceError ("CDialupConnection::GetProperties", hr);
  656. return hr;
  657. }
  658. STDMETHODIMP
  659. CDialupConnection::Rename (
  660. PCWSTR pszNewName)
  661. {
  662. HRESULT hr;
  663. // Validate parameters.
  664. //
  665. if (!pszNewName)
  666. {
  667. hr = E_POINTER;
  668. }
  669. else if (!m_fInitialized)
  670. {
  671. hr = E_UNEXPECTED;
  672. }
  673. else
  674. {
  675. hr = HrLockAndRenameEntry (pszNewName, this);
  676. }
  677. TraceError ("CDialupConnection::Rename", hr);
  678. return hr;
  679. }
  680. //+---------------------------------------------------------------------------
  681. // INetRasConnection
  682. //
  683. STDMETHODIMP
  684. CDialupConnection::GetRasConnectionInfo (
  685. RASCON_INFO* pRasConInfo)
  686. {
  687. HRESULT hr = HrGetRasConnectionInfo (pRasConInfo);
  688. TraceError ("CDialupConnection::GetRasConnectionInfo", hr);
  689. return hr;
  690. }
  691. STDMETHODIMP
  692. CDialupConnection::SetRasConnectionInfo (
  693. const RASCON_INFO* pRasConInfo)
  694. {
  695. HRESULT hr = HrSetRasConnectionInfo (pRasConInfo);
  696. TraceError ("CDialupConnection::SetRasConnectionInfo", hr);
  697. return hr;
  698. }
  699. STDMETHODIMP
  700. CDialupConnection::GetRasConnectionHandle (
  701. ULONG_PTR* phRasConn)
  702. {
  703. HRESULT hr = HrGetRasConnectionHandle (
  704. reinterpret_cast<HRASCONN*>(phRasConn));
  705. TraceError ("CDialupConnection::GetRasConnectionHandle",
  706. (S_FALSE == hr) ? S_OK : hr);
  707. return hr;
  708. }
  709. //+---------------------------------------------------------------------------
  710. // IPersistNetConnection
  711. //
  712. STDMETHODIMP
  713. CDialupConnection::GetClassID (
  714. CLSID* pclsid)
  715. {
  716. HRESULT hr = S_OK;
  717. // Validate parameters.
  718. //
  719. if (!pclsid)
  720. {
  721. hr = E_POINTER;
  722. }
  723. else
  724. {
  725. *pclsid = CLSID_DialupConnection;
  726. }
  727. TraceError ("CDialupConnection::GetClassID", hr);
  728. return hr;
  729. }
  730. STDMETHODIMP
  731. CDialupConnection::GetSizeMax (
  732. ULONG* pcbSize)
  733. {
  734. HRESULT hr = HrPersistGetSizeMax (pcbSize);
  735. TraceError ("CDialupConnection::GetSizeMax", hr);
  736. return hr;
  737. }
  738. STDMETHODIMP
  739. CDialupConnection::Load (
  740. const BYTE* pbBuf,
  741. ULONG cbSize)
  742. {
  743. HRESULT hr = HrPersistLoad (pbBuf, cbSize);
  744. TraceError ("CDialupConnection::Load", hr);
  745. return hr;
  746. }
  747. STDMETHODIMP
  748. CDialupConnection::Save (
  749. BYTE* pbBuf,
  750. ULONG cbSize)
  751. {
  752. HRESULT hr = HrPersistSave (pbBuf, cbSize);
  753. TraceError ("CDialupConnection::Save", hr);
  754. return hr;
  755. }
  756. //+---------------------------------------------------------------------------
  757. // INetConnectionBrandingInfo
  758. //
  759. //+---------------------------------------------------------------------------
  760. //
  761. // Member: CDialupConnection::GetBrandingIconPaths
  762. //
  763. // Purpose: Returns the full paths to three icons.
  764. //
  765. // Arguments: pConBrandInfo - pointer to an Icon branding structure
  766. //
  767. // Returns: S_OK or an error code
  768. //
  769. STDMETHODIMP
  770. CDialupConnection::GetBrandingIconPaths(
  771. CON_BRANDING_INFO ** ppConBrandInfo)
  772. {
  773. HRESULT hr = HrEnsureEntryPropertiesCached ();
  774. CON_BRANDING_INFO * pConBrandInfo = NULL;
  775. Assert(ppConBrandInfo);
  776. if (SUCCEEDED(hr))
  777. {
  778. if (!FIsBranded ())
  779. {
  780. hr = E_NOTIMPL;
  781. }
  782. else
  783. {
  784. WCHAR szTemp[MAX_PATH+1];
  785. WCHAR szIconName[MAX_PATH+1];
  786. const WCHAR* const CMSECTION = L"Connection Manager";
  787. HICON hIcon;
  788. hr = HrCoTaskMemAlloc(sizeof(CON_BRANDING_INFO), (LPVOID*)&pConBrandInfo);
  789. if (SUCCEEDED(hr))
  790. {
  791. ZeroMemory(pConBrandInfo, sizeof(CON_BRANDING_INFO));
  792. // Get the path to the cms file to get the Icon entries from.
  793. //
  794. hr = HrEnsureCmStringsLoaded();
  795. if (SUCCEEDED(hr))
  796. {
  797. // Get the Large Icon path
  798. //
  799. if (0 != GetPrivateProfileStringW(CMSECTION, L"Icon", L"",
  800. szIconName, celems(szIconName), PszwCmsFile ()))
  801. {
  802. lstrcpynW(szTemp, PszwCmDir (), celems(szTemp));
  803. lstrcatW(szTemp, szIconName);
  804. if (NULL != (hIcon = (HICON)LoadImage(NULL, szTemp, IMAGE_ICON, 32, 32, LR_LOADFROMFILE)))
  805. {
  806. DestroyIcon(hIcon);
  807. hr = HrCoTaskMemAllocAndDupSz (szTemp, &(pConBrandInfo->szwLargeIconPath));
  808. }
  809. }
  810. // See if the CM icon is hidden
  811. WCHAR szHideTrayIcon[MAX_PATH+1];
  812. DWORD dwHideTrayIcon = 1; // default is to hide the CM icon
  813. if (SUCCEEDED(hr) &&
  814. (0 != GetPrivateProfileStringW(CMSECTION, L"HideTrayIcon", L"1",
  815. szHideTrayIcon, celems(szHideTrayIcon), PszwCmsFile ())))
  816. {
  817. dwHideTrayIcon = _ttoi(szHideTrayIcon);
  818. }
  819. if (dwHideTrayIcon) // If the CM icon is not hidden, we don't want another branded icon. We'll use blinky lights instead
  820. {
  821. // Get the Tray Icon path
  822. //
  823. if (SUCCEEDED(hr) &&
  824. (0 != GetPrivateProfileStringW(CMSECTION, L"TrayIcon", L"",
  825. szIconName, celems(szIconName), PszwCmsFile ())))
  826. {
  827. lstrcpynW(szTemp, PszwCmDir (), celems(szTemp));
  828. lstrcatW(szTemp, szIconName);
  829. if (NULL != (hIcon = (HICON)LoadImage(NULL, szTemp, IMAGE_ICON, 16, 16, LR_LOADFROMFILE)))
  830. {
  831. DestroyIcon(hIcon);
  832. hr = HrCoTaskMemAllocAndDupSz (szTemp, &(pConBrandInfo->szwTrayIconPath));
  833. }
  834. }
  835. }
  836. }
  837. }
  838. }
  839. }
  840. // Fill in the out param struct if we succeeded, otherwise leave it alone so it will still
  841. // marshall.
  842. //
  843. if (SUCCEEDED(hr))
  844. {
  845. *ppConBrandInfo = pConBrandInfo;
  846. }
  847. TraceError ("CDialupConnection::GetBrandingIconPaths", hr);
  848. return hr;
  849. }
  850. //+---------------------------------------------------------------------------
  851. //
  852. // Member: CDialupConnection::GetTrayMenuEntries
  853. //
  854. // Purpose: Returns any branded menu items to be added to the tray menu.
  855. //
  856. // Arguments: pMenuData -- Pointer to a Tray Menu Data struct
  857. //
  858. // Returns: S_OK or an error code
  859. //
  860. STDMETHODIMP
  861. CDialupConnection::GetTrayMenuEntries(
  862. CON_TRAY_MENU_DATA** ppMenuData)
  863. {
  864. // initialize output
  865. Assert(ppMenuData);
  866. *ppMenuData = NULL;
  867. CON_TRAY_MENU_DATA * pMenuData = NULL;
  868. HRESULT hr = HrEnsureEntryPropertiesCached ();
  869. if (SUCCEEDED(hr))
  870. {
  871. if (!FIsBranded ())
  872. {
  873. hr = E_NOTIMPL;
  874. }
  875. else
  876. {
  877. hr = HrEnsureCmStringsLoaded();
  878. if (SUCCEEDED(hr))
  879. {
  880. //
  881. // Get the menu item section
  882. //
  883. WCHAR* pszMenuItemsSection = NULL;
  884. int nSize;
  885. hr = HrGetPrivateProfileSectionWithAlloc(&pszMenuItemsSection, &nSize);
  886. // Process the menu items
  887. //
  888. if (SUCCEEDED(hr) && (nSize>0))
  889. {
  890. // We have menu items to process. First make a copy of the data
  891. // and figure out a line count.
  892. //
  893. hr = HrCoTaskMemAlloc(sizeof(CON_TRAY_MENU_DATA), (LPVOID*)&pMenuData);
  894. if (SUCCEEDED(hr))
  895. {
  896. DWORD dwCount = 0;
  897. WCHAR*pszLine = NULL;
  898. WCHAR szName[MAX_PATH+1];
  899. WCHAR szCmdLine[MAX_PATH+1];
  900. WCHAR szParams[MAX_PATH+1];
  901. pszLine = pszMenuItemsSection;
  902. while ((NULL != pszLine) && (0 != *pszLine))
  903. {
  904. if (SUCCEEDED(HrGetMenuNameAndCmdLine(pszLine, szName,
  905. szCmdLine, szParams)))
  906. {
  907. dwCount++;
  908. }
  909. pszLine = pszLine + lstrlenW(pszLine) + 1;
  910. }
  911. ASSERT(0 != dwCount);
  912. // Now that we have an accurate count, lets
  913. // allocate the memory for the marshalling and
  914. // reparse the items.
  915. //
  916. hr = HrCoTaskMemAlloc(dwCount*sizeof(CON_TRAY_MENU_ENTRY),
  917. (LPVOID*)&pMenuData->pctme);
  918. if (SUCCEEDED(hr))
  919. {
  920. pMenuData->dwCount = dwCount;
  921. DWORD dwNumAdded = 0;
  922. pszLine = pszMenuItemsSection;
  923. while ((NULL != pszLine) && (0 != *pszLine) && SUCCEEDED(hr))
  924. {
  925. if (SUCCEEDED(HrGetMenuNameAndCmdLine(pszLine,
  926. szName, szCmdLine, szParams)) && (dwNumAdded <= dwCount))
  927. {
  928. hr = HrFillInConTrayMenuEntry(szName, szCmdLine, szParams,
  929. &(pMenuData->pctme[dwNumAdded]));
  930. if (FAILED(hr))
  931. {
  932. CoTaskMemFree(&pMenuData->pctme);
  933. }
  934. dwNumAdded++;
  935. }
  936. pszLine = pszLine + lstrlenW(pszLine) + 1;
  937. }
  938. }
  939. else
  940. {
  941. delete pMenuData;
  942. }
  943. }
  944. delete (pszMenuItemsSection);
  945. }
  946. }
  947. }
  948. }
  949. // Fill in the out param struct if we succeeded, otherwise leave it alone so it will still
  950. // marshall.
  951. //
  952. if (SUCCEEDED(hr))
  953. {
  954. *ppMenuData = pMenuData;
  955. }
  956. TraceError ("CDialupConnection::GetTrayMenuEntries", hr);
  957. return hr;
  958. }
  959. //+---------------------------------------------------------------------------
  960. //
  961. // Member: CDialupConnection::HrGetPrivateProfileSectionWithAlloc
  962. //
  963. // Purpose: This function ensures that the CM specific member vars for dialup
  964. // are loaded and usable by CM specific functions.
  965. //
  966. // Arguments: none
  967. //
  968. // Returns: S_OK or an error code
  969. //
  970. HRESULT
  971. CDialupConnection::HrGetPrivateProfileSectionWithAlloc (
  972. WCHAR** pszSection,
  973. int* pnSize)
  974. {
  975. Assert(pszSection);
  976. Assert(pnSize);
  977. HRESULT hr = HrEnsureCmStringsLoaded();
  978. if (!pszSection)
  979. {
  980. return E_POINTER;
  981. }
  982. if (!pnSize)
  983. {
  984. return E_POINTER;
  985. }
  986. if (SUCCEEDED(hr))
  987. {
  988. const int c_64K= 64*1024;
  989. int nAllocated = 1024;
  990. *pnSize = nAllocated - 2;
  991. while ((nAllocated <= c_64K) && ((*pnSize) == (nAllocated - 2)))
  992. {
  993. // Should never need more than the 4-5 lines we already allocated
  994. // but someone might want lots of menu options.
  995. //
  996. if (NULL != *pszSection)
  997. {
  998. delete (*pszSection);
  999. }
  1000. *pszSection = new WCHAR[nAllocated];
  1001. if (*pszSection)
  1002. {
  1003. *pnSize = GetPrivateProfileSectionW(L"Menu Options",
  1004. *pszSection, nAllocated,
  1005. PszwCmsFile ());
  1006. }
  1007. else
  1008. {
  1009. hr = E_OUTOFMEMORY;
  1010. break;
  1011. }
  1012. nAllocated = 2*nAllocated;
  1013. }
  1014. if (nAllocated > c_64K)
  1015. {
  1016. hr = E_UNEXPECTED;
  1017. }
  1018. if (nAllocated > c_64K || 0 == *pnSize)
  1019. {
  1020. // We need to free this in both cases, because if the size is 0, then the callers don't free this.
  1021. delete *pszSection;
  1022. }
  1023. }
  1024. TraceError ("CDialupConnection::HrGetPrivateProfileSectionWithAlloc", hr);
  1025. return hr;
  1026. }
  1027. //+---------------------------------------------------------------------------
  1028. //
  1029. // Member: CDialupConnection::HrGetMenuNameAndCmdLine
  1030. //
  1031. // Purpose: Given a menu item line from a CMS file parses out the Menu item name,
  1032. // Menu executable, and Menu item parameters.
  1033. //
  1034. // Arguments: pMenuData -- Pointer to a Tray Menu Data struct
  1035. //
  1036. // Returns: S_OK or an error code
  1037. //
  1038. HRESULT
  1039. CDialupConnection::HrGetMenuNameAndCmdLine(
  1040. PWSTR pszString,
  1041. PWSTR szName,
  1042. PWSTR szProgram,
  1043. PWSTR szParams)
  1044. {
  1045. WCHAR* pszPtr1;
  1046. WCHAR* pszPtr2;
  1047. WCHAR szLine[MAX_PATH+1];
  1048. BOOL fLong = FALSE;
  1049. HRESULT hr;
  1050. Assert(NULL != pszString);
  1051. Assert(NULL != szName);
  1052. Assert(NULL != szProgram);
  1053. Assert(NULL != szParams);
  1054. ZeroMemory(szName, celems(szName));
  1055. ZeroMemory(szProgram, celems(szProgram));
  1056. ZeroMemory(szParams, celems(szParams));
  1057. lstrcpynW(szLine, pszString, celems(szLine));
  1058. // Process the first portion, the "Name=" part
  1059. //
  1060. pszPtr1 = wcsstr(szLine, L"=");
  1061. if (pszPtr1)
  1062. {
  1063. *pszPtr1 = 0;
  1064. lstrcpynW(szName, szLine, MAX_PATH);
  1065. // Process next portion, the program name
  1066. //
  1067. pszPtr1++;
  1068. if (pszPtr1)
  1069. {
  1070. // Look for "+" or " " marking end of program portion
  1071. //
  1072. if (*pszPtr1 == L'+')
  1073. {
  1074. pszPtr1++;
  1075. pszPtr2 = wcsstr(pszPtr1, L"+");
  1076. fLong = TRUE;
  1077. }
  1078. else
  1079. {
  1080. // If not a long filename then we have two choices,
  1081. // either a short program name and params or just a
  1082. // short program name.
  1083. //
  1084. pszPtr2 = wcsstr(pszPtr1, L" ");
  1085. fLong = FALSE;
  1086. }
  1087. // Terminate program name and copy
  1088. //
  1089. if (pszPtr2)
  1090. {
  1091. if (*pszPtr2 != 0)
  1092. {
  1093. *pszPtr2 = 0;
  1094. pszPtr2++;
  1095. }
  1096. lstrcpynW(szProgram, pszPtr1, MAX_PATH);
  1097. // Process final portion, the params
  1098. //
  1099. if (fLong)
  1100. {
  1101. pszPtr2++; // skip blank
  1102. }
  1103. // Now we are have the param string
  1104. //
  1105. if (pszPtr2)
  1106. {
  1107. lstrcpynW(szParams, pszPtr2, MAX_PATH);
  1108. }
  1109. }
  1110. else
  1111. {
  1112. // Just a program with no params and no space seperator
  1113. // (this happens on memphis)
  1114. //
  1115. lstrcpynW(szProgram, pszPtr1, MAX_PATH);
  1116. }
  1117. }
  1118. hr = S_OK;
  1119. }
  1120. else
  1121. {
  1122. // No entries
  1123. //
  1124. hr = E_UNEXPECTED;
  1125. }
  1126. TraceError ("CDialupConnection::HrGetMenuNameAndCmdLine", hr);
  1127. return hr;
  1128. }
  1129. //+---------------------------------------------------------------------------
  1130. //
  1131. // Member: CDialupConnection::HrFillInConTrayMenuEntry
  1132. //
  1133. // Purpose: Given the elements of a ConTrayMenuEntry struct, the function
  1134. // allocs the memory necessary and copies of the given elements.
  1135. //
  1136. // Arguments: szwName - Display name of the command to show in the tray context menu
  1137. // szwCmdLine - actual command to run for this menu entry
  1138. // szwParams - command params for this command
  1139. // pMenuEntry - pointer to the struct to fill in and execute
  1140. //
  1141. // Returns: S_OK or an error code
  1142. //
  1143. HRESULT
  1144. CDialupConnection::HrFillInConTrayMenuEntry (
  1145. PCWSTR szName,
  1146. PCWSTR szCmdLine,
  1147. PCWSTR szParams,
  1148. CON_TRAY_MENU_ENTRY* pMenuEntry)
  1149. {
  1150. HRESULT hr;
  1151. ZeroMemory(pMenuEntry, sizeof(CON_TRAY_MENU_ENTRY));
  1152. hr = HrCoTaskMemAlloc ((lstrlenW(szName)+1)*sizeof(WCHAR),
  1153. (LPVOID*)&(pMenuEntry->szwMenuText));
  1154. if (SUCCEEDED(hr))
  1155. {
  1156. lstrcpyW(pMenuEntry->szwMenuText, szName);
  1157. hr = HrCoTaskMemAlloc ((lstrlenW(szParams)+1)*sizeof(WCHAR),
  1158. (LPVOID*)&(pMenuEntry->szwMenuParams));
  1159. if (S_OK == hr)
  1160. {
  1161. lstrcpyW(pMenuEntry->szwMenuParams, szParams);
  1162. if (0 == wcsncmp(PszwShortServiceName (), szCmdLine,
  1163. lstrlenW(PszwShortServiceName ())))
  1164. {
  1165. //
  1166. // Then we have an included file. Add the profile dir path
  1167. //
  1168. // Take out the "short service name" because it's already included in the path
  1169. PCWSTR pszFileName = szCmdLine + lstrlenW(PszwShortServiceName()) + 1;
  1170. hr = HrCoTaskMemAlloc ((lstrlenW(pszFileName)+lstrlenW(PszwProfileDir())+1)*sizeof(WCHAR),
  1171. (LPVOID*)&(pMenuEntry->szwMenuCmdLine));
  1172. if (S_OK == hr)
  1173. {
  1174. lstrcpyW(pMenuEntry->szwMenuCmdLine, PszwProfileDir ());
  1175. lstrcatW(pMenuEntry->szwMenuCmdLine, pszFileName);
  1176. }
  1177. }
  1178. else
  1179. {
  1180. hr = HrCoTaskMemAlloc ((lstrlenW(szCmdLine)+1)*sizeof(WCHAR),
  1181. (LPVOID*)&(pMenuEntry->szwMenuCmdLine));
  1182. if (S_OK == hr)
  1183. {
  1184. lstrcpyW(pMenuEntry->szwMenuCmdLine, szCmdLine);
  1185. }
  1186. }
  1187. }
  1188. }
  1189. if (FAILED(hr))
  1190. {
  1191. //
  1192. // We Failed so free the memory
  1193. //
  1194. CoTaskMemFree(pMenuEntry->szwMenuText);
  1195. CoTaskMemFree(pMenuEntry->szwMenuCmdLine);
  1196. CoTaskMemFree(pMenuEntry->szwMenuParams);
  1197. }
  1198. return hr;
  1199. }
  1200. //+---------------------------------------------------------------------------
  1201. //
  1202. // Member: CDialupConnection::HrGetCmpFileLocation
  1203. //
  1204. // Purpose: Compares the phonebook file path to path of the current user's
  1205. // application data dir. If the initial paths are the same we have
  1206. // a private profile. Please NOTE that calling this function
  1207. // requires the calling client to properly setup CoSetProxyBlanket for
  1208. // a private user profile (matches the call to CoImpersonateClient)
  1209. //
  1210. // Arguments: szwPhonebook -- path to the phonebook the CM connectoid lives in
  1211. //
  1212. // Returns: S_OK or an error code
  1213. //
  1214. HRESULT
  1215. CDialupConnection::HrGetCmpFileLocation(
  1216. PCWSTR szPhonebook,
  1217. PCWSTR szEntryName,
  1218. PWSTR szCmpFilePath)
  1219. {
  1220. DWORD dwSize = MAX_PATH;
  1221. HKEY hKey;
  1222. HANDLE hBaseKey = NULL;
  1223. HANDLE hFile;
  1224. HRESULT hr;
  1225. HRESULT hrImpersonate = E_FAIL;
  1226. static const WCHAR c_mappingsRegKey[] = L"Software\\Microsoft\\Connection Manager\\Mappings";
  1227. HANDLE hImpersonationToken = NULL; // The token of the thread
  1228. HANDLE hPrimaryToken = NULL; // The primary token for the new process
  1229. if ((NULL == szCmpFilePath) || (NULL == szPhonebook))
  1230. {
  1231. hr = E_POINTER;
  1232. }
  1233. else
  1234. {
  1235. hr = HrEnsureEntryPropertiesCached ();
  1236. if (SUCCEEDED(hr))
  1237. {
  1238. if (m_fForAllUsers)
  1239. {
  1240. // We have an all users key so get the information from HKLM
  1241. //
  1242. hBaseKey = HKEY_LOCAL_MACHINE;
  1243. }
  1244. else
  1245. {
  1246. // Then we have a private profile. Since netman runs as a system account,
  1247. // we must impersonate the client and then make an RTL call to get
  1248. // the current users HKCU hive before querying the registry for the
  1249. // cmp path. We also need to get the user token so that we can expand the
  1250. // cmp string in the single user case.
  1251. //
  1252. hrImpersonate = CoImpersonateClient ();
  1253. TraceError ("HrGetCmpFileLocation -- CoImpersonateClient", hr);
  1254. if (SUCCEEDED(hrImpersonate))
  1255. {
  1256. NTSTATUS ntstat = RtlOpenCurrentUser(KEY_READ | KEY_WRITE, &hBaseKey);
  1257. hr = HRESULT_FROM_NT(ntstat);
  1258. TraceError ("RtlOpenCurrentUser", hr);
  1259. if (SUCCEEDED(hr))
  1260. {
  1261. // Create a primary token
  1262. //
  1263. if (!OpenThreadToken(
  1264. GetCurrentThread(),
  1265. TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
  1266. TRUE,
  1267. &hImpersonationToken))
  1268. {
  1269. hr = HrFromLastWin32Error();
  1270. TraceError ("HrGetCmpFileLocation -- OpenThreadToken", hr);
  1271. }
  1272. else
  1273. {
  1274. if(!DuplicateTokenEx(hImpersonationToken,
  1275. TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
  1276. NULL,
  1277. SecurityImpersonation,
  1278. TokenPrimary,
  1279. &hPrimaryToken
  1280. ))
  1281. {
  1282. hr = HrFromLastWin32Error();
  1283. TraceError ("HrGetCmpFileLocation -- DuplicateTokenEx", hr);
  1284. }
  1285. }
  1286. }
  1287. }
  1288. }
  1289. // Now Open the mappings key and get the cmp file path
  1290. //
  1291. if (SUCCEEDED(hr))
  1292. {
  1293. hr = HrRegOpenKeyEx((HKEY)hBaseKey,
  1294. c_mappingsRegKey,
  1295. KEY_READ, &hKey);
  1296. if (SUCCEEDED(hr))
  1297. {
  1298. dwSize = MAX_PATH;
  1299. WCHAR szTemp[MAX_PATH+1];
  1300. hr = HrRegQuerySzBuffer(hKey, szEntryName, szTemp, &dwSize);
  1301. if (SUCCEEDED (hr))
  1302. {
  1303. // Check to see if the file exists
  1304. //
  1305. if (!m_fForAllUsers)
  1306. {
  1307. ExpandEnvironmentStringsForUserW(hPrimaryToken, szTemp,
  1308. szCmpFilePath, MAX_PATH);
  1309. }
  1310. else
  1311. {
  1312. lstrcpyW(szCmpFilePath, szTemp);
  1313. }
  1314. hFile = CreateFile(szCmpFilePath, GENERIC_READ, FILE_SHARE_READ,
  1315. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1316. if (INVALID_HANDLE_VALUE == hFile)
  1317. {
  1318. hr = HRESULT_FROM_WIN32(GetLastError());
  1319. }
  1320. else
  1321. {
  1322. CloseHandle(hFile);
  1323. hr = S_OK;
  1324. }
  1325. }
  1326. RegCloseKey(hKey);
  1327. }
  1328. }
  1329. }
  1330. if (!m_fForAllUsers)
  1331. {
  1332. if (hImpersonationToken)
  1333. {
  1334. CloseHandle(hImpersonationToken);
  1335. }
  1336. if (hPrimaryToken)
  1337. {
  1338. CloseHandle(hPrimaryToken);
  1339. }
  1340. // Close the handle opened by RtlOpenCurrentUser
  1341. //
  1342. NtClose(hBaseKey);
  1343. }
  1344. if (SUCCEEDED(hrImpersonate))
  1345. {
  1346. hr = CoRevertToSelf ();
  1347. TraceError ("HrGetCmpFileLocation -- CoRevertToSelf", hr);
  1348. }
  1349. }
  1350. TraceError ("CDialupConnection::HrGetCmpFileLocation", hr);
  1351. return hr;
  1352. }
  1353. //+---------------------------------------------------------------------------
  1354. //
  1355. // Member: CDialupConnection::HrEnsureCmStringsLoaded
  1356. //
  1357. // Purpose: This function ensures that the CM specific member vars for dialup
  1358. // are loaded and usable by CM specific functions. Please NOTE that
  1359. // calling EnsureCmStringsAreLoaded requires the calling client to
  1360. // properly setup CoSetProxyBlanket for a private user profile.
  1361. //
  1362. // Arguments: none
  1363. //
  1364. // Returns: S_OK or an error code
  1365. //
  1366. HRESULT
  1367. CDialupConnection::HrEnsureCmStringsLoaded()
  1368. {
  1369. HRESULT hr = S_OK;
  1370. if (!m_fCmPathsLoaded)
  1371. {
  1372. WCHAR szwCmpFile[MAX_PATH];
  1373. WCHAR szwCmsFile[MAX_PATH];
  1374. WCHAR szwDrive[MAX_PATH];
  1375. WCHAR szwDir[MAX_PATH];
  1376. WCHAR szwFileName[MAX_PATH];
  1377. WCHAR szwExtension[MAX_PATH];
  1378. WCHAR szwProfileDir[MAX_PATH];
  1379. WCHAR szwCmDir[MAX_PATH];
  1380. int nNumChars;
  1381. hr = HrGetCmpFileLocation(PszwPbkFile (), PszwEntryName (), szwCmpFile);
  1382. if (SUCCEEDED(hr))
  1383. {
  1384. // Now split the path
  1385. //
  1386. _wsplitpath(szwCmpFile, szwDrive, szwDir, szwFileName, szwExtension);
  1387. // Now construct the path to the cms file
  1388. //
  1389. nNumChars = wsprintfW(szwCmsFile, L"%s%s%s\\%s%s", szwDrive, szwDir, szwFileName, szwFileName, L".cms");
  1390. ASSERT(nNumChars < celems(szwCmsFile));
  1391. // Now construct the profile dir path
  1392. //
  1393. nNumChars = wsprintfW(szwProfileDir, L"%s%s%s\\", szwDrive, szwDir, szwFileName);
  1394. ASSERT(nNumChars < celems(szwProfileDir));
  1395. // Now construct the CM dir path
  1396. //
  1397. nNumChars = wsprintfW(szwCmDir, L"%s%s", szwDrive, szwDir);
  1398. ASSERT(nNumChars < celems(szwCmDir));
  1399. // Now transfer to the member variables
  1400. //
  1401. m_strCmsFile = szwCmsFile;
  1402. m_strProfileDir = szwProfileDir; // remember this already has the trailing slash
  1403. m_strCmDir = szwCmDir; // remember this already has the trailing slash
  1404. m_strShortServiceName = szwFileName;
  1405. m_fCmPathsLoaded = TRUE;
  1406. }
  1407. }
  1408. TraceError ("CDialupConnection::HrEnsureCmStringsLoaded", hr);
  1409. return hr;
  1410. }
  1411. // INetDefaultConnection
  1412. //+---------------------------------------------------------------------------
  1413. //
  1414. // Member: CDialupConnection::SetDefault
  1415. //
  1416. // Purpose: Set the default RAS connection
  1417. //
  1418. // Arguments: TRUE to set as default connection. FALSE to unset it
  1419. //
  1420. // Returns: S_OK or an error code
  1421. //
  1422. HRESULT
  1423. CDialupConnection::SetDefault(BOOL bDefault)
  1424. {
  1425. HRESULT hr = S_OK;
  1426. HRESULT hrT = S_OK;
  1427. if (!m_fInitialized)
  1428. {
  1429. hr = E_UNEXPECTED;
  1430. }
  1431. else
  1432. {
  1433. hr = HrEnsureEntryPropertiesCached ();
  1434. if (SUCCEEDED(hr))
  1435. {
  1436. RASAUTODIALENTRY adEntry;
  1437. ZeroMemory(&adEntry, sizeof(adEntry));
  1438. adEntry.dwSize = sizeof(adEntry);
  1439. if (bDefault)
  1440. {
  1441. wcsncpy(adEntry.szEntry, PszwEntryName(), sizeof(adEntry.szEntry) / sizeof(TCHAR));
  1442. }
  1443. hrT = CoImpersonateClient();
  1444. if (SUCCEEDED(hrT))
  1445. {
  1446. DWORD dwErr = RasSetAutodialAddress(
  1447. NULL,
  1448. NULL,
  1449. &adEntry,
  1450. sizeof(adEntry),
  1451. 1);
  1452. if (dwErr != NO_ERROR)
  1453. {
  1454. hr = HRESULT_FROM_WIN32(dwErr);
  1455. }
  1456. hrT = CoRevertToSelf();
  1457. }
  1458. }
  1459. }
  1460. TraceError ("CDialupConnection::SetDefault", hr);
  1461. return hr;
  1462. }
  1463. //+---------------------------------------------------------------------------
  1464. //
  1465. // Member: CDialupConnection::GetDefault
  1466. //
  1467. // Purpose: Get the default RAS connection
  1468. //
  1469. // Arguments: pbDefault - Is this the default connection
  1470. //
  1471. // Returns: S_OK or an error code
  1472. //
  1473. HRESULT
  1474. CDialupConnection::GetDefault (BOOL* pbDefault)
  1475. {
  1476. HRESULT hr = S_OK;
  1477. if (!m_fInitialized)
  1478. {
  1479. hr = E_UNEXPECTED;
  1480. }
  1481. else
  1482. {
  1483. hr = HrEnsureEntryPropertiesCached ();
  1484. if (SUCCEEDED(hr))
  1485. {
  1486. if (m_dwFlagsPriv & REED_F_Default)
  1487. {
  1488. *pbDefault = TRUE;
  1489. }
  1490. else
  1491. {
  1492. *pbDefault = FALSE;
  1493. }
  1494. }
  1495. }
  1496. TraceError ("CDialupConnection::GetDefault", hr);
  1497. return hr;
  1498. }
  1499. //+---------------------------------------------------------------------------
  1500. //
  1501. // Member: CDialupConnection::GetDefault
  1502. //
  1503. // Purpose: Get the default RAS connection
  1504. //
  1505. // Arguments: pbDefault - Is this the default connection
  1506. //
  1507. // Returns: S_OK or an error code
  1508. //
  1509. HRESULT
  1510. CDialupConnection::GetPropertiesEx(NETCON_PROPERTIES_EX** ppConnectionPropertiesEx)
  1511. {
  1512. HRESULT hr = S_OK;
  1513. *ppConnectionPropertiesEx = NULL;
  1514. if (!m_fInitialized)
  1515. {
  1516. hr = E_UNEXPECTED;
  1517. }
  1518. else
  1519. {
  1520. NETCON_PROPERTIES* pProps;
  1521. NETCON_PROPERTIES_EX* pPropsEx = reinterpret_cast<NETCON_PROPERTIES_EX*>(CoTaskMemAlloc(sizeof(NETCON_PROPERTIES_EX)));
  1522. if (pPropsEx)
  1523. {
  1524. ZeroMemory(pPropsEx, sizeof(NETCON_PROPERTIES_EX));
  1525. hr = GetProperties(&pProps);
  1526. if (SUCCEEDED(hr))
  1527. {
  1528. hr = HrBuildPropertiesExFromProperties(pProps, pPropsEx, dynamic_cast<IPersistNetConnection *>(this));
  1529. if (SUCCEEDED(hr))
  1530. {
  1531. pPropsEx->bstrPhoneOrHostAddress = SysAllocString(m_strPhoneNumber.c_str());
  1532. *ppConnectionPropertiesEx = pPropsEx;
  1533. }
  1534. FreeNetconProperties(pProps);
  1535. }
  1536. }
  1537. else
  1538. {
  1539. hr = E_OUTOFMEMORY;
  1540. }
  1541. }
  1542. TraceError ("CDialupConnection::GetPropertiesEx", hr);
  1543. return hr;
  1544. }