Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1874 lines
51 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: S I P C F G . C P P
  7. //
  8. // Contents: The rendering of the UI for the network status monitor's state
  9. // page. Most of them are ipconfig info
  10. //
  11. // Notes:
  12. //
  13. // Author: NSun Dec 2000
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "pch.h"
  17. #pragma hdrstop
  18. #include "sminc.h"
  19. #include "smpsh.h"
  20. #include "smhelp.h"
  21. #include "ncui.h"
  22. #include "ncreg.h"
  23. #include "ncperms.h"
  24. #include "windutil.h"
  25. extern "C"
  26. {
  27. #include <dhcpcapi.h>
  28. extern DWORD DhcpStaticRefreshParams(IN LPWSTR Adapter);
  29. }
  30. #include <dnsapi.h>
  31. #include <nbtioctl.h>
  32. #include "..\lanui\lanui.h"
  33. #include "repair.h"
  34. #define LOCAL_WINS_ADDRESS 0x7f000000 // 127.0.0.0
  35. DWORD WINAPI IPAddrListenProc(
  36. LPVOID lpParameter // thread data
  37. );
  38. DWORD WINAPI IPAddrListenProc(
  39. LPVOID lpParameter // thread data
  40. );
  41. void DwordToIPAddrString(DWORD dw, tstring * pstr);
  42. const WCHAR c_szTcpipInterfaces[] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
  43. const WCHAR c_szAddressType[] = L"AddressType";
  44. const WCHAR c_szActiveConfigurations[] = L"ActiveConfigurations";
  45. const WCHAR c_szAlternate[] = L"Alternate_";
  46. const WCHAR c_szNameServer[] = L"NameServer";
  47. const WCHAR c_szDhcpNameServer[] = L"DhcpNameServer";
  48. const WCHAR c_szNbtDevicePrefix[] = L"\\Device\\NetBT_Tcpip_";
  49. ////////////////////////////////////////////////////////////////////////////////////////
  50. // Implementation CPspStatusMonitorIpcfg
  51. //
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Member: CPspStatusMonitorIpcfg::~CPspStatusMonitorIpcfg(
  55. //
  56. // Purpose: constructor
  57. //
  58. CPspStatusMonitorIpcfg::CPspStatusMonitorIpcfg(VOID) :
  59. m_adwHelpIDs(NULL),
  60. m_ncmType(NCM_NONE),
  61. m_pConn(NULL),
  62. m_fDhcp(TRUE),
  63. m_dhcpAddrType(NORMAL_ADDR),
  64. m_fListenAddrChange(FALSE),
  65. m_fEnableOpButtons(TRUE),
  66. m_fIsFirstPage(FALSE)
  67. {
  68. TraceFileFunc(ttidStatMon);
  69. ZeroMemory(&m_guidConnection, sizeof(m_guidConnection));
  70. //Create events that are used to control the thread listening to
  71. //address change notifications
  72. m_hEventAddrListenThreadStopCommand = CreateEvent(NULL, TRUE, FALSE, NULL);
  73. m_hEventAddrListenThreadStopNotify = CreateEvent(NULL, TRUE, FALSE, NULL);
  74. }
  75. //+---------------------------------------------------------------------------
  76. //
  77. // Member: CPspStatusMonitorIpcfg::~CPspStatusMonitorIpcfg(
  78. //
  79. // Purpose: destructor
  80. //
  81. CPspStatusMonitorIpcfg::~CPspStatusMonitorIpcfg(VOID)
  82. {
  83. if (m_hEventAddrListenThreadStopCommand)
  84. {
  85. CloseHandle(m_hEventAddrListenThreadStopCommand);
  86. }
  87. if (m_hEventAddrListenThreadStopNotify)
  88. {
  89. CloseHandle(m_hEventAddrListenThreadStopNotify);
  90. }
  91. CleanupPage();
  92. }
  93. //+---------------------------------------------------------------------------
  94. //
  95. // Member: CPspStatusMonitorIpcfg::HrInitPage
  96. //
  97. // Purpose: Initialize the Network State page class before the page has been
  98. // created
  99. //
  100. // Arguments: pnConnection - The connection associated with this monitor
  101. // dwHelpIDs - The context sensitive help ID array
  102. //
  103. // Returns: Error code
  104. //
  105. HRESULT CPspStatusMonitorIpcfg::HrInitPage(
  106. INetConnection * pnConnection,
  107. const DWORD * adwHelpIDs)
  108. {
  109. TraceFileFunc(ttidStatMon);
  110. HRESULT hr = S_OK;
  111. Assert(pnConnection);
  112. m_adwHelpIDs = adwHelpIDs;
  113. NETCON_PROPERTIES* pProps;
  114. hr = pnConnection->GetProperties(&pProps);
  115. if (SUCCEEDED(hr))
  116. {
  117. m_strConnectionName = pProps->pszwName;
  118. m_guidConnection = pProps->guidId;
  119. m_ncmType = pProps->MediaType;
  120. m_dlgAdvanced.InitDialog(m_guidConnection,
  121. g_aHelpIDs_IDD_DIALOG_ADV_IPCFG);
  122. FreeNetconProperties(pProps);
  123. if (m_pConn)
  124. {
  125. m_pConn->Release();
  126. }
  127. m_pConn = pnConnection;
  128. ::AddRefObj(m_pConn);
  129. }
  130. return hr;
  131. }
  132. //+---------------------------------------------------------------------------
  133. //
  134. // Member: CPspStatusMonitorIpcfg::CleanupPage
  135. //
  136. // Purpose: Cleanup the INetConnection ref count we are holding
  137. //
  138. // Arguments: pnConnection - The connection associated with this monitor
  139. // dwHelpIDs - The context sensitive help ID array
  140. //
  141. // Returns: Error code
  142. //
  143. VOID CPspStatusMonitorIpcfg::CleanupPage()
  144. {
  145. TraceFileFunc(ttidStatMon);
  146. if (m_pConn)
  147. {
  148. m_pConn->Release();
  149. m_pConn = NULL;
  150. }
  151. }
  152. //+---------------------------------------------------------------------------
  153. //
  154. // Member: CPspStatusMonitorIpcfg::OnInitDialog
  155. //
  156. // Purpose: Do the initialization required when the page has just been created
  157. //
  158. // Arguments: Standard window messsage parameters
  159. //
  160. // Returns: Standard window message return value
  161. //
  162. LRESULT CPspStatusMonitorIpcfg::OnInitDialog(
  163. UINT uMsg,
  164. WPARAM wParam,
  165. LPARAM lParam,
  166. BOOL & bHandled)
  167. {
  168. TraceFileFunc(ttidStatMon);
  169. m_fEnableOpButtons = FHasPermission(NCPERM_Repair);
  170. if (m_fIsFirstPage)
  171. {
  172. // get window handle to propertysheet
  173. HWND hwndParent=GetParent();
  174. Assert(hwndParent);
  175. // center the property sheet on desktop
  176. FCenterWindow (hwndParent, NULL);
  177. // hide the "ok" button
  178. //
  179. ::ShowWindow(::GetDlgItem(hwndParent, IDOK), FALSE);
  180. }
  181. //The initialization is in the OnActive method so that we will update the UI
  182. //when the user active this page
  183. return 0;
  184. }
  185. //+---------------------------------------------------------------------------
  186. //
  187. // Member: CPspStatusMonitorIpcfg::OnActive
  188. //
  189. // Purpose: Refresh the UI and start listening to the address change notification
  190. // when the page has just been created
  191. //
  192. // Arguments: Standard window messsage parameters
  193. //
  194. // Returns: Standard window message return value
  195. //
  196. LRESULT CPspStatusMonitorIpcfg::OnActive(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
  197. {
  198. TraceFileFunc(ttidStatMon);
  199. RefreshUI();
  200. if (m_hEventAddrListenThreadStopCommand && m_hEventAddrListenThreadStopNotify)
  201. {
  202. ResetEvent(m_hEventAddrListenThreadStopCommand);
  203. ResetEvent(m_hEventAddrListenThreadStopNotify);
  204. QueueUserWorkItem(IPAddrListenProc, this, WT_EXECUTELONGFUNCTION);
  205. m_fListenAddrChange = TRUE;
  206. }
  207. return 0;
  208. }
  209. //+---------------------------------------------------------------------------
  210. //
  211. // Member: CPspStatusMonitorIpcfg::OnKillActive
  212. //
  213. // Purpose: Do the operation required when the page is no longer the active one
  214. //
  215. // Arguments: Standard window messsage parameters
  216. //
  217. // Returns: Standard window message return value
  218. //
  219. LRESULT CPspStatusMonitorIpcfg::OnKillActive(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
  220. {
  221. TraceFileFunc(ttidStatMon);
  222. //If the advanced dialog is there, we need to close it
  223. //This happens when the connection is disabled or media disconnected when
  224. //we still have the connection status dialog open.
  225. HWND hwndAdv = m_dlgAdvanced.m_hWnd;
  226. if (hwndAdv)
  227. {
  228. ::SendMessage(hwndAdv, WM_CLOSE, 0, 0);
  229. }
  230. //Stop listening to the address change
  231. if (m_fListenAddrChange)
  232. {
  233. StopAddressListenThread();
  234. m_fListenAddrChange = FALSE;
  235. }
  236. return 0;
  237. }
  238. //+---------------------------------------------------------------------------
  239. //
  240. // Member: CPspStatusMonitorIpcfg::OnDestroy
  241. //
  242. // Purpose: Do the operation required when the page is destroyed.
  243. //
  244. // Arguments: Standard window messsage parameters
  245. //
  246. // Returns: Standard window message return value
  247. //
  248. LRESULT CPspStatusMonitorIpcfg::OnDestroy(
  249. UINT uMsg,
  250. WPARAM wParam,
  251. LPARAM lParam,
  252. BOOL& bHandled)
  253. {
  254. TraceFileFunc(ttidStatMon);
  255. //If the advanced dialog is there, we need to close it
  256. //This happens when the connection is disabled or media disconnected when
  257. //we still have the connection status dialog open.
  258. HWND hwndAdv = m_dlgAdvanced.m_hWnd;
  259. if (hwndAdv)
  260. {
  261. ::SendMessage(hwndAdv, WM_CLOSE, 0, 0);
  262. }
  263. //Stop listening to the address change
  264. if (m_fListenAddrChange)
  265. {
  266. StopAddressListenThread();
  267. m_fListenAddrChange = FALSE;
  268. }
  269. CleanupPage();
  270. return 0;
  271. }
  272. //+---------------------------------------------------------------------------
  273. //
  274. // Member: CPspStatusMonitorIpcfg::OnUpdateDisplay
  275. //
  276. // Purpose: Handling the user defined PWM_UPDATE_IPCFG_DISPLAY message
  277. //
  278. // Arguments: Standard window messsage parameters
  279. //
  280. // Returns: Standard window message return value
  281. //
  282. LRESULT CPspStatusMonitorIpcfg::OnUpdateDisplay(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  283. {
  284. TraceFileFunc(ttidStatMon);
  285. //The thread listening to address changes will post a PWM_UPDATE_IPCFG_DISPLAY
  286. //message to us once the IP address is changed.
  287. //We need refresh the UI.
  288. RefreshUI();
  289. return 0;
  290. }
  291. //+---------------------------------------------------------------------------
  292. //
  293. // Member: CPspStatusMonitorIpcfg::OnRepair
  294. //
  295. // Purpose: Repair the connection if the "Repair" button is pressed
  296. //
  297. // Arguments: Standard window messsage parameters
  298. //
  299. // Returns: Standard window message return value
  300. //
  301. LRESULT CPspStatusMonitorIpcfg::OnRepair(
  302. WORD wNotifyCode,
  303. WORD wID,
  304. HWND hWndCtl,
  305. BOOL& fHandled)
  306. {
  307. TraceFileFunc(ttidStatMon);
  308. tstring strMessage = L"";
  309. HRESULT hr = S_OK;
  310. HWND hwndPsh = GetParent();
  311. Assert(hwndPsh);
  312. {
  313. CWaitCursor cursorWait;
  314. CLanConnectionUiDlg dlg;
  315. HWND hwndDlg = NULL;
  316. //bring up the dialog to tell the user we're doing the fix
  317. Assert(m_pConn);
  318. if (m_pConn)
  319. {
  320. dlg.SetConnection(m_pConn);
  321. hwndDlg = dlg.Create(hwndPsh);
  322. PCWSTR szw = SzLoadIds(IDS_FIX_REPAIRING);
  323. ::SetDlgItemText(hwndDlg, IDC_TXT_Caption, szw);
  324. }
  325. //do the fix
  326. hr = HrTryToFix(m_guidConnection, strMessage);
  327. if (NULL != hwndDlg)
  328. {
  329. ::DestroyWindow(hwndDlg);
  330. }
  331. }
  332. //tell users the results
  333. NcMsgBox(_Module.GetResourceInstance(),
  334. hwndPsh,
  335. IDS_FIX_CAPTION,
  336. IDS_FIX_MESSAGE,
  337. MB_OK,
  338. strMessage.c_str());
  339. //We may get new settings. So need to refresh the UI.
  340. RefreshUI();
  341. return 0;
  342. }
  343. //+---------------------------------------------------------------------------
  344. //
  345. // Member: CPspStatusMonitorIpcfg::OnDetails
  346. //
  347. // Purpose: Open the Advanced Ipconfig dialog if the "Advanced" button is pressed
  348. //
  349. // Arguments: Standard window messsage parameters
  350. //
  351. // Returns: Standard window message return value
  352. //
  353. LRESULT CPspStatusMonitorIpcfg::OnDetails(
  354. WORD wNotifyCode,
  355. WORD wID,
  356. HWND hWndCtl,
  357. BOOL& fHandled)
  358. {
  359. TraceFileFunc(ttidStatMon);
  360. //Since the status dialog will be automatically closed if the connection becomes
  361. //disconnected or disabled, we also need to force the Advanced dialog to close in
  362. //such case.
  363. //So We cannot launch the Advanced dialog as a modal dialog. Instead, we launch the
  364. //dialog in another thread.
  365. QueueUserWorkItem(AdvIpCfgProc, this, WT_EXECUTEDEFAULT);
  366. return 0;
  367. }
  368. //+---------------------------------------------------------------------------
  369. //
  370. // Member: CPspStatusMonitorIpcfg::OnContextMenu
  371. //
  372. // Purpose: When right click a control, bring up help
  373. //
  374. // Arguments: Standard command parameters
  375. //
  376. // Returns: Standard return
  377. //
  378. LRESULT
  379. CPspStatusMonitorIpcfg::OnContextMenu(UINT uMsg,
  380. WPARAM wParam,
  381. LPARAM lParam,
  382. BOOL& fHandled)
  383. {
  384. TraceFileFunc(ttidStatMon);
  385. if (m_adwHelpIDs != NULL)
  386. {
  387. ::WinHelp(m_hWnd,
  388. c_szNetCfgHelpFile,
  389. HELP_CONTEXTMENU,
  390. (ULONG_PTR)m_adwHelpIDs);
  391. }
  392. return 0;
  393. }
  394. //+---------------------------------------------------------------------------
  395. //
  396. // Member: CPspStatusMonitorIpcfg::OnHelp
  397. //
  398. // Purpose: When drag context help icon over a control, bring up help
  399. //
  400. // Arguments: Standard command parameters
  401. //
  402. // Returns: Standard return
  403. //
  404. LRESULT
  405. CPspStatusMonitorIpcfg::OnHelp(UINT uMsg,
  406. WPARAM wParam,
  407. LPARAM lParam,
  408. BOOL& fHandled)
  409. {
  410. TraceFileFunc(ttidStatMon);
  411. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  412. Assert(lphi);
  413. if ((m_adwHelpIDs != NULL) && (HELPINFO_WINDOW == lphi->iContextType))
  414. {
  415. ::WinHelp(static_cast<HWND>(lphi->hItemHandle),
  416. c_szNetCfgHelpFile,
  417. HELP_WM_HELP,
  418. (ULONG_PTR)m_adwHelpIDs);
  419. }
  420. return 0;
  421. }
  422. //+---------------------------------------------------------------------------
  423. //
  424. // Member: CPspStatusMonitorIpcfg::InitializeData
  425. //
  426. // Purpose: Cleanup the saved IP settings
  427. //
  428. // Arguments: None
  429. //
  430. // Returns: None
  431. //
  432. VOID CPspStatusMonitorIpcfg::InitializeData()
  433. {
  434. TraceFileFunc(ttidStatMon);
  435. m_strIPAddress = L"";
  436. m_strSubnetMask = L"";
  437. m_strGateway = L"";
  438. m_fDhcp = TRUE;
  439. }
  440. //+---------------------------------------------------------------------------
  441. //
  442. // Member: CPspStatusMonitorIpcfg::StopAddressListenThread
  443. //
  444. // Purpose: Stop the thread that listens to address changes
  445. //
  446. // Arguments: None
  447. //
  448. // Returns: None
  449. //
  450. VOID CPspStatusMonitorIpcfg::StopAddressListenThread()
  451. {
  452. TraceFileFunc(ttidStatMon);
  453. if (m_hEventAddrListenThreadStopCommand &&
  454. m_hEventAddrListenThreadStopNotify)
  455. {
  456. Assert(m_hEventAddrListenThreadStopNotify);
  457. SetEvent(m_hEventAddrListenThreadStopCommand);
  458. WaitForSingleObject(m_hEventAddrListenThreadStopNotify, 5000);
  459. }
  460. }
  461. //+---------------------------------------------------------------------------
  462. //
  463. // Member: CPspStatusMonitorIpcfg::GetIPConfigInfo
  464. //
  465. // Purpose: Load the TCP/IP running settings of this connection
  466. //
  467. // Arguments: None
  468. //
  469. // Returns: error code
  470. //
  471. HRESULT CPspStatusMonitorIpcfg::GetIPConfigInfo()
  472. {
  473. TraceFileFunc(ttidStatMon);
  474. HRESULT hr = S_OK;
  475. PIP_ADAPTER_INFO pAdapterInfo = NULL;
  476. DWORD dwOutBufLen = 0;
  477. DWORD dwRet = ERROR_SUCCESS;
  478. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  479. if (dwRet == ERROR_BUFFER_OVERFLOW)
  480. {
  481. pAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc(dwOutBufLen);
  482. if (NULL == pAdapterInfo)
  483. return E_OUTOFMEMORY;
  484. }
  485. else if (ERROR_SUCCESS == dwRet)
  486. {
  487. return E_FAIL;
  488. }
  489. else
  490. {
  491. return HRESULT_FROM_WIN32(dwRet);
  492. }
  493. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  494. if (ERROR_SUCCESS != dwRet)
  495. {
  496. CoTaskMemFree(pAdapterInfo);
  497. return HRESULT_FROM_WIN32(dwRet);
  498. }
  499. WCHAR wszGuid[c_cchGuidWithTerm];
  500. ::StringFromGUID2(m_guidConnection, wszGuid,
  501. c_cchGuidWithTerm);
  502. BOOL fFound = FALSE;
  503. PIP_ADAPTER_INFO pAdapterInfoEnum = pAdapterInfo;
  504. while (pAdapterInfoEnum)
  505. {
  506. USES_CONVERSION;
  507. if (lstrcmp(wszGuid, A2W(pAdapterInfoEnum->AdapterName)) == 0)
  508. {
  509. m_strIPAddress = A2W(pAdapterInfoEnum->IpAddressList.IpAddress.String);
  510. m_strSubnetMask = A2W(pAdapterInfoEnum->IpAddressList.IpMask.String);
  511. m_strGateway = A2W(pAdapterInfoEnum->GatewayList.IpAddress.String);
  512. m_fDhcp = pAdapterInfoEnum->DhcpEnabled;
  513. fFound = TRUE;
  514. break;
  515. }
  516. pAdapterInfoEnum = pAdapterInfoEnum->Next;
  517. }
  518. CoTaskMemFree(pAdapterInfo);
  519. if (!fFound)
  520. {
  521. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  522. }
  523. else
  524. {
  525. if (m_fDhcp)
  526. {
  527. hr = HrGetAutoNetSetting(wszGuid, &m_dhcpAddrType);
  528. }
  529. }
  530. return hr;
  531. }
  532. //+---------------------------------------------------------------------------
  533. //
  534. // Member: CPspStatusMonitorIpcfg::RefreshUI
  535. //
  536. // Purpose: refresh the UI
  537. //
  538. // Arguments: none
  539. //
  540. // Returns: none
  541. //
  542. VOID CPspStatusMonitorIpcfg::RefreshUI()
  543. {
  544. TraceFileFunc(ttidStatMon);
  545. HRESULT hr = S_OK;
  546. BOOL fZeroIP = FALSE;
  547. InitializeData();
  548. hr = GetIPConfigInfo();
  549. if (FAILED(hr))
  550. {
  551. ::SetWindowText(GetDlgItem(IDC_STATE_SOURCE), SzLoadString(_Module.GetResourceInstance(), IDS_ADDRESS_UNAVALABLE));
  552. ::SetWindowText(GetDlgItem(IDC_STATE_IPADDR), SzLoadString(_Module.GetResourceInstance(), IDS_ADDRESS_UNAVALABLE));
  553. ::SetWindowText(GetDlgItem(IDC_STATE_SUBNET), SzLoadString(_Module.GetResourceInstance(), IDS_ADDRESS_UNAVALABLE));
  554. ::SetWindowText(GetDlgItem(IDC_STATE_GATEWAY), SzLoadString(_Module.GetResourceInstance(), IDS_ADDRESS_UNAVALABLE));
  555. ::EnableWindow(GetDlgItem(IDC_STATE_BTN_REPAIR), FALSE);
  556. ::EnableWindow(GetDlgItem(IDC_STATE_BTN_DETAIL), FALSE);
  557. return;
  558. }
  559. else
  560. {
  561. ::EnableWindow(GetDlgItem(IDC_STATE_BTN_REPAIR), TRUE);
  562. ::EnableWindow(GetDlgItem(IDC_STATE_BTN_DETAIL), TRUE);
  563. }
  564. fZeroIP = (m_strIPAddress == L"0.0.0.0");
  565. ::SetWindowText(GetDlgItem(IDC_STATE_IPADDR), m_strIPAddress.c_str());
  566. ::SetWindowText(GetDlgItem(IDC_STATE_SUBNET), m_strSubnetMask.c_str());
  567. ::SetWindowText(GetDlgItem(IDC_STATE_GATEWAY), m_strGateway.c_str());
  568. if (!m_fDhcp)
  569. {
  570. ::SetWindowText(GetDlgItem(IDC_STATE_SOURCE),
  571. SzLoadString(_Module.GetResourceInstance(), IDS_STATIC_CFG));
  572. }
  573. else
  574. {
  575. UINT idString = IDS_DHCP;
  576. switch(m_dhcpAddrType)
  577. {
  578. case NORMAL_ADDR:
  579. idString = IDS_DHCP;
  580. break;
  581. case AUTONET_ADDR:
  582. idString = IDS_AUTONET;
  583. break;
  584. case ALTERNATE_ADDR:
  585. idString = IDS_ALTERNATE_ADDR;
  586. break;
  587. }
  588. ::SetWindowText(GetDlgItem(IDC_STATE_SOURCE),
  589. SzLoadString(_Module.GetResourceInstance(), idString));
  590. }
  591. if (fZeroIP)
  592. {
  593. ::SetWindowText(GetDlgItem(IDC_STATE_SOURCE),
  594. SzLoadString(_Module.GetResourceInstance(), IDS_INVALID_ADDR));
  595. }
  596. if (!m_fEnableOpButtons)
  597. {
  598. ::EnableWindow(GetDlgItem(IDC_STATE_BTN_REPAIR), FALSE);
  599. }
  600. }
  601. //+---------------------------------------------------------------------------
  602. //
  603. // Member: CPspStatusMonitorIpcfg::IPAddrListenProc
  604. //
  605. // Purpose: the call back proc to launch the thead to listen to address changes
  606. //
  607. // Arguments: lpParameter - the CPspStatusMonitroIpcfg instance
  608. //
  609. // Returns: 0
  610. //
  611. DWORD WINAPI CPspStatusMonitorIpcfg::IPAddrListenProc(
  612. LPVOID lpParameter // thread data
  613. )
  614. {
  615. TraceFileFunc(ttidStatMon);
  616. HANDLE hEvents[2];
  617. OVERLAPPED NotifyAddrOverLapped;
  618. HANDLE hNotifyAddr = NULL;
  619. DWORD dwRet = 0;
  620. CPspStatusMonitorIpcfg * pDialog = (CPspStatusMonitorIpcfg*) lpParameter;
  621. hEvents[0] = pDialog->m_hEventAddrListenThreadStopCommand;
  622. ZeroMemory(&NotifyAddrOverLapped, sizeof(OVERLAPPED));
  623. NotifyAddrOverLapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  624. if (NotifyAddrOverLapped.hEvent)
  625. {
  626. if (ERROR_IO_PENDING == NotifyAddrChange(&hNotifyAddr, &NotifyAddrOverLapped))
  627. {
  628. hEvents[1] = NotifyAddrOverLapped.hEvent;
  629. do
  630. {
  631. dwRet = WaitForMultipleObjects(
  632. celems(hEvents),
  633. hEvents,
  634. FALSE,
  635. INFINITE);
  636. if (WAIT_OBJECT_0 + 1 == dwRet)
  637. {
  638. ResetEvent(hEvents[1]);
  639. ::PostMessage(pDialog->m_hWnd, PWM_UPDATE_IPCFG_DISPLAY, 0, 0);
  640. HWND hwndAdv = pDialog->m_dlgAdvanced.m_hWnd;
  641. if (hwndAdv)
  642. {
  643. ::PostMessage(hwndAdv, PWM_UPDATE_IPCFG_DISPLAY, 0, 0);
  644. }
  645. hNotifyAddr = NULL;
  646. if (ERROR_IO_PENDING != NotifyAddrChange(&hNotifyAddr, &NotifyAddrOverLapped))
  647. {
  648. TraceTag(ttidStatMon, "Could not register for IP address change notifications");
  649. break;
  650. }
  651. }
  652. else
  653. {
  654. break;
  655. }
  656. }while (TRUE);
  657. }
  658. else
  659. {
  660. TraceTag(ttidStatMon, "Could not register for IP address change notifications");
  661. }
  662. }
  663. if (hNotifyAddr)
  664. {
  665. CancelIo(hNotifyAddr);
  666. }
  667. SetEvent(pDialog->m_hEventAddrListenThreadStopNotify);
  668. return 0;
  669. }
  670. //+---------------------------------------------------------------------------
  671. //
  672. // Member: CPspStatusMonitorIpcfg::AdvIpCfgProc
  673. //
  674. // Purpose: the call back proc to launch the advanced dialog in another thread
  675. //
  676. // Arguments: lpParameter - the CPspStatusMonitroIpcfg instance
  677. //
  678. // Returns: 0
  679. //
  680. DWORD WINAPI CPspStatusMonitorIpcfg::AdvIpCfgProc(
  681. LPVOID lpParameter // thread data
  682. )
  683. {
  684. TraceFileFunc(ttidStatMon);
  685. CPspStatusMonitorIpcfg * pMainDialog = (CPspStatusMonitorIpcfg*) lpParameter;
  686. Assert(pMainDialog);
  687. //disable the status propsheet
  688. HWND hwndPsh = pMainDialog->GetParent();
  689. Assert(hwndPsh);
  690. pMainDialog->m_dlgAdvanced.DoModal(hwndPsh);
  691. return 0;
  692. }
  693. ///////////////////////////////////////////////////////////////////////
  694. // Implementation of CAdvIpcfgDlg
  695. //
  696. //+---------------------------------------------------------------------------
  697. //
  698. // Member: CAdvIpcfgDlg::CAdvIpcfgDlg
  699. //
  700. // Purpose: constructor
  701. //
  702. CAdvIpcfgDlg::CAdvIpcfgDlg() :
  703. m_hList(NULL),
  704. m_adwHelpIDs(NULL)
  705. {
  706. TraceFileFunc(ttidStatMon);
  707. }
  708. //+---------------------------------------------------------------------------
  709. //
  710. // Member: CAdvIpcfgDlg::OnInitDialog
  711. //
  712. // Purpose: do the initialize required when the dialog is created
  713. //
  714. // Arguments: Standard window messsage parameters
  715. //
  716. // Returns: Standard window message return value
  717. //
  718. LRESULT CAdvIpcfgDlg::OnInitDialog(
  719. UINT uMsg,
  720. WPARAM wParam,
  721. LPARAM lParam,
  722. BOOL& fHandled
  723. )
  724. {
  725. TraceFileFunc(ttidStatMon);
  726. const UINT c_nColumns = 2;
  727. LV_COLUMN lvCol = {0};
  728. RECT rect;
  729. int iIndex = 0;
  730. int iParamColWidth = 0;
  731. m_hList = GetDlgItem(IDC_LIST_IPCFG);
  732. ::GetClientRect(m_hList, &rect);
  733. iParamColWidth = (rect.right/c_nColumns);
  734. lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT ;
  735. lvCol.fmt = LVCFMT_LEFT; // left-align column
  736. lvCol.cx = iParamColWidth;
  737. lvCol.pszText = (PWSTR) SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_PRAMETER);
  738. iIndex = ListView_InsertColumn(m_hList, iIndex, &lvCol);
  739. iIndex++;
  740. lvCol.cx = rect.right - iParamColWidth;
  741. lvCol.pszText = (PWSTR) SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_VALUE);
  742. iIndex = ListView_InsertColumn(m_hList, iIndex, &lvCol);
  743. ListView_SetExtendedListViewStyle(m_hList, LVS_EX_FULLROWSELECT);
  744. PopulateListControl();
  745. return 0;
  746. }
  747. VOID CAdvIpcfgDlg::AddToListControl(int iIndex, LPWSTR szFirst, LPWSTR szSecond)
  748. {
  749. TraceFileFunc(ttidStatMon);
  750. LV_ITEM lvi = {0};
  751. lvi.mask = LVIF_PARAM;
  752. lvi.lParam = 0;
  753. lvi.iItem = iIndex;
  754. ListView_InsertItem(m_hList, &lvi);
  755. ListView_SetItemText(m_hList,
  756. iIndex,
  757. 0,
  758. szFirst);
  759. ListView_SetItemText(m_hList,
  760. iIndex,
  761. 1,
  762. szSecond);
  763. }
  764. //+---------------------------------------------------------------------------
  765. //
  766. // Member: CAdvIpcfgDlg::PopulateListControl
  767. //
  768. // Purpose: load the connection running settings and show them up in
  769. // the list control
  770. //
  771. // Arguments: none
  772. //
  773. // Returns: error code
  774. //
  775. HRESULT CAdvIpcfgDlg::PopulateListControl()
  776. {
  777. TraceFileFunc(ttidStatMon);
  778. HRESULT hr = S_OK;
  779. PIP_ADAPTER_INFO pAdapterInfo = NULL;
  780. DWORD dwOutBufLen = 0;
  781. DWORD dwRet = ERROR_SUCCESS;
  782. tstring strDns = L"";
  783. WCHAR wszGuid[c_cchGuidWithTerm] = {0};
  784. tstring strTemp = L"";
  785. tstring strTemp2 = L"";
  786. BOOL fDisplayDhcpItems = TRUE;
  787. ListView_DeleteAllItems(m_hList);
  788. ::StringFromGUID2(m_guidConnection, wszGuid,
  789. c_cchGuidWithTerm);
  790. //Get other settings
  791. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  792. if (dwRet == ERROR_BUFFER_OVERFLOW)
  793. {
  794. pAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc(dwOutBufLen);
  795. if (NULL == pAdapterInfo)
  796. return E_OUTOFMEMORY;
  797. }
  798. else if (ERROR_SUCCESS == dwRet)
  799. {
  800. return E_FAIL;
  801. }
  802. else
  803. {
  804. return HRESULT_FROM_WIN32(dwRet);
  805. }
  806. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  807. if (ERROR_SUCCESS != dwRet)
  808. {
  809. CoTaskMemFree(pAdapterInfo);
  810. return HRESULT_FROM_WIN32(dwRet);
  811. }
  812. BOOL fFound = FALSE;
  813. PIP_ADAPTER_INFO pAdapterInfoEnum = pAdapterInfo;
  814. while (pAdapterInfoEnum)
  815. {
  816. USES_CONVERSION;
  817. if (lstrcmp(wszGuid, A2W(pAdapterInfoEnum->AdapterName)) == 0)
  818. {
  819. fFound = TRUE;
  820. break;
  821. }
  822. pAdapterInfoEnum = pAdapterInfoEnum->Next;
  823. }
  824. if (!fFound)
  825. {
  826. CoTaskMemFree(pAdapterInfo);
  827. return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  828. }
  829. int iTemp = 0;
  830. int iIndex = 0;
  831. struct tm * ptmLocalTime = NULL;
  832. WCHAR szBuf[8];
  833. fDisplayDhcpItems = !!pAdapterInfoEnum->DhcpEnabled;
  834. if (fDisplayDhcpItems)
  835. {
  836. DHCP_ADDRESS_TYPE AddrType;
  837. if (SUCCEEDED(HrGetAutoNetSetting(wszGuid, &AddrType)))
  838. {
  839. fDisplayDhcpItems = (AUTONET_ADDR != AddrType && ALTERNATE_ADDR != AddrType);
  840. }
  841. }
  842. LV_ITEM lvi = {0};
  843. lvi.mask = LVIF_PARAM;
  844. lvi.lParam = 0;
  845. //Physical Address
  846. strTemp = L"";
  847. for (UINT i = 0; i < pAdapterInfoEnum->AddressLength; i++)
  848. {
  849. if (i > 0)
  850. {
  851. strTemp += L"-";
  852. }
  853. wsprintf(szBuf, L"%02X", pAdapterInfoEnum->Address[i]);
  854. strTemp += szBuf;
  855. }
  856. AddToListControl(iIndex,
  857. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_PH_ADDR),
  858. (LPWSTR)strTemp.c_str());
  859. iIndex++;
  860. //IP Address and subnet mask
  861. iTemp = IPAddrToString(&pAdapterInfoEnum->IpAddressList, &strTemp, &strTemp2);
  862. //if the ip is zero, don't display DHCP items
  863. if (L"0.0.0.0" == strTemp)
  864. {
  865. fDisplayDhcpItems = FALSE;
  866. }
  867. iIndex += AddIPAddrToListControl(iIndex,
  868. &pAdapterInfoEnum->IpAddressList,
  869. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_IPADDR),
  870. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_SUBNET),
  871. TRUE
  872. );
  873. //Default Gateway
  874. iTemp = IPAddrToString(&pAdapterInfoEnum->GatewayList, &strTemp);
  875. iIndex += AddIPAddrToListControl(iIndex,
  876. &pAdapterInfoEnum->GatewayList,
  877. (LPWSTR)SzLoadString(_Module.GetResourceInstance(),
  878. (iTemp > 1) ? IDS_IPCFG_DEFGW_PL : IDS_IPCFG_DEFGW)
  879. );
  880. //Dhcp Server
  881. if (fDisplayDhcpItems)
  882. {
  883. IPAddrToString(&pAdapterInfoEnum->DhcpServer, &strTemp);
  884. AddToListControl(iIndex,
  885. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_DHCP),
  886. (LPWSTR)strTemp.c_str());
  887. iIndex++;
  888. }
  889. //Lease Obtain time
  890. if (fDisplayDhcpItems)
  891. {
  892. if (SUCCEEDED(FormatTime(pAdapterInfoEnum->LeaseObtained, strTemp)))
  893. {
  894. AddToListControl(iIndex,
  895. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_LEASE_OBT),
  896. (LPWSTR)strTemp.c_str());
  897. iIndex++;
  898. }
  899. //Lease expire time
  900. if (SUCCEEDED(FormatTime(pAdapterInfoEnum->LeaseExpires, strTemp)))
  901. {
  902. AddToListControl(iIndex,
  903. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_LEASE_EXP),
  904. (LPWSTR)strTemp.c_str());
  905. iIndex++;
  906. }
  907. }
  908. //Get the DNS servers
  909. HKEY hkeyInterface = NULL;
  910. tstring strInterfaceKey = c_szTcpipInterfaces;
  911. strInterfaceKey += wszGuid;
  912. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
  913. strInterfaceKey.c_str(),
  914. KEY_QUERY_VALUE,
  915. &hkeyInterface);
  916. if (SUCCEEDED(hr))
  917. {
  918. BOOL fStaticDns = TRUE;
  919. int iPos = 0;
  920. Assert(hkeyInterface);
  921. hr = HrRegQueryString(hkeyInterface,
  922. c_szNameServer,
  923. &strTemp);
  924. if (0 == strTemp.size() || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  925. {
  926. HrRegQueryString(hkeyInterface,
  927. c_szDhcpNameServer,
  928. &strTemp);
  929. fStaticDns = FALSE;
  930. }
  931. //the static DNS server list is in the format "x.x.x.x,y.y.y.y" and
  932. //the dhcp DNS server list is in the format "x.x.x.x y.y.y.y". We need to
  933. //re-format them to the same style
  934. //fFirst is used to identify whether this is the first DNS server
  935. int fFirst = TRUE;
  936. while(tstring::npos != (iPos = strTemp.find(fStaticDns ? L',' :L' ')))
  937. {
  938. strDns = strTemp.substr(0, iPos);
  939. strTemp = strTemp.erase(0, iPos + 1);
  940. AddToListControl(iIndex,
  941. fFirst ? (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_DNS_PL) : L"",
  942. (LPWSTR)strDns.c_str());;
  943. iIndex++;
  944. fFirst = FALSE;
  945. }
  946. strDns = strTemp;
  947. AddToListControl(iIndex,
  948. fFirst ? (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_DNS) : L"",
  949. (LPWSTR)strDns.c_str());;
  950. iIndex++;
  951. RegCloseKey(hkeyInterface);
  952. }
  953. iIndex += AddWinsServersToList(iIndex);
  954. if (pAdapterInfo)
  955. {
  956. CoTaskMemFree(pAdapterInfo);
  957. }
  958. return hr;
  959. }
  960. //+---------------------------------------------------------------------------
  961. //
  962. // Member: CAdvIpcfgDlg::OnClose
  963. //
  964. // Purpose: handle the WM_CLOSE message
  965. //
  966. // Arguments: Standard window messsage parameters
  967. //
  968. // Returns: Standard window message return value
  969. //
  970. LRESULT CAdvIpcfgDlg::OnClose(
  971. UINT uMsg,
  972. WPARAM wParam,
  973. LPARAM lParam,
  974. BOOL& fHandled
  975. )
  976. {
  977. TraceFileFunc(ttidStatMon);
  978. EndDialog(IDCANCEL);
  979. return 0;
  980. }
  981. //+---------------------------------------------------------------------------
  982. //
  983. // Member: CAdvIpcfgDlg::OnOk
  984. //
  985. // Purpose: close the dialog when the OK button is pressed
  986. //
  987. // Arguments: Standard window messsage parameters
  988. //
  989. // Returns: Standard window message return value
  990. //
  991. LRESULT CAdvIpcfgDlg::OnOk(
  992. WORD wNotifyCode,
  993. WORD wID,
  994. HWND hWndCtl,
  995. BOOL& fHandled
  996. )
  997. {
  998. TraceFileFunc(ttidStatMon);
  999. EndDialog(IDOK);
  1000. return 0;
  1001. }
  1002. LRESULT CAdvIpcfgDlg::OnCancel(
  1003. WORD wNotifyCode,
  1004. WORD wID,
  1005. HWND hWndCtl,
  1006. BOOL& fHandled
  1007. )
  1008. {
  1009. TraceFileFunc(ttidStatMon);
  1010. EndDialog(IDCANCEL);
  1011. return 0;
  1012. }
  1013. //+---------------------------------------------------------------------------
  1014. //
  1015. // Member: CAdvIpcfgDlg::OnUpdateDisplay
  1016. //
  1017. // Purpose: Handling the user defined PWM_UPDATE_IPCFG_DISPLAY message
  1018. //
  1019. // Arguments: Standard window messsage parameters
  1020. //
  1021. // Returns: Standard window message return value
  1022. //
  1023. LRESULT CAdvIpcfgDlg::OnUpdateDisplay(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1024. {
  1025. TraceFileFunc(ttidStatMon);
  1026. //The thread listening to address changes will post a PWM_UPDATE_IPCFG_DISPLAY
  1027. //message to us once the IP address is changed.
  1028. //We need refresh the UI.
  1029. PopulateListControl();
  1030. return 0;
  1031. }
  1032. //+---------------------------------------------------------------------------
  1033. //
  1034. // Member: CPspStatusMonitorIpcfg::OnContextMenu
  1035. //
  1036. // Purpose: When right click a control, bring up help
  1037. //
  1038. // Arguments: Standard command parameters
  1039. //
  1040. // Returns: Standard return
  1041. //
  1042. LRESULT
  1043. CAdvIpcfgDlg::OnContextMenu(UINT uMsg,
  1044. WPARAM wParam,
  1045. LPARAM lParam,
  1046. BOOL& fHandled)
  1047. {
  1048. TraceFileFunc(ttidStatMon);
  1049. if (m_adwHelpIDs != NULL)
  1050. {
  1051. ::WinHelp(m_hWnd,
  1052. c_szNetCfgHelpFile,
  1053. HELP_CONTEXTMENU,
  1054. (ULONG_PTR)m_adwHelpIDs);
  1055. }
  1056. return 0;
  1057. }
  1058. //+---------------------------------------------------------------------------
  1059. //
  1060. // Member: CPspStatusMonitorIpcfg::OnHelp
  1061. //
  1062. // Purpose: When drag context help icon over a control, bring up help
  1063. //
  1064. // Arguments: Standard command parameters
  1065. //
  1066. // Returns: Standard return
  1067. //
  1068. LRESULT
  1069. CAdvIpcfgDlg::OnHelp(UINT uMsg,
  1070. WPARAM wParam,
  1071. LPARAM lParam,
  1072. BOOL& fHandled)
  1073. {
  1074. TraceFileFunc(ttidStatMon);
  1075. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  1076. Assert(lphi);
  1077. if ((m_adwHelpIDs != NULL) && (HELPINFO_WINDOW == lphi->iContextType))
  1078. {
  1079. ::WinHelp(static_cast<HWND>(lphi->hItemHandle),
  1080. c_szNetCfgHelpFile,
  1081. HELP_WM_HELP,
  1082. (ULONG_PTR)m_adwHelpIDs);
  1083. }
  1084. return 0;
  1085. }
  1086. LRESULT
  1087. CAdvIpcfgDlg::OnListKeyDown(int idCtrl,
  1088. LPNMHDR pnmh,
  1089. BOOL& fHandled)
  1090. {
  1091. TraceFileFunc(ttidStatMon);
  1092. LPNMLVKEYDOWN pnmlv = (LPNMLVKEYDOWN) pnmh;
  1093. if (NULL == pnmlv)
  1094. return 0;
  1095. if (IDC_LIST_IPCFG != idCtrl)
  1096. return 0;
  1097. BOOL fControlDown = (GetKeyState(VK_CONTROL) < 0);
  1098. switch (pnmlv->wVKey)
  1099. {
  1100. case VK_INSERT:
  1101. case 'c':
  1102. case 'C':
  1103. CopyListToClipboard();
  1104. break;
  1105. }
  1106. return 0;
  1107. }
  1108. VOID CAdvIpcfgDlg::CopyListToClipboard()
  1109. {
  1110. TraceFileFunc(ttidStatMon);
  1111. WCHAR szBuff[256] = {0};
  1112. int iIndex = -1;
  1113. tstring str = L"";
  1114. BOOL fFirst = TRUE;
  1115. while(-1 != (iIndex = ListView_GetNextItem(m_hList, iIndex, LVNI_ALL)))
  1116. {
  1117. szBuff[0] = 0;
  1118. ListView_GetItemText(m_hList, iIndex, 0, szBuff, celems(szBuff) - 1);
  1119. if (0 == lstrlen(szBuff))
  1120. {
  1121. str += L", ";
  1122. }
  1123. else
  1124. {
  1125. if (!fFirst)
  1126. {
  1127. str += L"\r\n";
  1128. }
  1129. else
  1130. {
  1131. fFirst = FALSE;
  1132. }
  1133. str += szBuff;
  1134. str += L": ";
  1135. }
  1136. szBuff[0] = 0;
  1137. ListView_GetItemText(m_hList, iIndex, 1, szBuff, celems(szBuff) -1);
  1138. str += szBuff;
  1139. }
  1140. int nLength = str.length() + 1;
  1141. nLength *= sizeof(WCHAR);
  1142. HLOCAL hMem = LocalAlloc(LPTR, nLength);
  1143. if (hMem)
  1144. {
  1145. memcpy(hMem, str.c_str(), nLength);
  1146. if (!OpenClipboard())
  1147. {
  1148. LocalFree(hMem);
  1149. }
  1150. else
  1151. {
  1152. EmptyClipboard();
  1153. SetClipboardData(CF_UNICODETEXT, hMem);
  1154. CloseClipboard();
  1155. }
  1156. }
  1157. }
  1158. //+---------------------------------------------------------------------------
  1159. //
  1160. // Member: CAdvIpcfgDlg::AddIPAddrToListControl
  1161. //
  1162. // Purpose: helper routine to add a list of IP address/mask pairs to the list control
  1163. //
  1164. // Arguments: iStartIndex [in] the starting index of the list control
  1165. // pszAddrDescription [in] the description of the address
  1166. // pszMaskDescription [in] the description of the mask, this can be null
  1167. // fShowDescriptionForMutliple [in] whether show the description for each entry if we have multiple entris
  1168. // pAddrList [in] the address/mask pair list
  1169. //
  1170. // Returns: number of IP addresses in the string
  1171. //
  1172. int CAdvIpcfgDlg::AddIPAddrToListControl(int iStartIndex,
  1173. PIP_ADDR_STRING pAddrList,
  1174. LPWSTR pszAddrDescription,
  1175. LPWSTR pszMaskDescription,
  1176. BOOL fShowDescriptionForMutliple
  1177. )
  1178. {
  1179. TraceFileFunc(ttidStatMon);
  1180. Assert(pAddrList);
  1181. Assert(pszAddrDescription);
  1182. if (NULL == pAddrList || NULL == pszAddrDescription)
  1183. return 0;
  1184. tstring strTmp = L"";
  1185. BOOL fFirst = TRUE;
  1186. int iIndex = iStartIndex;
  1187. PIP_ADDR_STRING pCurrentAddr = NULL;
  1188. for (pCurrentAddr = pAddrList; NULL != pCurrentAddr; pCurrentAddr = pCurrentAddr->Next)
  1189. {
  1190. USES_CONVERSION;
  1191. strTmp = A2W(pCurrentAddr->IpAddress.String);
  1192. AddToListControl(iIndex,
  1193. (fFirst || fShowDescriptionForMutliple) ? pszAddrDescription : L"",
  1194. (LPWSTR) strTmp.c_str());
  1195. iIndex++;
  1196. if (pszMaskDescription)
  1197. {
  1198. strTmp = A2W(pCurrentAddr->IpMask.String);
  1199. AddToListControl(iIndex,
  1200. (fFirst || fShowDescriptionForMutliple) ? pszMaskDescription : L"",
  1201. (LPWSTR) strTmp.c_str());
  1202. iIndex++;
  1203. }
  1204. if (fFirst)
  1205. {
  1206. fFirst = FALSE;
  1207. }
  1208. }
  1209. return iIndex - iStartIndex;
  1210. }
  1211. //+---------------------------------------------------------------------------
  1212. //
  1213. // Member: CAdvIpcfgDlg::IPAddrToString
  1214. //
  1215. // Purpose: helper routine to convert IP_ADDR_STRING to a string
  1216. //
  1217. // Arguments: pAddrList - the IP_ADDR_STRING
  1218. // pstrAddr [out] the string contains the IP address
  1219. // pstrMask [out] the string contains the Mask
  1220. //
  1221. // Returns: number of IP addresses in the string
  1222. //
  1223. int CAdvIpcfgDlg::IPAddrToString(
  1224. PIP_ADDR_STRING pAddrList,
  1225. tstring * pstrAddr,
  1226. tstring * pstrMask
  1227. )
  1228. {
  1229. TraceFileFunc(ttidStatMon);
  1230. int i = 0;
  1231. PIP_ADDR_STRING pCurrentAddr = NULL;
  1232. if (pstrAddr)
  1233. {
  1234. *pstrAddr = L"";
  1235. }
  1236. if (pstrMask)
  1237. {
  1238. *pstrMask = L"";
  1239. }
  1240. for (pCurrentAddr = pAddrList; NULL != pCurrentAddr; pCurrentAddr = pCurrentAddr->Next)
  1241. {
  1242. USES_CONVERSION;
  1243. if (pstrAddr)
  1244. {
  1245. if (0 != i)
  1246. {
  1247. (*pstrAddr) += L", ";
  1248. }
  1249. (*pstrAddr) += A2W(pCurrentAddr->IpAddress.String);
  1250. }
  1251. if (pstrMask)
  1252. {
  1253. if (0 != i)
  1254. {
  1255. (*pstrMask) += L", ";
  1256. }
  1257. (*pstrMask) += A2W(pCurrentAddr->IpMask.String);
  1258. }
  1259. i++;
  1260. }
  1261. return i;
  1262. }
  1263. //+---------------------------------------------------------------------------
  1264. //
  1265. // Member: CAdvIpcfgDlg::AddWinsServersToList
  1266. //
  1267. // Purpose: Get the list of WINS servers from the NBT driver and add them
  1268. // into the list control
  1269. //
  1270. // Arguments: iStartIndex [in] - the starting index of the list control
  1271. // that we should use to add the WINS servers
  1272. //
  1273. // Returns: number of entris added to the list control
  1274. //
  1275. int CAdvIpcfgDlg::AddWinsServersToList(int iStartIndex)
  1276. {
  1277. TraceFileFunc(ttidStatMon);
  1278. int iIndex = iStartIndex;
  1279. WCHAR wszGuid[c_cchGuidWithTerm] = {0};
  1280. ::StringFromGUID2(m_guidConnection, wszGuid,
  1281. c_cchGuidWithTerm);
  1282. HANDLE hNbt = INVALID_HANDLE_VALUE;
  1283. tWINS_NODE_INFO NodeInfo = {0};
  1284. int nCount = 0;
  1285. tstring strTemp = L"";
  1286. if (FAILED(OpenNbt(wszGuid, &hNbt)))
  1287. {
  1288. AddToListControl(iStartIndex,
  1289. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_WINS),
  1290. (LPWSTR)L"");
  1291. return 1;
  1292. }
  1293. do
  1294. {
  1295. NTSTATUS status = 0;
  1296. DWORD dwSize = 0;
  1297. if (!DeviceIoControl(hNbt,
  1298. IOCTL_NETBT_GET_WINS_ADDR,
  1299. NULL,
  1300. 0,
  1301. (LPVOID)&NodeInfo,
  1302. sizeof(NodeInfo),
  1303. &dwSize,
  1304. NULL))
  1305. {
  1306. break;
  1307. }
  1308. if( LOCAL_WINS_ADDRESS == NodeInfo.NameServerAddress ||
  1309. INADDR_ANY == NodeInfo.NameServerAddress ||
  1310. INADDR_BROADCAST == NodeInfo.NameServerAddress )
  1311. {
  1312. break;
  1313. }
  1314. BOOL fHaveSecondWins = !(LOCAL_WINS_ADDRESS == NodeInfo.BackupServer ||
  1315. INADDR_ANY == NodeInfo.BackupServer ||
  1316. INADDR_BROADCAST == NodeInfo.BackupServer);
  1317. DwordToIPAddrString(NodeInfo.NameServerAddress, &strTemp);
  1318. AddToListControl(iIndex,
  1319. (LPWSTR)SzLoadString(_Module.GetResourceInstance(),
  1320. fHaveSecondWins ? IDS_IPCFG_WINS_PL : IDS_IPCFG_WINS),
  1321. (LPWSTR)strTemp.c_str());
  1322. iIndex++;
  1323. if (!fHaveSecondWins)
  1324. {
  1325. break;
  1326. }
  1327. DwordToIPAddrString(NodeInfo.BackupServer, &strTemp);
  1328. AddToListControl(iIndex,
  1329. (LPWSTR)L"",
  1330. (LPWSTR)strTemp.c_str());
  1331. iIndex++;
  1332. int NumOfServers = (NodeInfo.NumOtherServers <= MAX_NUM_OTHER_NAME_SERVERS) ?
  1333. NodeInfo.NumOtherServers : MAX_NUM_OTHER_NAME_SERVERS;
  1334. for (int i = 0; i < NumOfServers; i++)
  1335. {
  1336. if( LOCAL_WINS_ADDRESS == NodeInfo.Others[i] ||
  1337. INADDR_ANY == NodeInfo.Others[i] ||
  1338. INADDR_BROADCAST == NodeInfo.Others[i] )
  1339. {
  1340. break;
  1341. }
  1342. DwordToIPAddrString(NodeInfo.Others[i], &strTemp);
  1343. AddToListControl(iIndex,
  1344. (LPWSTR)L"",
  1345. (LPWSTR)strTemp.c_str());
  1346. iIndex++;
  1347. }
  1348. } while (FALSE);
  1349. NtClose(hNbt);
  1350. int iRet = iIndex - iStartIndex;
  1351. //if somehow we didn't add any WINS entris to the list, we need to add an empty "WINS Server" entry to the list
  1352. if (0 == iRet)
  1353. {
  1354. AddToListControl(iStartIndex,
  1355. (LPWSTR)SzLoadString(_Module.GetResourceInstance(), IDS_IPCFG_WINS),
  1356. (LPWSTR)L"");
  1357. iRet = 1;
  1358. }
  1359. return iRet;
  1360. }
  1361. //+---------------------------------------------------------------------------
  1362. //
  1363. // Member: CAdvIpcfgDlg::FormatTime
  1364. //
  1365. // Purpose: convert time_t to a string.
  1366. //
  1367. // Arguments: pAddrList - the IP_ADDR_STRING
  1368. // pstrAddr [out] the string contains the IP address
  1369. // pstrMask [out] the string contains the Mask
  1370. //
  1371. // Returns: error code
  1372. //
  1373. // Note: _wasctime has some localization problems. So we do the formatting ourselves
  1374. HRESULT CAdvIpcfgDlg::FormatTime(time_t t, tstring & str)
  1375. {
  1376. TraceFileFunc(ttidStatMon);
  1377. time_t timeCurrent = time(NULL);
  1378. LONGLONG llTimeDiff = 0;
  1379. FILETIME ftCurrent = {0};
  1380. FILETIME ftLocal = {0};
  1381. SYSTEMTIME SysTime;
  1382. WCHAR szBuff[256] = {0};
  1383. str = L"";
  1384. GetSystemTimeAsFileTime(&ftCurrent);
  1385. llTimeDiff = (LONGLONG)t - (LONGLONG)timeCurrent;
  1386. llTimeDiff *= 10000000;
  1387. *((LONGLONG UNALIGNED64 *)&ftCurrent) += llTimeDiff;
  1388. if (!FileTimeToLocalFileTime(&ftCurrent, &ftLocal ))
  1389. {
  1390. return HRESULT_FROM_WIN32(GetLastError());
  1391. }
  1392. if (!FileTimeToSystemTime( &ftLocal, &SysTime ))
  1393. {
  1394. return HRESULT_FROM_WIN32(GetLastError());
  1395. }
  1396. if (0 == GetDateFormat(LOCALE_USER_DEFAULT,
  1397. 0,
  1398. &SysTime,
  1399. NULL,
  1400. szBuff,
  1401. celems(szBuff)))
  1402. {
  1403. return HRESULT_FROM_WIN32(GetLastError());
  1404. }
  1405. str = szBuff;
  1406. str += L" ";
  1407. ZeroMemory(szBuff, sizeof(szBuff));
  1408. if (0 == GetTimeFormat(LOCALE_USER_DEFAULT,
  1409. 0,
  1410. &SysTime,
  1411. NULL,
  1412. szBuff,
  1413. celems(szBuff)))
  1414. {
  1415. return HRESULT_FROM_WIN32(GetLastError());
  1416. }
  1417. str += szBuff;
  1418. return S_OK;
  1419. }
  1420. //+---------------------------------------------------------------------------
  1421. //
  1422. // Function: HrGetAutoNetSetting
  1423. //
  1424. // Purpose: Query the Autonet settings
  1425. //
  1426. // Arguments: pszGuid - guid of the connection
  1427. // pAddrType [out] - contains the type of the address
  1428. //
  1429. // Returns: error code
  1430. //
  1431. HRESULT HrGetAutoNetSetting(PWSTR pszGuid, DHCP_ADDRESS_TYPE * pAddrType)
  1432. {
  1433. TraceFileFunc(ttidStatMon);
  1434. Assert(pszGuid);
  1435. Assert(pAddrType);
  1436. *pAddrType = UNKNOWN_ADDR;
  1437. HRESULT hr = S_OK;
  1438. DWORD dwType = 0;
  1439. HKEY hkeyInterface = NULL;
  1440. tstring strInterfaceKey = c_szTcpipInterfaces;
  1441. strInterfaceKey += pszGuid;
  1442. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1443. strInterfaceKey.c_str(),
  1444. KEY_QUERY_VALUE,
  1445. &hkeyInterface);
  1446. if (SUCCEEDED(hr))
  1447. {
  1448. Assert(hkeyInterface);
  1449. hr = HrRegQueryDword(hkeyInterface,
  1450. c_szAddressType,
  1451. &dwType);
  1452. if (SUCCEEDED(hr))
  1453. {
  1454. if (0 == dwType)
  1455. {
  1456. *pAddrType = NORMAL_ADDR;
  1457. }
  1458. else
  1459. {
  1460. tstring strConfigurationName = c_szAlternate;
  1461. strConfigurationName += pszGuid;
  1462. //assume default is AUTONET_ADDR
  1463. *pAddrType = AUTONET_ADDR;
  1464. // if ActiveConfigurations contain a string "Alternate_{Interface GUID}"
  1465. // then there is customized fall-back settings, otherwise Autonet
  1466. vector<tstring *> vstrTmp;
  1467. hr = HrRegQueryColString( hkeyInterface,
  1468. c_szActiveConfigurations,
  1469. &vstrTmp);
  1470. if (SUCCEEDED(hr))
  1471. {
  1472. for (int i = 0; i < (int)vstrTmp.size(); i++)
  1473. {
  1474. if (strConfigurationName == *vstrTmp[i])
  1475. {
  1476. *pAddrType = ALTERNATE_ADDR;
  1477. break;
  1478. }
  1479. }
  1480. DeleteColString(&vstrTmp);
  1481. }
  1482. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  1483. {
  1484. hr = S_OK;
  1485. }
  1486. }
  1487. }
  1488. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  1489. {
  1490. //if the value is not there, assume the default (No autonet)
  1491. *pAddrType = NORMAL_ADDR;
  1492. hr = S_OK;
  1493. }
  1494. RegSafeCloseKey(hkeyInterface);
  1495. }
  1496. return hr;
  1497. }
  1498. HRESULT HrGetAutoNetSetting(REFGUID pGuidId, DHCP_ADDRESS_TYPE * pAddrType)
  1499. {
  1500. TraceFileFunc(ttidStatMon);
  1501. Assert(pAddrType);
  1502. *pAddrType = UNKNOWN_ADDR;
  1503. WCHAR wszGuid[MAX_PATH];
  1504. ::StringFromGUID2(pGuidId, wszGuid, MAX_PATH);
  1505. HRESULT hr = S_OK;
  1506. PIP_ADAPTER_INFO pAdapterInfo = NULL;
  1507. DWORD dwOutBufLen = 0;
  1508. DWORD dwRet = ERROR_SUCCESS;
  1509. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  1510. if (dwRet == ERROR_BUFFER_OVERFLOW)
  1511. {
  1512. pAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc(dwOutBufLen);
  1513. if (NULL == pAdapterInfo)
  1514. return E_OUTOFMEMORY;
  1515. }
  1516. else if (ERROR_SUCCESS == dwRet)
  1517. {
  1518. return E_FAIL;
  1519. }
  1520. else
  1521. {
  1522. return HRESULT_FROM_WIN32(dwRet);
  1523. }
  1524. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  1525. if (ERROR_SUCCESS != dwRet)
  1526. {
  1527. CoTaskMemFree(pAdapterInfo);
  1528. return HRESULT_FROM_WIN32(dwRet);
  1529. }
  1530. BOOL fFound = FALSE;
  1531. PIP_ADAPTER_INFO pAdapterInfoEnum = pAdapterInfo;
  1532. while (pAdapterInfoEnum)
  1533. {
  1534. USES_CONVERSION;
  1535. if (lstrcmp(wszGuid, A2W(pAdapterInfoEnum->AdapterName)) == 0)
  1536. {
  1537. fFound = TRUE;
  1538. break;
  1539. }
  1540. pAdapterInfoEnum = pAdapterInfoEnum->Next;
  1541. }
  1542. if (fFound)
  1543. {
  1544. if (pAdapterInfoEnum->DhcpEnabled)
  1545. {
  1546. hr = HrGetAutoNetSetting(wszGuid, pAddrType);
  1547. }
  1548. else
  1549. {
  1550. *pAddrType = STATIC_ADDR;
  1551. hr = S_OK;
  1552. }
  1553. }
  1554. else
  1555. {
  1556. hr = S_FALSE;
  1557. }
  1558. CoTaskMemFree(pAdapterInfo);
  1559. return hr;
  1560. }
  1561. void DwordToIPAddrString(DWORD dw, tstring * pstr)
  1562. {
  1563. TraceFileFunc(ttidStatMon);
  1564. WCHAR szBuff[32] = {0};
  1565. Assert(pstr);
  1566. _itow((dw & 0xff000000) >> 24, szBuff, 10);
  1567. *pstr = szBuff;
  1568. *pstr += L".";
  1569. _itow((dw & 0x00ff0000) >> 16, szBuff, 10);
  1570. *pstr += szBuff;
  1571. *pstr += L".";
  1572. _itow((dw & 0x0000ff00) >> 8, szBuff, 10);
  1573. *pstr += szBuff;
  1574. *pstr += L".";
  1575. _itow(dw & 0x000000ff, szBuff, 10);
  1576. *pstr += szBuff;
  1577. }