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.

1912 lines
68 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. IN REFIID riid,
  48. OUT VOID** ppv,
  49. OUT 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. IN PCWSTR pszPbkFile,
  151. IN PCWSTR pszEntryName,
  152. IN REFIID riid,
  153. OUT 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. OUT 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. IN PCWSTR pszDuplicateName,
  349. OUT 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. OUT 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. NETCON_MAX_NAME_LEN);
  549. if (FAILED(hrT))
  550. {
  551. hr = hrT;
  552. }
  553. hrT = HrCoTaskMemAllocAndDupSz (
  554. PszwDeviceName(),
  555. &pProps->pszwDeviceName,
  556. NETCON_MAX_NAME_LEN);
  557. if (FAILED(hrT))
  558. {
  559. hr = hrT;
  560. }
  561. // Status
  562. //
  563. hrT = HrGetStatus (&pProps->Status);
  564. if (FAILED(hrT))
  565. {
  566. hr = hrT;
  567. }
  568. // Verify that the status return is accurate. HrGetStatus returns NCS_DISCONNECTED
  569. // if the connectoid is NCS_CONNECTING, which is wrong!!!!.
  570. //
  571. if( pProps->Status == NCS_DISCONNECTED )
  572. {
  573. // CMUtil remebers the Hidden connection (Connection Manager) and the status of
  574. // any ras events (i.e. Connecting, Disconnecting etc). The Data is filled in
  575. // in function RasEventNotify.
  576. //
  577. hrHiddenCM = CCMUtil::Instance().HrGetEntry(pProps->guidId,cm);
  578. if ( S_OK == hrHiddenCM )
  579. {
  580. // Use CCMUtil's status, its more accurate.
  581. //
  582. pProps->Status = cm.m_ncs;
  583. }
  584. }
  585. // Check if this connection has a child connection
  586. //
  587. hrHiddenCM = CCMUtil::Instance().HrGetEntry(PszwEntryName(),cm);
  588. if( hrHiddenCM == S_OK )
  589. {
  590. // It has a child connectoid
  591. // Now we have to determine which one describes the overall status of the connection
  592. //
  593. if( cm.m_ncs == NCS_CONNECTING || cm.m_ncs == NCS_DISCONNECTING ||
  594. cm.m_ncs == NCS_CONNECTED)
  595. {
  596. if( pProps->Status == NCS_DISCONNECTING )
  597. {
  598. // This case happens if the parent is disconnecting
  599. // The parent is disconnecting, so the child will be disconnecting.
  600. // Change the status of the child to disconnecting so that we do not
  601. // get confused later on when the child is connected at the parent is
  602. // disconnected. i.e. are we overall connecting or disconnecting!!!!
  603. //
  604. CCMUtil::Instance().SetEntry(GuidId (), PszwEntryName(),pProps->Status);
  605. }
  606. else
  607. if( cm.m_ncs == NCS_CONNECTED && pProps->Status == NCS_DISCONNECTED )
  608. {
  609. // This case will only happen if the child is connected and the parent is still
  610. // disconnected.
  611. //
  612. pProps->Status = NCS_CONNECTING;
  613. }
  614. else if (!IsEqualGUID(pProps->guidId, cm.m_guid))
  615. {
  616. TraceTag(ttidWanCon, "Overwriting parent connection status: %s with child status: %s", DbgNcs(pProps->Status), DbgNcs(cm.m_ncs));
  617. // When in doubt and the GUID's are different (ie. not a BAP/Multilink connection) take the childs status =)
  618. //
  619. pProps->Status = cm.m_ncs;
  620. }
  621. }
  622. }
  623. // Type
  624. //
  625. pProps->MediaType = MediaType ();
  626. // dwCharacter
  627. //
  628. hrT = HrGetCharacteristics (&pProps->dwCharacter);
  629. if (FAILED(hrT))
  630. {
  631. hr = hrT;
  632. }
  633. // clsidThisObject
  634. //
  635. pProps->clsidThisObject = CLSID_DialupConnection;
  636. // clsidUiObject
  637. //
  638. hrT = GetUiObjectClassId (&pProps->clsidUiObject);
  639. if (FAILED(hrT))
  640. {
  641. hr = hrT;
  642. }
  643. // Assign the output parameter or cleanup if we had any failures.
  644. //
  645. if (SUCCEEDED(hr))
  646. {
  647. *ppProps = pProps;
  648. }
  649. else
  650. {
  651. Assert (NULL == *ppProps);
  652. FreeNetconProperties (pProps);
  653. }
  654. }
  655. }
  656. }
  657. TraceError ("CDialupConnection::GetProperties", hr);
  658. return hr;
  659. }
  660. STDMETHODIMP
  661. CDialupConnection::Rename (
  662. IN PCWSTR pszNewName)
  663. {
  664. HRESULT hr;
  665. // Validate parameters.
  666. //
  667. if (!pszNewName)
  668. {
  669. hr = E_POINTER;
  670. }
  671. else if (!m_fInitialized)
  672. {
  673. hr = E_UNEXPECTED;
  674. }
  675. else
  676. {
  677. hr = HrLockAndRenameEntry (pszNewName, this);
  678. }
  679. TraceError ("CDialupConnection::Rename", hr);
  680. return hr;
  681. }
  682. //+---------------------------------------------------------------------------
  683. // INetRasConnection
  684. //
  685. STDMETHODIMP
  686. CDialupConnection::GetRasConnectionInfo (
  687. OUT RASCON_INFO* pRasConInfo)
  688. {
  689. HRESULT hr = HrGetRasConnectionInfo (pRasConInfo);
  690. TraceError ("CDialupConnection::GetRasConnectionInfo", hr);
  691. return hr;
  692. }
  693. STDMETHODIMP
  694. CDialupConnection::SetRasConnectionInfo (
  695. IN const RASCON_INFO* pRasConInfo)
  696. {
  697. HRESULT hr = HrSetRasConnectionInfo (pRasConInfo);
  698. TraceError ("CDialupConnection::SetRasConnectionInfo", hr);
  699. return hr;
  700. }
  701. STDMETHODIMP
  702. CDialupConnection::GetRasConnectionHandle (
  703. OUT ULONG_PTR* phRasConn)
  704. {
  705. HRESULT hr = HrGetRasConnectionHandle (
  706. reinterpret_cast<HRASCONN*>(phRasConn));
  707. TraceError ("CDialupConnection::GetRasConnectionHandle",
  708. (S_FALSE == hr) ? S_OK : hr);
  709. return hr;
  710. }
  711. //+---------------------------------------------------------------------------
  712. // IPersistNetConnection
  713. //
  714. STDMETHODIMP
  715. CDialupConnection::GetClassID (
  716. OUT CLSID* pclsid)
  717. {
  718. HRESULT hr = S_OK;
  719. // Validate parameters.
  720. //
  721. if (!pclsid)
  722. {
  723. hr = E_POINTER;
  724. }
  725. else
  726. {
  727. *pclsid = CLSID_DialupConnection;
  728. }
  729. TraceError ("CDialupConnection::GetClassID", hr);
  730. return hr;
  731. }
  732. STDMETHODIMP
  733. CDialupConnection::GetSizeMax (
  734. OUT ULONG* pcbSize)
  735. {
  736. HRESULT hr = HrPersistGetSizeMax (pcbSize);
  737. TraceError ("CDialupConnection::GetSizeMax", hr);
  738. return hr;
  739. }
  740. STDMETHODIMP
  741. CDialupConnection::Load (
  742. IN const BYTE* pbBuf,
  743. IN ULONG cbSize)
  744. {
  745. HRESULT hr = HrPersistLoad (pbBuf, cbSize);
  746. TraceError ("CDialupConnection::Load", hr);
  747. return hr;
  748. }
  749. STDMETHODIMP
  750. CDialupConnection::Save (
  751. OUT BYTE* pbBuf,
  752. OUT ULONG cbSize)
  753. {
  754. HRESULT hr = HrPersistSave (pbBuf, cbSize);
  755. TraceError ("CDialupConnection::Save", hr);
  756. return hr;
  757. }
  758. //+---------------------------------------------------------------------------
  759. // INetConnectionBrandingInfo
  760. //
  761. //+---------------------------------------------------------------------------
  762. //
  763. // Member: CDialupConnection::GetBrandingIconPaths
  764. //
  765. // Purpose: Returns the full paths to three icons.
  766. //
  767. // Arguments: pConBrandInfo - pointer to an Icon branding structure
  768. //
  769. // Returns: S_OK or an error code
  770. //
  771. STDMETHODIMP
  772. CDialupConnection::GetBrandingIconPaths(
  773. OUT CON_BRANDING_INFO ** ppConBrandInfo)
  774. {
  775. HRESULT hr = HrEnsureEntryPropertiesCached ();
  776. CON_BRANDING_INFO * pConBrandInfo = NULL;
  777. BOOL fRunOldVersion = TRUE;
  778. typedef DWORD (WINAPI* pfnGetCustomPropertiesFunc)(LPCWSTR, LPCWSTR, LPWSTR, PBYTE*, DWORD*);
  779. Assert(ppConBrandInfo);
  780. if (SUCCEEDED(hr))
  781. {
  782. if (!FIsBranded ())
  783. {
  784. hr = E_NOTIMPL;
  785. }
  786. else
  787. {
  788. WCHAR szTemp[MAX_PATH+1];
  789. WCHAR szIconName[MAX_PATH+1];
  790. const WCHAR* const CMSECTION = L"Connection Manager";
  791. HICON hIcon;
  792. hr = HrCoTaskMemAlloc(sizeof(CON_BRANDING_INFO), (LPVOID*)&pConBrandInfo);
  793. if (SUCCEEDED(hr))
  794. {
  795. ZeroMemory(pConBrandInfo, sizeof(CON_BRANDING_INFO));
  796. WCHAR szExpandedCustomDLL[MAX_PATH+1] = {0};
  797. HMODULE hCustomDll = NULL;
  798. DWORD dwRetCode = ERROR_SUCCESS;
  799. RASENTRY re = {0};
  800. DWORD dwNeededSize = sizeof(re);
  801. re.dwSize = dwNeededSize;
  802. DWORD dwTODOREMOVE = sizeof(re.szCustomDialDll)/sizeof(WCHAR);
  803. DWORD dwNum = GetPrivateProfileStringW(PszwEntryName (), L"CustomRasDialDll", L"", &re.szCustomDialDll[0],
  804. (sizeof(re.szCustomDialDll)/sizeof(WCHAR))-1, PszwPbkFile ());
  805. if (0 == dwNum)
  806. {
  807. dwRetCode = RasGetEntryProperties(PszwPbkFile (), PszwEntryName (), &re, &dwNeededSize, NULL, NULL);
  808. }
  809. if ((ERROR_SUCCESS == dwRetCode) && (lstrlenW(re.szCustomDialDll)))
  810. {
  811. BOOL fRetCode = ExpandEnvironmentStringsForUserW(NULL, re.szCustomDialDll, szExpandedCustomDLL, MAX_PATH);
  812. if (fRetCode)
  813. {
  814. hCustomDll = LoadLibrary(szExpandedCustomDLL);
  815. if (hCustomDll)
  816. {
  817. WCHAR szIconPath[(2*MAX_PATH) + 1] = {0};
  818. WCHAR szHideTrayIcon[(2*MAX_PATH) + 1] = {0};
  819. WCHAR szTrayIcon[(2*MAX_PATH) + 1] = {0};
  820. pfnGetCustomPropertiesFunc pfnGetCustomProperties = NULL;
  821. pfnGetCustomProperties = (pfnGetCustomPropertiesFunc)GetProcAddress(hCustomDll, "GetCustomProperty");
  822. if (pfnGetCustomProperties)
  823. {
  824. DWORD dwSize = 2*MAX_PATH;
  825. BOOL fRet = pfnGetCustomProperties(PszwPbkFile (), PszwEntryName (), L"Icon", (PBYTE*)&szIconPath, &dwSize);
  826. if (fRet)
  827. {
  828. if (NULL != (hIcon = (HICON)LoadImage(NULL, szIconPath, IMAGE_ICON, 32, 32, LR_LOADFROMFILE)))
  829. {
  830. DestroyIcon(hIcon);
  831. hr = HrCoTaskMemAllocAndDupSz (szIconPath, &(pConBrandInfo->szwLargeIconPath), MAX_PATH);
  832. }
  833. }
  834. dwSize = 2*MAX_PATH;
  835. fRet = pfnGetCustomProperties(PszwPbkFile (), PszwEntryName (), L"HideTrayIcon", (PBYTE*)&szHideTrayIcon, &dwSize);
  836. // We don't care if we the call fails just need to check the length below
  837. if (SUCCEEDED(hr))
  838. {
  839. DWORD dwNewHideTrayIcon = 1; // default is to hide the icon
  840. if (szHideTrayIcon)
  841. {
  842. if (lstrlenW(szHideTrayIcon))
  843. {
  844. dwNewHideTrayIcon = _ttoi(szHideTrayIcon);
  845. }
  846. }
  847. if (dwNewHideTrayIcon)
  848. {
  849. dwSize = 2*MAX_PATH;
  850. fRet = pfnGetCustomProperties(PszwPbkFile (), PszwEntryName (), L"TrayIcon", (PBYTE*)&szTrayIcon, &dwSize);
  851. if (fRet)
  852. {
  853. if (NULL != (hIcon = (HICON)LoadImage(NULL, szTrayIcon, IMAGE_ICON, 16, 16, LR_LOADFROMFILE)))
  854. {
  855. DestroyIcon(hIcon);
  856. hr = HrCoTaskMemAllocAndDupSz (szTrayIcon, &(pConBrandInfo->szwTrayIconPath), MAX_PATH);
  857. if (SUCCEEDED(hr))
  858. {
  859. //
  860. // We got all the info for the icons
  861. //
  862. fRunOldVersion = FALSE;
  863. }
  864. }
  865. }
  866. }
  867. else
  868. {
  869. //
  870. // We got this far (meaning the call for getting the Icon succeeded),
  871. // thus no need to run the older code which is left for compatibility reasons.
  872. //
  873. fRunOldVersion = FALSE;
  874. }
  875. }
  876. }
  877. FreeLibrary(hCustomDll);
  878. hCustomDll = NULL;
  879. }
  880. }
  881. }
  882. //
  883. // For compatibility reasons we leave this code. If the CustomDialDll doesn't have the appropriate
  884. // entry point, then we'll just use this version of the code.
  885. //
  886. if (fRunOldVersion)
  887. {
  888. // Get the path to the cms file to get the Icon entries from.
  889. //
  890. hr = HrEnsureCmStringsLoaded();
  891. if (SUCCEEDED(hr))
  892. {
  893. // Get the Large Icon path
  894. //
  895. if (0 != GetPrivateProfileStringW(CMSECTION, L"Icon", L"",
  896. szIconName, celems(szIconName), PszwCmsFile ()))
  897. {
  898. lstrcpynW(szTemp, PszwCmDir (), celems(szTemp));
  899. lstrcatW(szTemp, szIconName);
  900. if (NULL != (hIcon = (HICON)LoadImage(NULL, szTemp, IMAGE_ICON, 32, 32, LR_LOADFROMFILE)))
  901. {
  902. DestroyIcon(hIcon);
  903. hr = HrCoTaskMemAllocAndDupSz (szTemp, &(pConBrandInfo->szwLargeIconPath), MAX_PATH);
  904. }
  905. }
  906. // See if the CM icon is hidden
  907. WCHAR szHideTrayIcon[MAX_PATH+1];
  908. DWORD dwHideTrayIcon = 1; // default is to hide the CM icon
  909. if (SUCCEEDED(hr) &&
  910. (0 != GetPrivateProfileStringW(CMSECTION, L"HideTrayIcon", L"1",
  911. szHideTrayIcon, celems(szHideTrayIcon), PszwCmsFile ())))
  912. {
  913. dwHideTrayIcon = _ttoi(szHideTrayIcon);
  914. }
  915. if (dwHideTrayIcon) // If the CM icon is not hidden, we don't want another branded icon. We'll use blinky lights instead
  916. {
  917. // Get the Tray Icon path
  918. //
  919. if (SUCCEEDED(hr) &&
  920. (0 != GetPrivateProfileStringW(CMSECTION, L"TrayIcon", L"",
  921. szIconName, celems(szIconName), PszwCmsFile ())))
  922. {
  923. lstrcpynW(szTemp, PszwCmDir (), celems(szTemp));
  924. lstrcatW(szTemp, szIconName);
  925. if (NULL != (hIcon = (HICON)LoadImage(NULL, szTemp, IMAGE_ICON, 16, 16, LR_LOADFROMFILE)))
  926. {
  927. DestroyIcon(hIcon);
  928. hr = HrCoTaskMemAllocAndDupSz (szTemp, &(pConBrandInfo->szwTrayIconPath), MAX_PATH);
  929. }
  930. }
  931. }
  932. }
  933. }
  934. }
  935. }
  936. }
  937. // Fill in the out param struct if we succeeded, otherwise leave it alone so it will still
  938. // marshall.
  939. //
  940. if (SUCCEEDED(hr))
  941. {
  942. *ppConBrandInfo = pConBrandInfo;
  943. }
  944. TraceError ("CDialupConnection::GetBrandingIconPaths", hr);
  945. return hr;
  946. }
  947. //+---------------------------------------------------------------------------
  948. //
  949. // Member: CDialupConnection::GetTrayMenuEntries
  950. //
  951. // Purpose: Returns any branded menu items to be added to the tray menu.
  952. //
  953. // Arguments: pMenuData -- Pointer to a Tray Menu Data struct
  954. //
  955. // Returns: S_OK or an error code
  956. //
  957. STDMETHODIMP
  958. CDialupConnection::GetTrayMenuEntries(
  959. OUT CON_TRAY_MENU_DATA** ppMenuData)
  960. {
  961. // initialize output
  962. Assert(ppMenuData);
  963. *ppMenuData = NULL;
  964. CON_TRAY_MENU_DATA * pMenuData = NULL;
  965. HRESULT hr = HrEnsureEntryPropertiesCached ();
  966. BOOL fRunOldVersion = TRUE;
  967. typedef DWORD (WINAPI* pfnGetCustomPropertiesFunc)(LPCWSTR, LPCWSTR, LPWSTR, PBYTE*, DWORD*);
  968. if (SUCCEEDED(hr))
  969. {
  970. if (!FIsBranded ())
  971. {
  972. hr = E_NOTIMPL;
  973. }
  974. else
  975. {
  976. WCHAR szExpandedCustomDLL[MAX_PATH+1] = {0};
  977. HMODULE hCustomDll = NULL;
  978. DWORD dwRetCode = ERROR_SUCCESS;
  979. RASENTRY re = {0};
  980. DWORD dwNeededSize = sizeof(re);
  981. re.dwSize = dwNeededSize;
  982. DWORD dwNum = GetPrivateProfileStringW(PszwEntryName (), L"CustomRasDialDll", L"", &re.szCustomDialDll[0],
  983. (sizeof(re.szCustomDialDll)/sizeof(WCHAR))-1, PszwPbkFile ());
  984. if (0 == dwNum)
  985. {
  986. dwRetCode = RasGetEntryProperties(PszwPbkFile (), PszwEntryName (), &re, &dwNeededSize, NULL, NULL);
  987. }
  988. if ((ERROR_SUCCESS == dwRetCode) && (lstrlenW(re.szCustomDialDll)))
  989. {
  990. BOOL fRetCode = ExpandEnvironmentStringsForUserW(NULL, re.szCustomDialDll, szExpandedCustomDLL, MAX_PATH);
  991. if (fRetCode)
  992. {
  993. hCustomDll = LoadLibrary(szExpandedCustomDLL);
  994. if (hCustomDll)
  995. {
  996. pfnGetCustomPropertiesFunc pfnGetCustomProperties = NULL;
  997. pfnGetCustomProperties = (pfnGetCustomPropertiesFunc)GetProcAddress(hCustomDll, "GetCustomProperty");
  998. if (pfnGetCustomProperties)
  999. {
  1000. //
  1001. // This call actually allocates memory and fills in the whole structure inside
  1002. // the GetCustomProperty call
  1003. //
  1004. DWORD dwSize = 0;
  1005. BOOL fRet = pfnGetCustomProperties(PszwPbkFile (), PszwEntryName (), L"Menu Items", (PBYTE*)&pMenuData, &dwSize);
  1006. if (fRet)
  1007. {
  1008. hr = S_OK; // needed at the end of the function
  1009. fRunOldVersion = FALSE;
  1010. }
  1011. }
  1012. FreeLibrary(hCustomDll);
  1013. hCustomDll = NULL;
  1014. }
  1015. }
  1016. }
  1017. //
  1018. // For compatibility reasons we leave this code. If the CustomDialDll doesn't have the appropriate
  1019. // entry point, then we'll just use this version of the code.
  1020. //
  1021. if (fRunOldVersion)
  1022. {
  1023. hr = HrEnsureCmStringsLoaded();
  1024. if (SUCCEEDED(hr))
  1025. {
  1026. //
  1027. // Get the menu item section
  1028. //
  1029. WCHAR* pszMenuItemsSection = NULL;
  1030. int nSize;
  1031. hr = HrGetPrivateProfileSectionWithAlloc(&pszMenuItemsSection, &nSize);
  1032. // Process the menu items
  1033. //
  1034. if (SUCCEEDED(hr) && (nSize>0))
  1035. {
  1036. // We have menu items to process. First make a copy of the data
  1037. // and figure out a line count.
  1038. //
  1039. hr = HrCoTaskMemAlloc(sizeof(CON_TRAY_MENU_DATA), (LPVOID*)&pMenuData);
  1040. if (SUCCEEDED(hr))
  1041. {
  1042. DWORD dwCount = 0;
  1043. WCHAR*pszLine = NULL;
  1044. WCHAR szName[MAX_PATH+1];
  1045. WCHAR szCmdLine[MAX_PATH+1];
  1046. WCHAR szParams[MAX_PATH+1];
  1047. pszLine = pszMenuItemsSection;
  1048. while ((NULL != pszLine) && (0 != *pszLine))
  1049. {
  1050. if (SUCCEEDED(HrGetMenuNameAndCmdLine(pszLine, szName,
  1051. szCmdLine, szParams)))
  1052. {
  1053. dwCount++;
  1054. }
  1055. pszLine = pszLine + lstrlenW(pszLine) + 1;
  1056. }
  1057. ASSERT(0 != dwCount);
  1058. // Now that we have an accurate count, lets
  1059. // allocate the memory for the marshalling and
  1060. // reparse the items.
  1061. //
  1062. hr = HrCoTaskMemAlloc(dwCount*sizeof(CON_TRAY_MENU_ENTRY),
  1063. (LPVOID*)&pMenuData->pctme);
  1064. if (SUCCEEDED(hr))
  1065. {
  1066. pMenuData->dwCount = dwCount;
  1067. DWORD dwNumAdded = 0;
  1068. pszLine = pszMenuItemsSection;
  1069. while ((NULL != pszLine) && (0 != *pszLine) && SUCCEEDED(hr))
  1070. {
  1071. if (SUCCEEDED(HrGetMenuNameAndCmdLine(pszLine,
  1072. szName, szCmdLine, szParams)) && (dwNumAdded <= dwCount))
  1073. {
  1074. hr = HrFillInConTrayMenuEntry(szName, szCmdLine, szParams,
  1075. &(pMenuData->pctme[dwNumAdded]));
  1076. if (FAILED(hr))
  1077. {
  1078. CoTaskMemFree(&pMenuData->pctme);
  1079. }
  1080. dwNumAdded++;
  1081. }
  1082. pszLine = pszLine + lstrlenW(pszLine) + 1;
  1083. }
  1084. }
  1085. else
  1086. {
  1087. delete pMenuData;
  1088. }
  1089. }
  1090. delete (pszMenuItemsSection);
  1091. }
  1092. }
  1093. }
  1094. }
  1095. }
  1096. // Fill in the out param struct if we succeeded, otherwise leave it alone so it will still
  1097. // marshall.
  1098. //
  1099. if (SUCCEEDED(hr))
  1100. {
  1101. *ppMenuData = pMenuData;
  1102. }
  1103. TraceError ("CDialupConnection::GetTrayMenuEntries", hr);
  1104. return hr;
  1105. }
  1106. //+---------------------------------------------------------------------------
  1107. //
  1108. // Member: CDialupConnection::HrGetPrivateProfileSectionWithAlloc
  1109. //
  1110. // Purpose: This function ensures that the CM specific member vars for dialup
  1111. // are loaded and usable by CM specific functions.
  1112. //
  1113. // Arguments: none
  1114. //
  1115. // Returns: S_OK or an error code
  1116. //
  1117. HRESULT
  1118. CDialupConnection::HrGetPrivateProfileSectionWithAlloc (
  1119. OUT WCHAR** pszSection,
  1120. OUT int* pnSize)
  1121. {
  1122. Assert(pszSection);
  1123. Assert(pnSize);
  1124. HRESULT hr = HrEnsureCmStringsLoaded();
  1125. if (!pszSection)
  1126. {
  1127. return E_POINTER;
  1128. }
  1129. if (!pnSize)
  1130. {
  1131. return E_POINTER;
  1132. }
  1133. if (SUCCEEDED(hr))
  1134. {
  1135. const int c_64K= 64*1024;
  1136. int nAllocated = 1024;
  1137. *pnSize = nAllocated - 2;
  1138. while ((nAllocated <= c_64K) && ((*pnSize) == (nAllocated - 2)))
  1139. {
  1140. // Should never need more than the 4-5 lines we already allocated
  1141. // but someone might want lots of menu options.
  1142. //
  1143. if (NULL != *pszSection)
  1144. {
  1145. delete (*pszSection);
  1146. }
  1147. *pszSection = new WCHAR[nAllocated];
  1148. if (*pszSection)
  1149. {
  1150. *pnSize = GetPrivateProfileSectionW(L"Menu Options",
  1151. *pszSection, nAllocated,
  1152. PszwCmsFile ());
  1153. }
  1154. else
  1155. {
  1156. hr = E_OUTOFMEMORY;
  1157. break;
  1158. }
  1159. nAllocated = 2*nAllocated;
  1160. }
  1161. if (nAllocated > c_64K)
  1162. {
  1163. hr = E_UNEXPECTED;
  1164. }
  1165. if (nAllocated > c_64K || 0 == *pnSize)
  1166. {
  1167. // We need to free this in both cases, because if the size is 0, then the callers don't free this.
  1168. delete *pszSection;
  1169. }
  1170. }
  1171. TraceError ("CDialupConnection::HrGetPrivateProfileSectionWithAlloc", hr);
  1172. return hr;
  1173. }
  1174. //+---------------------------------------------------------------------------
  1175. //
  1176. // Member: CDialupConnection::HrGetMenuNameAndCmdLine
  1177. //
  1178. // Purpose: Given a menu item line from a CMS file parses out the Menu item name,
  1179. // Menu executable, and Menu item parameters.
  1180. //
  1181. // Arguments: pMenuData -- Pointer to a Tray Menu Data struct
  1182. //
  1183. // Returns: S_OK or an error code
  1184. //
  1185. HRESULT
  1186. CDialupConnection::HrGetMenuNameAndCmdLine(
  1187. IN PCWSTR pszString,
  1188. OUT PWSTR szName,
  1189. OUT PWSTR szProgram,
  1190. OUT PWSTR szParams)
  1191. {
  1192. WCHAR* pszPtr1;
  1193. WCHAR* pszPtr2;
  1194. WCHAR szLine[MAX_PATH+1];
  1195. BOOL fLong = FALSE;
  1196. HRESULT hr;
  1197. Assert(NULL != pszString);
  1198. Assert(NULL != szName);
  1199. Assert(NULL != szProgram);
  1200. Assert(NULL != szParams);
  1201. ZeroMemory(szName, celems(szName));
  1202. ZeroMemory(szProgram, celems(szProgram));
  1203. ZeroMemory(szParams, celems(szParams));
  1204. lstrcpynW(szLine, pszString, celems(szLine));
  1205. // Process the first portion, the "Name=" part
  1206. //
  1207. pszPtr1 = wcsstr(szLine, L"=");
  1208. if (pszPtr1)
  1209. {
  1210. *pszPtr1 = 0;
  1211. lstrcpynW(szName, szLine, MAX_PATH);
  1212. // Process next portion, the program name
  1213. //
  1214. pszPtr1++;
  1215. if (pszPtr1)
  1216. {
  1217. // Look for "+" or " " marking end of program portion
  1218. //
  1219. if (*pszPtr1 == L'+')
  1220. {
  1221. pszPtr1++;
  1222. pszPtr2 = wcsstr(pszPtr1, L"+");
  1223. fLong = TRUE;
  1224. }
  1225. else
  1226. {
  1227. // If not a long filename then we have two choices,
  1228. // either a short program name and params or just a
  1229. // short program name.
  1230. //
  1231. pszPtr2 = wcsstr(pszPtr1, L" ");
  1232. fLong = FALSE;
  1233. }
  1234. // Terminate program name and copy
  1235. //
  1236. if (pszPtr2)
  1237. {
  1238. if (*pszPtr2 != 0)
  1239. {
  1240. *pszPtr2 = 0;
  1241. pszPtr2++;
  1242. }
  1243. lstrcpynW(szProgram, pszPtr1, MAX_PATH);
  1244. // Process final portion, the params
  1245. //
  1246. if (fLong)
  1247. {
  1248. pszPtr2++; // skip blank
  1249. }
  1250. // Now we are have the param string
  1251. //
  1252. if (pszPtr2)
  1253. {
  1254. lstrcpynW(szParams, pszPtr2, MAX_PATH);
  1255. }
  1256. }
  1257. else
  1258. {
  1259. // Just a program with no params and no space seperator
  1260. // (this happens on memphis)
  1261. //
  1262. lstrcpynW(szProgram, pszPtr1, MAX_PATH);
  1263. }
  1264. }
  1265. hr = S_OK;
  1266. }
  1267. else
  1268. {
  1269. // No entries
  1270. //
  1271. hr = E_UNEXPECTED;
  1272. }
  1273. TraceError ("CDialupConnection::HrGetMenuNameAndCmdLine", hr);
  1274. return hr;
  1275. }
  1276. //+---------------------------------------------------------------------------
  1277. //
  1278. // Member: CDialupConnection::HrFillInConTrayMenuEntry
  1279. //
  1280. // Purpose: Given the elements of a ConTrayMenuEntry struct, the function
  1281. // allocs the memory necessary and copies of the given elements.
  1282. //
  1283. // Arguments: szwName - Display name of the command to show in the tray context menu
  1284. // szwCmdLine - actual command to run for this menu entry
  1285. // szwParams - command params for this command
  1286. // pMenuEntry - pointer to the struct to fill in and execute
  1287. //
  1288. // Returns: S_OK or an error code
  1289. //
  1290. HRESULT
  1291. CDialupConnection::HrFillInConTrayMenuEntry (
  1292. IN PCWSTR szName,
  1293. IN PCWSTR szCmdLine,
  1294. IN PCWSTR szParams,
  1295. OUT CON_TRAY_MENU_ENTRY* pMenuEntry)
  1296. {
  1297. HRESULT hr;
  1298. ZeroMemory(pMenuEntry, sizeof(CON_TRAY_MENU_ENTRY));
  1299. hr = HrCoTaskMemAlloc ((lstrlenW(szName)+1)*sizeof(WCHAR),
  1300. (LPVOID*)&(pMenuEntry->szwMenuText));
  1301. if (SUCCEEDED(hr))
  1302. {
  1303. lstrcpyW(pMenuEntry->szwMenuText, szName);
  1304. hr = HrCoTaskMemAlloc ((lstrlenW(szParams)+1)*sizeof(WCHAR),
  1305. (LPVOID*)&(pMenuEntry->szwMenuParams));
  1306. if (S_OK == hr)
  1307. {
  1308. lstrcpyW(pMenuEntry->szwMenuParams, szParams);
  1309. if (0 == wcsncmp(PszwShortServiceName (), szCmdLine,
  1310. lstrlenW(PszwShortServiceName ())))
  1311. {
  1312. //
  1313. // Then we have an included file. Add the profile dir path
  1314. //
  1315. // Take out the "short service name" because it's already included in the path
  1316. PCWSTR pszFileName = szCmdLine + lstrlenW(PszwShortServiceName()) + 1;
  1317. hr = HrCoTaskMemAlloc ((lstrlenW(pszFileName)+lstrlenW(PszwProfileDir())+1)*sizeof(WCHAR),
  1318. (LPVOID*)&(pMenuEntry->szwMenuCmdLine));
  1319. if (S_OK == hr)
  1320. {
  1321. lstrcpyW(pMenuEntry->szwMenuCmdLine, PszwProfileDir ());
  1322. lstrcatW(pMenuEntry->szwMenuCmdLine, pszFileName);
  1323. }
  1324. }
  1325. else
  1326. {
  1327. hr = HrCoTaskMemAlloc ((lstrlenW(szCmdLine)+1)*sizeof(WCHAR),
  1328. (LPVOID*)&(pMenuEntry->szwMenuCmdLine));
  1329. if (S_OK == hr)
  1330. {
  1331. lstrcpyW(pMenuEntry->szwMenuCmdLine, szCmdLine);
  1332. }
  1333. }
  1334. }
  1335. }
  1336. if (FAILED(hr))
  1337. {
  1338. //
  1339. // We Failed so free the memory
  1340. //
  1341. CoTaskMemFree(pMenuEntry->szwMenuText);
  1342. CoTaskMemFree(pMenuEntry->szwMenuCmdLine);
  1343. CoTaskMemFree(pMenuEntry->szwMenuParams);
  1344. }
  1345. return hr;
  1346. }
  1347. //+---------------------------------------------------------------------------
  1348. //
  1349. // Member: CDialupConnection::HrGetCmpFileLocation
  1350. //
  1351. // Purpose: Compares the phonebook file path to path of the current user's
  1352. // application data dir. If the initial paths are the same we have
  1353. // a private profile. Please NOTE that calling this function
  1354. // requires the calling client to properly setup CoSetProxyBlanket for
  1355. // a private user profile (matches the call to CoImpersonateClient)
  1356. //
  1357. // Arguments: szwPhonebook -- path to the phonebook the CM connectoid lives in
  1358. //
  1359. // Returns: S_OK or an error code
  1360. //
  1361. HRESULT
  1362. CDialupConnection::HrGetCmpFileLocation(
  1363. IN PCWSTR szPhonebook,
  1364. IN PCWSTR szEntryName,
  1365. OUT PWSTR szCmpFilePath)
  1366. {
  1367. DWORD dwSize = MAX_PATH;
  1368. HKEY hKey;
  1369. HANDLE hBaseKey = NULL;
  1370. HANDLE hFile;
  1371. HRESULT hr;
  1372. HRESULT hrImpersonate = E_FAIL;
  1373. static const WCHAR c_mappingsRegKey[] = L"Software\\Microsoft\\Connection Manager\\Mappings";
  1374. HANDLE hImpersonationToken = NULL; // The token of the thread
  1375. HANDLE hPrimaryToken = NULL; // The primary token for the new process
  1376. if ((NULL == szCmpFilePath) || (NULL == szPhonebook))
  1377. {
  1378. hr = E_POINTER;
  1379. }
  1380. else
  1381. {
  1382. hr = HrEnsureEntryPropertiesCached ();
  1383. if (SUCCEEDED(hr))
  1384. {
  1385. if (m_fForAllUsers)
  1386. {
  1387. // We have an all users key so get the information from HKLM
  1388. //
  1389. hBaseKey = HKEY_LOCAL_MACHINE;
  1390. }
  1391. else
  1392. {
  1393. // Then we have a private profile. Since netman runs as a system account,
  1394. // we must impersonate the client and then make an RTL call to get
  1395. // the current users HKCU hive before querying the registry for the
  1396. // cmp path. We also need to get the user token so that we can expand the
  1397. // cmp string in the single user case.
  1398. //
  1399. hrImpersonate = CoImpersonateClient ();
  1400. TraceError ("HrGetCmpFileLocation -- CoImpersonateClient", hr);
  1401. if (SUCCEEDED(hrImpersonate))
  1402. {
  1403. NTSTATUS ntstat = RtlOpenCurrentUser(KEY_READ | KEY_WRITE, &hBaseKey);
  1404. hr = HRESULT_FROM_NT(ntstat);
  1405. TraceError ("RtlOpenCurrentUser", hr);
  1406. if (SUCCEEDED(hr))
  1407. {
  1408. // Create a primary token
  1409. //
  1410. if (!OpenThreadToken(
  1411. GetCurrentThread(),
  1412. TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
  1413. TRUE,
  1414. &hImpersonationToken))
  1415. {
  1416. hr = HrFromLastWin32Error();
  1417. TraceError ("HrGetCmpFileLocation -- OpenThreadToken", hr);
  1418. }
  1419. else
  1420. {
  1421. if(!DuplicateTokenEx(hImpersonationToken,
  1422. TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
  1423. NULL,
  1424. SecurityImpersonation,
  1425. TokenPrimary,
  1426. &hPrimaryToken
  1427. ))
  1428. {
  1429. hr = HrFromLastWin32Error();
  1430. TraceError ("HrGetCmpFileLocation -- DuplicateTokenEx", hr);
  1431. }
  1432. }
  1433. }
  1434. }
  1435. else
  1436. {
  1437. hr = hrImpersonate;
  1438. }
  1439. }
  1440. // Now Open the mappings key and get the cmp file path
  1441. //
  1442. if (SUCCEEDED(hr) && hBaseKey)
  1443. {
  1444. hr = HrRegOpenKeyEx((HKEY)hBaseKey,
  1445. c_mappingsRegKey,
  1446. KEY_READ, &hKey);
  1447. if (SUCCEEDED(hr))
  1448. {
  1449. dwSize = MAX_PATH;
  1450. WCHAR szTemp[MAX_PATH+1];
  1451. hr = HrRegQuerySzBuffer(hKey, szEntryName, szTemp, &dwSize);
  1452. if (SUCCEEDED (hr))
  1453. {
  1454. // Check to see if the file exists
  1455. //
  1456. if (!m_fForAllUsers)
  1457. {
  1458. ExpandEnvironmentStringsForUserW(hPrimaryToken, szTemp,
  1459. szCmpFilePath, MAX_PATH);
  1460. }
  1461. else
  1462. {
  1463. lstrcpyW(szCmpFilePath, szTemp);
  1464. }
  1465. hFile = CreateFile(szCmpFilePath, GENERIC_READ, FILE_SHARE_READ,
  1466. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1467. if (INVALID_HANDLE_VALUE == hFile)
  1468. {
  1469. hr = HRESULT_FROM_WIN32(GetLastError());
  1470. }
  1471. else
  1472. {
  1473. CloseHandle(hFile);
  1474. hr = S_OK;
  1475. }
  1476. }
  1477. RegCloseKey(hKey);
  1478. }
  1479. }
  1480. }
  1481. if (!m_fForAllUsers)
  1482. {
  1483. if (hImpersonationToken)
  1484. {
  1485. CloseHandle(hImpersonationToken);
  1486. }
  1487. if (hPrimaryToken)
  1488. {
  1489. CloseHandle(hPrimaryToken);
  1490. }
  1491. // If it's a valid key that is not NULL then we can close it because we opened it.
  1492. if (hBaseKey)
  1493. {
  1494. // Close the handle opened by RtlOpenCurrentUser
  1495. //
  1496. NtClose(hBaseKey);
  1497. }
  1498. }
  1499. if (SUCCEEDED(hrImpersonate))
  1500. {
  1501. hr = CoRevertToSelf ();
  1502. TraceError ("HrGetCmpFileLocation -- CoRevertToSelf", hr);
  1503. }
  1504. }
  1505. TraceError ("CDialupConnection::HrGetCmpFileLocation", hr);
  1506. return hr;
  1507. }
  1508. //+---------------------------------------------------------------------------
  1509. //
  1510. // Member: CDialupConnection::HrEnsureCmStringsLoaded
  1511. //
  1512. // Purpose: This function ensures that the CM specific member vars for dialup
  1513. // are loaded and usable by CM specific functions. Please NOTE that
  1514. // calling EnsureCmStringsAreLoaded requires the calling client to
  1515. // properly setup CoSetProxyBlanket for a private user profile.
  1516. //
  1517. // Arguments: none
  1518. //
  1519. // Returns: S_OK or an error code
  1520. //
  1521. HRESULT
  1522. CDialupConnection::HrEnsureCmStringsLoaded()
  1523. {
  1524. HRESULT hr = S_OK;
  1525. if (!m_fCmPathsLoaded)
  1526. {
  1527. WCHAR szwCmpFile[MAX_PATH];
  1528. WCHAR szwCmsFile[MAX_PATH];
  1529. WCHAR szwDrive[MAX_PATH];
  1530. WCHAR szwDir[MAX_PATH];
  1531. WCHAR szwFileName[MAX_PATH];
  1532. WCHAR szwExtension[MAX_PATH];
  1533. WCHAR szwProfileDir[MAX_PATH];
  1534. WCHAR szwCmDir[MAX_PATH];
  1535. int nNumChars;
  1536. hr = HrGetCmpFileLocation(PszwPbkFile (), PszwEntryName (), szwCmpFile);
  1537. if (SUCCEEDED(hr))
  1538. {
  1539. // Now split the path
  1540. //
  1541. _wsplitpath(szwCmpFile, szwDrive, szwDir, szwFileName, szwExtension);
  1542. // Now construct the path to the cms file
  1543. //
  1544. nNumChars = wsprintfW(szwCmsFile, L"%s%s%s\\%s%s", szwDrive, szwDir, szwFileName, szwFileName, L".cms");
  1545. ASSERT(nNumChars < celems(szwCmsFile));
  1546. // Now construct the profile dir path
  1547. //
  1548. nNumChars = wsprintfW(szwProfileDir, L"%s%s%s\\", szwDrive, szwDir, szwFileName);
  1549. ASSERT(nNumChars < celems(szwProfileDir));
  1550. // Now construct the CM dir path
  1551. //
  1552. nNumChars = wsprintfW(szwCmDir, L"%s%s", szwDrive, szwDir);
  1553. ASSERT(nNumChars < celems(szwCmDir));
  1554. // Now transfer to the member variables
  1555. //
  1556. m_strCmsFile = szwCmsFile;
  1557. m_strProfileDir = szwProfileDir; // remember this already has the trailing slash
  1558. m_strCmDir = szwCmDir; // remember this already has the trailing slash
  1559. m_strShortServiceName = szwFileName;
  1560. m_fCmPathsLoaded = TRUE;
  1561. }
  1562. }
  1563. TraceError ("CDialupConnection::HrEnsureCmStringsLoaded", hr);
  1564. return hr;
  1565. }
  1566. // INetDefaultConnection
  1567. //+---------------------------------------------------------------------------
  1568. //
  1569. // Member: CDialupConnection::SetDefault
  1570. //
  1571. // Purpose: Set the default RAS connection
  1572. //
  1573. // Arguments: TRUE to set as default connection. FALSE to unset it
  1574. //
  1575. // Returns: S_OK or an error code
  1576. //
  1577. HRESULT
  1578. CDialupConnection::SetDefault(IN BOOL bDefault)
  1579. {
  1580. HRESULT hr = S_OK;
  1581. HRESULT hrT = S_OK;
  1582. if (!m_fInitialized)
  1583. {
  1584. hr = E_UNEXPECTED;
  1585. }
  1586. else
  1587. {
  1588. hr = HrEnsureEntryPropertiesCached ();
  1589. if (SUCCEEDED(hr))
  1590. {
  1591. RASAUTODIALENTRY adEntry;
  1592. ZeroMemory(&adEntry, sizeof(adEntry));
  1593. adEntry.dwSize = sizeof(adEntry);
  1594. if (bDefault)
  1595. {
  1596. wcsncpy(adEntry.szEntry, PszwEntryName(), sizeof(adEntry.szEntry) / sizeof(TCHAR));
  1597. }
  1598. hrT = CoImpersonateClient();
  1599. if (SUCCEEDED(hrT))
  1600. {
  1601. DWORD dwErr = RasSetAutodialAddress(
  1602. NULL,
  1603. NULL,
  1604. &adEntry,
  1605. sizeof(adEntry),
  1606. 1);
  1607. if (dwErr != NO_ERROR)
  1608. {
  1609. hr = HRESULT_FROM_WIN32(dwErr);
  1610. }
  1611. hrT = CoRevertToSelf();
  1612. }
  1613. }
  1614. }
  1615. TraceError ("CDialupConnection::SetDefault", hr);
  1616. return hr;
  1617. }
  1618. //+---------------------------------------------------------------------------
  1619. //
  1620. // Member: CDialupConnection::GetDefault
  1621. //
  1622. // Purpose: Get the default RAS connection
  1623. //
  1624. // Arguments: pbDefault - Is this the default connection
  1625. //
  1626. // Returns: S_OK or an error code
  1627. //
  1628. HRESULT
  1629. CDialupConnection::GetDefault (OUT BOOL* pbDefault)
  1630. {
  1631. HRESULT hr = S_OK;
  1632. if (!m_fInitialized)
  1633. {
  1634. hr = E_UNEXPECTED;
  1635. }
  1636. else
  1637. {
  1638. hr = HrEnsureEntryPropertiesCached ();
  1639. if (SUCCEEDED(hr))
  1640. {
  1641. if (m_dwFlagsPriv & REED_F_Default)
  1642. {
  1643. *pbDefault = TRUE;
  1644. }
  1645. else
  1646. {
  1647. *pbDefault = FALSE;
  1648. }
  1649. }
  1650. }
  1651. TraceError ("CDialupConnection::GetDefault", hr);
  1652. return hr;
  1653. }
  1654. //+---------------------------------------------------------------------------
  1655. //
  1656. // Member: CDialupConnection::GetPropertiesEx
  1657. //
  1658. // Purpose: Get the GetPropertiesEx for this connection
  1659. //
  1660. // Arguments: ppConnectionPropertiesEx [out]
  1661. //
  1662. // Returns: S_OK or an error code
  1663. //
  1664. HRESULT
  1665. CDialupConnection::GetPropertiesEx(OUT NETCON_PROPERTIES_EX** ppConnectionPropertiesEx)
  1666. {
  1667. HRESULT hr = S_OK;
  1668. *ppConnectionPropertiesEx = NULL;
  1669. if (!m_fInitialized)
  1670. {
  1671. hr = E_UNEXPECTED;
  1672. }
  1673. else
  1674. {
  1675. NETCON_PROPERTIES* pProps;
  1676. NETCON_PROPERTIES_EX* pPropsEx = reinterpret_cast<NETCON_PROPERTIES_EX*>(CoTaskMemAlloc(sizeof(NETCON_PROPERTIES_EX)));
  1677. if (pPropsEx)
  1678. {
  1679. ZeroMemory(pPropsEx, sizeof(NETCON_PROPERTIES_EX));
  1680. hr = GetProperties(&pProps);
  1681. if (SUCCEEDED(hr))
  1682. {
  1683. hr = HrBuildPropertiesExFromProperties(pProps, pPropsEx, dynamic_cast<IPersistNetConnection *>(this));
  1684. if (SUCCEEDED(hr))
  1685. {
  1686. pPropsEx->bstrPhoneOrHostAddress = SysAllocString(m_strPhoneNumber.c_str());
  1687. *ppConnectionPropertiesEx = pPropsEx;
  1688. }
  1689. FreeNetconProperties(pProps);
  1690. }
  1691. if (FAILED(hr))
  1692. {
  1693. CoTaskMemFree(pPropsEx);
  1694. }
  1695. }
  1696. else
  1697. {
  1698. hr = E_OUTOFMEMORY;
  1699. }
  1700. }
  1701. TraceError ("CDialupConnection::GetPropertiesEx", hr);
  1702. return hr;
  1703. }