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.

2927 lines
76 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000 Microsoft Corporation
  4. //
  5. // Module: ConnMgr.cpp
  6. //
  7. // Author: Dan Elliott
  8. //
  9. // Abstract:
  10. //
  11. // Environment:
  12. // Neptune
  13. //
  14. // Revision History:
  15. //
  16. //////////////////////////////////////////////////////////////////////////////
  17. //////////////////////////////////////////////////////////////////////////////
  18. //
  19. // Include files
  20. //
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <windows.h>
  25. #include <netcon.h>
  26. #include <wininet.h>
  27. #include <winsock2.h>
  28. #include <ws2tcpip.h>
  29. #include <devguid.h>
  30. #include <mswsock.h>
  31. #include <util.h>
  32. #include <commerr.h>
  33. #include "connmgr.h"
  34. #include "msobcomm.h"
  35. #define STRSAFE_NO_DEPRECATE
  36. #include <strsafe.h>
  37. const static int MAX_NUM_NET_COMPONENTS = 128;
  38. const static int MAX_GUID_LEN = 40;
  39. const DWORD CConnectionManager::RAS_AUTODIAL_ENABLED = 0;
  40. const DWORD CConnectionManager::RAS_AUTODIAL_DISABLED = 1;
  41. const DWORD CConnectionManager::RAS_AUTODIAL_DONT_KNOW = 2;
  42. ////////////////////////////////
  43. // Wininet/URL Helpers
  44. ////////////////////////////////
  45. STDAPI InternetOpenWrap(
  46. LPCTSTR pszAgent,
  47. DWORD dwAccessType,
  48. LPCTSTR pszProxy,
  49. LPCTSTR pszProxyBypass,
  50. DWORD dwFlags,
  51. HINTERNET * phFileHandle
  52. );
  53. STDAPI InternetOpenUrlWrap(
  54. HINTERNET hInternet,
  55. LPCTSTR pszUrl,
  56. LPCTSTR pszHeaders,
  57. DWORD dwHeadersLength,
  58. DWORD dwFlags,
  59. DWORD_PTR dwContext,
  60. HINTERNET * phFileHandle
  61. );
  62. STDAPI HttpQueryInfoWrap(
  63. HINTERNET hRequest,
  64. DWORD dwInfoLevel,
  65. LPVOID lpvBuffer,
  66. LPDWORD lpdwBufferLength,
  67. LPDWORD lpdwIndex
  68. );
  69. BOOL
  70. IsGlobalOffline(
  71. VOID
  72. );
  73. VOID
  74. SetOffline(
  75. IN BOOL fOffline
  76. );
  77. STDAPI PingWebServer(
  78. HINTERNET hInternet,
  79. LPCTSTR pszUrl,
  80. BOOL* pfConnected
  81. );
  82. static NLA_BLOB* _NLABlobNext(
  83. IN NLA_BLOB* pnlaBlob
  84. );
  85. static int _AllocWSALookupServiceNext(
  86. IN HANDLE hQuery,
  87. IN DWORD dwControlFlags,
  88. OUT LPWSAQUERYSET* ppResults
  89. );
  90. static int StringCmpGUID(
  91. IN LPCWSTR szGuid,
  92. IN const GUID* pguid
  93. );
  94. //////////////////////////////////////////////////////////////////////////////
  95. //
  96. // CConnectionManager
  97. //
  98. // Default constructor
  99. //
  100. // parameters:
  101. // None.
  102. //
  103. // returns:
  104. // Nothing.
  105. //
  106. //////////////////////////////////////////////////////////////////////////////
  107. CConnectionManager::CConnectionManager()
  108. : m_dwConnectionCapabilities(CONNECTIONTYPE_INVALID),
  109. m_dwPreferredConnection(CONNECTIONTYPE_INVALID),
  110. m_pPreferredConnection(NULL),
  111. m_cLanConnections(0),
  112. m_cPhoneConnections(0),
  113. m_hInternetPing(NULL),
  114. m_bProxySaved(FALSE),
  115. m_bProxyApplied(FALSE),
  116. m_bUseProxy(FALSE),
  117. m_dwRasAutodialDisable(RAS_AUTODIAL_DONT_KNOW),
  118. m_bForceOnline(FALSE),
  119. m_bExclude1394(FALSE)
  120. {
  121. ZeroMemory(&m_CurrentProxySettings, sizeof(m_CurrentProxySettings));
  122. } // CConnectionManager::CConnectionManager
  123. //////////////////////////////////////////////////////////////////////////////
  124. //
  125. // ~CConnectionManager
  126. //
  127. // Destructor.
  128. //
  129. // parameters:
  130. // None.
  131. //
  132. // returns:
  133. // Nothing.
  134. //
  135. //////////////////////////////////////////////////////////////////////////////
  136. CConnectionManager::~CConnectionManager()
  137. {
  138. if (m_hInternetPing)
  139. {
  140. InternetCloseHandle(m_hInternetPing);
  141. }
  142. if (m_bProxySaved)
  143. {
  144. RestoreProxySettings();
  145. FreeProxyOptionList(&m_CurrentProxySettings);
  146. }
  147. if (m_bForceOnline)
  148. {
  149. SetOffline(TRUE);
  150. TRACE(L"Set wininet back to offline");
  151. }
  152. if (m_pPreferredConnection)
  153. {
  154. m_pPreferredConnection->Release();
  155. }
  156. } // CConnectionManager::~CConnectionManager
  157. //////////////////////////////////////////////////////////////////////////////
  158. //
  159. // GetCapabilities
  160. //
  161. // Queries the system for network connection capabilities. In addition, the
  162. // number of phone and LAN connections are counted and a preferred connection
  163. // type is determined.
  164. //
  165. // parameters:
  166. // None.
  167. //
  168. // returns:
  169. // A bitmask indicating the capabilities that are present.
  170. //
  171. //////////////////////////////////////////////////////////////////////////////
  172. STDMETHODIMP
  173. CConnectionManager::GetCapabilities(
  174. DWORD* pdwCapabilities
  175. )
  176. {
  177. TRACE(L"CConnectionManager::GetCapabilities\n");
  178. HRESULT hr = S_OK;
  179. if (NULL == pdwCapabilities)
  180. {
  181. MYASSERT(NULL != pdwCapabilities);
  182. return E_POINTER;
  183. }
  184. #ifndef CONNMGR_INITFROMREGISTRY
  185. // The #else part of this directive contains test code that retrieves
  186. // connection capabilities and preference settings from the registry
  187. //
  188. DWORD m_cLanConnections = 0;
  189. DWORD m_cPhoneConnections = 0;
  190. // Initialize the net connection enumeration. For each interface
  191. // retrieved, SetProxyBlanket must be called to set the authentication for
  192. // the interface proxy handle because the Network Connection Manager lives
  193. // in a remote process with a different security context.
  194. //
  195. INetConnectionManager* pmgr = NULL;
  196. if ( SUCCEEDED(hr = CoCreateInstance(
  197. CLSID_ConnectionManager,
  198. NULL,
  199. CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  200. IID_PPV_ARG(INetConnectionManager, &pmgr)
  201. )
  202. )
  203. && SUCCEEDED(hr = SetProxyBlanket(pmgr))
  204. )
  205. {
  206. TRACE(L"INetConnectionManager\n");
  207. IEnumNetConnection* penum = NULL;
  208. if ( SUCCEEDED(hr = pmgr->EnumConnections(NCME_DEFAULT, &penum))
  209. && SUCCEEDED(hr = SetProxyBlanket(penum))
  210. )
  211. {
  212. TRACE(L"IEnumNetConnection\n");
  213. hr = penum->Reset();
  214. while (S_OK == hr)
  215. {
  216. INetConnection* pnc = NULL;
  217. ULONG ulRetrieved;
  218. if ( S_OK == (hr = penum->Next(1, &pnc, &ulRetrieved))
  219. && SUCCEEDED(hr = SetProxyBlanket(pnc))
  220. )
  221. {
  222. NETCON_PROPERTIES* pprops = NULL;
  223. hr = pnc->GetProperties(&pprops);
  224. if (SUCCEEDED(hr))
  225. {
  226. // Log the network connectivity detected
  227. TRACE4(L"INetConnection: %s--%s--%d--%d\n",
  228. pprops->pszwName,
  229. pprops->pszwDeviceName,
  230. pprops->MediaType,
  231. pprops->Status);
  232. if (IsEnabledConnection(pprops))
  233. {
  234. switch(pprops->MediaType)
  235. {
  236. case NCM_LAN:
  237. m_cLanConnections++;
  238. if (! (HasConnection(
  239. CONNECTIONTYPE_LAN_INDETERMINATE
  240. )
  241. )
  242. )
  243. {
  244. if (HasBroadband())
  245. {
  246. AddConnectionCapability(
  247. CONNECTIONTYPE_LAN_INDETERMINATE
  248. );
  249. ClearConnectionCapability(
  250. CONNECTIONTYPE_LAN_BROADBAND
  251. );
  252. }
  253. else
  254. {
  255. AddConnectionCapability(
  256. CONNECTIONTYPE_LAN_BROADBAND
  257. );
  258. }
  259. }
  260. break;
  261. case NCM_SHAREDACCESSHOST_LAN:
  262. case NCM_SHAREDACCESSHOST_RAS:
  263. // Do not increment LAN connection count here.
  264. // This media type is in addition to the NCM_LAN
  265. // for the NIC.
  266. //
  267. AddConnectionCapability(CONNECTIONTYPE_LAN_ICS);
  268. break;
  269. case NCM_PHONE:
  270. #ifdef BLACKCOMB
  271. // For Whistler, determination of modem capability is done via
  272. // CObCommunicationManager::CheckDialReady.
  273. m_cPhoneConnections++;
  274. AddConnectionCapability(CONNECTIONTYPE_MODEM);
  275. #endif // BLACKCOMB
  276. break;
  277. case NCM_ISDN:
  278. case NCM_PPPOE:
  279. AddConnectionCapability(CONNECTIONTYPE_OTHER);
  280. break;
  281. } // switch
  282. }
  283. NcFreeNetconProperties(pprops);
  284. }
  285. }
  286. if (NULL != pnc)
  287. {
  288. pnc->Release();
  289. }
  290. }
  291. if (S_FALSE == hr)
  292. {
  293. // IEnumNetConnection::Next returned S_FALSE to indicate
  294. // that no more elements were available.
  295. hr = S_OK;
  296. }
  297. }
  298. if (NULL != penum)
  299. {
  300. penum->Release();
  301. }
  302. }
  303. if (NULL != pmgr)
  304. {
  305. pmgr->Release();
  306. }
  307. DeterminePreferredConnection();
  308. #else
  309. HKEY hKey = NULL;
  310. DWORD dwSize;
  311. if(ERROR_SUCCESS == (lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  312. OOBE_MAIN_REG_KEY,
  313. 0,
  314. KEY_QUERY_VALUE,
  315. &hKey)
  316. )
  317. )
  318. {
  319. dwSize = sizeof(DWORD);
  320. if (ERROR_SUCCESS != (lResult = RegQueryValueEx(hKey,
  321. L"ConnectionCapabilities",
  322. 0,
  323. NULL,
  324. (LPBYTE)&m_dwConnectionCapabilities,
  325. &dwSize)
  326. )
  327. )
  328. {
  329. m_dwConnectionCapabilities = CONNECTIONTYPE_INVALID;
  330. }
  331. if (ERROR_SUCCESS != (lResult = RegQueryValueEx(hKey,
  332. L"PreferredConnection",
  333. 0,
  334. NULL,
  335. (LPBYTE)&m_dwPreferredConnection,
  336. &dwSize
  337. )
  338. )
  339. )
  340. {
  341. m_dwPreferredConnection = CONNECTIONTYPE_INVALID;
  342. }
  343. RegCloseKey(hKey);
  344. }
  345. else
  346. {
  347. m_dwConnectionCapabilities = CONNECTIONTYPE_INVALID;
  348. m_dwPreferredConnection = CONNECTIONTYPE_INVALID;
  349. }
  350. #endif // CONNMGR_INITFROMREGISTRY
  351. TRACE(L"Exiting CConnectionManager::GetCapabilities\n");
  352. *pdwCapabilities = m_dwConnectionCapabilities;
  353. return hr;
  354. } // CConnectionManager::GetCapabilities
  355. //////////////////////////////////////////////////////////////////////////////
  356. //
  357. // SetPreferredConnection
  358. //
  359. // Set the preferred connection type. This allows an override of the
  360. // internally determined preference.
  361. //
  362. // parameters:
  363. // dwType one of the CONNECTIONTYPE_* values from obcomm.h.
  364. //
  365. // returns:
  366. // Boolean indicating whether the preferred connection was set.
  367. //
  368. //////////////////////////////////////////////////////////////////////////////
  369. STDMETHODIMP
  370. CConnectionManager::SetPreferredConnection(
  371. const DWORD dwType,
  372. BOOL* pfSupportedType
  373. )
  374. {
  375. BOOL fSupportedType = FALSE;
  376. switch (dwType)
  377. {
  378. case CONNECTIONTYPE_NONE:
  379. fSupportedType = TRUE;
  380. break;
  381. case CONNECTIONTYPE_MODEM:
  382. #ifdef BLACKCOMB
  383. // Modem capability for Whistler is handled via
  384. // CObCommunicationManager::CheckDialReady. However, CONNECTIONTYPE_MODEM is a
  385. // valid enum value to pass to this function so we don't want to hit the
  386. // default and assert. Hence, the case and break aren't ifdef'd.
  387. if (HasModem())
  388. {
  389. fSupportedType = TRUE;
  390. }
  391. #endif // BLACKCOMB
  392. break;
  393. case CONNECTIONTYPE_LAN_ICS:
  394. if (HasIcs())
  395. {
  396. fSupportedType = TRUE;
  397. }
  398. break;
  399. case CONNECTIONTYPE_LAN_BROADBAND:
  400. if (HasBroadband())
  401. {
  402. fSupportedType = TRUE;
  403. }
  404. break;
  405. default:
  406. // Unsupported connection type or multiple connection types
  407. MYASSERT(FALSE);
  408. } // switch
  409. if (fSupportedType)
  410. {
  411. TRACE1(L"SetPreferredConnection %d", dwType);
  412. m_dwPreferredConnection = dwType;
  413. GetPreferredConnection();
  414. }
  415. else
  416. {
  417. TRACE1(L"Unsupported Connection type %d", dwType);
  418. }
  419. if (NULL != pfSupportedType)
  420. {
  421. *pfSupportedType = fSupportedType;
  422. }
  423. return fSupportedType;
  424. } // CConnectionManager::SetPreferredConnection
  425. //////////////////////////////////////////////////////////////////////////////
  426. //
  427. // ConnectedToInternet
  428. //
  429. // Determines whether the system is currently connected to the Internet.
  430. //
  431. // parameters:
  432. // pfConnected pointer to a buffer that will receive the boolean
  433. // indicating whether the connection exists.
  434. //
  435. // returns:
  436. // TRUE if system is connected to the internet via LAN or
  437. // dial-up or can be connected via dial-up
  438. // FALSE otherwise
  439. //
  440. //////////////////////////////////////////////////////////////////////////////
  441. STDMETHODIMP
  442. CConnectionManager::ConnectedToInternet(
  443. BOOL* pfConnected
  444. )
  445. {
  446. DWORD dwFlags;
  447. if (NULL == pfConnected)
  448. {
  449. MYASSERT(NULL != pfConnected);
  450. return E_POINTER;
  451. }
  452. *pfConnected = InternetGetConnectedState(&dwFlags, 0);
  453. // Log the network connectivity detected
  454. TRACE2(L"InternetGetConnectedState %d, 0x%08lx", *pfConnected, dwFlags);
  455. return S_OK;
  456. } // CConnectionManager::ConnectedToInternet
  457. ///////////////////////////////////////////////////////////
  458. //
  459. // SetPreferredConnectionTcpipProperties
  460. //
  461. STDMETHODIMP
  462. CConnectionManager::SetPreferredConnectionTcpipProperties(
  463. BOOL fAutoIpAddress,
  464. DWORD StaticIp_A,
  465. DWORD StaticIp_B,
  466. DWORD StaticIp_C,
  467. DWORD StaticIp_D,
  468. DWORD SubnetMask_A,
  469. DWORD SubnetMask_B,
  470. DWORD SubnetMask_C,
  471. DWORD SubnetMask_D,
  472. DWORD DefGateway_A,
  473. DWORD DefGateway_B,
  474. DWORD DefGateway_C,
  475. DWORD DefGateway_D,
  476. BOOL fAutoDns,
  477. DWORD DnsPref_A,
  478. DWORD DnsPref_B,
  479. DWORD DnsPref_C,
  480. DWORD DnsPref_D,
  481. DWORD DnsAlt_A,
  482. DWORD DnsAlt_B,
  483. DWORD DnsAlt_C,
  484. DWORD DnsAlt_D
  485. )
  486. {
  487. HRESULT hr;
  488. REMOTE_IPINFO ipInfo;
  489. struct in_addr inaddr;
  490. WCHAR rgchStaticIp[INET_ADDRSTRLEN];
  491. WCHAR rgchSubnetMask[INET_ADDRSTRLEN];
  492. WCHAR rgchDefGateway[2 * INET_ADDRSTRLEN] = L"DefGw=";
  493. WCHAR rgchGatewayMetric[2 * INET_ADDRSTRLEN] = L"GwMetric=";
  494. WCHAR rgchDnsAddr[3 * INET_ADDRSTRLEN] = L"DNS=";
  495. WCHAR* pch = NULL;
  496. NETCON_PROPERTIES* pncProps = NULL;
  497. memset(&ipInfo, 0, sizeof(REMOTE_IPINFO));
  498. hr = m_pPreferredConnection->GetProperties(&pncProps);
  499. if (FAILED(hr))
  500. {
  501. TRACE1(L"Failed to retrieve preferred connection properties (0x%08X)\n", hr);
  502. goto SetPreferredConnectionTcpipPropertiesExit;
  503. }
  504. ipInfo.dwEnableDhcp = fAutoIpAddress;
  505. if (! fAutoIpAddress)
  506. {
  507. // if a static ip address was specified, convert it to a string and add
  508. // it to the REMOTE_IPINFO structure
  509. //
  510. memset(&inaddr, 0, sizeof(struct in_addr));
  511. inaddr.S_un.S_un_b.s_b1 = (BYTE)StaticIp_A;
  512. inaddr.S_un.S_un_b.s_b2 = (BYTE)StaticIp_B;
  513. inaddr.S_un.S_un_b.s_b3 = (BYTE)StaticIp_C;
  514. inaddr.S_un.S_un_b.s_b4 = (BYTE)StaticIp_D;
  515. if (! INetNToW(inaddr, rgchStaticIp))
  516. {
  517. hr = E_FAIL;
  518. TRACE1(L"Failed to create ip address string (0x%08X)\n", hr);
  519. goto SetPreferredConnectionTcpipPropertiesExit;
  520. }
  521. ipInfo.pszwIpAddrList = rgchStaticIp;
  522. memset(&inaddr, 0, sizeof(struct in_addr));
  523. inaddr.S_un.S_un_b.s_b1 = (BYTE)SubnetMask_A;
  524. inaddr.S_un.S_un_b.s_b2 = (BYTE)SubnetMask_B;
  525. inaddr.S_un.S_un_b.s_b3 = (BYTE)SubnetMask_C;
  526. inaddr.S_un.S_un_b.s_b4 = (BYTE)SubnetMask_D;
  527. if (! INetNToW(inaddr, rgchSubnetMask))
  528. {
  529. hr = E_FAIL;
  530. TRACE1(L"Failed to create ip address string (0x%08X)\n", hr);
  531. goto SetPreferredConnectionTcpipPropertiesExit;
  532. }
  533. ipInfo.pszwSubnetMaskList = rgchSubnetMask;
  534. pch = rgchDefGateway + lstrlen(rgchDefGateway);
  535. memset(&inaddr, 0, sizeof(struct in_addr));
  536. inaddr.S_un.S_un_b.s_b1 = (BYTE)DefGateway_A;
  537. inaddr.S_un.S_un_b.s_b2 = (BYTE)DefGateway_B;
  538. inaddr.S_un.S_un_b.s_b3 = (BYTE)DefGateway_C;
  539. inaddr.S_un.S_un_b.s_b4 = (BYTE)DefGateway_D;
  540. if (! INetNToW(inaddr, pch))
  541. {
  542. hr = E_FAIL;
  543. TRACE1(L"Failed to create ip address string (0x%08X)\n", hr);
  544. goto SetPreferredConnectionTcpipPropertiesExit;
  545. }
  546. lstrcat(rgchGatewayMetric, L"1");
  547. TRACE4(L"Tcpip StaticIp %d.%d.%d.%d",
  548. StaticIp_A, StaticIp_B, StaticIp_C, StaticIp_D);
  549. TRACE4(L"Tcpip SubnetMask %d.%d.%d.%d",
  550. SubnetMask_A, SubnetMask_B, SubnetMask_C, SubnetMask_D);
  551. TRACE4(L"Tcpip DefGateway %d.%d.%d.%d",
  552. DefGateway_A, DefGateway_B, DefGateway_C, DefGateway_D);
  553. //ipInfo.pszwIpAddrList = rgchDefGateway;
  554. }
  555. if (! fAutoDns)
  556. {
  557. // if dns addresses were specified, convert them to strings and add
  558. // them to the REMOTE_IPINFO structure
  559. //
  560. pch = rgchDnsAddr + lstrlen(rgchDnsAddr);
  561. memset(&inaddr, 0, sizeof(struct in_addr));
  562. inaddr.S_un.S_un_b.s_b1 = (BYTE)DnsPref_A;
  563. inaddr.S_un.S_un_b.s_b2 = (BYTE)DnsPref_B;
  564. inaddr.S_un.S_un_b.s_b3 = (BYTE)DnsPref_C;
  565. inaddr.S_un.S_un_b.s_b4 = (BYTE)DnsPref_D;
  566. if (! INetNToW(inaddr, pch))
  567. {
  568. hr = E_FAIL;
  569. TRACE1(L"Failed to create dns address string (0x%08X)\n", hr);
  570. goto SetPreferredConnectionTcpipPropertiesExit;
  571. }
  572. pch += lstrlen(pch);
  573. *pch++ = L',';
  574. inaddr.S_un.S_un_b.s_b1 = (BYTE)DnsAlt_A;
  575. inaddr.S_un.S_un_b.s_b2 = (BYTE)DnsAlt_B;
  576. inaddr.S_un.S_un_b.s_b3 = (BYTE)DnsAlt_C;
  577. inaddr.S_un.S_un_b.s_b4 = (BYTE)DnsAlt_D;
  578. if (! INetNToW(inaddr, pch))
  579. {
  580. hr = E_FAIL;
  581. TRACE1(L"Failed to create alternate dns address string (0x%08X)\n", hr);
  582. goto SetPreferredConnectionTcpipPropertiesExit;
  583. }
  584. TRACE4(L"Tcpip DnsPref %d.%d.%d.%d",
  585. DnsPref_A, DnsPref_B, DnsPref_C, DnsPref_D);
  586. TRACE4(L"Tcpip DnsAlt %d.%d.%d.%d",
  587. DnsAlt_A, DnsAlt_B, DnsAlt_C, DnsAlt_D);
  588. }
  589. // plus 4 for 3 semi-colons and the null-terminator
  590. ipInfo.pszwOptionList = (WCHAR*) malloc((lstrlen(rgchDefGateway)
  591. + lstrlen(rgchGatewayMetric)
  592. + lstrlen(rgchDnsAddr)
  593. + 4)
  594. * sizeof(WCHAR)
  595. );
  596. if (NULL == ipInfo.pszwOptionList)
  597. {
  598. TRACE(L"Failed to allocate memory for option list\n");
  599. goto SetPreferredConnectionTcpipPropertiesExit;
  600. }
  601. wsprintf(ipInfo.pszwOptionList, L"%s;%s;%s;",
  602. rgchDefGateway, rgchGatewayMetric, rgchDnsAddr
  603. );
  604. hr = SetTcpipProperties(pncProps->guidId, &ipInfo);
  605. if (FAILED(hr))
  606. {
  607. TRACE1(L"Failed to set TCPIP info (0x%08X)\n", hr);
  608. }
  609. SetPreferredConnectionTcpipPropertiesExit:
  610. if (NULL != ipInfo.pszwOptionList)
  611. {
  612. free(ipInfo.pszwOptionList);
  613. ipInfo.pszwOptionList = NULL;
  614. }
  615. if (NULL != pncProps)
  616. {
  617. NcFreeNetconProperties(pncProps);
  618. pncProps = NULL;
  619. }
  620. return hr;
  621. } // CObCommunicationManager::SetPreferredConnectionTcpipProperties
  622. ///////////////////////////////////////////////////////////
  623. //
  624. // SetTcpipProperties
  625. //
  626. HRESULT
  627. CConnectionManager::SetTcpipProperties(
  628. GUID guid,
  629. REMOTE_IPINFO* pipInfo
  630. )
  631. {
  632. HRESULT hr;
  633. INetCfg* pNetCfg = NULL;
  634. ITcpipProperties* pTcpipProps = NULL;
  635. hr = GetNetCfgInterface(TRUE, &pNetCfg);
  636. if (SUCCEEDED(hr))
  637. {
  638. hr = GetTcpipPrivateInterface(pNetCfg, &pTcpipProps);
  639. if (SUCCEEDED(hr))
  640. {
  641. hr = pTcpipProps->SetIpInfoForAdapter(&guid, pipInfo);
  642. TRACE1(L"SetIpInfoForAdapter 0x%08lx", hr);
  643. if (SUCCEEDED(hr))
  644. {
  645. hr = pNetCfg->Apply();
  646. TRACE1(L"INetCfg::Apply 0x%08lx", hr);
  647. }
  648. pTcpipProps->Release();
  649. }
  650. ReleaseNetCfgInterface(pNetCfg, TRUE);
  651. }
  652. return hr;
  653. } // CObCommunicationManager::SetTcpipProperties
  654. //////////////////////////////////////////////////////////////////////////////
  655. //
  656. // LanConnectionReady
  657. //
  658. // Determines whether the system has a LAN connection that is connected to the
  659. // Internet.
  660. //
  661. // parameters:
  662. // None.
  663. //
  664. // returns:
  665. // Boolean indicating whether or not their is a ready connection.
  666. //
  667. //////////////////////////////////////////////////////////////////////////////
  668. BOOL
  669. CConnectionManager::LanConnectionReady()
  670. {
  671. BOOL fReady = FALSE;
  672. #ifndef CONNMGR_INITFROMREGISTRY
  673. if (HasBroadband() || HasIcs())
  674. {
  675. DWORD dwFlags = 0;
  676. if ( InternetGetConnectedState(&dwFlags, 0)
  677. && (INTERNET_CONNECTION_LAN & dwFlags)
  678. )
  679. {
  680. fReady = TRUE;
  681. }
  682. }
  683. #else
  684. DWORD dwLanConnectionReady;
  685. DWORD dwSize = sizeof(DWORD);
  686. if(ERROR_SUCCESS == (lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  687. OOBE_MAIN_REG_KEY,
  688. 0,
  689. KEY_QUERY_VALUE,
  690. &hKey)
  691. )
  692. )
  693. {
  694. lResult = RegQueryValueEx(hKey,
  695. L"LanConnectionReady",
  696. 0,
  697. NULL,
  698. (LPBYTE)&dwLanConnectionReady,
  699. &dwSize
  700. );
  701. RegCloseKey(hKey);
  702. }
  703. fReady = (ERROR_SUCCESS == lResult) ? (BOOL)dwLanConnectionReady : FALSE;
  704. #endif // CONNMGR_INITFROMREGISTRY
  705. return fReady;
  706. } // CConnectionManager::LanConnectionReady
  707. //////////////////////////////////////////////////////////////////////////////
  708. //
  709. // SetProxyBlanket
  710. //
  711. // Set the authentication settings for the binding handle for the
  712. // interface proxy. This is necessary for setting up security for interface
  713. // pointers returned by a remote process, such as the Network Connections
  714. // Manager (netman.dll).
  715. //
  716. // parameters:
  717. // pUnk pointer to the interface for which the proxy will be
  718. // bound.
  719. //
  720. // returns:
  721. // HRESULT returned by CoSetProxyBlanket.
  722. //
  723. //////////////////////////////////////////////////////////////////////////////
  724. HRESULT
  725. CConnectionManager::SetProxyBlanket(
  726. IUnknown* pUnk
  727. )
  728. {
  729. HRESULT hr;
  730. hr = CoSetProxyBlanket (
  731. pUnk,
  732. RPC_C_AUTHN_WINNT, // use NT default security
  733. RPC_C_AUTHZ_NONE, // use NT default authentication
  734. NULL, // must be null if default
  735. RPC_C_AUTHN_LEVEL_CALL, // call
  736. RPC_C_IMP_LEVEL_IMPERSONATE,
  737. NULL, // use process token
  738. EOAC_NONE);
  739. if(SUCCEEDED(hr))
  740. {
  741. IUnknown * pUnkSet = NULL;
  742. hr = pUnk->QueryInterface(IID_PPV_ARG(IUnknown, &pUnkSet));
  743. if(SUCCEEDED(hr))
  744. {
  745. hr = CoSetProxyBlanket (
  746. pUnkSet,
  747. RPC_C_AUTHN_WINNT, // use NT default security
  748. RPC_C_AUTHZ_NONE, // use NT default authentication
  749. NULL, // must be null if default
  750. RPC_C_AUTHN_LEVEL_CALL, // call
  751. RPC_C_IMP_LEVEL_IMPERSONATE,
  752. NULL, // use process token
  753. EOAC_NONE);
  754. pUnkSet->Release();
  755. }
  756. }
  757. return hr;
  758. } // CConnectionManager::SetProxyBlanket
  759. //////////////////////////////////////////////////////////////////////////////
  760. //
  761. // DeterminePreferredConnection
  762. //
  763. // Determine the preferred connection. The order of preference is
  764. // * ICS
  765. // * Broadband (DSL, cable modem, etc.)
  766. // * Modem
  767. //
  768. // parameters:
  769. // None.
  770. //
  771. // returns:
  772. // Nothing.
  773. //
  774. //////////////////////////////////////////////////////////////////////////////
  775. void
  776. CConnectionManager::DeterminePreferredConnection()
  777. {
  778. // REVIEW: Differences between full-screen and desktop in using default
  779. // connectoid.
  780. //
  781. if (HasIcs())
  782. {
  783. m_dwPreferredConnection = CONNECTIONTYPE_LAN_ICS;
  784. }
  785. else if (HasBroadband())
  786. {
  787. m_dwPreferredConnection = CONNECTIONTYPE_LAN_BROADBAND;
  788. }
  789. #ifdef BLACKCOMB
  790. // Modem capability for Whistler is handled via
  791. // CObCommunicationManager::CheckDialReady
  792. else if (HasModem())
  793. {
  794. m_dwPreferredConnection = CONNECTIONTYPE_MODEM;
  795. }
  796. #endif // BLACKCOMB
  797. else // CONNECTIONTYPE_NONE || CONNECTIONTYPE_LAN_INDETERMINATE
  798. {
  799. m_dwPreferredConnection = CONNECTIONTYPE_NONE;
  800. }
  801. GetPreferredConnection();
  802. } // CConnectionManager::DeterminePreferredConnection
  803. //////////////////////////////////////////////////////////////////////////////
  804. //
  805. // GetPreferredConnection
  806. //
  807. // Determine the name of the connectoid for the preferred connection.
  808. //
  809. // parameters:
  810. // None.
  811. //
  812. // returns:
  813. // Nothing.
  814. //
  815. //////////////////////////////////////////////////////////////////////////////
  816. void
  817. CConnectionManager::GetPreferredConnection()
  818. {
  819. HRESULT hr;
  820. NETCON_MEDIATYPE ncMediaType = NCM_NONE; // assume no connection
  821. switch (m_dwPreferredConnection)
  822. {
  823. case CONNECTIONTYPE_LAN_ICS:
  824. ncMediaType = NCM_SHAREDACCESSHOST_LAN;
  825. break;
  826. case CONNECTIONTYPE_LAN_BROADBAND:
  827. ncMediaType = NCM_LAN;
  828. break;
  829. } // switch(m_dwPreferredConnection)
  830. // Free up previous preferred connection properties
  831. //
  832. if (NULL != m_pPreferredConnection)
  833. {
  834. m_pPreferredConnection->Release();
  835. m_pPreferredConnection = NULL;
  836. }
  837. if (NCM_NONE != ncMediaType)
  838. {
  839. INetConnectionManager* pmgr = NULL;
  840. if ( SUCCEEDED(hr = CoCreateInstance(
  841. CLSID_ConnectionManager,
  842. NULL,
  843. CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  844. IID_PPV_ARG(INetConnectionManager, &pmgr)
  845. )
  846. )
  847. && SUCCEEDED(hr = SetProxyBlanket(pmgr))
  848. )
  849. {
  850. TRACE(L"INetConnectionManager\n");
  851. IEnumNetConnection* penum = NULL;
  852. if ( SUCCEEDED(hr = pmgr->EnumConnections(NCME_DEFAULT, &penum))
  853. && SUCCEEDED(hr = SetProxyBlanket(penum))
  854. )
  855. {
  856. TRACE(L"IEnumNetConnection\n");
  857. MYASSERT(NULL == m_pPreferredConnection);
  858. hr = penum->Reset();
  859. // Find the first connection matching the preferred type. This
  860. // works because the only types we are concerned with are
  861. // broadband and ICS. By definition, we should not be here if
  862. // there are more than 1 of these connections. If there are
  863. // more than 1 of these we should be deferring to the HomeNet
  864. // Wizard.
  865. //
  866. // ONCE THIS OBJECT SUPPORTS MODEM CONNECTIONS OR MULTIPLE
  867. // BROADBAND CONNECTIONS we'll need a more sophisticated method
  868. // of determining that we've found the correct connection.
  869. //
  870. while (S_OK == hr && NULL == m_pPreferredConnection)
  871. {
  872. INetConnection* pnc = NULL;
  873. ULONG ulRetrieved;
  874. if ( S_OK == (hr = penum->Next(1, &pnc, &ulRetrieved))
  875. && SUCCEEDED(hr = SetProxyBlanket(pnc))
  876. )
  877. {
  878. NETCON_PROPERTIES* pprops = NULL;
  879. hr = pnc->GetProperties(&pprops);
  880. // Log the network connectivity detected
  881. TRACE4(L"INetConnection: %s--%s--%d--%d\n",
  882. pprops->pszwName,
  883. pprops->pszwDeviceName,
  884. pprops->MediaType,
  885. pprops->Status);
  886. if (SUCCEEDED(hr))
  887. {
  888. if (IsEnabledConnection(pprops))
  889. {
  890. if (ncMediaType == pprops->MediaType)
  891. {
  892. m_pPreferredConnection = pnc;
  893. pnc = NULL;
  894. }
  895. }
  896. NcFreeNetconProperties(pprops);
  897. }
  898. }
  899. if (NULL != pnc)
  900. {
  901. pnc->Release();
  902. }
  903. }
  904. if (S_FALSE == hr)
  905. {
  906. // IEnumNetConnection::Next returned S_FALSE to indicate
  907. // that no more elements were available.
  908. hr = S_OK;
  909. }
  910. }
  911. if (NULL != penum)
  912. {
  913. penum->Release();
  914. }
  915. }
  916. if (NULL != pmgr)
  917. {
  918. pmgr->Release();
  919. }
  920. }
  921. } // CConnectionManager::GetPreferredConnection
  922. //////////////////////////////////////////////////////////////////////////////
  923. //
  924. // GetPreferredConnectionName
  925. //
  926. // Fills in a user-allocated buffer with the name of the connectoid for the
  927. // preferred connection.
  928. //
  929. // parameters:
  930. // szConnectionName buffer that will recieve the name of the preferred
  931. // connectoid
  932. // cchConnectionName count of characters that the buffer can hold
  933. //
  934. // returns:
  935. // S_OK if the name is retrieved successfully
  936. // S_FALSE if there is no default connectoid
  937. // E_INVALIDARG if there is no buffer or if the buffer size is 0
  938. //
  939. //////////////////////////////////////////////////////////////////////////////
  940. HRESULT
  941. CConnectionManager::GetPreferredConnectionName(
  942. LPWSTR szConnectionName,
  943. DWORD cchConnectionName
  944. )
  945. {
  946. HRESULT hr = S_FALSE;
  947. if (NULL == szConnectionName || 0 == cchConnectionName)
  948. {
  949. MYASSERT(NULL != szConnectionName);
  950. MYASSERT(0 < cchConnectionName);
  951. return E_INVALIDARG;
  952. }
  953. if (NULL != m_pPreferredConnection)
  954. {
  955. NETCON_PROPERTIES* pprops = NULL;
  956. hr = m_pPreferredConnection->GetProperties(&pprops);
  957. if (SUCCEEDED(hr))
  958. {
  959. MYASSERT(NULL != pprops);
  960. if (NULL == pprops->pszwName)
  961. {
  962. hr = S_FALSE;
  963. }
  964. if (S_OK == hr)
  965. {
  966. lstrcpyn(szConnectionName,
  967. pprops->pszwName,
  968. cchConnectionName
  969. );
  970. }
  971. NcFreeNetconProperties(pprops);
  972. }
  973. }
  974. return hr;
  975. } // CConnectionManager::GetPreferredConnectionName
  976. HRESULT
  977. CConnectionManager::GetNetCfgInterface(
  978. BOOL fNeedWriteLock,
  979. INetCfg** ppNetCfg
  980. )
  981. {
  982. HRESULT hr;
  983. INetCfg* pNetCfg = NULL;
  984. if (NULL == ppNetCfg)
  985. {
  986. ASSERT(NULL != ppNetCfg);
  987. return E_INVALIDARG;
  988. }
  989. *ppNetCfg = NULL;
  990. hr = CoCreateInstance(CLSID_CNetCfg,
  991. NULL,
  992. CLSCTX_SERVER,
  993. IID_INetCfg,
  994. (LPVOID*)&pNetCfg
  995. );
  996. if (SUCCEEDED(hr))
  997. {
  998. INetCfgLock* pNetCfgLock = NULL;
  999. if (fNeedWriteLock)
  1000. {
  1001. hr = pNetCfg->QueryInterface(IID_INetCfgLock, (VOID**)&pNetCfgLock);
  1002. if (SUCCEEDED(hr))
  1003. {
  1004. hr = pNetCfgLock->AcquireWriteLock(
  1005. 5, // millisec timeout
  1006. L"Out-of-Box Experience",
  1007. NULL // name of previous holder
  1008. );
  1009. if (S_FALSE == hr)
  1010. {
  1011. hr = NETCFG_E_NO_WRITE_LOCK;
  1012. TRACE(L"AcquireWriteLock failed");
  1013. }
  1014. pNetCfgLock->Release();
  1015. }
  1016. else
  1017. {
  1018. TRACE1(L"QueryInterface IID_INetCfgLock 0x%08lx", hr);
  1019. }
  1020. }
  1021. if (SUCCEEDED(hr))
  1022. {
  1023. hr = pNetCfg->Initialize(NULL);
  1024. if (SUCCEEDED(hr))
  1025. {
  1026. *ppNetCfg = pNetCfg;
  1027. }
  1028. else
  1029. {
  1030. TRACE1(L"INetCfg Initialize 0x%08lx", hr);
  1031. }
  1032. }
  1033. }
  1034. else
  1035. {
  1036. TRACE1(L"CoCreateInstance CLSID_CNetCfg IID_INetCfg 0x%08lx", hr);
  1037. }
  1038. if (FAILED(hr))
  1039. {
  1040. if (pNetCfg != NULL)
  1041. {
  1042. pNetCfg->Release();
  1043. }
  1044. }
  1045. return hr;
  1046. } // CConnectionManager::GetNetCfgInterface
  1047. void
  1048. CConnectionManager::ReleaseNetCfgInterface(
  1049. INetCfg* pNetCfg,
  1050. BOOL fHasWriteLock
  1051. )
  1052. {
  1053. HRESULT hr = S_OK;
  1054. if (NULL != pNetCfg)
  1055. {
  1056. hr = pNetCfg->Uninitialize();
  1057. INetCfgLock* pNetCfgLock = NULL;
  1058. if (fHasWriteLock)
  1059. {
  1060. hr = pNetCfg->QueryInterface(IID_INetCfgLock, (VOID**)&pNetCfgLock);
  1061. if (SUCCEEDED(hr))
  1062. {
  1063. hr = pNetCfgLock->ReleaseWriteLock();
  1064. pNetCfgLock->Release();
  1065. }
  1066. }
  1067. pNetCfg->Release();
  1068. }
  1069. } // CConnectionManager::ReleaseNetCfgInterface
  1070. HRESULT
  1071. CConnectionManager::GetTcpipPrivateInterface(
  1072. INetCfg* pNetCfg,
  1073. ITcpipProperties** ppTcpipProperties
  1074. )
  1075. {
  1076. HRESULT hr;
  1077. if (NULL == ppTcpipProperties)
  1078. {
  1079. return E_INVALIDARG;
  1080. }
  1081. INetCfgClass* pncclass = NULL;
  1082. hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS,
  1083. IID_INetCfgClass,
  1084. (void**)&pncclass
  1085. );
  1086. if (SUCCEEDED(hr))
  1087. {
  1088. INetCfgComponent* pnccItem = NULL;
  1089. hr = pncclass->FindComponent(NETCFG_TRANS_CID_MS_TCPIP, &pnccItem);
  1090. if (SUCCEEDED(hr))
  1091. {
  1092. INetCfgComponentPrivate* pinccp = NULL;
  1093. hr = pnccItem->QueryInterface(IID_INetCfgComponentPrivate,
  1094. (void**) &pinccp
  1095. );
  1096. if (SUCCEEDED(hr))
  1097. {
  1098. hr = pinccp->QueryNotifyObject(IID_ITcpipProperties,
  1099. (void**) ppTcpipProperties
  1100. );
  1101. if (FAILED(hr))
  1102. {
  1103. TRACE1(L"QueryNotifyObject IID_ITcpipProperties 0x%08lx", hr);
  1104. }
  1105. pinccp->Release();
  1106. pinccp = NULL;
  1107. }
  1108. else
  1109. {
  1110. TRACE1(L"QueryInterface IID_INetCfgComponentPrivate 0x%08lx", hr);
  1111. }
  1112. pnccItem->Release();
  1113. pnccItem = NULL;
  1114. }
  1115. else
  1116. {
  1117. TRACE1(L"FindComponent NETCFG_TRANS_CID_MS_TCPIP 0x%08lx", hr);
  1118. }
  1119. pncclass->Release();
  1120. pncclass = NULL;
  1121. }
  1122. else
  1123. {
  1124. TRACE1(L"QueryNetCfgClass IID_INetCfgClass 0x%08lx", hr);
  1125. }
  1126. return hr;
  1127. } // CConnectionManager::GetTcpipPrivateInterface
  1128. STDAPI InternetOpenWrap(
  1129. LPCTSTR pszAgent,
  1130. DWORD dwAccessType,
  1131. LPCTSTR pszProxy,
  1132. LPCTSTR pszProxyBypass,
  1133. DWORD dwFlags,
  1134. HINTERNET * phFileHandle
  1135. )
  1136. {
  1137. HRESULT hr = S_OK;
  1138. DWORD dwError = 0;
  1139. *phFileHandle = InternetOpen(pszAgent, dwAccessType, pszProxy, pszProxyBypass, dwFlags);
  1140. if (!*phFileHandle)
  1141. {
  1142. dwError = GetLastError();
  1143. TRACE1(L"InternetOpen failed (WININET Error %d)", dwError);
  1144. hr = HRESULT_FROM_WIN32(dwError);
  1145. }
  1146. return hr;
  1147. }
  1148. STDAPI InternetOpenUrlWrap(
  1149. HINTERNET hInternet,
  1150. LPCTSTR pszUrl,
  1151. LPCTSTR pszHeaders,
  1152. DWORD dwHeadersLength,
  1153. DWORD dwFlags,
  1154. DWORD_PTR dwContext,
  1155. HINTERNET * phFileHandle
  1156. )
  1157. {
  1158. HRESULT hr = S_OK;
  1159. DWORD dwError = 0;
  1160. *phFileHandle = InternetOpenUrl(hInternet, pszUrl, pszHeaders, dwHeadersLength, dwFlags, dwContext);
  1161. if (!*phFileHandle)
  1162. {
  1163. dwError = GetLastError();
  1164. TRACE1(L"InternetOpenUrl failed (WININET Error %d)", dwError);
  1165. hr = HRESULT_FROM_WIN32(dwError);
  1166. }
  1167. return hr;
  1168. }
  1169. STDAPI HttpQueryInfoWrap(
  1170. HINTERNET hRequest,
  1171. DWORD dwInfoLevel,
  1172. LPVOID lpvBuffer,
  1173. LPDWORD lpdwBufferLength,
  1174. LPDWORD lpdwIndex
  1175. )
  1176. {
  1177. HRESULT hr = S_OK;
  1178. if (!HttpQueryInfo(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex))
  1179. {
  1180. DWORD dwError;
  1181. dwError = GetLastError();
  1182. TRACE1(L"HttpQueryInfo failed (WININET Error %d)", dwError);
  1183. hr = HRESULT_FROM_WIN32(dwError);
  1184. }
  1185. return hr;
  1186. }
  1187. BOOL
  1188. IsGlobalOffline(
  1189. VOID
  1190. )
  1191. /*++
  1192. Routine Description:
  1193. Determines whether wininet is in global offline mode
  1194. Arguments:
  1195. None
  1196. Return Value:
  1197. BOOL
  1198. TRUE - offline
  1199. FALSE - online
  1200. --*/
  1201. {
  1202. DWORD dwState = 0;
  1203. DWORD dwSize = sizeof(DWORD);
  1204. BOOL fRet = FALSE;
  1205. if(InternetQueryOption(
  1206. NULL,
  1207. INTERNET_OPTION_CONNECTED_STATE,
  1208. &dwState,
  1209. &dwSize
  1210. ))
  1211. {
  1212. if (dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
  1213. {
  1214. fRet = TRUE;
  1215. }
  1216. }
  1217. return fRet;
  1218. }
  1219. VOID
  1220. SetOffline(
  1221. IN BOOL fOffline
  1222. )
  1223. /*++
  1224. Routine Description:
  1225. Sets wininet's offline mode
  1226. Arguments:
  1227. fOffline - online or offline
  1228. Return Value:
  1229. None.
  1230. --*/
  1231. {
  1232. INTERNET_CONNECTED_INFO ci;
  1233. memset(&ci, 0, sizeof(ci));
  1234. if (fOffline)
  1235. {
  1236. ci.dwConnectedState = INTERNET_STATE_DISCONNECTED_BY_USER;
  1237. ci.dwFlags = ISO_FORCE_DISCONNECTED;
  1238. } else
  1239. {
  1240. ci.dwConnectedState = INTERNET_STATE_CONNECTED;
  1241. }
  1242. InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
  1243. }
  1244. STDAPI PingWebServer(
  1245. HINTERNET hInternet,
  1246. LPCTSTR pszUrl,
  1247. BOOL* pfConnected
  1248. )
  1249. {
  1250. HRESULT hr = E_FAIL;
  1251. HINTERNET hOpenUrlSession;
  1252. *pfConnected = FALSE;
  1253. hr = InternetOpenUrlWrap(
  1254. hInternet,
  1255. pszUrl,
  1256. NULL,
  1257. 0,
  1258. INTERNET_FLAG_NO_UI |
  1259. INTERNET_FLAG_PRAGMA_NOCACHE |
  1260. INTERNET_FLAG_NO_CACHE_WRITE |
  1261. INTERNET_FLAG_RELOAD,
  1262. NULL,
  1263. &hOpenUrlSession);
  1264. if (SUCCEEDED(hr))
  1265. {
  1266. DWORD dwSize = sizeof(DWORD);
  1267. DWORD dwStatusCode;
  1268. hr = HttpQueryInfoWrap(
  1269. hOpenUrlSession,
  1270. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  1271. (LPVOID) &dwStatusCode,
  1272. &dwSize,
  1273. NULL);
  1274. if (SUCCEEDED(hr))
  1275. {
  1276. // HTTP status code greater than or equal to 500 means server
  1277. // or network problem occur
  1278. *pfConnected = (dwStatusCode < 500);
  1279. TRACE1(L"HTTP status code from WPA HTTP server %d", dwStatusCode);
  1280. }
  1281. InternetCloseHandle(hOpenUrlSession);
  1282. }
  1283. return hr;
  1284. }
  1285. BOOL
  1286. CConnectionManager::GetInternetHandleForPinging(
  1287. HINTERNET* phInternet
  1288. )
  1289. {
  1290. static const WCHAR OOBE_HTTP_AGENT_NAME[] =
  1291. L"Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.1)";
  1292. static const int TIMEOUT_IN_MILLISEC = 30000;
  1293. if (m_hInternetPing == NULL)
  1294. {
  1295. HINTERNET hInternet;
  1296. if (SUCCEEDED(InternetOpenWrap(
  1297. OOBE_HTTP_AGENT_NAME,
  1298. PRE_CONFIG_INTERNET_ACCESS,
  1299. NULL,
  1300. NULL,
  1301. 0,
  1302. &hInternet
  1303. )))
  1304. {
  1305. DWORD dwValue;
  1306. dwValue = TIMEOUT_IN_MILLISEC;
  1307. InternetSetOption(
  1308. hInternet,
  1309. INTERNET_OPTION_CONNECT_TIMEOUT,
  1310. &dwValue,
  1311. sizeof(DWORD));
  1312. m_hInternetPing = hInternet;
  1313. }
  1314. }
  1315. *phInternet = m_hInternetPing;
  1316. return (m_hInternetPing != NULL);
  1317. }
  1318. //////////////////////////////////////////////////////////////////////////////
  1319. //
  1320. // ConnectedToInternetEx
  1321. //
  1322. // Determines whether the system is currently connected to the Internet.
  1323. //
  1324. // parameters:
  1325. // pfConnected pointer to a buffer that will receive the boolean
  1326. // indicating whether the connection exists.
  1327. //
  1328. // returns:
  1329. // TRUE if the system is connected to the internet. Note it may
  1330. // trigger autodial if it is enabled and no connection is
  1331. // available when this is called
  1332. // FALSE otherwise
  1333. //
  1334. //////////////////////////////////////////////////////////////////////////////
  1335. STDMETHODIMP
  1336. CConnectionManager::ConnectedToInternetEx(
  1337. BOOL* pfConnected
  1338. )
  1339. {
  1340. const WCHAR MS_URL[] = L"http://WPA.one.microsoft.com";
  1341. HINTERNET hInternet;
  1342. HRESULT hr = E_FAIL;
  1343. *pfConnected = FALSE;
  1344. TRACE(L"tries to connect to the WPA HTTP server");
  1345. if (IsGlobalOffline())
  1346. {
  1347. SetOffline(FALSE);
  1348. m_bForceOnline = TRUE;
  1349. TRACE(L"Force wininet to go online");
  1350. }
  1351. DisableRasAutodial();
  1352. //
  1353. // Try to use the proxy settings from winnt32.exe first because it is
  1354. // quite likely a proper configuration. If the settings
  1355. // is not available or if we failed to connect to the web server
  1356. // using these settings, use the original settings and check the web
  1357. // server connectivity once more.
  1358. //
  1359. if (GetInternetHandleForPinging(&hInternet))
  1360. {
  1361. DWORD dwDisable = 0;
  1362. DWORD dwSize = sizeof(DWORD);
  1363. DWORD dwOrigDisable;
  1364. if (!InternetQueryOption(
  1365. hInternet,
  1366. INTERNET_OPTION_DISABLE_AUTODIAL,
  1367. (LPVOID) &dwOrigDisable,
  1368. &dwSize))
  1369. {
  1370. // Assume the orginal state is autodial-enabled.
  1371. dwOrigDisable = 0;
  1372. }
  1373. // InternetSetOption for INTERNET_OPTION_DISABLE_AUTODIAL affects the
  1374. // behavior of an application, e.g. it cause InternetAutodial
  1375. // elsewhere to fail. It does not affect other applications, however.
  1376. dwDisable = 1;
  1377. InternetSetOption(
  1378. hInternet,
  1379. INTERNET_OPTION_DISABLE_AUTODIAL,
  1380. &dwDisable,
  1381. sizeof(DWORD));
  1382. if (m_bUseProxy)
  1383. {
  1384. //
  1385. // If we have already applied or we can successfully apply the
  1386. // proxy settings
  1387. //
  1388. if (ApplyWinntProxySettings())
  1389. {
  1390. // User or we may have update the proxy and other settings in
  1391. // registry
  1392. InternetSetOption(
  1393. hInternet,
  1394. INTERNET_OPTION_REFRESH,
  1395. NULL,
  1396. 0);
  1397. hr = PingWebServer(hInternet, MS_URL, pfConnected);
  1398. }
  1399. }
  1400. if (*pfConnected == FALSE)
  1401. {
  1402. //
  1403. // Restore proxy setting if it is already applied
  1404. //
  1405. if (m_bUseProxy)
  1406. {
  1407. // Don't revert the change by SetProxySettings call.
  1408. RestoreProxySettings();
  1409. }
  1410. // User or we may have update the proxy and other settings in
  1411. // registry
  1412. InternetSetOption(
  1413. hInternet,
  1414. INTERNET_OPTION_REFRESH,
  1415. NULL,
  1416. 0);
  1417. hr = PingWebServer(hInternet, MS_URL, pfConnected);
  1418. }
  1419. InternetSetOption(
  1420. hInternet,
  1421. INTERNET_OPTION_DISABLE_AUTODIAL,
  1422. &dwOrigDisable,
  1423. sizeof(DWORD));
  1424. }
  1425. RestoreRasAutoDial();
  1426. TRACE1(L"%s connect to WPA HTTP server",
  1427. (*pfConnected) ? L"could" : L"could not");
  1428. return hr;
  1429. } // CConnectionManager::ConnectedToInternetEx
  1430. typedef struct tagConnmgrPARAM
  1431. {
  1432. HWND hwnd;
  1433. CConnectionManager *pConnmgr;
  1434. } CONNMGRPARAM, *PCONNMGRPARAM;
  1435. DWORD WINAPI ConnectedToInternetExThread(LPVOID vpParam)
  1436. {
  1437. BOOL fConnected = FALSE;
  1438. PCONNMGRPARAM pParam = (PCONNMGRPARAM) vpParam;
  1439. HRESULT hr = S_OK;
  1440. hr = pParam->pConnmgr->ConnectedToInternetEx(&fConnected);
  1441. PostMessage(pParam->hwnd, WM_OBCOMM_NETCHECK_DONE, fConnected, hr);
  1442. GlobalFree(pParam);
  1443. return 0;
  1444. }
  1445. //////////////////////////////////////////////////////////////////////////////
  1446. //
  1447. // AsyncConnectedToInternetEx
  1448. //
  1449. // Determines whether the system is currently connected to the Internet.
  1450. //
  1451. // parameters:
  1452. // pfConnected pointer to a buffer that will receive the boolean
  1453. // indicating whether the connection exists.
  1454. //
  1455. // returns:
  1456. // TRUE if the system is connected to the internet. Note it may
  1457. // trigger autodial if it is enabled and no connection is
  1458. // available when this is called
  1459. // FALSE otherwise
  1460. //
  1461. // note:
  1462. // Deprecated.
  1463. //
  1464. //////////////////////////////////////////////////////////////////////////////
  1465. STDMETHODIMP
  1466. CConnectionManager::AsyncConnectedToInternetEx(
  1467. const HWND hwnd
  1468. )
  1469. {
  1470. DWORD threadId;
  1471. HANDLE hThread;
  1472. PCONNMGRPARAM pParam = NULL;
  1473. HRESULT hr = S_OK;
  1474. DWORD dwError;
  1475. pParam = (PCONNMGRPARAM) GlobalAlloc(GPTR, sizeof(CONNMGRPARAM));
  1476. if (pParam)
  1477. {
  1478. pParam->hwnd = hwnd;
  1479. pParam->pConnmgr = this;
  1480. hThread = CreateThread(NULL, 0, ConnectedToInternetExThread, pParam, 0, &threadId);
  1481. if (hThread == NULL)
  1482. {
  1483. dwError = GetLastError();
  1484. hr = HRESULT_FROM_WIN32(dwError);
  1485. }
  1486. }
  1487. else
  1488. {
  1489. hr = E_OUTOFMEMORY;
  1490. }
  1491. if (FAILED(hr))
  1492. {
  1493. // Notify the script so that it won't hang
  1494. PostMessage(hwnd, WM_OBCOMM_NETCHECK_DONE, FALSE, hr);
  1495. }
  1496. return hr;
  1497. } // CConnectionManager::AsyncConnectedToInternetEx
  1498. //////////////////////////////////////////////////////////////////////////////
  1499. //
  1500. // IsEnabledConnection
  1501. //
  1502. // Determines whether a connection should be considered as having Internet
  1503. // capability or not, based on its media type and current status.
  1504. //
  1505. // parameters:
  1506. // ncMedia The media type of the connection
  1507. // ncStatus The current status of the connection
  1508. //
  1509. // returns:
  1510. // TRUE We should not considered it as having Internet capability
  1511. // FALSE otherwise
  1512. //
  1513. //////////////////////////////////////////////////////////////////////////////
  1514. BOOL
  1515. CConnectionManager::IsEnabledConnection(
  1516. NETCON_PROPERTIES* pprops
  1517. )
  1518. {
  1519. BOOL bRet;
  1520. switch (pprops->MediaType)
  1521. {
  1522. case NCM_LAN:
  1523. bRet = (pprops->Status != NCS_DISCONNECTED);
  1524. if (bRet && m_bExclude1394 && Is1394Adapter(&(pprops->guidId)))
  1525. {
  1526. TRACE1(L"%s not considered as LAN", pprops->pszwName);
  1527. bRet = FALSE;
  1528. }
  1529. break;
  1530. case NCM_SHAREDACCESSHOST_LAN:
  1531. case NCM_SHAREDACCESSHOST_RAS:
  1532. bRet = (pprops->Status != NCS_DISCONNECTED);
  1533. break;
  1534. default:
  1535. bRet = TRUE;
  1536. }
  1537. return bRet;
  1538. }
  1539. //////////////////////////////////////////////////////////////////////////////
  1540. //
  1541. // SaveProxySettings
  1542. //
  1543. // Save existing proxy settings for current user.
  1544. //
  1545. // returns:
  1546. // TRUE The value is successfully saved
  1547. // FALSE otherwise
  1548. //
  1549. //////////////////////////////////////////////////////////////////////////////
  1550. BOOL
  1551. CConnectionManager::SaveProxySettings()
  1552. {
  1553. if (!m_bProxySaved)
  1554. {
  1555. TRACE(TEXT("try to save the existing proxy settings"));
  1556. if (AllocProxyOptionList(&m_CurrentProxySettings))
  1557. {
  1558. DWORD dwBufferLength = sizeof(m_CurrentProxySettings);
  1559. if (InternetQueryOption(
  1560. NULL,
  1561. INTERNET_OPTION_PER_CONNECTION_OPTION,
  1562. &m_CurrentProxySettings,
  1563. &dwBufferLength
  1564. ))
  1565. {
  1566. m_bProxySaved = TRUE;
  1567. TRACE(TEXT("successfully save the proxy settings"));
  1568. }
  1569. else
  1570. {
  1571. FreeProxyOptionList(&m_CurrentProxySettings);
  1572. }
  1573. }
  1574. if (!m_bProxySaved)
  1575. {
  1576. TRACE1(
  1577. TEXT("fail to save the proxy settings (Error %d)"),
  1578. GetLastError()
  1579. );
  1580. }
  1581. }
  1582. return m_bProxySaved;
  1583. }
  1584. //////////////////////////////////////////////////////////////////////////////
  1585. //
  1586. // RestoreProxySettings
  1587. //
  1588. // Restore the setting captured by SaveProxySettings.
  1589. //
  1590. //////////////////////////////////////////////////////////////////////////////
  1591. void
  1592. CConnectionManager::RestoreProxySettings()
  1593. {
  1594. BOOL bRestored = FALSE;
  1595. if (m_bProxyApplied)
  1596. {
  1597. TRACE(TEXT("try to restore the original proxy settings"));
  1598. bRestored = InternetSetOption(
  1599. NULL,
  1600. INTERNET_OPTION_PER_CONNECTION_OPTION,
  1601. &m_CurrentProxySettings,
  1602. sizeof(m_CurrentProxySettings)
  1603. );
  1604. if (bRestored)
  1605. {
  1606. m_bProxyApplied = FALSE;
  1607. TRACE(TEXT("successfully restored the proxy settings"));
  1608. }
  1609. else
  1610. {
  1611. TRACE1(
  1612. TEXT("failed to restore the proxy settings (WININET Error %d)"),
  1613. GetLastError()
  1614. );
  1615. }
  1616. }
  1617. }
  1618. static LPTSTR
  1619. pDuplicateString(
  1620. LPCTSTR szText
  1621. )
  1622. {
  1623. int cchText;
  1624. LPTSTR szOutText;
  1625. if (szText == NULL)
  1626. {
  1627. return NULL;
  1628. }
  1629. cchText = lstrlen(szText);
  1630. szOutText = (LPTSTR) GlobalAlloc(GPTR, sizeof(TCHAR) * (cchText + 1));
  1631. if (szOutText)
  1632. {
  1633. lstrcpyn(szOutText, szText, cchText + 1);
  1634. }
  1635. return szOutText;
  1636. }
  1637. //////////////////////////////////////////////////////////////////////////////
  1638. //
  1639. // ApplyWinntProxySettings
  1640. //
  1641. // Apply the proxy settings for NIC saved during winnt32.exe to the current user.
  1642. // Before the values is applied, it makes sure that existing settings is saved.
  1643. //
  1644. // returns:
  1645. // TRUE the proxy settings was successfully applied
  1646. // FALSE otherwise
  1647. //
  1648. //////////////////////////////////////////////////////////////////////////////
  1649. BOOL
  1650. CConnectionManager::ApplyWinntProxySettings()
  1651. {
  1652. #define MAX_URL_LENGTH 2048
  1653. DWORD dwProxyFlags = 0;
  1654. LPTSTR szProxyList = NULL;
  1655. TCHAR szWinntPath[MAX_PATH];
  1656. //
  1657. // Save proxy settings if it has not been saved.
  1658. //
  1659. SaveProxySettings();
  1660. //
  1661. // Apply proxy settings if it has not been applied.
  1662. //
  1663. if (m_bProxySaved && !m_bProxyApplied)
  1664. {
  1665. TRACE1(TEXT("tries to apply proxy settings, saved in %s"),
  1666. WINNT_INF_FILENAME);
  1667. if (GetCanonicalizedPath(szWinntPath, WINNT_INF_FILENAME))
  1668. {
  1669. DWORD dwEnableOobeProxy;
  1670. dwEnableOobeProxy = GetPrivateProfileInt(
  1671. OOBE_PROXY_SECTION,
  1672. OOBE_ENABLE_OOBY_PROXY,
  1673. 0,
  1674. szWinntPath
  1675. );
  1676. if (dwEnableOobeProxy)
  1677. {
  1678. INTERNET_PER_CONN_OPTION_LIST PrevProxySettings;
  1679. if (AllocProxyOptionList(&PrevProxySettings))
  1680. {
  1681. INTERNET_PER_CONN_OPTION* pOption = PrevProxySettings.pOptions;
  1682. DWORD dwBufferLength = sizeof(PrevProxySettings);
  1683. TCHAR szBuffer[MAX_URL_LENGTH];
  1684. pOption[0].Value.dwValue = GetPrivateProfileInt(
  1685. OOBE_PROXY_SECTION,
  1686. OOBE_FLAGS,
  1687. 0,
  1688. szWinntPath
  1689. );
  1690. if (GetPrivateProfileString(
  1691. OOBE_PROXY_SECTION,
  1692. OOBE_PROXY_SERVER,
  1693. TEXT(""),
  1694. szBuffer,
  1695. MAX_URL_LENGTH,
  1696. szWinntPath
  1697. ))
  1698. {
  1699. pOption[1].Value.pszValue = pDuplicateString(szBuffer);
  1700. }
  1701. if (GetPrivateProfileString(
  1702. OOBE_PROXY_SECTION,
  1703. OOBE_PROXY_BYPASS,
  1704. TEXT(""),
  1705. szBuffer,
  1706. MAX_URL_LENGTH,
  1707. szWinntPath
  1708. ))
  1709. {
  1710. pOption[2].Value.pszValue = pDuplicateString(szBuffer);
  1711. }
  1712. if (GetPrivateProfileString(
  1713. OOBE_PROXY_SECTION,
  1714. OOBE_AUTOCONFIG_URL,
  1715. TEXT(""),
  1716. szBuffer,
  1717. MAX_URL_LENGTH,
  1718. szWinntPath
  1719. ))
  1720. {
  1721. pOption[3].Value.pszValue = pDuplicateString(szBuffer);
  1722. }
  1723. pOption[4].Value.dwValue = GetPrivateProfileInt(
  1724. OOBE_PROXY_SECTION,
  1725. OOBE_AUTODISCOVERY_FLAGS,
  1726. 0,
  1727. szWinntPath
  1728. );
  1729. if (GetPrivateProfileString(
  1730. OOBE_PROXY_SECTION,
  1731. OOBE_AUTOCONFIG_SECONDARY_URL,
  1732. TEXT(""),
  1733. szBuffer,
  1734. MAX_URL_LENGTH,
  1735. szWinntPath
  1736. ))
  1737. {
  1738. pOption[5].Value.pszValue = pDuplicateString(szBuffer);
  1739. }
  1740. m_bProxyApplied = InternetSetOption(
  1741. NULL,
  1742. INTERNET_OPTION_PER_CONNECTION_OPTION,
  1743. &PrevProxySettings,
  1744. sizeof(PrevProxySettings)
  1745. );
  1746. FreeProxyOptionList(&PrevProxySettings);
  1747. }
  1748. }
  1749. }
  1750. if (m_bProxyApplied)
  1751. {
  1752. TRACE(TEXT("successfully load the proxy settings"));
  1753. }
  1754. else
  1755. {
  1756. TRACE1(TEXT("could not load the proxy settings (WIN32 Error %d)"),
  1757. GetLastError());
  1758. }
  1759. }
  1760. return m_bProxyApplied;
  1761. }
  1762. void
  1763. CConnectionManager::UseWinntProxySettings()
  1764. {
  1765. m_bUseProxy = TRUE;
  1766. }
  1767. void
  1768. CConnectionManager::DisableWinntProxySettings()
  1769. {
  1770. TCHAR szWinntPath[MAX_PATH];
  1771. if (GetCanonicalizedPath(szWinntPath, WINNT_INF_FILENAME))
  1772. {
  1773. WritePrivateProfileString(
  1774. OOBE_PROXY_SECTION,
  1775. OOBE_ENABLE_OOBY_PROXY,
  1776. TEXT("0"),
  1777. szWinntPath
  1778. );
  1779. TRACE1(TEXT("disabled the proxy settings in %s"),
  1780. WINNT_INF_FILENAME);
  1781. }
  1782. }
  1783. BOOL
  1784. CConnectionManager::AllocProxyOptionList(
  1785. INTERNET_PER_CONN_OPTION_LIST *pList
  1786. )
  1787. {
  1788. INTERNET_PER_CONN_OPTION* pOption;
  1789. pOption = (INTERNET_PER_CONN_OPTION*) GlobalAlloc(
  1790. GPTR,
  1791. sizeof(INTERNET_PER_CONN_OPTION) * NUM_PROXY_OPTIONS);
  1792. if (pOption)
  1793. {
  1794. pList->dwSize = sizeof(*pList);
  1795. pList->pszConnection = NULL;
  1796. pList->dwOptionCount = NUM_PROXY_OPTIONS;
  1797. pList->pOptions = pOption;
  1798. pOption[0].dwOption = INTERNET_PER_CONN_FLAGS;
  1799. pOption[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
  1800. pOption[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
  1801. pOption[3].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
  1802. pOption[4].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
  1803. pOption[5].dwOption = INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL;
  1804. }
  1805. else
  1806. {
  1807. pList->pOptions = NULL;
  1808. }
  1809. return (pOption != NULL);
  1810. }
  1811. void
  1812. CConnectionManager::FreeProxyOptionList(
  1813. INTERNET_PER_CONN_OPTION_LIST *pList
  1814. )
  1815. {
  1816. INTERNET_PER_CONN_OPTION* pOption = pList->pOptions;
  1817. if (pOption)
  1818. {
  1819. if (pOption[1].Value.pszValue)
  1820. {
  1821. GlobalFree(pOption[1].Value.pszValue);
  1822. }
  1823. if (pOption[2].Value.pszValue)
  1824. {
  1825. GlobalFree(pOption[2].Value.pszValue);
  1826. }
  1827. if (pOption[3].Value.pszValue)
  1828. {
  1829. GlobalFree(pOption[3].Value.pszValue);
  1830. }
  1831. if (pOption[5].Value.pszValue)
  1832. {
  1833. GlobalFree(pOption[5].Value.pszValue);
  1834. }
  1835. GlobalFree(pOption);
  1836. pList->pOptions = NULL;
  1837. }
  1838. }
  1839. void CConnectionManager::DisableRasAutodial()
  1840. {
  1841. DWORD dwValue = RAS_AUTODIAL_DISABLED;
  1842. if (m_dwRasAutodialDisable == RAS_AUTODIAL_DONT_KNOW)
  1843. {
  1844. DWORD dwSize = sizeof(m_dwRasAutodialDisable);
  1845. if (RasGetAutodialParam(
  1846. RASADP_LoginSessionDisable,
  1847. &m_dwRasAutodialDisable,
  1848. &dwSize
  1849. ) != ERROR_SUCCESS)
  1850. {
  1851. m_dwRasAutodialDisable = RAS_AUTODIAL_ENABLED;
  1852. }
  1853. else
  1854. {
  1855. TRACE1(
  1856. L"Save value of RASADP_LoginSessionDisable %d",
  1857. m_dwRasAutodialDisable
  1858. );
  1859. }
  1860. }
  1861. if (RasSetAutodialParam(
  1862. RASADP_LoginSessionDisable,
  1863. &dwValue,
  1864. sizeof(dwValue)
  1865. ) == ERROR_SUCCESS)
  1866. {
  1867. TRACE(L"Disabled RAS Autodial for current logon session");
  1868. }
  1869. }
  1870. void CConnectionManager::RestoreRasAutoDial()
  1871. {
  1872. if (m_dwRasAutodialDisable != RAS_AUTODIAL_DONT_KNOW)
  1873. {
  1874. if (RasSetAutodialParam(
  1875. RASADP_LoginSessionDisable,
  1876. &m_dwRasAutodialDisable,
  1877. sizeof(m_dwRasAutodialDisable)
  1878. ) == ERROR_SUCCESS)
  1879. {
  1880. TRACE(L"Restore value of RAS Autodial for current logon session");
  1881. }
  1882. }
  1883. }
  1884. HRESULT CConnectionManager::GetProxySettings(
  1885. BOOL* pbUseAuto,
  1886. BOOL* pbUseScript,
  1887. BSTR* pszScriptUrl,
  1888. BOOL* pbUseProxy,
  1889. BSTR* pszProxy
  1890. )
  1891. {
  1892. HRESULT hr = E_FAIL;
  1893. //
  1894. // Save proxy settings if it has not been saved.
  1895. //
  1896. SaveProxySettings();
  1897. if (m_bProxySaved)
  1898. {
  1899. INTERNET_PER_CONN_OPTION* pOption = m_CurrentProxySettings.pOptions;
  1900. *pbUseAuto = pOption[0].Value.dwValue & PROXY_TYPE_AUTO_DETECT;
  1901. *pbUseScript = pOption[0].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL;
  1902. *pbUseProxy = pOption[0].Value.dwValue & PROXY_TYPE_PROXY;
  1903. if (pOption[1].Value.pszValue)
  1904. {
  1905. *pszProxy = SysAllocString(pOption[1].Value.pszValue);
  1906. }
  1907. else
  1908. {
  1909. *pszProxy = NULL;
  1910. }
  1911. if (pOption[3].Value.pszValue)
  1912. {
  1913. *pszScriptUrl = SysAllocString(pOption[3].Value.pszValue);
  1914. }
  1915. else
  1916. {
  1917. *pszScriptUrl = NULL;
  1918. }
  1919. hr = S_OK;
  1920. }
  1921. return hr;
  1922. }
  1923. HRESULT CConnectionManager::SetProxySettings(
  1924. BOOL bUseAuto,
  1925. BOOL bUseScript,
  1926. BSTR szScriptUrl,
  1927. BOOL bUseProxy,
  1928. BSTR szProxy
  1929. )
  1930. {
  1931. HRESULT hr = E_FAIL;
  1932. //
  1933. // We don't behavior correctly in this->ConnectedToInternetEx if we
  1934. // also use proxy settings saved in winnt32.
  1935. //
  1936. MYASSERT(!m_bUseProxy);
  1937. //
  1938. // Save proxy settings if it has not been saved.
  1939. //
  1940. SaveProxySettings();
  1941. if (m_bProxySaved)
  1942. {
  1943. INTERNET_PER_CONN_OPTION_LIST ProxySettings;
  1944. if (AllocProxyOptionList(&ProxySettings))
  1945. {
  1946. INTERNET_PER_CONN_OPTION* pOption = ProxySettings.pOptions;
  1947. pOption[0].Value.dwValue = PROXY_TYPE_DIRECT;
  1948. if (bUseAuto)
  1949. {
  1950. pOption[0].Value.dwValue |= PROXY_TYPE_AUTO_DETECT;
  1951. }
  1952. if (bUseScript)
  1953. {
  1954. pOption[0].Value.dwValue |= PROXY_TYPE_AUTO_PROXY_URL;
  1955. }
  1956. if (bUseProxy)
  1957. {
  1958. pOption[0].Value.dwValue |= PROXY_TYPE_PROXY;
  1959. }
  1960. pOption[1].Value.pszValue = szProxy;
  1961. pOption[2].Value.pszValue = NULL;
  1962. pOption[3].Value.pszValue = szScriptUrl;
  1963. pOption[4].Value.dwValue = m_CurrentProxySettings.pOptions[4].Value.dwValue;
  1964. if (bUseAuto)
  1965. {
  1966. pOption[4].Value.dwValue |= AUTO_PROXY_FLAG_USER_SET;
  1967. }
  1968. pOption[5].Value.pszValue = m_CurrentProxySettings.pOptions[5].Value.pszValue;
  1969. TRACE5(TEXT("tries to set LAN proxy: %d, %s, %s, %d"),
  1970. pOption[0].Value.dwValue,
  1971. pOption[1].Value.pszValue,
  1972. pOption[3].Value.pszValue,
  1973. pOption[4].Value.dwValue,
  1974. pOption[5].Value.pszValue
  1975. );
  1976. if (InternetSetOption(
  1977. NULL,
  1978. INTERNET_OPTION_PER_CONNECTION_OPTION,
  1979. &ProxySettings,
  1980. sizeof(ProxySettings)
  1981. ))
  1982. {
  1983. m_bProxyApplied = TRUE;
  1984. hr = S_OK;
  1985. }
  1986. // so that we don't free the memory from the caller in
  1987. // FreeProxyOptionList
  1988. pOption[1].Value.pszValue = NULL;
  1989. pOption[3].Value.pszValue = NULL;
  1990. pOption[5].Value.pszValue = NULL;
  1991. FreeProxyOptionList(&ProxySettings);
  1992. }
  1993. }
  1994. if (SUCCEEDED(hr))
  1995. {
  1996. TRACE(TEXT("successfully set the proxy settings"));
  1997. }
  1998. else
  1999. {
  2000. TRACE1(TEXT("could not set the proxy settings (WIN32 Error %d)"),
  2001. GetLastError());
  2002. }
  2003. return hr;
  2004. }
  2005. STDMETHODIMP
  2006. CConnectionManager::GetPublicLanCount(int* pcPublicLan)
  2007. {
  2008. PSTRINGLIST PubList = NULL;
  2009. HRESULT hr = S_OK;
  2010. EnumPublicAdapters(&PubList);
  2011. int i = 0;
  2012. for (PSTRINGLIST p = PubList; p; p = p->Next)
  2013. {
  2014. i++;
  2015. }
  2016. *pcPublicLan = i;
  2017. if (PubList)
  2018. {
  2019. DestroyList(PubList);
  2020. }
  2021. return hr;
  2022. }
  2023. HRESULT
  2024. CConnectionManager::Enum1394Adapters(
  2025. OUT PSTRINGLIST* pList
  2026. )
  2027. {
  2028. UINT i;
  2029. INetCfgComponent* arrayComp[MAX_NUM_NET_COMPONENTS];
  2030. IEnumNetCfgComponent* pEnum = NULL;
  2031. INetCfgClass* pNetCfgClass = NULL;
  2032. INetCfgComponent* pNetCfgComp = NULL;
  2033. LPWSTR szPnpId = NULL;
  2034. HRESULT hr = S_OK;
  2035. DWORD dwCharacteristics = 0;
  2036. ULONG iCount = 0;
  2037. PSTRINGLIST List = NULL;
  2038. PSTRINGLIST Cell = NULL;
  2039. GUID guidInstance;
  2040. WCHAR szInstanceGuid[MAX_GUID_LEN + 1] = L"";
  2041. INetCfg* pNetCfg = NULL;
  2042. ZeroMemory(arrayComp, sizeof(arrayComp));
  2043. hr = GetNetCfgInterface(FALSE, &pNetCfg);
  2044. if (FAILED(hr))
  2045. {
  2046. goto cleanup;
  2047. }
  2048. //
  2049. // Obtain the INetCfgClass interface pointer
  2050. //
  2051. hr = pNetCfg->QueryNetCfgClass( &GUID_DEVCLASS_NET,
  2052. IID_INetCfgClass,
  2053. (void**)&pNetCfgClass );
  2054. if( FAILED( hr ) )
  2055. {
  2056. goto cleanup;
  2057. }
  2058. //
  2059. // Retrieve the enumerator interface
  2060. //
  2061. hr = pNetCfgClass->EnumComponents( &pEnum );
  2062. if( FAILED( hr ) )
  2063. {
  2064. goto cleanup;
  2065. }
  2066. hr = pEnum->Next( MAX_NUM_NET_COMPONENTS, &arrayComp[0], &iCount );
  2067. if( FAILED( hr ) )
  2068. {
  2069. goto cleanup;
  2070. }
  2071. MYASSERT( iCount <= MAX_NUM_NET_COMPONENTS );
  2072. if ( iCount > MAX_NUM_NET_COMPONENTS )
  2073. {
  2074. hr = E_UNEXPECTED;
  2075. goto cleanup;
  2076. }
  2077. for( i = 0; i < iCount; i++ )
  2078. {
  2079. pNetCfgComp = arrayComp[i];
  2080. hr = pNetCfgComp->GetCharacteristics( &dwCharacteristics );
  2081. if( FAILED( hr ) )
  2082. {
  2083. goto cleanup;
  2084. }
  2085. //
  2086. // If this is a physical adapter
  2087. //
  2088. if( dwCharacteristics & NCF_PHYSICAL )
  2089. {
  2090. hr = pNetCfgComp->GetId( &szPnpId );
  2091. if (FAILED(hr))
  2092. {
  2093. goto cleanup;
  2094. }
  2095. //
  2096. // If this is a 1394 network adapter
  2097. //
  2098. if (!lstrcmpi(szPnpId, L"v1394\\nic1394"))
  2099. {
  2100. hr = pNetCfgComp->GetInstanceGuid(&guidInstance);
  2101. if (FAILED(hr))
  2102. {
  2103. goto cleanup;
  2104. }
  2105. if (!StringFromGUID2(guidInstance, szInstanceGuid, MAX_GUID_LEN))
  2106. {
  2107. goto cleanup;
  2108. }
  2109. Cell = CreateStringCell(szInstanceGuid);
  2110. if (!Cell)
  2111. {
  2112. goto cleanup;
  2113. }
  2114. InsertList(&List, Cell);
  2115. Cell = NULL;
  2116. }
  2117. CoTaskMemFree( szPnpId );
  2118. szPnpId = NULL;
  2119. }
  2120. }
  2121. *pList = List;
  2122. List = NULL;
  2123. cleanup:
  2124. if (List)
  2125. {
  2126. DestroyList(List);
  2127. }
  2128. if (Cell)
  2129. {
  2130. DeleteStringCell(Cell);
  2131. }
  2132. if (szPnpId)
  2133. {
  2134. CoTaskMemFree(szPnpId);
  2135. }
  2136. for (i = 0; i < iCount; i++)
  2137. {
  2138. if (arrayComp[i])
  2139. {
  2140. arrayComp[i]->Release();
  2141. }
  2142. }
  2143. if (pNetCfgClass)
  2144. {
  2145. pNetCfgClass->Release();
  2146. }
  2147. if (pEnum)
  2148. {
  2149. pEnum->Release();
  2150. }
  2151. if (pNetCfg)
  2152. {
  2153. ReleaseNetCfgInterface(pNetCfg, FALSE);
  2154. }
  2155. return hr;
  2156. }
  2157. BOOL
  2158. CConnectionManager::Is1394Adapter(
  2159. GUID* pguid
  2160. )
  2161. {
  2162. PSTRINGLIST List = NULL;
  2163. PSTRINGLIST p;
  2164. BOOL bRet = FALSE;
  2165. Enum1394Adapters(&List);
  2166. if (List)
  2167. {
  2168. for (p = List; p; p = p->Next)
  2169. {
  2170. if (!StringCmpGUID(p->String, pguid))
  2171. {
  2172. bRet = TRUE;
  2173. break;
  2174. }
  2175. }
  2176. DestroyList(List);
  2177. }
  2178. return bRet;
  2179. }
  2180. HRESULT
  2181. CConnectionManager::EnumPublicConnections(
  2182. OUT PSTRINGLIST* pList
  2183. )
  2184. {
  2185. HRESULT hr = S_OK;
  2186. PSTRINGLIST PubList = NULL;
  2187. TRACE(L"Begin EnumPublicConnections ...");
  2188. EnumPublicAdapters(&PubList);
  2189. if (!PubList)
  2190. {
  2191. *pList = NULL;
  2192. return hr;
  2193. }
  2194. // Initialize the net connection enumeration. For each interface
  2195. // retrieved, SetProxyBlanket must be called to set the authentication for
  2196. // the interface proxy handle because the Network Connection Manager lives
  2197. // in a remote process with a different security context.
  2198. //
  2199. INetConnectionManager* pmgr = NULL;
  2200. IEnumNetConnection* penum = NULL;
  2201. NETCON_PROPERTIES* pprops = NULL;
  2202. INetConnection* pnc = NULL;
  2203. PSTRINGLIST List = NULL;
  2204. PSTRINGLIST p = NULL;
  2205. PSTRINGLIST Cell = NULL;
  2206. ULONG ulRetrieved;
  2207. hr = CoCreateInstance(
  2208. CLSID_ConnectionManager,
  2209. NULL,
  2210. CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  2211. IID_INetConnectionManager,
  2212. (VOID**) &pmgr
  2213. );
  2214. if (FAILED(hr))
  2215. {
  2216. goto cleanup;
  2217. }
  2218. hr = SetProxyBlanket(pmgr);
  2219. if (FAILED(hr))
  2220. {
  2221. goto cleanup;
  2222. }
  2223. hr = pmgr->EnumConnections(NCME_DEFAULT, &penum);
  2224. if (FAILED(hr))
  2225. {
  2226. goto cleanup;
  2227. }
  2228. hr = SetProxyBlanket(penum);
  2229. if (FAILED(hr))
  2230. {
  2231. goto cleanup;
  2232. }
  2233. hr = penum->Reset();
  2234. if (FAILED(hr))
  2235. {
  2236. goto cleanup;
  2237. }
  2238. hr = penum->Next(1, &pnc, &ulRetrieved);
  2239. while (S_OK == hr)
  2240. {
  2241. hr = SetProxyBlanket(pnc);
  2242. if (FAILED(hr))
  2243. {
  2244. goto cleanup;
  2245. }
  2246. hr = pnc->GetProperties(&pprops);
  2247. if (FAILED(hr))
  2248. {
  2249. goto cleanup;
  2250. }
  2251. if (pprops->MediaType == NCM_LAN && pprops->Status != NCS_DISCONNECTED)
  2252. {
  2253. for (p = PubList; p; p = p->Next)
  2254. {
  2255. if (!StringCmpGUID(p->String, &(pprops->guidId)))
  2256. {
  2257. Cell = CreateStringCell(pprops->pszwName);
  2258. if (Cell)
  2259. {
  2260. TRACE1(L" + %s", pprops->pszwName);
  2261. InsertList(&List, Cell);
  2262. }
  2263. }
  2264. }
  2265. }
  2266. NcFreeNetconProperties(pprops);
  2267. pprops = NULL;
  2268. pnc->Release();
  2269. pnc = NULL;
  2270. hr = penum->Next(1, &pnc, &ulRetrieved);
  2271. }
  2272. if (hr != S_FALSE)
  2273. {
  2274. goto cleanup;
  2275. }
  2276. // IEnumNetConnection::Next returned S_FALSE to indicate
  2277. // that no more elements were available.
  2278. hr = S_OK;
  2279. *pList = List;
  2280. List = NULL;
  2281. cleanup:
  2282. if (List)
  2283. {
  2284. DestroyList(List);
  2285. }
  2286. if (NULL != pprops)
  2287. {
  2288. NcFreeNetconProperties(pprops);
  2289. }
  2290. if (NULL != pnc)
  2291. {
  2292. pnc->Release();
  2293. }
  2294. if (NULL != penum)
  2295. {
  2296. penum->Release();
  2297. }
  2298. if (NULL != pmgr)
  2299. {
  2300. pmgr->Release();
  2301. }
  2302. TRACE1(L"End EnumPublicConnections (0x%08lx)", hr);
  2303. return hr;
  2304. }
  2305. HRESULT
  2306. CConnectionManager::EnumPublicAdapters(
  2307. OUT PSTRINGLIST* pList
  2308. )
  2309. {
  2310. static GUID g_guidNLAServiceClass = NLA_SERVICE_CLASS_GUID;
  2311. static const int MAX_ADAPTER_NAME_LEN = 256;
  2312. WSADATA wsaData;
  2313. int error;
  2314. PSTRINGLIST AdapterList = NULL;
  2315. PSTRINGLIST ExcludeList = NULL;
  2316. TRACE(L"Begin EnumPublicAdapters ...");
  2317. if (m_bExclude1394)
  2318. {
  2319. Enum1394Adapters(&ExcludeList);
  2320. }
  2321. if (0 == (error = WSAStartup(MAKEWORD(2, 2), &wsaData)))
  2322. {
  2323. // Init query for network names
  2324. WSAQUERYSET restrictions = {0};
  2325. restrictions.dwSize = sizeof(restrictions);
  2326. restrictions.lpServiceClassId = &g_guidNLAServiceClass;
  2327. restrictions.dwNameSpace = NS_NLA;
  2328. HANDLE hQuery;
  2329. // Make sure we do not ask for the (chicken) blobs that take a long time to get
  2330. if (0 == (error = WSALookupServiceBegin(&restrictions, LUP_NOCONTAINERS | LUP_DEEP, &hQuery)))
  2331. {
  2332. PWSAQUERYSET pqsResults = NULL;
  2333. while (0 == _AllocWSALookupServiceNext(hQuery, 0, &pqsResults))
  2334. {
  2335. if (NULL != pqsResults->lpBlob)
  2336. {
  2337. NLA_BLOB* pnlaBlob = (NLA_BLOB*) pqsResults->lpBlob->pBlobData;
  2338. WCHAR szAdapterWide[MAX_ADAPTER_NAME_LEN] = L"";
  2339. NLA_INTERNET nlaInternet = NLA_INTERNET_UNKNOWN;
  2340. while (NULL != pnlaBlob)
  2341. {
  2342. switch (pnlaBlob->header.type)
  2343. {
  2344. case NLA_INTERFACE:
  2345. MultiByteToWideChar(
  2346. CP_ACP,
  2347. 0,
  2348. pnlaBlob->data.interfaceData.adapterName,
  2349. -1,
  2350. szAdapterWide,
  2351. ARRAYSIZE(szAdapterWide)
  2352. );
  2353. break;
  2354. case NLA_CONNECTIVITY:
  2355. nlaInternet = pnlaBlob->data.connectivity.internet;
  2356. break;
  2357. }
  2358. pnlaBlob = _NLABlobNext(pnlaBlob);
  2359. }
  2360. if (nlaInternet == NLA_INTERNET_YES && szAdapterWide[0])
  2361. {
  2362. PSTRINGLIST p = NULL;
  2363. for (p = ExcludeList; p; p = p->Next)
  2364. {
  2365. if (!lstrcmpi(p->String, szAdapterWide))
  2366. {
  2367. break;
  2368. }
  2369. }
  2370. //
  2371. // Check if the adapter is excluded.
  2372. //
  2373. if (!p)
  2374. {
  2375. PSTRINGLIST Cell = CreateStringCell(szAdapterWide);
  2376. if (Cell)
  2377. {
  2378. TRACE1(L" + %s", szAdapterWide);
  2379. InsertList(&AdapterList, Cell);
  2380. }
  2381. }
  2382. }
  2383. }
  2384. LocalFree(pqsResults);
  2385. }
  2386. WSALookupServiceEnd(pqsResults);
  2387. }
  2388. WSACleanup();
  2389. if (error == 0)
  2390. {
  2391. *pList = AdapterList;
  2392. }
  2393. else
  2394. {
  2395. if (AdapterList)
  2396. {
  2397. DestroyList(AdapterList);
  2398. }
  2399. }
  2400. }
  2401. TRACE1(L"End EnumPublicAdapters (%d)", error);
  2402. return HRESULT_FROM_WIN32(error);
  2403. }
  2404. NLA_BLOB* _NLABlobNext(
  2405. IN NLA_BLOB* pnlaBlob
  2406. )
  2407. {
  2408. NLA_BLOB* pNext = NULL;
  2409. if (pnlaBlob->header.nextOffset)
  2410. {
  2411. pNext = (NLA_BLOB*) (((BYTE*) pnlaBlob) + pnlaBlob->header.nextOffset);
  2412. }
  2413. return pNext;
  2414. }
  2415. int _AllocWSALookupServiceNext(
  2416. IN HANDLE hQuery,
  2417. IN DWORD dwControlFlags,
  2418. OUT LPWSAQUERYSET* ppResults
  2419. )
  2420. {
  2421. *ppResults = NULL;
  2422. DWORD cb = 0;
  2423. int error = 0;
  2424. if (SOCKET_ERROR == WSALookupServiceNext(hQuery, dwControlFlags, &cb, NULL))
  2425. {
  2426. error = WSAGetLastError();
  2427. if (WSAEFAULT == error)
  2428. {
  2429. assert(cb);
  2430. *ppResults = (LPWSAQUERYSET) LocalAlloc(LPTR, cb);
  2431. if (NULL != *ppResults)
  2432. {
  2433. error = 0;
  2434. if (SOCKET_ERROR == WSALookupServiceNext(hQuery, dwControlFlags, &cb, *ppResults))
  2435. {
  2436. error = WSAGetLastError();
  2437. }
  2438. }
  2439. else
  2440. {
  2441. error = WSA_NOT_ENOUGH_MEMORY;
  2442. }
  2443. }
  2444. }
  2445. // May as well map outdated error code while we're here.
  2446. if (WSAENOMORE == error)
  2447. {
  2448. error = WSA_E_NO_MORE;
  2449. }
  2450. if (error && (*ppResults))
  2451. {
  2452. LocalFree(*ppResults);
  2453. *ppResults = NULL;
  2454. }
  2455. return error;
  2456. }
  2457. static int StringCmpGUID(
  2458. IN LPCWSTR szGuid,
  2459. IN const GUID* pguid
  2460. )
  2461. {
  2462. WCHAR szGuid1[MAX_GUID_LEN + 1];
  2463. if (!StringFromGUID2(*pguid, szGuid1, MAX_GUID_LEN))
  2464. {
  2465. // consider it as szGuid is greater than pguid
  2466. return 1;
  2467. }
  2468. return lstrcmpi(szGuid, szGuid1);
  2469. }