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.

2242 lines
58 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: L A N . C P P
  7. //
  8. // Contents: Implementation of LAN connection objects
  9. //
  10. // Notes:
  11. //
  12. // Author: danielwe 2 Oct 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <ncreg.h>
  18. #include <ncsetup.h>
  19. #include "lan.h"
  20. #include "lancmn.h"
  21. #include "nccom.h"
  22. #include "ncmisc.h"
  23. #include "ncnetcon.h"
  24. #include "sensapip.h" // For SensNotifyNetconEvent
  25. #include "ncstring.h"
  26. #include "ncras.h"
  27. #include "naming.h"
  28. #include "wzcsvc.h"
  29. #include "cobase.h"
  30. #include "gpnla.h"
  31. #include "ncperms.h"
  32. #include "nmpolicy.h"
  33. LONG g_CountLanConnectionObjects;
  34. extern CGroupPolicyNetworkLocationAwareness* g_pGPNLA;
  35. static const WCHAR c_szConnName[] = L"Name";
  36. static const WCHAR c_szShowIcon[] = L"ShowIcon";
  37. static const WCHAR c_szAutoConnect[] = L"AutoConnect";
  38. extern const WCHAR c_szRegKeyInterfacesFromInstance[];
  39. extern const WCHAR c_szRegValueUpperRange[];
  40. static const WCHAR c_chComma = L',';
  41. extern const WCHAR c_szBiNdisAtm[];
  42. static const DWORD c_cchMaxConnNameLen = 256;
  43. static const CLSID CLSID_LanConnectionUi =
  44. {0x7007ACC5,0x3202,0x11D1,{0xAA,0xD2,0x00,0x80,0x5F,0xC1,0x27,0x0E}};
  45. typedef DWORD (APIENTRY *PFNSENSNOTIFY) (PSENS_NOTIFY_NETCON pEvent);
  46. #define NETCFG_S_NOTEXIST 0x00000002
  47. //
  48. // CComObject overrides
  49. //
  50. //+---------------------------------------------------------------------------
  51. //
  52. // Member: CLanConnection::CreateInstance
  53. //
  54. // Purpose: Static function to create an instance of a LAN connection
  55. // object
  56. //
  57. // Arguments:
  58. // hdi [in] Device installer device info
  59. // deid [in] Device installer device info
  60. // riid [in] Initial interface to query for
  61. // ppv [out] Returns the new interface pointer
  62. //
  63. // Returns: S_OK if success, otherwise OLE or Win32 error code
  64. //
  65. // Author: danielwe 2 Oct 1997
  66. //
  67. // Notes:
  68. //
  69. HRESULT CLanConnection::CreateInstance(HDEVINFO hdi,
  70. const SP_DEVINFO_DATA &deid,
  71. PCWSTR pszPnpId,
  72. REFIID riid, LPVOID *ppv)
  73. {
  74. HRESULT hr = E_OUTOFMEMORY;
  75. CLanConnection * pObj;
  76. pObj = new CComObject<CLanConnection>;
  77. if (pObj)
  78. {
  79. // Initialize our members.
  80. //
  81. pObj->m_hkeyConn = NULL;
  82. pObj->m_hdi = hdi;
  83. pObj->m_deid = deid;
  84. // Do the standard CComCreator::CreateInstance stuff.
  85. //
  86. pObj->SetVoid (NULL);
  87. pObj->InternalFinalConstructAddRef();
  88. hr = pObj->FinalConstruct();
  89. pObj->InternalFinalConstructRelease();
  90. if (SUCCEEDED(hr))
  91. {
  92. hr = pObj->HrInitialize(pszPnpId);
  93. if (SUCCEEDED(hr))
  94. {
  95. hr = pObj->GetUnknown()->QueryInterface(riid, ppv);
  96. }
  97. }
  98. if (FAILED(hr))
  99. {
  100. delete pObj;
  101. }
  102. }
  103. else
  104. {
  105. SetupDiDestroyDeviceInfoList(hdi);
  106. }
  107. TraceError("CLanConnection::CreateInstance", hr);
  108. return hr;
  109. }
  110. BOOL VerifyUniqueConnectionName(CIntelliName *pIntelliName, PCWSTR pszPotentialName, NETCON_MEDIATYPE *pncm, NETCON_SUBMEDIATYPE *pncms)
  111. {
  112. HRESULT hr = S_OK;
  113. DWORD dwSuffix = 2;
  114. HKEY hkey;
  115. BOOL fDupFound = FALSE;
  116. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\"
  117. L"Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
  118. KEY_READ, &hkey);
  119. if (S_OK == hr)
  120. {
  121. FILETIME ft;
  122. DWORD dwIndex = 0;
  123. WCHAR szKeyName[MAX_PATH];
  124. DWORD cchName = celems(szKeyName);
  125. while (!fDupFound && (S_OK == (hr = HrRegEnumKeyEx(hkey, dwIndex, szKeyName,
  126. &cchName, NULL, NULL, &ft))) )
  127. {
  128. HKEY hkeyConn;
  129. WCHAR szSubKey[MAX_PATH];
  130. wsprintfW(szSubKey, L"%s\\Connection", szKeyName);
  131. hr = HrRegOpenKeyEx(hkey, szSubKey, KEY_READ, &hkeyConn);
  132. if (S_OK == hr)
  133. {
  134. tstring strName;
  135. hr = HrRegQueryString(hkeyConn, c_szConnName, &strName);
  136. if (S_OK == hr)
  137. {
  138. if (!lstrcmpiW(pszPotentialName, strName.c_str()))
  139. {
  140. fDupFound = TRUE;
  141. CLSID guidName;
  142. if (SUCCEEDED(CLSIDFromString(szKeyName, &guidName)))
  143. {
  144. hr = pIntelliName->HrGetPseudoMediaTypes(guidName, pncm, pncms);
  145. if (FAILED(hr))
  146. {
  147. *pncm = NCM_LAN;
  148. *pncms = NCSM_LAN;
  149. }
  150. }
  151. else
  152. {
  153. AssertSz(FALSE, "This doesn't look like a GUID.");
  154. }
  155. break;
  156. }
  157. else
  158. {
  159. dwIndex++;
  160. }
  161. }
  162. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  163. {
  164. // If value doesn't exist, that's ok. This is a new
  165. // connection.
  166. hr = S_OK;
  167. dwIndex++;
  168. }
  169. RegCloseKey(hkeyConn);
  170. }
  171. else
  172. {
  173. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  174. {
  175. // If key doesn't exist, that's ok. This is not a
  176. // connection.
  177. hr = S_OK;
  178. dwIndex++;
  179. }
  180. }
  181. cchName = celems(szKeyName);
  182. }
  183. RegCloseKey(hkey);
  184. }
  185. return fDupFound;
  186. }
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Member: CLanConnection::HrInitialize
  190. //
  191. // Purpose: Initializes the connection object for the first time.
  192. //
  193. // Arguments:
  194. // (none)
  195. //
  196. // Returns: S_OK if success, Win32 or OLE error code otherwise
  197. //
  198. // Author: danielwe 4 Nov 1997
  199. //
  200. // Notes: This function is only called when the object is created for
  201. // the very first time and has no identity.
  202. //
  203. HRESULT CLanConnection::HrInitialize(
  204. PCWSTR pszPnpId)
  205. {
  206. HRESULT hr = S_OK;
  207. GUID guid;
  208. AssertSz(m_hdi, "We should have a component at this point!");
  209. Assert(pszPnpId);
  210. hr = HrGetInstanceGuid(m_hdi, m_deid, &guid);
  211. if (S_OK == hr)
  212. {
  213. // Open the main connection key. If it doesn't exist, we'll create it
  214. // here.
  215. hr = HrOpenConnectionKey(&guid, NULL, KEY_READ_WRITE,
  216. OCCF_CREATE_IF_NOT_EXIST, pszPnpId,
  217. &m_hkeyConn);
  218. if (SUCCEEDED(hr))
  219. {
  220. tstring strName;
  221. // First see if a name already exists for this connection
  222. hr = HrRegQueryString(m_hkeyConn, c_szConnName, &strName);
  223. if (FAILED(hr))
  224. {
  225. // no name?
  226. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  227. {
  228. //$ REVIEW (danielwe) 30 Oct 1997: If I can be assured
  229. // that get_Name is never called before Rename, I
  230. // don't need this function to be called.
  231. // Note: (danielwe) 31 Oct 1997: This could result in
  232. // duplicate names, but we cannot check for duplicates
  233. // without recursing infinitely
  234. // Set default connection name
  235. CIntelliName IntelliName(_Module.GetResourceInstance(), VerifyUniqueConnectionName);
  236. GUID gdDevice;
  237. LPWSTR szNewName = NULL;
  238. hr = HrGetInstanceGuid(m_hdi, m_deid, &gdDevice);
  239. Assert(SUCCEEDED(hr));
  240. if (SUCCEEDED(hr))
  241. {
  242. BOOL fNetworkBridge;
  243. hr = HrIsConnectionNetworkBridge(&fNetworkBridge);
  244. if (SUCCEEDED(hr) && fNetworkBridge)
  245. {
  246. hr = IntelliName.GenerateName(gdDevice, NCM_BRIDGE, 0, NULL, &szNewName);
  247. }
  248. else
  249. {
  250. hr = IntelliName.GenerateName(gdDevice, NCM_LAN, 0, NULL, &szNewName);
  251. }
  252. if (SUCCEEDED(hr))
  253. {
  254. hr = HrRegSetSz(m_hkeyConn, c_szConnName, szNewName);
  255. CoTaskMemFree(szNewName);
  256. }
  257. }
  258. Assert(SUCCEEDED(hr));
  259. }
  260. }
  261. }
  262. }
  263. if (SUCCEEDED(hr))
  264. {
  265. m_fInitialized = TRUE;
  266. }
  267. TraceError("CLanConnection::HrInitialize", hr);
  268. return hr;
  269. }
  270. //+---------------------------------------------------------------------------
  271. //
  272. // Member: CLanConnection::HrOpenRegistryKeys
  273. //
  274. // Purpose: Opens the registry keys that this LAN connection object will
  275. // use
  276. //
  277. // Arguments:
  278. // guid [in] Guid of adapter that this connection uses
  279. //
  280. // Returns: S_OK if success, Win32 error otherwise
  281. //
  282. // Author: danielwe 11 Nov 1997
  283. //
  284. // Notes: Keys are expected to exist and this will fail if either do
  285. // not
  286. //
  287. HRESULT CLanConnection::HrOpenRegistryKeys(const GUID &guid)
  288. {
  289. HRESULT hr = S_OK;
  290. AssertSz(!m_hkeyConn, "Don't call this more than once "
  291. "on the same connection object!");
  292. // This should only be called from HrLoad so these keys had better be
  293. // there.
  294. hr = HrOpenConnectionKey(&guid, NULL, KEY_READ_WRITE,
  295. OCCF_NONE, NULL, &m_hkeyConn);
  296. TraceError("CLanConnection::HrOpenRegistryKeys", hr);
  297. return hr;
  298. }
  299. //+---------------------------------------------------------------------------
  300. //
  301. // Member: CLanConnection::HrLoad
  302. //
  303. // Purpose: Implements the bulk of IPersistNetConnection::Load.
  304. //
  305. // Arguments:
  306. // guid [in] GUID from which to receive identity
  307. //
  308. // Returns: S_OK if success, OLE or Win32 error code otherwise
  309. //
  310. // Author: danielwe 4 Nov 1997
  311. //
  312. // Notes:
  313. //
  314. HRESULT CLanConnection::HrLoad(const GUID &guid)
  315. {
  316. HRESULT hr = S_OK;
  317. hr = HrLoadDevInfoFromGuid(guid);
  318. if (SUCCEEDED(hr))
  319. {
  320. hr = HrOpenRegistryKeys(guid);
  321. if (SUCCEEDED(hr))
  322. {
  323. // No need to call HrInitialize because this object should
  324. // already be created properly at a previous time
  325. m_fInitialized = TRUE;
  326. }
  327. }
  328. TraceError("CLanConnection::HrLoad", hr);
  329. return hr;
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Member: CLanConnection::~CLanConnection
  334. //
  335. // Purpose: Called when the connection object is released for the last
  336. // time.
  337. //
  338. // Arguments:
  339. // (none)
  340. //
  341. // Returns: Nothing
  342. //
  343. // Author: danielwe 3 Oct 1997
  344. //
  345. // Notes:
  346. //
  347. CLanConnection::~CLanConnection()
  348. {
  349. RegSafeCloseKey(m_hkeyConn);
  350. SetupDiDestroyDeviceInfoListSafe(m_hdi);
  351. InterlockedDecrement(&g_CountLanConnectionObjects);
  352. CoTaskMemFree(m_pHNetProperties);
  353. }
  354. //
  355. // INetConnection
  356. //
  357. //+---------------------------------------------------------------------------
  358. //
  359. // Member: CLanConnection::Rename
  360. //
  361. // Purpose: Changes the name of the connection
  362. //
  363. // Arguments:
  364. // pszName [in] New connection name (must be valid)
  365. //
  366. // Returns: S_OK if success, OLE error code otherwise
  367. //
  368. // Author: danielwe 2 Oct 1997
  369. //
  370. // Notes:
  371. //
  372. STDMETHODIMP CLanConnection::Rename(PCWSTR pszName)
  373. {
  374. HRESULT hr = S_OK;
  375. if (!pszName)
  376. {
  377. hr = E_POINTER;
  378. }
  379. else if (!*pszName)
  380. {
  381. hr = E_INVALIDARG;
  382. }
  383. else if (!m_fInitialized)
  384. {
  385. hr = E_UNEXPECTED;
  386. }
  387. else if (!FIsValidConnectionName(pszName))
  388. {
  389. // Bad connection name
  390. hr = E_INVALIDARG;
  391. }
  392. else
  393. {
  394. AssertSz(m_hkeyConn, "Why don't I have a connection key?");
  395. // Get the current name for this connection
  396. tstring strName;
  397. hr = HrRegQueryString(m_hkeyConn, c_szConnName, &strName);
  398. if (S_OK == hr)
  399. {
  400. // Only do something if names are different
  401. if (lstrcmpiW(pszName, strName.c_str()))
  402. {
  403. hr = HrPutName(pszName);
  404. }
  405. }
  406. }
  407. TraceError("CLanConnection::Rename", hr);
  408. return hr;
  409. }
  410. //+---------------------------------------------------------------------------
  411. //
  412. // Member: CLanConnection::HrPutName
  413. //
  414. // Purpose: Sets the connection name using the given name
  415. //
  416. // Arguments:
  417. // pszName [in] New name for connection
  418. //
  419. // Returns: S_OK if success, OLE error code otherwise
  420. //
  421. // Author: danielwe 31 Oct 1997
  422. //
  423. // Notes: Doesn't check if name is already set to this
  424. //
  425. HRESULT CLanConnection::HrPutName(PCWSTR pszName)
  426. {
  427. HRESULT hr = S_OK;
  428. GUID guid;
  429. // Get my device guid first
  430. hr = GetDeviceGuid(&guid);
  431. if (S_OK == hr)
  432. {
  433. hr = HrIsConnectionNameUnique(guid, pszName);
  434. if (S_OK == hr)
  435. {
  436. hr = HrRegSetSz(m_hkeyConn, c_szConnName, pszName);
  437. if (S_OK == hr)
  438. {
  439. LanEventNotify(CONNECTION_RENAMED, NULL, pszName, &guid);
  440. }
  441. }
  442. else if (S_FALSE == hr)
  443. {
  444. hr = HRESULT_FROM_WIN32(ERROR_DUP_NAME);
  445. }
  446. }
  447. TraceErrorOptional("CLanConnection::HrPutName", hr,
  448. (hr == HRESULT_FROM_WIN32(ERROR_DUP_NAME)));
  449. return hr;
  450. }
  451. //+---------------------------------------------------------------------------
  452. //
  453. // Member: CLanConnection::FIsMediaPresent
  454. //
  455. // Purpose: Determines as best as can be basically whether the cable is
  456. // plugged in to the network card.
  457. //
  458. // Arguments:
  459. // (none)
  460. //
  461. // Returns: TRUE if cable is plugged in, FALSE if not
  462. //
  463. // Author: danielwe 22 Sep 1998
  464. //
  465. // Notes: This function returns TRUE by default.
  466. //
  467. BOOL CLanConnection::FIsMediaPresent()
  468. {
  469. BOOL fRet = TRUE;
  470. GUID guid;
  471. if (S_OK == GetDeviceGuid(&guid))
  472. {
  473. fRet = ::FIsMediaPresent(&guid);
  474. }
  475. return fRet;
  476. }
  477. //+---------------------------------------------------------------------------
  478. //
  479. // Member: CLanConnection::GetStatus
  480. //
  481. // Purpose: Returns the status of this LAN connection
  482. //
  483. // Arguments:
  484. // pStatus [out] Returns status value
  485. //
  486. // Returns: S_OK if success, OLE or Win32 error code otherwise
  487. //
  488. // Author: danielwe 3 Oct 1997
  489. //
  490. // Notes:
  491. //
  492. HRESULT CLanConnection::GetStatus(NETCON_STATUS *pStatus)
  493. {
  494. HRESULT hr;
  495. if (!pStatus)
  496. {
  497. hr = E_POINTER;
  498. }
  499. else if (!m_fInitialized)
  500. {
  501. hr = E_UNEXPECTED;
  502. }
  503. else
  504. {
  505. GUID guid;
  506. hr = GetDeviceGuid(&guid);
  507. if (S_OK == hr)
  508. {
  509. hr = HrGetDevInstStatus(m_deid.DevInst, &guid, pStatus);
  510. }
  511. }
  512. TraceError("CLanConnection::GetStatus", hr);
  513. return hr;
  514. }
  515. //+---------------------------------------------------------------------------
  516. //
  517. // Member: CLanConnection::GetDeviceName
  518. //
  519. // Purpose: Returns the name of the device being used by this connection
  520. //
  521. // Arguments:
  522. // ppszwDeviceName [out] Receives device name
  523. //
  524. // Returns: S_OK if success, OLE error code otherwise
  525. //
  526. // Author: danielwe 2 Oct 1997
  527. //
  528. // Notes: Returned string must be freed with CoTaskMemFree.
  529. //
  530. HRESULT CLanConnection::GetDeviceName(PWSTR* ppszwDeviceName)
  531. {
  532. Assert (ppszwDeviceName);
  533. Assert(m_hdi);
  534. // Initialize the output parameter.
  535. *ppszwDeviceName = NULL;
  536. PWSTR szDesc;
  537. HRESULT hr = HrSetupDiGetDeviceName(m_hdi, &m_deid, &szDesc);
  538. if (SUCCEEDED(hr))
  539. {
  540. hr = HrCoTaskMemAllocAndDupSz (szDesc, ppszwDeviceName);
  541. delete [] reinterpret_cast<BYTE*>(szDesc);
  542. }
  543. TraceError("CLanConnection::GetDeviceName", hr);
  544. return hr;
  545. }
  546. //+---------------------------------------------------------------------------
  547. //
  548. // Member: CLanConnection::GetCharacteristics
  549. //
  550. // Purpose: Returns the characteristics of this connection type
  551. //
  552. // Arguments:
  553. // pdwFlags [out] Returns characteristics flags
  554. //
  555. // Returns: S_OK if successful, OLE or Win32 error code otherwise
  556. //
  557. // Author: danielwe 3 Oct 1997
  558. //
  559. // Notes:
  560. //
  561. HRESULT CLanConnection::GetCharacteristics(NETCON_MEDIATYPE ncm, DWORD* pdwFlags)
  562. {
  563. Assert (pdwFlags);
  564. *pdwFlags = NCCF_ALL_USERS | NCCF_ALLOW_RENAME;
  565. DWORD dwValue;
  566. HRESULT hr = HrRegQueryDword(m_hkeyConn, c_szShowIcon, &dwValue);
  567. if (SUCCEEDED(hr) && dwValue)
  568. {
  569. *pdwFlags |= NCCF_SHOW_ICON;
  570. }
  571. BOOL fShared;
  572. hr = HrIsConnectionIcsPublic(&fShared);
  573. if(SUCCEEDED(hr) && TRUE == fShared)
  574. {
  575. *pdwFlags |= NCCF_SHARED;
  576. }
  577. BOOL fBridged;
  578. hr = HrIsConnectionBridged(&fBridged);
  579. if(SUCCEEDED(hr) && TRUE == fBridged)
  580. {
  581. *pdwFlags |= NCCF_BRIDGED;
  582. }
  583. BOOL bFirewalled;
  584. hr = HrIsConnectionFirewalled(&bFirewalled);
  585. if(SUCCEEDED(hr) && TRUE == bFirewalled)
  586. {
  587. *pdwFlags |= NCCF_FIREWALLED;
  588. }
  589. if(NCM_BRIDGE == ncm)
  590. {
  591. hr = HrEnsureValidNlaPolicyEngine();
  592. if(SUCCEEDED(hr))
  593. {
  594. BOOL fHasPermission;
  595. hr = m_pNetMachinePolicies->VerifyPermission(NCPERM_AllowNetBridge_NLA, &fHasPermission);
  596. if(SUCCEEDED(hr) && fHasPermission)
  597. {
  598. *pdwFlags |= NCCF_ALLOW_REMOVAL;
  599. }
  600. }
  601. }
  602. hr = S_OK;
  603. TraceError("CLanConnection::GetCharacteristics", hr);
  604. return hr;
  605. }
  606. //+---------------------------------------------------------------------------
  607. //
  608. // Member: CLanConnection::GetUiObjectClassId
  609. //
  610. // Purpose: Returns the CLSID of the object that handles UI for this
  611. // connection type
  612. //
  613. // Arguments:
  614. // pclsid [out] Returns CLSID of UI object
  615. //
  616. // Returns: S_OK if success, OLE error code otherwise
  617. //
  618. // Author: danielwe 6 Oct 1997
  619. //
  620. // Notes:
  621. //
  622. STDMETHODIMP CLanConnection::GetUiObjectClassId(CLSID *pclsid)
  623. {
  624. HRESULT hr = S_OK;
  625. // Validate parameters.
  626. //
  627. if (!pclsid)
  628. {
  629. hr = E_POINTER;
  630. }
  631. else if (!m_fInitialized)
  632. {
  633. hr = E_UNEXPECTED;
  634. }
  635. else
  636. {
  637. *pclsid = CLSID_LanConnectionUi;
  638. }
  639. TraceError("CLanConnection::GetUiObjectClassId", hr);
  640. return hr;
  641. }
  642. static const WCHAR c_szLibPath[] = L"sens.dll";
  643. static const CHAR c_szaFunction[] = "SensNotifyNetconEvent";
  644. //+---------------------------------------------------------------------------
  645. //
  646. // Member: CLanConnection::HrCallSens
  647. //
  648. // Purpose: Calls the external SENS notification DLL to let it know that
  649. // we connected or disconnected.
  650. //
  651. // Arguments:
  652. // fConnect [in] TRUE if connecting, FALSE if disconnecting
  653. //
  654. // Returns: S_OK if success, Win32 error code otherwise
  655. //
  656. // Author: danielwe 16 Jun 1998
  657. //
  658. // Notes:
  659. //
  660. HRESULT CLanConnection::HrCallSens(BOOL fConnect)
  661. {
  662. HRESULT hr = S_OK;
  663. HMODULE hmod;
  664. PFNSENSNOTIFY pfnSensNotifyNetconEvent;
  665. hr = HrLoadLibAndGetProc(c_szLibPath, c_szaFunction, &hmod,
  666. reinterpret_cast<FARPROC *>(&pfnSensNotifyNetconEvent));
  667. if (SUCCEEDED(hr))
  668. {
  669. DWORD dwErr;
  670. SENS_NOTIFY_NETCON snl = {0};
  671. snl.eType = fConnect ? SENS_NOTIFY_LAN_CONNECT :
  672. SENS_NOTIFY_LAN_DISCONNECT;
  673. snl.pINetConnection = this;
  674. TraceTag(ttidLanCon, "Calling SENS to notify of %s.",
  675. fConnect ? "connect" : "disconnect");
  676. dwErr = pfnSensNotifyNetconEvent(&snl);
  677. if (dwErr != ERROR_SUCCESS)
  678. {
  679. hr = HRESULT_FROM_WIN32(dwErr);
  680. }
  681. else
  682. {
  683. TraceTag(ttidLanCon, "Successfully notified SENS.");
  684. }
  685. FreeLibrary(hmod);
  686. }
  687. TraceError("CLanConnection::HrCallSens", hr);
  688. return hr;
  689. }
  690. //+---------------------------------------------------------------------------
  691. //
  692. // Member: CLanConnection::HrConnectOrDisconnect
  693. //
  694. // Purpose: Connects or disconnects this LAN connection
  695. //
  696. // Arguments:
  697. // fConnect [in] TRUE if connect, FALSE if disconnect
  698. //
  699. // Returns: S_OK if success, OLE or Win32 error code otherwise
  700. //
  701. // Author: danielwe 4 Dec 1997
  702. //
  703. // Notes:
  704. //
  705. HRESULT CLanConnection::HrConnectOrDisconnect(BOOL fConnect)
  706. {
  707. HRESULT hr = S_OK;
  708. if (!m_hdi)
  709. {
  710. hr = E_UNEXPECTED;
  711. }
  712. else if (!m_fInitialized)
  713. {
  714. hr = E_UNEXPECTED;
  715. }
  716. else
  717. {
  718. // Before attempting to connect, check media state. If it is
  719. // disconnected, return error code that indicates that network is
  720. // not present because the cable is unplugged.
  721. //
  722. if (fConnect)
  723. {
  724. if (!FIsMediaPresent())
  725. {
  726. hr = HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
  727. }
  728. }
  729. if (SUCCEEDED(hr))
  730. {
  731. hr = HrSetupDiSendPropertyChangeNotification(m_hdi, &m_deid,
  732. fConnect ? DICS_ENABLE : DICS_DISABLE,
  733. DICS_FLAG_CONFIGSPECIFIC, 0);
  734. if (SUCCEEDED(hr))
  735. {
  736. NETCON_STATUS status;
  737. hr = GetStatus(&status);
  738. if (SUCCEEDED(hr))
  739. {
  740. if (fConnect)
  741. {
  742. int nSecondsToWait = 5;
  743. HRESULT hrRetry = S_OK;
  744. while ((nSecondsToWait) && SUCCEEDED(hrRetry) &&
  745. ((NCS_CONNECTING == status) || (NCS_MEDIA_DISCONNECTED == status) || (NCS_INVALID_ADDRESS == status)))
  746. {
  747. //#300520: check a few more times since the connection is
  748. // still coming up
  749. Sleep(1000);
  750. hrRetry = GetStatus(&status);
  751. nSecondsToWait --;
  752. }
  753. if (status != NCS_CONNECTED)
  754. {
  755. // did not connect successfully
  756. hr = HRESULT_FROM_WIN32(ERROR_RETRY);
  757. TraceError("HrConnectOrDisconnect - failed to "
  758. "connect!", hr);
  759. }
  760. }
  761. else
  762. {
  763. if (status != NCS_DISCONNECTED)
  764. {
  765. // did not disconnect successfully
  766. hr = HRESULT_FROM_WIN32(ERROR_RETRY);
  767. TraceError("HrConnectOrDisconnect - failed to "
  768. "disconnect!", hr);
  769. }
  770. }
  771. }
  772. if (SUCCEEDED(hr))
  773. {
  774. hr = HrCallSens(fConnect);
  775. if (FAILED(hr))
  776. {
  777. TraceTag(ttidLanCon, "Failed to notify SENS on %s. "
  778. "Non-fatal 0x%08X",
  779. fConnect ? "connect" : "disconnect", hr);
  780. hr = S_OK;
  781. }
  782. }
  783. }
  784. }
  785. }
  786. TraceError("CLanConnection::HrConnectOrDisconnect", hr);
  787. return hr;
  788. }
  789. //+---------------------------------------------------------------------------
  790. //
  791. // Member: CLanConnection::Connect
  792. //
  793. // Purpose: Activates the current LAN connection by telling its underlying
  794. // adapter to activate itself.
  795. //
  796. // Arguments:
  797. // (none)
  798. //
  799. // Returns: S_OK if success, OLE or Win32 error code otherwise
  800. //
  801. // Author: danielwe 14 Oct 1997
  802. //
  803. // Notes: Causes auto-connect value of TRUE to be written for this
  804. // connection in the current hardware profile.
  805. //
  806. STDMETHODIMP CLanConnection::Connect()
  807. {
  808. HRESULT hr = S_OK;
  809. hr = HrConnectOrDisconnect(TRUE);
  810. TraceError("CLanConnection::Connect", hr);
  811. return hr;
  812. }
  813. //+---------------------------------------------------------------------------
  814. //
  815. // Member: CLanConnection::Disconnect
  816. //
  817. // Purpose: Deactivates the current LAN connection by telling its
  818. // underlying adapter to deactivate itself.
  819. //
  820. // Arguments:
  821. // (none)
  822. //
  823. // Returns: S_OK if success, OLE or Win32 error code otherwise
  824. //
  825. // Author: danielwe 14 Oct 1997
  826. //
  827. // Notes: Causes auto-connect value of FALSE to be written for this
  828. // connection in the current hardware profile.
  829. //
  830. STDMETHODIMP CLanConnection::Disconnect()
  831. {
  832. HRESULT hr = S_OK;
  833. hr = HrConnectOrDisconnect(FALSE);
  834. TraceError("CLanConnection::Disconnect", hr);
  835. return hr;
  836. }
  837. //+---------------------------------------------------------------------------
  838. //
  839. // Member: CLanConnection::Delete
  840. //
  841. // Purpose: Delete the LAN connection. This not allowed.
  842. //
  843. // Arguments:
  844. // (none)
  845. //
  846. // Returns: E_UNEXPECTED;
  847. //
  848. // Author: shaunco 21 Jan 1998
  849. //
  850. // Notes: This function is not expected to ever be called.
  851. //
  852. STDMETHODIMP CLanConnection::Delete()
  853. {
  854. HRESULT hr;
  855. NETCON_PROPERTIES* pProperties;
  856. hr = GetProperties(&pProperties);
  857. if(SUCCEEDED(hr))
  858. {
  859. if(NCM_BRIDGE == pProperties->MediaType)
  860. {
  861. IHNetConnection *pHNetConnection;
  862. IHNetBridge* pNetBridge;
  863. Assert(m_fInitialized);
  864. hr = HrGetIHNetConnection(&pHNetConnection);
  865. if (SUCCEEDED(hr))
  866. {
  867. hr = pHNetConnection->GetControlInterface(
  868. IID_IHNetBridge,
  869. reinterpret_cast<void**>(&pNetBridge)
  870. );
  871. ReleaseObj(pHNetConnection);
  872. AssertSz(SUCCEEDED(hr), "Unable to retrieve IHNetBridge");
  873. }
  874. if(SUCCEEDED(hr))
  875. {
  876. hr = pNetBridge->Destroy();
  877. ReleaseObj(pNetBridge);
  878. }
  879. }
  880. else
  881. {
  882. hr = E_FAIL; // can't delete anything but NCM_BRIDGE
  883. }
  884. FreeNetconProperties(pProperties);
  885. }
  886. return hr;
  887. }
  888. STDMETHODIMP CLanConnection::Duplicate (
  889. PCWSTR pszDuplicateName,
  890. INetConnection** ppCon)
  891. {
  892. return E_NOTIMPL;
  893. }
  894. //+---------------------------------------------------------------------------
  895. //
  896. // Member: CLanConnection::GetProperties
  897. //
  898. // Purpose: Get all of the properties associated with the connection.
  899. // Returning all of them at once saves us RPCs vs. returning
  900. // each one individually.
  901. //
  902. // Arguments:
  903. // ppProps [out] Returned block of properties.
  904. //
  905. // Returns: S_OK or an error.
  906. //
  907. // Author: shaunco 1 Feb 1998
  908. //
  909. // Notes:
  910. //
  911. STDMETHODIMP CLanConnection::GetProperties (
  912. NETCON_PROPERTIES** ppProps)
  913. {
  914. HRESULT hr = S_OK;
  915. // Validate parameters.
  916. //
  917. if (!ppProps)
  918. {
  919. hr = E_POINTER;
  920. }
  921. else if (!m_fInitialized)
  922. {
  923. hr = E_UNEXPECTED;
  924. }
  925. else
  926. {
  927. // Initialize the output parameter.
  928. //
  929. *ppProps = NULL;
  930. NETCON_PROPERTIES* pProps;
  931. NETCON_STATUS ncStatus;
  932. hr = HrCoTaskMemAlloc (sizeof (NETCON_PROPERTIES),
  933. reinterpret_cast<void**>(&pProps));
  934. if (SUCCEEDED(hr))
  935. {
  936. HRESULT hrT;
  937. ZeroMemory (pProps, sizeof (NETCON_PROPERTIES));
  938. // guidId
  939. //
  940. hrT = GetDeviceGuid(&pProps->guidId);
  941. if (FAILED(hrT))
  942. {
  943. hr = hrT;
  944. }
  945. // pszwName
  946. //
  947. tstring strName;
  948. hrT = HrRegQueryString(m_hkeyConn, c_szConnName, &strName);
  949. if (SUCCEEDED(hrT))
  950. {
  951. hrT = HrCoTaskMemAllocAndDupSz (strName.c_str(),
  952. &pProps->pszwName);
  953. }
  954. if (FAILED(hrT))
  955. {
  956. hr = hrT;
  957. }
  958. // pszwDeviceName
  959. //
  960. PWSTR szDesc;
  961. hrT = HrSetupDiGetDeviceName(m_hdi, &m_deid, &szDesc);
  962. if (SUCCEEDED(hrT))
  963. {
  964. hrT = HrCoTaskMemAllocAndDupSz (szDesc,
  965. &pProps->pszwDeviceName);
  966. delete [] reinterpret_cast<BYTE*>(szDesc);
  967. }
  968. if (FAILED(hrT))
  969. {
  970. hr = hrT;
  971. }
  972. // Status
  973. //
  974. hrT = GetStatus (&pProps->Status);
  975. if (FAILED(hrT))
  976. {
  977. hr = hrT;
  978. }
  979. // Get additional Status information from 802.1X
  980. //
  981. if ((NCS_CONNECTED == pProps->Status)
  982. || (NCS_INVALID_ADDRESS == pProps->Status)
  983. || (NCS_MEDIA_DISCONNECTED == pProps->Status))
  984. {
  985. hrT = WZCQueryGUIDNCSState(&pProps->guidId, &ncStatus);
  986. if (S_OK == hrT)
  987. {
  988. pProps->Status = ncStatus;
  989. }
  990. }
  991. // Type
  992. //
  993. BOOL fNetworkBridge;
  994. hrT = HrIsConnectionNetworkBridge(&fNetworkBridge);
  995. if(SUCCEEDED(hrT) && TRUE == fNetworkBridge)
  996. {
  997. pProps->MediaType = NCM_BRIDGE;
  998. }
  999. else
  1000. {
  1001. pProps->MediaType = NCM_LAN;
  1002. }
  1003. // dwCharacter
  1004. //
  1005. hrT = GetCharacteristics (pProps->MediaType, &pProps->dwCharacter);
  1006. if (FAILED(hrT))
  1007. {
  1008. hr = hrT;
  1009. }
  1010. // clsidThisObject
  1011. //
  1012. pProps->clsidThisObject = CLSID_LanConnection;
  1013. // clsidUiObject
  1014. //
  1015. pProps->clsidUiObject = CLSID_LanConnectionUi;
  1016. // Assign the output parameter or cleanup if we had any failures.
  1017. //
  1018. if (SUCCEEDED(hr))
  1019. {
  1020. *ppProps = pProps;
  1021. }
  1022. else
  1023. {
  1024. Assert (NULL == *ppProps);
  1025. FreeNetconProperties (pProps);
  1026. }
  1027. }
  1028. }
  1029. TraceError ("CLanConnection::GetProperties", hr);
  1030. return hr;
  1031. }
  1032. //
  1033. // INetLanConnection
  1034. //
  1035. //+---------------------------------------------------------------------------
  1036. //
  1037. // Member: CLanConnection::GetInfo
  1038. //
  1039. // Purpose: Returns information about this connection
  1040. //
  1041. // Arguments:
  1042. // dwMask [in] Flags that control which fields to return. Use
  1043. // LCIF_ALL to get all fields.
  1044. // pLanConInfo [out] Structure that holds returned information
  1045. //
  1046. // Returns: S_OK if success, OLE error code otherwise
  1047. //
  1048. // Author: danielwe 6 Oct 1997
  1049. //
  1050. // Notes: Caller should delete the szwConnName value.
  1051. //
  1052. STDMETHODIMP CLanConnection::GetInfo(DWORD dwMask, LANCON_INFO* pLanConInfo)
  1053. {
  1054. HRESULT hr = S_OK;
  1055. if (!pLanConInfo)
  1056. {
  1057. hr = E_POINTER;
  1058. }
  1059. else if (!m_hdi)
  1060. {
  1061. hr = E_UNEXPECTED;
  1062. }
  1063. else if (!m_fInitialized)
  1064. {
  1065. hr = E_UNEXPECTED;
  1066. }
  1067. else
  1068. {
  1069. ZeroMemory(pLanConInfo, sizeof(LANCON_INFO));
  1070. if (dwMask & LCIF_COMP)
  1071. {
  1072. GUID guid;
  1073. hr = HrGetInstanceGuid(m_hdi, m_deid, &guid);
  1074. pLanConInfo->guid = guid;
  1075. }
  1076. if (dwMask & LCIF_NAME)
  1077. {
  1078. hr = GetDeviceName(&pLanConInfo->szwConnName);
  1079. }
  1080. if (dwMask & LCIF_ICON)
  1081. {
  1082. if (SUCCEEDED(hr))
  1083. {
  1084. DWORD dwValue;
  1085. hr = HrRegQueryDword(m_hkeyConn, c_szShowIcon, &dwValue);
  1086. // OK if value not there. Default to FALSE always.
  1087. //
  1088. if (S_OK == hr)
  1089. {
  1090. pLanConInfo->fShowIcon = !!(dwValue);
  1091. }
  1092. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  1093. {
  1094. hr = NETCFG_S_NOTEXIST;
  1095. }
  1096. }
  1097. }
  1098. }
  1099. // Mask S_FALSE if it slipped thru.
  1100. if (S_FALSE == hr)
  1101. {
  1102. hr = S_OK;
  1103. }
  1104. TraceError("CLanConnection::GetInfo", hr);
  1105. return hr;
  1106. }
  1107. //+---------------------------------------------------------------------------
  1108. //
  1109. // Member: CLanConnection::SetInfo
  1110. //
  1111. // Purpose: Sets information about this connection.
  1112. //
  1113. // Arguments:
  1114. // dwMask [in] Flags that control which fields to set
  1115. // pLanConInfo [in] Structure containing information to set
  1116. //
  1117. // Returns: S_OK if success, OLE or Win32 error code otherwise
  1118. //
  1119. // Author: danielwe 6 Oct 1997
  1120. //
  1121. // Notes: The guid member can only be set if the object is not yet
  1122. // initialized.
  1123. // The AutoConnect value is never set because it is set only upon
  1124. // connect or disconnect.
  1125. // If szwConnName is NULL, it is left unchanged.
  1126. //
  1127. STDMETHODIMP CLanConnection::SetInfo(DWORD dwMask,
  1128. const LANCON_INFO* pLanConInfo)
  1129. {
  1130. HRESULT hr = S_OK;
  1131. if (!pLanConInfo)
  1132. {
  1133. hr = E_POINTER;
  1134. }
  1135. else if (!m_fInitialized)
  1136. {
  1137. // If we're not yet initialized, the only thing we will allow is the
  1138. // flag that gets us initialized
  1139. if (dwMask != LCIF_COMP)
  1140. {
  1141. hr = E_UNEXPECTED;
  1142. }
  1143. else
  1144. {
  1145. hr = HrLoad(pLanConInfo->guid);
  1146. if (SUCCEEDED(hr))
  1147. {
  1148. WCHAR szPnpId[MAX_DEVICE_ID_LEN];
  1149. hr = HrSetupDiGetDeviceInstanceId(m_hdi, &m_deid, szPnpId,
  1150. MAX_DEVICE_ID_LEN, NULL);
  1151. if (S_OK == hr)
  1152. {
  1153. hr = HrInitialize(szPnpId);
  1154. }
  1155. }
  1156. }
  1157. }
  1158. else
  1159. {
  1160. if (dwMask & LCIF_NAME)
  1161. {
  1162. AssertSz(pLanConInfo->szwConnName,
  1163. "If you're going to set it, set it!");
  1164. // Set connection name
  1165. hr = Rename(pLanConInfo->szwConnName);
  1166. }
  1167. if (dwMask & LCIF_ICON)
  1168. {
  1169. if (SUCCEEDED(hr))
  1170. {
  1171. // Set ShowIcon value
  1172. hr = HrRegSetDword(m_hkeyConn, c_szShowIcon,
  1173. pLanConInfo->fShowIcon);
  1174. }
  1175. }
  1176. if (SUCCEEDED(hr))
  1177. {
  1178. LanEventNotify(CONNECTION_MODIFIED, this, NULL, NULL);
  1179. }
  1180. }
  1181. TraceError("CLanConnection::SetInfo", hr);
  1182. return hr;
  1183. }
  1184. //+---------------------------------------------------------------------------
  1185. //
  1186. // Member: CLanConnection::GetDeviceGuid
  1187. //
  1188. // Purpose: Returns the instance GUID of the device being used by this
  1189. // connection
  1190. //
  1191. // Arguments:
  1192. // pguid [out] Receives GUID of device
  1193. //
  1194. // Returns: S_OK if success, NetCfg error code otherwise
  1195. //
  1196. // Author: danielwe 2 Oct 1997
  1197. //
  1198. // Notes:
  1199. //
  1200. STDMETHODIMP CLanConnection::GetDeviceGuid(GUID *pguid)
  1201. {
  1202. HRESULT hr;
  1203. AssertSz(m_hdi, "No component?!");
  1204. if (!pguid)
  1205. {
  1206. hr = E_POINTER;
  1207. }
  1208. else if (!m_fInitialized)
  1209. {
  1210. hr = E_UNEXPECTED;
  1211. }
  1212. else
  1213. {
  1214. hr = HrGetInstanceGuid(m_hdi, m_deid, pguid);
  1215. }
  1216. TraceError("CLanConnection::GetDeviceGuid", hr);
  1217. return hr;
  1218. }
  1219. //+---------------------------------------------------------------------------
  1220. // IPersistNetConnection
  1221. //
  1222. //+---------------------------------------------------------------------------
  1223. //
  1224. // Member: CLanConnection::GetClassID
  1225. //
  1226. // Purpose: Returns the CLSID of LAN connection objects
  1227. //
  1228. // Arguments:
  1229. // pclsid [out] Returns CLSID to caller
  1230. //
  1231. // Returns: S_OK if success, OLE error otherwise
  1232. //
  1233. // Author: danielwe 4 Nov 1997
  1234. //
  1235. // Notes:
  1236. //
  1237. STDMETHODIMP CLanConnection::GetClassID(CLSID* pclsid)
  1238. {
  1239. HRESULT hr = S_OK;
  1240. // Validate parameters.
  1241. //
  1242. if (!pclsid)
  1243. {
  1244. hr = E_POINTER;
  1245. }
  1246. else
  1247. {
  1248. *pclsid = CLSID_LanConnection;
  1249. }
  1250. TraceError("CLanConnection::GetClassID", hr);
  1251. return hr;
  1252. }
  1253. //+---------------------------------------------------------------------------
  1254. //
  1255. // Member: CLanConnection::GetSizeMax
  1256. //
  1257. // Purpose: Returns the maximum size of the persistence data
  1258. //
  1259. // Arguments:
  1260. // pcbSize [out] Returns size
  1261. //
  1262. // Returns: S_OK if success, OLE error otherwise
  1263. //
  1264. // Author: danielwe 4 Nov 1997
  1265. //
  1266. // Notes:
  1267. //
  1268. STDMETHODIMP CLanConnection::GetSizeMax(ULONG *pcbSize)
  1269. {
  1270. HRESULT hr = S_OK;
  1271. // Validate parameters.
  1272. //
  1273. if (!pcbSize)
  1274. {
  1275. hr = E_POINTER;
  1276. }
  1277. else if (!m_fInitialized)
  1278. {
  1279. hr = E_UNEXPECTED;
  1280. }
  1281. else
  1282. {
  1283. *pcbSize = sizeof(GUID);
  1284. }
  1285. TraceError("CLanConnection::GetSizeMax", hr);
  1286. return hr;
  1287. }
  1288. //+---------------------------------------------------------------------------
  1289. //
  1290. // Member: CLanConnection::Load
  1291. //
  1292. // Purpose: Allows the connection object to initialize (restore) itself
  1293. // from previously persisted data
  1294. //
  1295. // Arguments:
  1296. // pbBuf [in] Private data to use for restoring
  1297. // cbSize [in] Size of data
  1298. //
  1299. // Returns: S_OK if success, OLE error otherwise
  1300. //
  1301. // Author: danielwe 4 Nov 1997
  1302. //
  1303. // Notes:
  1304. //
  1305. STDMETHODIMP CLanConnection::Load(const BYTE *pbBuf, ULONG cbSize)
  1306. {
  1307. HRESULT hr = E_INVALIDARG;
  1308. // Validate parameters.
  1309. //
  1310. if (!pbBuf)
  1311. {
  1312. hr = E_POINTER;
  1313. }
  1314. else if (cbSize != sizeof(GUID))
  1315. {
  1316. hr = E_INVALIDARG;
  1317. }
  1318. // We can only accept one call on this method and only if we're not
  1319. // already initialized.
  1320. //
  1321. else if (m_fInitialized)
  1322. {
  1323. hr = E_UNEXPECTED;
  1324. }
  1325. else
  1326. {
  1327. GUID guid;
  1328. CopyMemory(&guid, pbBuf, sizeof(GUID));
  1329. hr = HrLoad(guid);
  1330. }
  1331. TraceError("CLanConnection::Load", hr);
  1332. return hr;
  1333. }
  1334. //+---------------------------------------------------------------------------
  1335. //
  1336. // Member: CLanConnection::Save
  1337. //
  1338. // Purpose: Provides the caller with data to use in restoring this object
  1339. // at a later time.
  1340. //
  1341. // Arguments:
  1342. // pbBuf [out] Returns data to use for restoring
  1343. // cbSize [in] Size of data buffer
  1344. //
  1345. // Returns: S_OK if success, OLE error otherwise
  1346. //
  1347. // Author: danielwe 4 Nov 1997
  1348. //
  1349. // Notes:
  1350. //
  1351. STDMETHODIMP CLanConnection::Save(BYTE *pbBuf, ULONG cbSize)
  1352. {
  1353. HRESULT hr;
  1354. // Validate parameters.
  1355. //
  1356. if (!pbBuf)
  1357. {
  1358. hr = E_POINTER;
  1359. }
  1360. else if (!m_fInitialized || !m_hdi)
  1361. {
  1362. hr = E_UNEXPECTED;
  1363. }
  1364. else
  1365. {
  1366. GUID guid;
  1367. hr = HrGetInstanceGuid(m_hdi, m_deid, &guid);
  1368. if (S_OK == hr)
  1369. {
  1370. CopyMemory(pbBuf, &guid, cbSize);
  1371. }
  1372. }
  1373. TraceError("CLanConnection::Save", hr);
  1374. return hr;
  1375. }
  1376. //
  1377. // Private functions
  1378. //
  1379. extern const WCHAR c_szRegValueNetCfgInstanceId[];
  1380. //+---------------------------------------------------------------------------
  1381. //
  1382. // Function: HrGetInstanceGuid
  1383. //
  1384. // Purpose: Given device info, returns the NetCfg instance GUID of the
  1385. // connection.
  1386. //
  1387. // Arguments:
  1388. // hdi [in] SetupAPI data
  1389. // deid [in] SetupAPI data
  1390. // pguid [out] GUID of netcfg component
  1391. //
  1392. // Returns: S_OK if success, Win32 or SetupAPI error otherwise
  1393. //
  1394. // Author: danielwe 7 Jan 1998
  1395. //
  1396. // Notes:
  1397. //
  1398. HRESULT HrGetInstanceGuid(HDEVINFO hdi, const SP_DEVINFO_DATA &deid,
  1399. LPGUID pguid)
  1400. {
  1401. HRESULT hr;
  1402. HKEY hkey;
  1403. Assert(pguid);
  1404. hr = HrSetupDiOpenDevRegKey(hdi, const_cast<SP_DEVINFO_DATA *>(&deid),
  1405. DICS_FLAG_GLOBAL, 0,
  1406. DIREG_DRV, KEY_READ, &hkey);
  1407. if (S_OK == hr)
  1408. {
  1409. WCHAR szGuid[c_cchGuidWithTerm];
  1410. DWORD cbBuf = sizeof(szGuid);
  1411. hr = HrRegQuerySzBuffer(hkey, c_szRegValueNetCfgInstanceId,
  1412. szGuid, &cbBuf);
  1413. if (S_OK == hr)
  1414. {
  1415. IIDFromString(szGuid, pguid);
  1416. }
  1417. RegCloseKey(hkey);
  1418. }
  1419. TraceError("HrInstanceGuidFromDeid", hr);
  1420. return hr;
  1421. }
  1422. static const WCHAR c_szKeyFmt[] = L"%s\\%s\\%s\\Connection";
  1423. extern const WCHAR c_szRegKeyComponentClasses[];
  1424. extern const WCHAR c_szRegValuePnpInstanceId[];
  1425. //+---------------------------------------------------------------------------
  1426. //
  1427. // Function: HrLoadDevInfoFromGuid
  1428. //
  1429. // Purpose: Given a NetCfg instance GUID, loads the m_hdi and m_deid
  1430. // members from the device installer.
  1431. //
  1432. // Arguments:
  1433. // guid [in] GUID of connection
  1434. //
  1435. // Returns: S_OK if success, Win32 or SetupAPI error otherwise
  1436. //
  1437. // Author: danielwe 7 Jan 1998
  1438. //
  1439. // Notes:
  1440. //
  1441. HRESULT CLanConnection::HrLoadDevInfoFromGuid(const GUID &guid)
  1442. {
  1443. HRESULT hr = S_OK;
  1444. SP_DEVINFO_DATA deid = {0};
  1445. HKEY hkeyNetCfg;
  1446. WCHAR szRegPath[c_cchMaxRegKeyLengthWithNull];
  1447. WCHAR szGuid[c_cchGuidWithTerm];
  1448. WCHAR szClassGuid[c_cchGuidWithTerm];
  1449. StringFromGUID2(GUID_DEVCLASS_NET, szClassGuid, c_cchGuidWithTerm);
  1450. StringFromGUID2(guid, szGuid, c_cchGuidWithTerm);
  1451. wsprintfW(szRegPath, c_szKeyFmt, c_szRegKeyComponentClasses,
  1452. szClassGuid, szGuid);
  1453. // Open the Control\Network\{CLASS}\{Instance GUID} key
  1454. //
  1455. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath,
  1456. KEY_READ, &hkeyNetCfg);
  1457. if (SUCCEEDED(hr))
  1458. {
  1459. tstring strInstanceId;
  1460. hr = HrRegQueryString(hkeyNetCfg, c_szRegValuePnpInstanceId,
  1461. &strInstanceId);
  1462. if (SUCCEEDED(hr))
  1463. {
  1464. hr = HrSetupDiCreateDeviceInfoList(&GUID_DEVCLASS_NET,
  1465. NULL, &m_hdi);
  1466. if (SUCCEEDED(hr))
  1467. {
  1468. hr = HrSetupDiOpenDeviceInfo(m_hdi, strInstanceId.c_str(),
  1469. NULL, 0, &m_deid);
  1470. }
  1471. }
  1472. RegCloseKey(hkeyNetCfg);
  1473. }
  1474. TraceError("HrLoadDevInfoFromGuid", hr);
  1475. return hr;
  1476. }
  1477. //+---------------------------------------------------------------------------
  1478. //
  1479. // Function: HrIsAtmAdapterFromHkey
  1480. //
  1481. // Purpose: Determines if the given HKEY describes an ATM physical adapter
  1482. //
  1483. // Arguments:
  1484. // hkey [in] HKEY under Control\Class\{GUID}\<instance> (aka driver key)
  1485. //
  1486. // Returns: S_OK if device is ATM physical adapter, S_FALSE if not,
  1487. // Win32 error otherwise
  1488. //
  1489. // Author: tongl 10 Dec 1998
  1490. //
  1491. // Notes:
  1492. //
  1493. HRESULT CLanConnection::HrIsAtmAdapterFromHkey(HKEY hkey)
  1494. {
  1495. HRESULT hr = S_OK;
  1496. WCHAR szBuf[256];
  1497. DWORD cbBuf = sizeof(szBuf);
  1498. list<tstring *> lstr;
  1499. list<tstring *>::iterator lstrIter;
  1500. BOOL fMatch = FALSE;
  1501. HKEY hkeyInterfaces;
  1502. hr = HrRegOpenKeyEx(hkey, c_szRegKeyInterfacesFromInstance,
  1503. KEY_READ, &hkeyInterfaces);
  1504. if (SUCCEEDED(hr))
  1505. {
  1506. hr = HrRegQuerySzBuffer(hkeyInterfaces, c_szRegValueUpperRange,
  1507. szBuf, &cbBuf);
  1508. if (SUCCEEDED(hr))
  1509. {
  1510. ConvertStringToColString(szBuf, c_chComma, lstr);
  1511. for (lstrIter = lstr.begin(); lstrIter != lstr.end(); lstrIter++)
  1512. {
  1513. // See if it matches one of these
  1514. if (!lstrcmpiW((*lstrIter)->c_str(), c_szBiNdisAtm))
  1515. {
  1516. fMatch = TRUE;
  1517. break;
  1518. }
  1519. }
  1520. DeleteColString(&lstr);
  1521. }
  1522. RegCloseKey(hkeyInterfaces);
  1523. }
  1524. if (SUCCEEDED(hr))
  1525. {
  1526. if (fMatch)
  1527. {
  1528. hr = S_OK;
  1529. }
  1530. else
  1531. {
  1532. hr = S_FALSE;
  1533. }
  1534. }
  1535. TraceError("HrIsAtmAdapterFromHkey", (hr == S_FALSE) ? S_OK : hr);
  1536. return hr;
  1537. }
  1538. //+---------------------------------------------------------------------------
  1539. //
  1540. // Function: HrIsAtmElanFromHkey
  1541. //
  1542. // Purpose: Determines if the given HKEY describes an ATM ELAN adapter
  1543. //
  1544. // Arguments:
  1545. // hkey [in] HKEY under Control\Class\{GUID}\<instance> (aka driver key)
  1546. //
  1547. // Returns: S_OK if device is ELAN capable, S_FALSE if not, Win32 error
  1548. // otherwise
  1549. //
  1550. // Author: tongl 21 Oct 1998
  1551. //
  1552. // Notes:
  1553. //
  1554. HRESULT CLanConnection::HrIsAtmElanFromHkey(HKEY hkey)
  1555. {
  1556. HRESULT hr;
  1557. // pszInfId should have enough characters to hold "ms_atmelan".
  1558. // If the registry value is bigger than that, we know we don't have
  1559. // a match.
  1560. //
  1561. WCHAR pszInfId [24];
  1562. DWORD cbInfId = sizeof(pszInfId);
  1563. hr = HrRegQuerySzBuffer(hkey, L"ComponentId", pszInfId, &cbInfId);
  1564. if ((S_OK != hr) || (0 != _wcsicmp(pszInfId, L"ms_atmelan")))
  1565. {
  1566. hr = S_FALSE;
  1567. }
  1568. Assert ((S_OK == hr) || (S_FALSE == hr));
  1569. TraceError("HrIsAtmElanFromHkey", (hr == S_FALSE) ? S_OK : hr);
  1570. return hr;
  1571. }
  1572. //+---------------------------------------------------------------------------
  1573. //
  1574. // Function: HrIsConnectionBridged
  1575. //
  1576. // Purpose: Determines if connection is a member of a brigde
  1577. //
  1578. // Arguments:
  1579. // pfBridged [in] A boolean for the result
  1580. //
  1581. // Returns: S_OK if pfBridged is valid
  1582. // S_FALSE if pfBridged can't currently be determined
  1583. // Error otherwise
  1584. //
  1585. // Author: kenwic 11 July 2000
  1586. //
  1587. // Notes:
  1588. //
  1589. HRESULT CLanConnection::HrIsConnectionBridged(BOOL* pfBridged)
  1590. {
  1591. *pfBridged = FALSE;
  1592. HRESULT hResult = S_OK;
  1593. hResult = HrEnsureHNetPropertiesCached();
  1594. if (S_OK == hResult)
  1595. {
  1596. *pfBridged = m_pHNetProperties->fPartOfBridge;
  1597. }
  1598. return hResult;
  1599. }
  1600. //+---------------------------------------------------------------------------
  1601. //
  1602. // Function: HrIsConnectionFirewalled
  1603. //
  1604. // Purpose: Determines if connection is firewalled
  1605. //
  1606. // Arguments:
  1607. // pfFirewalled [in] A boolean for the result
  1608. //
  1609. // Returns: S_OK if pfFirewalled is valid
  1610. // S_FALSE if pfFirewalled can't currently be determined
  1611. // Error otherwise
  1612. //
  1613. // Author: kenwic 11 July 2000
  1614. //
  1615. // Notes:
  1616. //
  1617. HRESULT CLanConnection::HrIsConnectionFirewalled(BOOL* pfFirewalled)
  1618. {
  1619. HRESULT hr = S_OK;
  1620. BOOL fHasPermission = FALSE;
  1621. *pfFirewalled = FALSE;
  1622. // A Connection is only firewalled if the firewall is currently running, so
  1623. // we return FALSE if the permission denies the firewall from running.
  1624. hr = HrEnsureValidNlaPolicyEngine();
  1625. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "CRasConnectionBase::HrIsConnectionFirewalled calling HrEnsureValidNlaPolicyEngine", hr);
  1626. if (SUCCEEDED(hr))
  1627. {
  1628. hr = m_pNetMachinePolicies->VerifyPermission(NCPERM_PersonalFirewallConfig, &fHasPermission);
  1629. if (SUCCEEDED(hr) && fHasPermission)
  1630. {
  1631. hr = HrEnsureHNetPropertiesCached();
  1632. if (S_OK == hr)
  1633. {
  1634. *pfFirewalled = m_pHNetProperties->fFirewalled;
  1635. }
  1636. }
  1637. }
  1638. return hr;
  1639. }
  1640. //+---------------------------------------------------------------------------
  1641. //
  1642. // Function: HrIsConnectionNetworkBridge
  1643. //
  1644. // Purpose: Determines if a brigde
  1645. //
  1646. // Arguments:
  1647. // pfNetworkBridge [in] A boolean for the result
  1648. //
  1649. // Returns: S_OK if pfNetworkBridge is valid
  1650. // S_FALSE if pfNetworkBridge can't currently be determined
  1651. // Error otherwise
  1652. //
  1653. // Author: kenwic 11 July 2000
  1654. //
  1655. // Notes:
  1656. //
  1657. static const WCHAR c_szNetworkBridgeComponentId[] = L"ms_bridgemp";
  1658. extern const WCHAR c_szRegValueComponentId[];
  1659. HRESULT CLanConnection::HrIsConnectionNetworkBridge(BOOL* pfNetworkBridge)
  1660. {
  1661. *pfNetworkBridge = FALSE;
  1662. HRESULT hr = S_OK;
  1663. HKEY hkey;
  1664. hr = HrSetupDiOpenDevRegKey(m_hdi, const_cast<SP_DEVINFO_DATA *>(&m_deid),
  1665. DICS_FLAG_GLOBAL, 0,
  1666. DIREG_DRV, KEY_READ, &hkey);
  1667. if (S_OK == hr)
  1668. {
  1669. WCHAR szComponentId[60]; // if it's bigger than this, it's not the bridge, but make it big to shut up the tracing
  1670. DWORD cbBuf = sizeof(szComponentId);
  1671. hr = HrRegQuerySzBuffer(hkey, c_szRegValueComponentId,
  1672. szComponentId, &cbBuf);
  1673. if (S_OK == hr || HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr)
  1674. {
  1675. if(0 == lstrcmp(szComponentId, c_szNetworkBridgeComponentId))
  1676. {
  1677. *pfNetworkBridge = TRUE;
  1678. }
  1679. hr = S_OK;
  1680. }
  1681. RegCloseKey(hkey);
  1682. }
  1683. TraceError("HrIsConnectionNetworkBridge", hr);
  1684. return hr;
  1685. }
  1686. //+---------------------------------------------------------------------------
  1687. //
  1688. // Function: HrIsConnectionIcsPublic
  1689. //
  1690. // Purpose: Determines if connection is shared (ICS public)
  1691. //
  1692. // Arguments:
  1693. // pfIcsPublic [out] A boolean for the result
  1694. //
  1695. // Returns: S_OK if pfIcsPublic is valid
  1696. // S_FALSE if pfIcsPublic can't currently be determined
  1697. // Error otherwise
  1698. //
  1699. // Author: jonburs 31 July 2000
  1700. //
  1701. // Notes:
  1702. //
  1703. HRESULT CLanConnection::HrIsConnectionIcsPublic(BOOL* pfIcsPublic)
  1704. {
  1705. Assert(NULL != pfIcsPublic);
  1706. *pfIcsPublic = FALSE;
  1707. HRESULT hResult = S_OK;
  1708. hResult = HrEnsureHNetPropertiesCached();
  1709. if (S_OK == hResult)
  1710. {
  1711. *pfIcsPublic = m_pHNetProperties->fIcsPublic;
  1712. }
  1713. return hResult;
  1714. }
  1715. //+---------------------------------------------------------------------------
  1716. //
  1717. // Function: HrEnsureHNetPropertiesCached
  1718. //
  1719. // Purpose: Makes sure home networking properties are up-to-date
  1720. //
  1721. // Arguments:
  1722. //
  1723. // Returns: S_OK if m_pHNetProperties is now valid (success)
  1724. // S_FALSE if it's not currently possible to update the properties
  1725. // (e.g., recursive attempt to update)
  1726. //
  1727. // Author: jonburs 16 August 2000
  1728. //
  1729. // Notes:
  1730. //
  1731. HRESULT CLanConnection::HrEnsureHNetPropertiesCached(VOID)
  1732. {
  1733. HRESULT hr = S_OK;
  1734. Assert(TRUE == m_fInitialized);
  1735. if (!m_fHNetPropertiesCached
  1736. || m_lHNetModifiedEra != g_lHNetModifiedEra)
  1737. {
  1738. //
  1739. // Our cached properties are possibly out of date. Check
  1740. // to see that this is not a recursive entry
  1741. //
  1742. if (0 == InterlockedExchange(&m_lUpdatingHNetProperties, 1))
  1743. {
  1744. IHNetConnection *pHNetConn;
  1745. HNET_CONN_PROPERTIES *pProps;
  1746. hr = HrGetIHNetConnection(&pHNetConn);
  1747. if (SUCCEEDED(hr))
  1748. {
  1749. hr = pHNetConn->GetProperties(&pProps);
  1750. ReleaseObj(pHNetConn);
  1751. if (SUCCEEDED(hr))
  1752. {
  1753. //
  1754. // Store new properties, and free old. Note that CoTaskMemFree
  1755. // properly handles NULL input.
  1756. //
  1757. pProps =
  1758. reinterpret_cast<HNET_CONN_PROPERTIES*>(
  1759. InterlockedExchangePointer(
  1760. reinterpret_cast<PVOID*>(&m_pHNetProperties),
  1761. reinterpret_cast<PVOID>(pProps)
  1762. )
  1763. );
  1764. CoTaskMemFree(pProps);
  1765. //
  1766. // Update our era, and note that we have valid properties
  1767. //
  1768. InterlockedExchange(&m_lHNetModifiedEra, g_lHNetModifiedEra);
  1769. m_fHNetPropertiesCached = TRUE;
  1770. hr = S_OK;
  1771. }
  1772. }
  1773. else
  1774. {
  1775. //
  1776. // If we don't yet have a record of this connection w/in the
  1777. // home networking store, HrGetIHNetConnection will fail (as
  1778. // we ask it not to create new entries). We therefore convert
  1779. // failure to S_FALSE, which means we can't retrieve this info
  1780. // right now.
  1781. //
  1782. hr = S_FALSE;
  1783. }
  1784. //
  1785. // We're no longer updating our properties
  1786. //
  1787. InterlockedExchange(&m_lUpdatingHNetProperties, 0);
  1788. }
  1789. else
  1790. {
  1791. //
  1792. // Update is alredy going on (possibly an earlier call on
  1793. // the same thread). Return S_FALSE.
  1794. //
  1795. hr = S_FALSE;
  1796. }
  1797. }
  1798. return hr;
  1799. }
  1800. //+---------------------------------------------------------------------------
  1801. //
  1802. // Function: HrGetIHNetConnection
  1803. //
  1804. // Purpose: Retrieves the IHNetConnection for this connection
  1805. //
  1806. // Arguments:
  1807. //
  1808. // Returns: S_OK on success; error otherwise
  1809. //
  1810. // Author: jonburs 16 August 2000
  1811. //
  1812. // Notes:
  1813. //
  1814. HRESULT CLanConnection::HrGetIHNetConnection(IHNetConnection **ppHNetConnection)
  1815. {
  1816. HRESULT hr;
  1817. IHNetCfgMgr *pCfgMgr;
  1818. GUID guid;
  1819. Assert(ppHNetConnection);
  1820. hr = GetDeviceGuid(&guid);
  1821. if (SUCCEEDED(hr))
  1822. {
  1823. hr = HrGetHNetCfgMgr(&pCfgMgr);
  1824. }
  1825. if (SUCCEEDED(hr))
  1826. {
  1827. hr = pCfgMgr->GetIHNetConnectionForGuid(
  1828. &guid,
  1829. TRUE,
  1830. FALSE,
  1831. ppHNetConnection
  1832. );
  1833. ReleaseObj(pCfgMgr);
  1834. }
  1835. return hr;
  1836. }
  1837. //+---------------------------------------------------------------------------
  1838. //
  1839. // Function: ShowIcon
  1840. //
  1841. // Purpose: Sets the Icon state for the systray, fires an event to notify
  1842. // NetShell of the Change
  1843. //
  1844. // Arguments:
  1845. //
  1846. // Returns: S_OK on success; error otherwise
  1847. //
  1848. // Author: ckotze 25 September 2000
  1849. //
  1850. // Notes:
  1851. //
  1852. HRESULT CLanConnection::ShowIcon(const BOOL bShowIcon)
  1853. {
  1854. HRESULT hr;
  1855. LANCON_INFO lcInfo;
  1856. hr = GetInfo(LCIF_ICON, &lcInfo);
  1857. if (SUCCEEDED(hr))
  1858. {
  1859. lcInfo.fShowIcon = bShowIcon;
  1860. hr = SetInfo(LCIF_ICON, &lcInfo);
  1861. }
  1862. return hr;
  1863. }
  1864. //+---------------------------------------------------------------------------
  1865. //
  1866. // Function: IconStateChanged
  1867. //
  1868. // Purpose: Fires an event to notify NetShell of a Change occuring in an
  1869. // incoming connection.
  1870. //
  1871. // Arguments:
  1872. //
  1873. // Returns: S_OK on success; error otherwise
  1874. //
  1875. // Author: ckotze 25 September 2000
  1876. //
  1877. // Notes:
  1878. //
  1879. inline
  1880. HRESULT CLanConnection::IconStateChanged()
  1881. {
  1882. return E_NOTIMPL;
  1883. }
  1884. //+---------------------------------------------------------------------------
  1885. //
  1886. // Member: CLanConnection::GetProperties
  1887. //
  1888. // Purpose: Get all of the properties associated with the connection.
  1889. // Returning all of them at once saves us RPCs vs. returning
  1890. // each one individually.
  1891. //
  1892. // Arguments:
  1893. // ppProps [out] Returned block of properties.
  1894. //
  1895. // Returns: S_OK or an error.
  1896. //
  1897. // Author: shaunco 1 Feb 1998
  1898. //
  1899. // Notes:
  1900. //
  1901. HRESULT CLanConnection::GetPropertiesEx(NETCON_PROPERTIES_EX** ppConnectionPropertiesEx)
  1902. {
  1903. HRESULT hr = S_OK;
  1904. *ppConnectionPropertiesEx = NULL;
  1905. if (!m_fInitialized)
  1906. {
  1907. hr = E_UNEXPECTED;
  1908. }
  1909. else
  1910. {
  1911. NETCON_PROPERTIES* pProps;
  1912. NETCON_PROPERTIES_EX* pPropsEx = reinterpret_cast<NETCON_PROPERTIES_EX*>(CoTaskMemAlloc(sizeof(NETCON_PROPERTIES_EX)));
  1913. if (pPropsEx)
  1914. {
  1915. ZeroMemory(pPropsEx, sizeof(NETCON_PROPERTIES_EX));
  1916. hr = GetProperties(&pProps);
  1917. if (SUCCEEDED(hr))
  1918. {
  1919. hr = HrBuildPropertiesExFromProperties(pProps, pPropsEx, dynamic_cast<IPersistNetConnection *>(this));
  1920. if (SUCCEEDED(hr))
  1921. {
  1922. if (NCM_LAN == pPropsEx->ncMediaType)
  1923. {
  1924. CIntelliName inName(NULL, NULL);
  1925. NETCON_MEDIATYPE ncm;
  1926. NETCON_SUBMEDIATYPE ncsm;
  1927. hr = inName.HrGetPseudoMediaTypes(pPropsEx->guidId, &ncm, &ncsm);
  1928. if (FAILED(hr))
  1929. {
  1930. hr = HrGetPseudoMediaTypeFromConnection(pPropsEx->guidId, &ncsm);
  1931. TraceError("HrGetPseudoMediaTypeFromConnection failed.", hr);
  1932. hr = S_OK;
  1933. }
  1934. pPropsEx->ncSubMediaType = ncsm;
  1935. if (NCSM_WIRELESS == ncsm)
  1936. {
  1937. LANCON_INFO LanConInfo;
  1938. hr = GetInfo(LCIF_ICON, &LanConInfo);
  1939. if (NETCFG_S_NOTEXIST == hr)
  1940. {
  1941. LanConInfo.fShowIcon = TRUE;
  1942. hr = SetInfo(LCIF_ICON, &LanConInfo);
  1943. TraceError("SetInfo", hr);
  1944. pPropsEx->dwCharacter |= NCCF_SHOW_ICON;
  1945. hr = S_OK;
  1946. }
  1947. }
  1948. }
  1949. else
  1950. {
  1951. pPropsEx->ncSubMediaType = NCSM_NONE;
  1952. }
  1953. if (SUCCEEDED(hr))
  1954. {
  1955. *ppConnectionPropertiesEx = pPropsEx;
  1956. }
  1957. }
  1958. FreeNetconProperties(pProps);
  1959. }
  1960. if (FAILED(hr))
  1961. {
  1962. *ppConnectionPropertiesEx = NULL;
  1963. HrFreeNetConProperties2(pPropsEx);
  1964. }
  1965. }
  1966. else
  1967. {
  1968. hr = E_OUTOFMEMORY;
  1969. }
  1970. }
  1971. TraceError ("CLanConnection::GetPropertiesEx", hr);
  1972. return hr;
  1973. }
  1974. HRESULT CLanConnection::HrEnsureValidNlaPolicyEngine()
  1975. {
  1976. HRESULT hr = S_FALSE; // Assume we already have the object
  1977. if (!m_pNetMachinePolicies)
  1978. {
  1979. hr = CoCreateInstance(CLSID_NetGroupPolicies, NULL, CLSCTX_INPROC, IID_INetMachinePolicies, reinterpret_cast<void**>(&m_pNetMachinePolicies));
  1980. }
  1981. return hr;
  1982. }