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.

741 lines
16 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. ServBrow.cpp
  7. The server browser dialog
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "ServBrow.h"
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. BOOL g_bDhcpDsInitialized = FALSE;
  18. CAuthServerList::CAuthServerList()
  19. : m_pos(NULL), m_bInitialized(FALSE)
  20. {
  21. }
  22. CAuthServerList::~CAuthServerList()
  23. {
  24. Destroy();
  25. }
  26. HRESULT
  27. CAuthServerList::Destroy()
  28. {
  29. // we only call cleanup once for this process
  30. // ::DhcpDsCleanup();
  31. m_bInitialized = FALSE;
  32. return S_OK;
  33. }
  34. HRESULT
  35. CAuthServerList::Init()
  36. {
  37. DWORD dwErr = ERROR_SUCCESS;
  38. CSingleLock sl(&m_cs); // only one thread at a time in here
  39. // DhcpDsInit only needs to be called once per process and is time consuming.
  40. // if we've alredy called it then don't call again.
  41. if (!g_bDhcpDsInitialized)
  42. {
  43. dwErr = ::DhcpDsInit();
  44. if (dwErr == ERROR_SUCCESS)
  45. g_bDhcpDsInitialized = TRUE;
  46. }
  47. if (g_bDhcpDsInitialized)
  48. m_bInitialized = TRUE;
  49. return HRESULT_FROM_WIN32(dwErr);
  50. }
  51. HRESULT
  52. CAuthServerList::EnumServers()
  53. {
  54. LPDHCP_SERVER_INFO_ARRAY pServerInfoArray = NULL;
  55. DWORD dwErr = ERROR_SUCCESS;
  56. dwErr = ::DhcpEnumServers(0, NULL, &pServerInfoArray, NULL, NULL);
  57. if (dwErr != ERROR_SUCCESS)
  58. return HRESULT_FROM_WIN32(dwErr);
  59. Assert(pServerInfoArray);
  60. for (UINT i = 0; i < pServerInfoArray->NumElements; i++)
  61. {
  62. CServerInfo ServerInfo(pServerInfoArray->Servers[i].ServerAddress,
  63. pServerInfoArray->Servers[i].ServerName);
  64. AddTail(ServerInfo);
  65. }
  66. return S_OK;
  67. }
  68. BOOL
  69. CAuthServerList::IsAuthorized
  70. (
  71. DWORD dwIpAddress
  72. )
  73. {
  74. BOOL bValid = FALSE;
  75. POSITION pos = GetHeadPosition();
  76. while (pos)
  77. {
  78. if (GetNext(pos).m_dwIp == dwIpAddress)
  79. {
  80. bValid = TRUE;
  81. break;
  82. }
  83. }
  84. return bValid;
  85. }
  86. HRESULT
  87. CAuthServerList::AddServer
  88. (
  89. DWORD dwIpAddress,
  90. LPCTSTR pFQDN
  91. )
  92. {
  93. DWORD dwErr = ERROR_SUCCESS;
  94. DHCP_SERVER_INFO dhcpServerInfo = {0};
  95. dhcpServerInfo.ServerAddress = dwIpAddress;
  96. dhcpServerInfo.ServerName = (LPTSTR) pFQDN;
  97. dwErr = ::DhcpAddServer(0, NULL, &dhcpServerInfo, NULL, NULL);
  98. if (dwErr != ERROR_SUCCESS)
  99. return HRESULT_FROM_WIN32(dwErr);
  100. CServerInfo ServerInfo(dwIpAddress, pFQDN);
  101. AddTail(ServerInfo);
  102. return S_OK;
  103. }
  104. HRESULT
  105. CAuthServerList::RemoveServer
  106. (
  107. DWORD dwIpAddress
  108. )
  109. {
  110. DWORD dwErr = ERROR_SUCCESS;
  111. DHCP_SERVER_INFO dhcpServerInfo = {0};
  112. POSITION posCurrent;
  113. POSITION pos = GetHeadPosition();
  114. while (pos)
  115. {
  116. posCurrent = pos;
  117. CServerInfo & ServerInfo = GetNext(pos);
  118. if (ServerInfo.m_dwIp == dwIpAddress)
  119. {
  120. dhcpServerInfo.ServerAddress = ServerInfo.m_dwIp;
  121. dhcpServerInfo.ServerName = (LPTSTR) ((LPCTSTR)ServerInfo.m_strName);
  122. dwErr = ::DhcpDeleteServer(0, NULL, &dhcpServerInfo, NULL, NULL);
  123. if (dwErr == ERROR_SUCCESS)
  124. {
  125. // success, remove from list
  126. RemoveAt(posCurrent);
  127. }
  128. return HRESULT_FROM_WIN32(dwErr);
  129. }
  130. }
  131. return E_INVALIDARG;
  132. }
  133. void
  134. CAuthServerList::Clear()
  135. {
  136. RemoveAll();
  137. Reset();
  138. }
  139. void
  140. CAuthServerList::Reset()
  141. {
  142. m_pos = GetHeadPosition();
  143. }
  144. HRESULT
  145. CAuthServerList::Next
  146. (
  147. CServerInfo &ServerInfo
  148. )
  149. {
  150. if (m_pos)
  151. ServerInfo = GetNext(m_pos);
  152. else
  153. return E_FAIL;
  154. return S_OK;
  155. }
  156. /*---------------------------------------------------------------------------
  157. CAuthServerWorker
  158. ---------------------------------------------------------------------------*/
  159. CAuthServerWorker::CAuthServerWorker(CAuthServerList ** ppList)
  160. {
  161. m_ppList = ppList;
  162. }
  163. CAuthServerWorker::~CAuthServerWorker()
  164. {
  165. }
  166. void
  167. CAuthServerWorker::OnDoAction()
  168. {
  169. HRESULT hr = hrOK;
  170. m_pAuthList = &g_AuthServerList;
  171. hr = m_pAuthList->Init();
  172. Trace1("CAuthServerWorker::OnDoAction - Init returned %d\n", hr);
  173. hr = m_pAuthList->EnumServers();
  174. Trace1("CAuthServerWorker::OnDoAction - EnumServers returned %d\n", hr);
  175. if (!IsAbandoned())
  176. {
  177. if (m_ppList)
  178. *m_ppList = m_pAuthList;
  179. }
  180. }
  181. /*---------------------------------------------------------------------------
  182. CStandaloneAuthServerWorker
  183. ---------------------------------------------------------------------------*/
  184. CStandaloneAuthServerWorker::CStandaloneAuthServerWorker()
  185. : CAuthServerWorker(NULL)
  186. {
  187. m_bAutoDelete = TRUE;
  188. }
  189. CStandaloneAuthServerWorker::~CStandaloneAuthServerWorker()
  190. {
  191. }
  192. int
  193. CStandaloneAuthServerWorker::Run()
  194. {
  195. OnDoAction();
  196. return 0;
  197. }
  198. int CALLBACK ServerBrowseCompareFunc
  199. (
  200. LPARAM lParam1,
  201. LPARAM lParam2,
  202. LPARAM lParamSort
  203. )
  204. {
  205. return ((CServerBrowse *) lParamSort)->HandleSort(lParam1, lParam2);
  206. }
  207. /////////////////////////////////////////////////////////////////////////////
  208. // CServerBrowse dialog
  209. CServerBrowse::CServerBrowse(BOOL bMultiselect, CWnd* pParent /*=NULL*/)
  210. : CBaseDialog(CServerBrowse::IDD, pParent)
  211. {
  212. //{{AFX_DATA_INIT(CServerBrowse)
  213. //}}AFX_DATA_INIT
  214. m_bMultiselect = bMultiselect;
  215. ResetSort();
  216. }
  217. void CServerBrowse::DoDataExchange(CDataExchange* pDX)
  218. {
  219. CBaseDialog::DoDataExchange(pDX);
  220. //{{AFX_DATA_MAP(CServerBrowse)
  221. DDX_Control(pDX, IDOK, m_buttonOk);
  222. DDX_Control(pDX, IDC_BUTTON_REMOVE, m_buttonRemove);
  223. DDX_Control(pDX, IDC_LIST_VALID_SERVERS, m_listctrlServers);
  224. //}}AFX_DATA_MAP
  225. }
  226. BEGIN_MESSAGE_MAP(CServerBrowse, CBaseDialog)
  227. //{{AFX_MSG_MAP(CServerBrowse)
  228. ON_BN_CLICKED(IDC_BUTTON_REFRESH, OnButtonRefresh)
  229. ON_BN_CLICKED(IDC_BUTTON_REMOVE, OnButtonRemove)
  230. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_VALID_SERVERS, OnItemchangedListValidServers)
  231. ON_BN_CLICKED(IDC_BUTTON_AUTHORIZE, OnButtonAuthorize)
  232. ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST_VALID_SERVERS, OnColumnclickListValidServers)
  233. //}}AFX_MSG_MAP
  234. END_MESSAGE_MAP()
  235. /////////////////////////////////////////////////////////////////////////////
  236. // CServerBrowse message handlers
  237. BOOL CServerBrowse::OnInitDialog()
  238. {
  239. CBaseDialog::OnInitDialog();
  240. LV_COLUMN lvColumn;
  241. CString strText;
  242. strText.LoadString(IDS_NAME);
  243. ListView_SetExtendedListViewStyle(m_listctrlServers.GetSafeHwnd(), LVS_EX_FULLROWSELECT);
  244. lvColumn.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH;
  245. lvColumn.fmt = LVCFMT_LEFT;
  246. lvColumn.cx = 175;
  247. lvColumn.pszText = (LPTSTR) (LPCTSTR) strText;
  248. m_listctrlServers.InsertColumn(0, &lvColumn);
  249. strText.LoadString(IDS_IP_ADDRESS);
  250. lvColumn.pszText = (LPTSTR) (LPCTSTR) strText;
  251. lvColumn.cx = 100;
  252. m_listctrlServers.InsertColumn(1, &lvColumn);
  253. FillListCtrl();
  254. UpdateButtons();
  255. if (m_bMultiselect)
  256. {
  257. DWORD dwStyle = ::GetWindowLong(m_listctrlServers.GetSafeHwnd(), GWL_STYLE);
  258. dwStyle &= ~LVS_SINGLESEL;
  259. ::SetWindowLong(m_listctrlServers.GetSafeHwnd(), GWL_EXSTYLE, dwStyle);
  260. }
  261. return TRUE; // return TRUE unless you set the focus to a control
  262. // EXCEPTION: OCX Property Pages should return FALSE
  263. }
  264. void CServerBrowse::OnOK()
  265. {
  266. int nSelectedItem = m_listctrlServers.GetNextItem(-1, LVNI_SELECTED);
  267. while (nSelectedItem != -1)
  268. {
  269. m_astrName.Add(m_listctrlServers.GetItemText(nSelectedItem, 0));
  270. m_astrIp.Add(m_listctrlServers.GetItemText(nSelectedItem, 1));
  271. nSelectedItem = m_listctrlServers.GetNextItem(nSelectedItem, LVNI_SELECTED);
  272. }
  273. CBaseDialog::OnOK();
  274. }
  275. void CServerBrowse::RefreshData()
  276. {
  277. if (m_pServerList)
  278. {
  279. m_pServerList->Clear();
  280. m_pServerList->EnumServers();
  281. ResetSort();
  282. FillListCtrl();
  283. }
  284. }
  285. void CServerBrowse::UpdateButtons()
  286. {
  287. // Find the selected item
  288. int nSelectedItem = m_listctrlServers.GetNextItem(-1, LVNI_SELECTED);
  289. BOOL bEnable = (nSelectedItem != -1) ? TRUE : FALSE;
  290. m_buttonOk.EnableWindow(bEnable);
  291. m_buttonRemove.EnableWindow(bEnable);
  292. }
  293. void CServerBrowse::FillListCtrl()
  294. {
  295. CServerInfo ServerInfo;
  296. CString strIp;
  297. int nItem = 0;
  298. m_listctrlServers.DeleteAllItems();
  299. POSITION pos = m_pServerList->GetHeadPosition();
  300. // walk the list and add items to the list control
  301. while (pos != NULL)
  302. {
  303. POSITION lastpos = pos;
  304. // get the next item
  305. ServerInfo = m_pServerList->GetNext(pos);
  306. UtilCvtIpAddrToWstr(ServerInfo.m_dwIp, &strIp);
  307. nItem = m_listctrlServers.InsertItem(nItem, ServerInfo.m_strName);
  308. m_listctrlServers.SetItemText(nItem, 1, strIp);
  309. // save off the position value for sorting later
  310. m_listctrlServers.SetItemData(nItem, (DWORD_PTR) lastpos);
  311. }
  312. Sort(COLUMN_NAME);
  313. }
  314. void CServerBrowse::OnButtonAuthorize()
  315. {
  316. // put up the dialog to get the name and IP address of the server
  317. DWORD err;
  318. CGetServer dlgGetServer;
  319. if (dlgGetServer.DoModal() == IDOK)
  320. {
  321. BEGIN_WAIT_CURSOR;
  322. err = m_pServerList->AddServer(dlgGetServer.m_dwIpAddress, dlgGetServer.m_strName);
  323. if (err != ERROR_SUCCESS)
  324. {
  325. ::DhcpMessageBox(WIN32_FROM_HRESULT(err));
  326. }
  327. else
  328. {
  329. RefreshData();
  330. UpdateButtons();
  331. }
  332. END_WAIT_CURSOR;
  333. }
  334. }
  335. void CServerBrowse::OnButtonRefresh()
  336. {
  337. BEGIN_WAIT_CURSOR;
  338. RefreshData();
  339. UpdateButtons();
  340. END_WAIT_CURSOR;
  341. }
  342. void CServerBrowse::OnButtonRemove()
  343. {
  344. HRESULT hr;
  345. int nSelectedItem = m_listctrlServers.GetNextItem(-1, LVNI_SELECTED);
  346. if (nSelectedItem != -1)
  347. {
  348. CString strIp = m_listctrlServers.GetItemText(nSelectedItem, 1);
  349. DWORD dwIp = UtilCvtWstrToIpAddr(strIp);
  350. BEGIN_WAIT_CURSOR;
  351. hr = m_pServerList->RemoveServer(dwIp);
  352. END_WAIT_CURSOR;
  353. if (FAILED(hr))
  354. {
  355. ::DhcpMessageBox(WIN32_FROM_HRESULT(hr));
  356. }
  357. else
  358. {
  359. BEGIN_WAIT_CURSOR;
  360. RefreshData();
  361. UpdateButtons();
  362. END_WAIT_CURSOR;
  363. }
  364. }
  365. }
  366. void CServerBrowse::OnItemchangedListValidServers(NMHDR* pNMHDR, LRESULT* pResult)
  367. {
  368. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  369. UpdateButtons();
  370. *pResult = 0;
  371. }
  372. void CServerBrowse::OnColumnclickListValidServers(NMHDR* pNMHDR, LRESULT* pResult)
  373. {
  374. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  375. // sort depending on what column was clicked;
  376. Sort(pNMListView->iSubItem);
  377. *pResult = 0;
  378. }
  379. void CServerBrowse::Sort(int nCol)
  380. {
  381. if (m_nSortColumn == nCol)
  382. {
  383. // if the user is clicking the same column again, reverse the sort order
  384. m_aSortOrder[nCol] = m_aSortOrder[nCol] ? FALSE : TRUE;
  385. }
  386. else
  387. {
  388. m_nSortColumn = nCol;
  389. }
  390. m_listctrlServers.SortItems(ServerBrowseCompareFunc, (LPARAM) this);
  391. }
  392. int CServerBrowse::HandleSort(LPARAM lParam1, LPARAM lParam2)
  393. {
  394. int nCompare = 0;
  395. CServerInfo ServerInfo1, ServerInfo2;
  396. ServerInfo1 = m_pServerList->GetAt((POSITION) lParam1);
  397. ServerInfo2 = m_pServerList->GetAt((POSITION) lParam2);
  398. switch (m_nSortColumn)
  399. {
  400. case COLUMN_NAME:
  401. {
  402. nCompare = ServerInfo1.m_strName.CompareNoCase(ServerInfo2.m_strName);
  403. }
  404. // if the names are the same, fall back to the IP address
  405. if (nCompare != 0)
  406. {
  407. break;
  408. }
  409. case COLUMN_IP:
  410. {
  411. if (ServerInfo1.m_dwIp > ServerInfo2.m_dwIp)
  412. nCompare = 1;
  413. else
  414. if (ServerInfo1.m_dwIp < ServerInfo2.m_dwIp)
  415. nCompare = -1;
  416. }
  417. break;
  418. }
  419. if (m_aSortOrder[m_nSortColumn] == FALSE)
  420. {
  421. // descending
  422. return -nCompare;
  423. }
  424. else
  425. {
  426. // ascending
  427. return nCompare;
  428. }
  429. }
  430. void CServerBrowse::ResetSort()
  431. {
  432. m_nSortColumn = -1;
  433. for (int i = 0; i < COLUMN_MAX; i++)
  434. {
  435. m_aSortOrder[i] = TRUE; // ascending
  436. }
  437. }
  438. /////////////////////////////////////////////////////////////////////////////
  439. // CGetServer dialog
  440. CGetServer::CGetServer(CWnd* pParent /*=NULL*/)
  441. : CBaseDialog(CGetServer::IDD, pParent)
  442. {
  443. //{{AFX_DATA_INIT(CGetServer)
  444. // NOTE: the ClassWizard will add member initialization here
  445. //}}AFX_DATA_INIT
  446. m_dwIpAddress = 0;
  447. }
  448. void CGetServer::DoDataExchange(CDataExchange* pDX)
  449. {
  450. CBaseDialog::DoDataExchange(pDX);
  451. //{{AFX_DATA_MAP(CGetServer)
  452. // NOTE: the ClassWizard will add DDX and DDV calls here
  453. //}}AFX_DATA_MAP
  454. }
  455. BEGIN_MESSAGE_MAP(CGetServer, CBaseDialog)
  456. //{{AFX_MSG_MAP(CGetServer)
  457. ON_EN_CHANGE(IDC_EDIT_SERVER_NAME_IP, OnChangeEditServerNameIp)
  458. //}}AFX_MSG_MAP
  459. END_MESSAGE_MAP()
  460. /////////////////////////////////////////////////////////////////////////////
  461. // CGetServer message handlers
  462. BOOL CGetServer::OnInitDialog()
  463. {
  464. CBaseDialog::OnInitDialog();
  465. GetDlgItem(IDOK)->EnableWindow(FALSE);
  466. return TRUE; // return TRUE unless you set the focus to a control
  467. // EXCEPTION: OCX Property Pages should return FALSE
  468. }
  469. void CGetServer::OnOK()
  470. {
  471. CString strNameOrIp;
  472. DWORD err = 0;
  473. DHC_HOST_INFO_STRUCT dhcHostInfo;
  474. BEGIN_WAIT_CURSOR;
  475. GetDlgItem(IDC_EDIT_SERVER_NAME_IP)->GetWindowText(strNameOrIp);
  476. switch (UtilCategorizeName(strNameOrIp))
  477. {
  478. case HNM_TYPE_IP:
  479. m_dwIpAddress = ::UtilCvtWstrToIpAddr( strNameOrIp ) ;
  480. break ;
  481. case HNM_TYPE_NB:
  482. case HNM_TYPE_DNS:
  483. err = ::UtilGetHostAddress( strNameOrIp, &m_dwIpAddress ) ;
  484. m_strName = strNameOrIp; // default
  485. break ;
  486. default:
  487. err = IDS_ERR_BAD_HOST_NAME ;
  488. break;
  489. }
  490. // now that we have the address, try to get the full host info
  491. // an empty host name is valid here, so if we can't find a host
  492. // name then we'll just leave it blank.
  493. if (err == ERROR_SUCCESS)
  494. {
  495. err = UtilGetHostInfo(m_dwIpAddress, &dhcHostInfo);
  496. if (err == ERROR_SUCCESS)
  497. {
  498. m_strName = dhcHostInfo._chHostName;
  499. }
  500. }
  501. END_WAIT_CURSOR;
  502. // confirm choice with user, give them a chance to modify our findings
  503. CConfirmAuthorization dlgConfirm;
  504. dlgConfirm.m_strName = m_strName;
  505. dlgConfirm.m_dwAuthAddress = m_dwIpAddress;
  506. if (dlgConfirm.DoModal() != IDOK)
  507. {
  508. return;
  509. }
  510. // use whatever they selected
  511. m_strName = dlgConfirm.m_strName;
  512. m_dwIpAddress = dlgConfirm.m_dwAuthAddress;
  513. CBaseDialog::OnOK();
  514. }
  515. void CGetServer::OnChangeEditServerNameIp()
  516. {
  517. CString strText;
  518. BOOL fEnable = FALSE;
  519. GetDlgItem(IDC_EDIT_SERVER_NAME_IP)->GetWindowText(strText);
  520. if (!strText.IsEmpty())
  521. fEnable = TRUE;
  522. GetDlgItem(IDOK)->EnableWindow(fEnable);
  523. }
  524. /////////////////////////////////////////////////////////////////////////////
  525. // CConfirmAuthorization dialog
  526. CConfirmAuthorization::CConfirmAuthorization(CWnd* pParent /*=NULL*/)
  527. : CBaseDialog(CConfirmAuthorization::IDD, pParent)
  528. {
  529. //{{AFX_DATA_INIT(CConfirmAuthorization)
  530. m_strName = _T("");
  531. //}}AFX_DATA_INIT
  532. m_dwAuthAddress = 0;
  533. }
  534. void CConfirmAuthorization::DoDataExchange(CDataExchange* pDX)
  535. {
  536. CBaseDialog::DoDataExchange(pDX);
  537. //{{AFX_DATA_MAP(CConfirmAuthorization)
  538. DDX_Text(pDX, IDC_EDIT_AUTH_NAME, m_strName);
  539. //}}AFX_DATA_MAP
  540. DDX_Control(pDX, IDC_IPADDR_AUTH, m_ipaAuth);
  541. }
  542. BEGIN_MESSAGE_MAP(CConfirmAuthorization, CBaseDialog)
  543. //{{AFX_MSG_MAP(CConfirmAuthorization)
  544. //}}AFX_MSG_MAP
  545. END_MESSAGE_MAP()
  546. /////////////////////////////////////////////////////////////////////////////
  547. // CConfirmAuthorization message handlers
  548. BOOL CConfirmAuthorization::OnInitDialog()
  549. {
  550. CBaseDialog::OnInitDialog();
  551. if (m_dwAuthAddress != 0)
  552. {
  553. m_ipaAuth.SetAddress(m_dwAuthAddress);
  554. }
  555. else
  556. {
  557. m_ipaAuth.ClearAddress();
  558. }
  559. return TRUE; // return TRUE unless you set the focus to a control
  560. // EXCEPTION: OCX Property Pages should return FALSE
  561. }
  562. void CConfirmAuthorization::OnOK()
  563. {
  564. m_ipaAuth.GetAddress(&m_dwAuthAddress);
  565. if (m_dwAuthAddress == 0)
  566. {
  567. DhcpMessageBox(IDS_ERR_DLL_INVALID_ADDRESS);
  568. m_ipaAuth.SetFocus();
  569. return;
  570. }
  571. CBaseDialog::OnOK();
  572. }