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.

1900 lines
33 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. supdlgs.cpp
  5. Abstract:
  6. Supporting dialogs
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. --*/
  14. //
  15. // Include Files
  16. //
  17. #include "stdafx.h"
  18. #include <iiscnfgp.h>
  19. #include <winsock2.h>
  20. #include "common.h"
  21. #include "InetMgrApp.h"
  22. #include "supdlgs.h"
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27. #define new DEBUG_NEW
  28. //
  29. // Registry key name for this dialog
  30. //
  31. const TCHAR g_szRegKey[] = _T("Advanced");
  32. //
  33. // Site Security Listbox Column Definitions
  34. //
  35. // Note: IDS_IP_ADDRESS_SUBNET_MASK is overridden
  36. // in w3scfg
  37. //
  38. static const ODL_COLUMN_DEF g_aColumns[] =
  39. {
  40. // ===============================================
  41. // Weight Label
  42. // ===============================================
  43. { 4, IDS_ACCESS, },
  44. { 15, IDS_IP_ADDRESS_SUBNET_MASK, },
  45. };
  46. #define NUM_COLUMNS (sizeof(g_aColumns) / sizeof(g_aColumns[0]))
  47. //
  48. // CUserAccountDlg dialog
  49. //
  50. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  51. CUserAccountDlg::CUserAccountDlg(
  52. IN LPCTSTR lpstrServer,
  53. IN LPCTSTR lpstrUserName,
  54. IN LPCTSTR lpstrPassword,
  55. IN CWnd * pParent OPTIONAL
  56. )
  57. /*++
  58. Routine Description:
  59. Constructor for bringing up the user account dialog
  60. Arguments:
  61. LPCTSTR lpstrServer : Server
  62. LPCTSTR lpstrUserName : Starting Username
  63. LPCTSTR lpstrPassword : Starting Password
  64. CWnd * pParent : Parent window handle
  65. Return Value:
  66. N/A
  67. --*/
  68. : m_strUserName(lpstrUserName),
  69. m_strPassword(lpstrPassword),
  70. m_strServer(lpstrServer),
  71. CDialog(CUserAccountDlg::IDD, pParent)
  72. {
  73. //{{AFX_DATA_INIT(CUserAccountDlg)
  74. //}}AFX_DATA_INIT
  75. }
  76. void
  77. CUserAccountDlg::DoDataExchange(
  78. IN CDataExchange * pDX
  79. )
  80. /*++
  81. Routine Description:
  82. Initialise/Store control Data
  83. Arguments:
  84. CDataExchange * pDX : DDX/DDV struct
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. CDialog::DoDataExchange(pDX);
  90. //{{AFX_DATA_MAP(CUserAccountDlg)
  91. DDX_Control(pDX, IDC_EDIT_USERNAME, m_edit_UserName);
  92. DDX_Control(pDX, IDC_EDIT_PASSWORD, m_edit_Password);
  93. //}}AFX_DATA_MAP
  94. //
  95. // Private DDX/DDV Routines
  96. //
  97. DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUserName);
  98. DDV_MinMaxChars(pDX, m_strUserName, 1, UNLEN);
  99. DDX_Password(pDX, IDC_EDIT_PASSWORD, m_strPassword, g_lpszDummyPassword);
  100. DDV_MaxChars(pDX, m_strPassword, PWLEN);
  101. }
  102. //
  103. // Message Map
  104. //
  105. BEGIN_MESSAGE_MAP(CUserAccountDlg, CDialog)
  106. //{{AFX_MSG_MAP(CUserAccountDlg)
  107. ON_BN_CLICKED(IDC_BUTTON_BROWSE_USERS, OnButtonBrowseUsers)
  108. ON_BN_CLICKED(IDC_BUTTON_CHECK_PASSWORD, OnButtonCheckPassword)
  109. ON_EN_CHANGE(IDC_EDIT_USERNAME, OnChangeEditUsername)
  110. //}}AFX_MSG_MAP
  111. END_MESSAGE_MAP()
  112. //
  113. // Message Handlers
  114. //
  115. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  116. void
  117. CUserAccountDlg::OnButtonBrowseUsers()
  118. /*++
  119. Routine Description:
  120. User browse dialog pressed, bring up
  121. the user browser
  122. Arguments:
  123. None
  124. Return Value:
  125. None
  126. --*/
  127. {
  128. CString str;
  129. if (GetIUsrAccount(m_strServer, this, str))
  130. {
  131. //
  132. // If a name was selected, blank
  133. // out the password
  134. //
  135. m_edit_UserName.SetWindowText(str);
  136. m_edit_Password.SetFocus();
  137. }
  138. }
  139. void
  140. CUserAccountDlg::OnChangeEditUsername()
  141. /*++
  142. Routine Description:
  143. Handle change in user name edit box by blanking out the password
  144. Arguments:
  145. None
  146. Return Value:
  147. None
  148. --*/
  149. {
  150. m_edit_Password.SetWindowText(_T(""));
  151. }
  152. void
  153. CUserAccountDlg::OnButtonCheckPassword()
  154. /*++
  155. Routine Description:
  156. 'Check Password' has been pressed. Try to validate
  157. the password that has been entered
  158. Arguments:
  159. None
  160. Return Value:
  161. None
  162. --*/
  163. {
  164. if (!UpdateData(TRUE))
  165. {
  166. return;
  167. }
  168. CError err(CComAuthInfo::VerifyUserPassword(m_strUserName, m_strPassword));
  169. if (!err.MessageBoxOnFailure())
  170. {
  171. ::AfxMessageBox(IDS_PASSWORD_OK);
  172. }
  173. }
  174. //
  175. // Text dialog that warns of clear text violation
  176. //
  177. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  178. CClearTxtDlg::CClearTxtDlg(
  179. IN CWnd * pParent OPTIONAL
  180. )
  181. /*++
  182. Routine Description:
  183. Clear text dialog constructor
  184. Arguments:
  185. CWnd * pParent : Optional parent window
  186. Return Value:
  187. N/A
  188. --*/
  189. : CDialog(CClearTxtDlg::IDD, pParent)
  190. {
  191. //{{AFX_DATA_INIT(CClearTxtDlg)
  192. //}}AFX_DATA_INIT
  193. }
  194. void
  195. CClearTxtDlg::DoDataExchange(
  196. IN CDataExchange * pDX
  197. )
  198. /*++
  199. Routine Description:
  200. Initialise/Store control data
  201. Arguments:
  202. CDataExchange * pDX - DDX/DDV control structure
  203. Return Value:
  204. None
  205. --*/
  206. {
  207. CDialog::DoDataExchange(pDX);
  208. //{{AFX_DATA_MAP(CClearTxtDlg)
  209. //}}AFX_DATA_MAP
  210. }
  211. //
  212. // Message Map
  213. //
  214. BEGIN_MESSAGE_MAP(CClearTxtDlg, CDialog)
  215. //{{AFX_MSG_MAP(CClearTxtDlg)
  216. //}}AFX_MSG_MAP
  217. END_MESSAGE_MAP()
  218. //
  219. // Message Handlers
  220. //
  221. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  222. BOOL
  223. CClearTxtDlg::OnInitDialog()
  224. /*++
  225. Routine Description:
  226. WM_INITDIALOG handler. Initialize the dialog.
  227. Arguments:
  228. None.
  229. Return Value:
  230. TRUE if no focus is to be set automatically, FALSE if the focus
  231. is already set.
  232. --*/
  233. {
  234. CDialog::OnInitDialog();
  235. (GetDlgItem(IDCANCEL))->SetFocus();
  236. CenterWindow();
  237. MessageBeep(MB_ICONEXCLAMATION);
  238. return FALSE;
  239. }
  240. IMPLEMENT_DYNAMIC(CIPAccessDescriptorListBox, CHeaderListBox);
  241. //
  242. // Bitmap indices
  243. //
  244. enum
  245. {
  246. BMPID_GRANTED = 0,
  247. BMPID_DENIED,
  248. BMPID_SINGLE,
  249. BMPID_MULTIPLE,
  250. //
  251. // Don't move this one
  252. //
  253. BMPID_TOTAL
  254. };
  255. const int CIPAccessDescriptorListBox::nBitmaps = BMPID_TOTAL;
  256. CIPAccessDescriptorListBox::CIPAccessDescriptorListBox(
  257. IN BOOL fDomainsAllowed
  258. )
  259. /*++
  260. Routine Description:
  261. Constructor
  262. Arguments:
  263. fDomainsAllowed : TRUE if domain names are legal.
  264. Return Value:
  265. N/A
  266. --*/
  267. : m_fDomainsAllowed(fDomainsAllowed),
  268. CHeaderListBox(HLS_STRETCH, g_szRegKey)
  269. {
  270. m_strGranted.LoadString(IDS_GRANTED);
  271. m_strDenied.LoadString(IDS_DENIED);
  272. m_strFormat.LoadString(IDS_FMT_SECURITY);
  273. }
  274. void
  275. CIPAccessDescriptorListBox::DrawItemEx(
  276. IN CRMCListBoxDrawStruct & ds
  277. )
  278. /*++
  279. Routine Description:
  280. Draw item in the listbox
  281. Arguments:
  282. CRMCListBoxDrawStruct & ds : Draw item structure
  283. Return Value:
  284. None
  285. --*/
  286. {
  287. CIPAccessDescriptor * p = (CIPAccessDescriptor *)ds.m_ItemData;
  288. ASSERT_READ_PTR(p);
  289. //
  290. // Display Granted/Denied with appropriate bitmap
  291. //
  292. DrawBitmap(ds, 0, p->HasAccess() ? BMPID_GRANTED : BMPID_DENIED);
  293. ColumnText(ds, 0, TRUE, p->HasAccess() ? m_strGranted : m_strDenied);
  294. //
  295. // Display IP Address with multiple/single bitmap
  296. //
  297. DrawBitmap(ds, 1, p->IsSingle() ? BMPID_SINGLE : BMPID_MULTIPLE);
  298. if (p->IsDomainName())
  299. {
  300. ColumnText(ds, 1, TRUE, p->QueryDomainName());
  301. }
  302. else if (p->IsSingle())
  303. {
  304. //
  305. // Display only ip address
  306. //
  307. ColumnText(ds, 1, TRUE, p->QueryIPAddress());
  308. }
  309. else
  310. {
  311. //
  312. // Display ip address/subnet mask
  313. //
  314. CString str, strIP, strMask;
  315. str.Format(
  316. m_strFormat,
  317. (LPCTSTR)p->QueryIPAddress().QueryIPAddress(strIP),
  318. (LPCTSTR)p->QuerySubnetMask().QueryIPAddress(strMask)
  319. );
  320. ColumnText(ds, 1, TRUE, str);
  321. }
  322. }
  323. /* virtual */
  324. BOOL
  325. CIPAccessDescriptorListBox::Initialize()
  326. /*++
  327. Routine Description:
  328. Initialize the listbox. Insert the columns as requested, and lay
  329. them out appropriately
  330. Arguments:
  331. None
  332. Return Value:
  333. TRUE for succesful initialisation, FALSE otherwise
  334. --*/
  335. {
  336. if (!CHeaderListBox::Initialize())
  337. {
  338. return FALSE;
  339. }
  340. //
  341. // Build all columns
  342. //
  343. HINSTANCE hInst = AfxGetResourceHandle();
  344. for (int nCol = 0; nCol < NUM_COLUMNS; ++nCol)
  345. {
  346. InsertColumn(nCol, g_aColumns[nCol].nWeight, g_aColumns[nCol].nLabelID, hInst);
  347. }
  348. //
  349. // Try to set the widths from the stored registry value,
  350. // otherwise distribute according to column weights specified
  351. //
  352. // if (!SetWidthsFromReg())
  353. // {
  354. DistributeColumns();
  355. // }
  356. return TRUE;
  357. }
  358. //
  359. // CAccessEntryListBox - a listbox of user SIDs
  360. //
  361. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  362. IMPLEMENT_DYNAMIC(CAccessEntryListBox, CRMCListBox);
  363. const int CAccessEntryListBox::nBitmaps = 8;
  364. void
  365. CAccessEntryListBox::DrawItemEx(
  366. IN CRMCListBoxDrawStruct & ds
  367. )
  368. /*++
  369. Routine Description:
  370. Draw item in the listbox
  371. Arguments:
  372. CRMCListBoxDrawStruct & ds : Input data structure
  373. Return Value:
  374. N/A
  375. --*/
  376. {
  377. CAccessEntry * pEntry = (CAccessEntry *)ds.m_ItemData;
  378. ASSERT_READ_PTR(pEntry);
  379. ASSERT(pEntry->IsSIDResolved());
  380. DrawBitmap(ds, 0, pEntry->QueryPictureID());
  381. ColumnText(ds, 0, TRUE, pEntry->QueryUserName());
  382. }
  383. void
  384. CAccessEntryListBox::FillAccessListBox(
  385. IN CObListPlus & obl
  386. )
  387. /*++
  388. Routine Description:
  389. Fill a listbox with entries from the oblist.
  390. Entries will not be shown if the deleted flag is set, or if
  391. their access mask does not fit with the requested access mask.
  392. Arguments:
  393. CObListPlus & obl : List of access entries
  394. Return Value:
  395. None.
  396. --*/
  397. {
  398. CObListIter obli(obl);
  399. CAccessEntry * pAccessEntry;
  400. //
  401. // Remember the selection.
  402. //
  403. CAccessEntry * pSelEntry = GetSelectedItem();
  404. SetRedraw(FALSE);
  405. ResetContent();
  406. int cItems = 0;
  407. for ( /**/ ; pAccessEntry = (CAccessEntry *)obli.Next(); ++cItems)
  408. {
  409. if (pAccessEntry->IsVisible() && !pAccessEntry->IsDeleted())
  410. {
  411. AddItem(pAccessEntry);
  412. }
  413. }
  414. SetRedraw(TRUE);
  415. SelectItem(pSelEntry);
  416. }
  417. void
  418. CAccessEntryListBox::ResolveAccessList(
  419. IN CObListPlus &obl
  420. )
  421. /*++
  422. Routine Description:
  423. For each member of the list, resolve the SID into a username.
  424. Arguments:
  425. CObListPlus & obl : List of access entries
  426. Return Value:
  427. None.
  428. --*/
  429. {
  430. CObListIter obli(obl);
  431. CAccessEntry * pAccessEntry;
  432. while (pAccessEntry = (CAccessEntry *)obli.Next())
  433. {
  434. if (!pAccessEntry->IsSIDResolved())
  435. {
  436. pAccessEntry->ResolveSID();
  437. }
  438. }
  439. }
  440. BOOL
  441. CAccessEntryListBox::AddUserPermissions(
  442. IN LPCTSTR lpstrServer,
  443. IN CObListPlus &oblSID,
  444. IN CAccessEntry * newUser,
  445. IN ACCESS_MASK accPermissions
  446. )
  447. /*++
  448. Routine Description:
  449. Add a user to the service list. The return value is
  450. what would be its listbox index.
  451. Arguments:
  452. LPCTSTR lpstrServer : Server name
  453. CObListPlus &oblSID : List of SIDs
  454. CAccessEntry * newUser : User details from user browser
  455. ACCESS_MASK accPermissions : Access permissions
  456. Return Value:
  457. TRUE for success, FALSE for failure.
  458. --*/
  459. {
  460. CAccessEntry * pAccessEntry;
  461. //
  462. // Look it up in the list to see if it exists already
  463. //
  464. CObListIter obli(oblSID);
  465. while(pAccessEntry = (CAccessEntry *)obli.Next())
  466. {
  467. if (*pAccessEntry == newUser->GetSid())
  468. {
  469. TRACEEOLID("Found existing account -- adding permissions");
  470. if (pAccessEntry->IsDeleted())
  471. {
  472. //
  473. // Back again..
  474. //
  475. pAccessEntry->FlagForDeletion(FALSE);
  476. }
  477. break;
  478. }
  479. }
  480. if (pAccessEntry == NULL)
  481. {
  482. //
  483. // I am creating new entry here to be sure that I could delete
  484. // it from the input array. The SID is copied to new entry.
  485. //
  486. pAccessEntry = new CAccessEntry(*newUser);
  487. if (pAccessEntry)
  488. {
  489. pAccessEntry->MarkEntryAsNew();
  490. oblSID.AddTail(pAccessEntry);
  491. }
  492. else
  493. {
  494. return FALSE;
  495. }
  496. }
  497. pAccessEntry->AddPermissions(accPermissions);
  498. return TRUE;
  499. }
  500. /*
  501. BOOL
  502. CAccessEntryListBox::AddUserPermissions(
  503. IN LPCTSTR lpstrServer,
  504. IN CObListPlus &oblSID,
  505. IN LPUSERDETAILS pusdtNewUser,
  506. IN ACCESS_MASK accPermissions
  507. )
  508. /*++
  509. Routine Description:
  510. Add a user to the service list. The return value is
  511. the what would be its listbox index.
  512. Arguments:
  513. LPCTSTR lpstrServer : Server name
  514. CObListPlus &oblSID : List of SIDs
  515. LPUSERDETAILS pusdtNewUser : User details from user browser
  516. ACCESS_MASK accPermissions : Access permissions
  517. Return Value:
  518. TRUE for success, FALSE for failure.
  519. --/
  520. {
  521. //
  522. // Look it up in the list to see if it exists already
  523. //
  524. CObListIter obli(oblSID);
  525. CAccessEntry * pAccessEntry;
  526. while(pAccessEntry = (CAccessEntry *)obli.Next())
  527. {
  528. if (*pAccessEntry == pusdtNewUser->psidUser)
  529. {
  530. TRACEEOLID("Found existing account -- adding permissions");
  531. if (pAccessEntry->IsDeleted())
  532. {
  533. //
  534. // Back again..
  535. //
  536. pAccessEntry->FlagForDeletion(FALSE);
  537. }
  538. break;
  539. }
  540. }
  541. if (pAccessEntry == NULL)
  542. {
  543. TRACEEOLID("This account did not yet exist -- adding new one");
  544. pAccessEntry = new CAccessEntry(accPermissions,
  545. pusdtNewUser->psidUser,
  546. lpstrServer,
  547. TRUE
  548. );
  549. if (!pAccessEntry)
  550. {
  551. TRACEEOLID("AddUserPermissions: OOM");
  552. return FALSE;
  553. }
  554. pAccessEntry->MarkEntryAsNew();
  555. oblSID.AddTail(pAccessEntry);
  556. }
  557. else
  558. {
  559. pAccessEntry->AddPermissions(accPermissions);
  560. }
  561. return TRUE;
  562. }
  563. */
  564. BOOL
  565. CAccessEntryListBox::AddToAccessList(
  566. IN CWnd * pWnd,
  567. IN LPCTSTR lpstrServer,
  568. OUT CObListPlus & obl
  569. )
  570. /*++
  571. Routine Description:
  572. Bring up the Add Users and Groups dialogs from netui.
  573. Arguments:
  574. CWnd * pWnd : Parent window
  575. LPCTSTR lpstrServer : Server that owns the accounts
  576. CObListPlus & obl : Returns the list of selected users.
  577. Return Value:
  578. TRUE if anything was added, FALSE otherwise.
  579. --*/
  580. {
  581. CGetUsers usrBrowser(lpstrServer, TRUE);
  582. BOOL bRes = usrBrowser.GetUsers(pWnd->GetSafeHwnd());
  583. UINT cItems = 0;
  584. if (bRes)
  585. {
  586. //
  587. // Specify access mask for an operator
  588. //
  589. ACCESS_MASK accPermissions =
  590. (MD_ACR_READ | MD_ACR_WRITE | MD_ACR_ENUM_KEYS);
  591. for (int i = 0; i < usrBrowser.GetSize(); i++)
  592. {
  593. if (!AddUserPermissions(lpstrServer, obl, usrBrowser[i], accPermissions))
  594. {
  595. bRes = FALSE;
  596. break;
  597. }
  598. cItems++;
  599. }
  600. }
  601. if (cItems > 0)
  602. {
  603. FillAccessListBox(obl);
  604. }
  605. return bRes;
  606. }
  607. CDnsNameDlg::CDnsNameDlg(
  608. IN CIPAddressCtrl * pIpControl OPTIONAL,
  609. IN CWnd * pParent OPTIONAL
  610. )
  611. /*++
  612. Routine Description:
  613. Construct with optional associated IP address control
  614. Arguments:
  615. CWndIpAddress * pIpControl : Associated IP control
  616. CWnd * pParent : Pointer to parent window
  617. Return Value:
  618. N/A
  619. --*/
  620. : m_pIpControl(pIpControl),
  621. m_dwIPValue(0L),
  622. CDialog(CDnsNameDlg::IDD, pParent)
  623. {
  624. #if 0 // Keep class wizard happy
  625. //{{AFX_DATA_INIT(CDnsNameDlg)
  626. //}}AFX_DATA_INIT
  627. #endif // 0
  628. if (m_pIpControl)
  629. {
  630. m_pIpControl->GetAddress(m_dwIPValue);
  631. }
  632. }
  633. CDnsNameDlg::CDnsNameDlg(
  634. IN DWORD dwIPValue,
  635. IN CWnd * pParent OPTIONAL
  636. )
  637. /*++
  638. Routine Description:
  639. Construct with associated IP value
  640. Arguments:
  641. DWORD dwIPValue : IP Value
  642. CWnd * pParent : Pointer to parent window
  643. Return Value:
  644. N/A
  645. --*/
  646. : m_pIpControl(NULL),
  647. m_dwIPValue(dwIPValue),
  648. CDialog(CDnsNameDlg::IDD, pParent)
  649. {
  650. }
  651. void
  652. CDnsNameDlg::DoDataExchange(
  653. IN CDataExchange * pDX
  654. )
  655. /*++
  656. Routine Description:
  657. Initialise/Store control data
  658. Arguments:
  659. CDataExchange * pDX - DDX/DDV control structure
  660. Return Value:
  661. None
  662. --*/
  663. {
  664. CDialog::DoDataExchange(pDX);
  665. //{{AFX_DATA_MAP(CDnsNameDlg)
  666. DDX_Control(pDX, IDC_EDIT_DNS_NAME, m_edit_DNSName);
  667. DDX_Control(pDX, IDOK, m_button_OK);
  668. //}}AFX_DATA_MAP
  669. }
  670. //
  671. // Message Map
  672. //
  673. BEGIN_MESSAGE_MAP(CDnsNameDlg, CDialog)
  674. //{{AFX_MSG_MAP(CDnsNameDlg)
  675. ON_EN_CHANGE(IDC_EDIT_DNS_NAME, OnChangeEditDnsName)
  676. //}}AFX_MSG_MAP
  677. END_MESSAGE_MAP()
  678. DWORD
  679. CDnsNameDlg::FillIpControlFromName()
  680. /*++
  681. Routine Description:
  682. Do a DNS lookup from the hostname in the edit control, and place
  683. the ip value in the ip control if we have one.
  684. Arguments:
  685. None
  686. Return Value:
  687. Error return code
  688. --*/
  689. {
  690. CString str;
  691. DWORD err = 0;
  692. HOSTENT * pHostent = NULL;
  693. m_edit_DNSName.GetWindowText(str);
  694. BeginWaitCursor();
  695. #ifdef _UNICODE
  696. CHAR * pAnsi = AllocAnsiString(str);
  697. if (pAnsi == NULL)
  698. {
  699. return ERROR_NOT_ENOUGH_MEMORY;
  700. }
  701. pHostent = ::gethostbyname(pAnsi);
  702. #else
  703. pHostent = ::gethostbyname((LPCTSTR)str);
  704. #endif // _UNICODE;
  705. if (pHostent != NULL)
  706. {
  707. //
  708. // Got a valid lookup. Convert the value to host order,
  709. // optionally set the value in the associated ip control
  710. //
  711. m_dwIPValue = ::ntohl(*((u_long *)pHostent->h_addr_list[0]));
  712. if (m_pIpControl)
  713. {
  714. m_pIpControl->SetAddress(m_dwIPValue);
  715. }
  716. }
  717. else
  718. {
  719. err = ::WSAGetLastError();
  720. }
  721. EndWaitCursor();
  722. #ifdef _UNICODE
  723. FreeMem(pAnsi);
  724. #endif // _UNICODE
  725. return err;
  726. }
  727. DWORD
  728. CDnsNameDlg::FillNameFromIpValue()
  729. /*++
  730. Routine Description:
  731. Given the ip value, fill, do a reverse lookup, and fill the name in
  732. the edit control.
  733. Arguments:
  734. None
  735. Return Value:
  736. Error return code
  737. --*/
  738. {
  739. DWORD err = ERROR_SUCCESS;
  740. if (m_dwIPValue == 0L)
  741. {
  742. //
  743. // Don't bother filling this
  744. // one in -- not an error, though
  745. //
  746. return err;
  747. }
  748. //
  749. // Call the Winsock API to get host name and alias information.
  750. //
  751. u_long ulAddrInNetOrder = ::htonl((u_long)m_dwIPValue);
  752. BeginWaitCursor();
  753. HOSTENT * pHostInfo = ::gethostbyaddr(
  754. (CHAR *)&ulAddrInNetOrder,
  755. sizeof ulAddrInNetOrder,
  756. PF_INET
  757. );
  758. EndWaitCursor();
  759. if (pHostInfo == NULL)
  760. {
  761. return ::WSAGetLastError();
  762. }
  763. try
  764. {
  765. CString str(pHostInfo->h_name);
  766. m_edit_DNSName.SetWindowText(str);
  767. }
  768. catch(CException * e)
  769. {
  770. err = ::GetLastError();
  771. e->Delete();
  772. }
  773. return err;
  774. }
  775. //
  776. // Message Handlers
  777. //
  778. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  779. void
  780. CDnsNameDlg::OnOK()
  781. /*++
  782. Routine Description:
  783. Attempt to resolve the the IP address in response to the OK button
  784. being pressed. Don't dismiss the dialog if the name is not
  785. resolvable.
  786. Arguments:
  787. None
  788. Return Value:
  789. None
  790. --*/
  791. {
  792. CError err(FillIpControlFromName());
  793. if (err.Failed())
  794. {
  795. UINT errId = 0;
  796. if (err.Win32Error() == WSAHOST_NOT_FOUND)
  797. {
  798. errId = IDS_WSAHOST_NOT_FOUND;
  799. }
  800. if (errId == 0)
  801. {
  802. err.MessageBoxOnFailure();
  803. }
  804. else
  805. {
  806. ::AfxMessageBox(errId);
  807. }
  808. //
  809. // Failed, don't dismiss the dialog
  810. //
  811. return;
  812. }
  813. //
  814. // Dismiss the dialog
  815. //
  816. CDialog::OnOK();
  817. }
  818. void
  819. CDnsNameDlg::OnChangeEditDnsName()
  820. /*++
  821. Routine Description:
  822. Enable/disable the ok button depending on the contents of the edit control.
  823. Arguments:
  824. None
  825. Return Value:
  826. None
  827. --*/
  828. {
  829. m_button_OK.EnableWindow(m_edit_DNSName.GetWindowTextLength() > 0);
  830. }
  831. BOOL
  832. CDnsNameDlg::OnInitDialog()
  833. /*++
  834. Routine Description:
  835. WM_INITDIALOG handler. Initialize the dialog.
  836. Arguments:
  837. None.
  838. Return Value:
  839. TRUE if focus is to be set automatically, FALSE if the focus
  840. is already set.
  841. --*/
  842. {
  843. CDialog::OnInitDialog();
  844. //
  845. // If an address has been pre-set do a reverse lookup
  846. //
  847. if (m_dwIPValue)
  848. {
  849. CError err(FillNameFromIpValue());
  850. err.MessageBoxOnFailure();
  851. }
  852. OnChangeEditDnsName();
  853. return TRUE;
  854. }
  855. //
  856. // IP Access Dialog
  857. //
  858. CIPAccessDlg::CIPAccessDlg(
  859. IN BOOL fDenyAccessMode,
  860. IN OUT CIPAccessDescriptor *& pAccess,
  861. IN CObListPlus * poblAccessList OPTIONAL,
  862. IN CWnd * pParent OPTIONAL,
  863. IN BOOL fAllowDomains
  864. )
  865. /*++
  866. Routine Description:
  867. Constructor for the access descriptor editor dialog. If constructed
  868. with a NULL access descriptor pointer, the access descriptor will
  869. be allocated, otherwise the dialog will edit the existing one in
  870. place.
  871. Arguments:
  872. BOOL fDenyAccessMode : If TRUE, we're denying access, if FALSE,
  873. we're granting access.
  874. CIPAccessDescriptor *& pAccess : Object being edited, or NULL to allocate
  875. a new access descriptor
  876. CObListPlus * poblAccessList : List of already existing entries to check
  877. for duplicates, or NULL
  878. CWnd * pParent, : Pointer to parent window or NULL
  879. BOOL fAllowDomains : If TRUE, domain names are valid, otherwise
  880. they will not be available
  881. Return Value:
  882. N/A
  883. --*/
  884. : CDialog(CIPAccessDlg::IDD, pParent),
  885. m_pAccess(pAccess),
  886. m_poblAccessList(poblAccessList),
  887. m_fNew(pAccess == NULL),
  888. m_fDenyAccessMode(fDenyAccessMode),
  889. m_fAllowDomains(fAllowDomains)
  890. {
  891. #if 0 // Keep Class Wizard happy
  892. //{{AFX_DATA_INIT(CIPAccessDlg)
  893. m_nStyle = RADIO_SINGLE;
  894. //}}AFX_DATA_INIT
  895. #endif // 0
  896. if (m_pAccess == NULL)
  897. {
  898. //
  899. // Allocate new one
  900. //
  901. m_pAccess = new CIPAccessDescriptor;
  902. if (m_pAccess)
  903. {
  904. m_pAccess->GrantAccess(!m_fDenyAccessMode);
  905. }
  906. }
  907. if (m_pAccess == NULL)
  908. {
  909. TRACEEOLID("Invalid access object -- possible memory failure");
  910. return;
  911. }
  912. if (m_pAccess->IsDomainName())
  913. {
  914. m_nStyle = RADIO_DOMAIN;
  915. }
  916. else
  917. {
  918. m_nStyle = m_pAccess->IsSingle() ? RADIO_SINGLE : RADIO_MULTIPLE;
  919. }
  920. //
  921. // We can only look at granted items when
  922. // deny by default is on and vice versa
  923. //
  924. ASSERT(m_pAccess->HasAccess() == !m_fDenyAccessMode);
  925. //
  926. // Load static strings
  927. //
  928. VERIFY(m_bstrIPAddress.LoadString(IDS_PROMPT_IP_ADDRESS));
  929. VERIFY(m_bstrNetworkID.LoadString(IDS_PROMPT_NETWORK_ID));
  930. VERIFY(m_bstrDomainName.LoadString(IDS_PROMPT_DOMAIN));
  931. }
  932. void
  933. CIPAccessDlg::DoDataExchange(
  934. IN CDataExchange * pDX
  935. )
  936. /*++
  937. Routine Description:
  938. Initialise/Store control data
  939. Arguments:
  940. CDataExchange * pDX - DDX/DDV control structure
  941. Return Value:
  942. None
  943. --*/
  944. {
  945. CDialog::DoDataExchange(pDX);
  946. //{{AFX_DATA_MAP(CIPAccessDlg)
  947. DDX_Control(pDX, IDOK, m_button_OK);
  948. DDX_Control(pDX, IDC_EDIT_DOMAIN, m_edit_Domain);
  949. DDX_Control(pDX, IDC_STATIC_IP_ADDRESS, m_static_IpAddress);
  950. DDX_Control(pDX, IDC_STATIC_SUBNET_MASK, m_static_SubnetMask);
  951. DDX_Control(pDX, IDC_BUTTON_DNS, m_button_DNS);
  952. DDX_Radio(pDX, IDC_RADIO_SINGLE, m_nStyle);
  953. //}}AFX_DATA_MAP
  954. DDX_Control(pDX, IDC_RADIO_DOMAIN, m_radio_Domain);
  955. DDX_Control(pDX, IDC_IPA_IPADDRESS, m_ipa_IPAddress);
  956. DDX_Control(pDX, IDC_IPA_SUBNET_MASK, m_ipa_SubnetMask);
  957. }
  958. //
  959. // Message Map
  960. //
  961. BEGIN_MESSAGE_MAP(CIPAccessDlg, CDialog)
  962. //{{AFX_MSG_MAP(CIPAccessDlg)
  963. ON_BN_CLICKED(IDC_RADIO_MULTIPLE, OnRadioMultiple)
  964. ON_BN_CLICKED(IDC_RADIO_SINGLE, OnRadioSingle)
  965. ON_BN_CLICKED(IDC_RADIO_DOMAIN, OnRadioDomain)
  966. ON_BN_CLICKED(IDC_BUTTON_DNS, OnButtonDns)
  967. //}}AFX_MSG_MAP
  968. ON_EN_CHANGE(IDC_IPA_IPADDRESS, OnItemChanged)
  969. ON_EN_CHANGE(IDC_IPA_SUBNET_MASK, OnItemChanged)
  970. ON_EN_CHANGE(IDC_EDIT_DOMAIN, OnItemChanged)
  971. END_MESSAGE_MAP()
  972. void
  973. CIPAccessDlg::SetControlStates(
  974. IN int nStyle
  975. )
  976. /*++
  977. Routine Description:
  978. Show/hide controls depending on the type of access descriptor we're
  979. editing.
  980. Arguments:
  981. int nStyle : Radio button style
  982. Return Value:
  983. None
  984. --*/
  985. {
  986. m_nStyle = nStyle;
  987. ActivateControl(m_ipa_IPAddress, m_nStyle != RADIO_DOMAIN);
  988. ActivateControl(m_static_SubnetMask, m_nStyle == RADIO_MULTIPLE);
  989. ActivateControl(m_ipa_SubnetMask, m_nStyle == RADIO_MULTIPLE);
  990. ActivateControl(m_button_DNS, m_nStyle == RADIO_SINGLE);
  991. ActivateControl(m_edit_Domain, m_nStyle == RADIO_DOMAIN);
  992. //
  993. // Change the prompt over the editbox/ip address box to explain
  994. // what's supposed to be edited.
  995. //
  996. switch(m_nStyle)
  997. {
  998. case RADIO_SINGLE:
  999. m_static_IpAddress.SetWindowText(m_bstrIPAddress);
  1000. break;
  1001. case RADIO_MULTIPLE:
  1002. m_static_IpAddress.SetWindowText(m_bstrNetworkID);
  1003. break;
  1004. case RADIO_DOMAIN:
  1005. ASSERT(m_fAllowDomains);
  1006. m_static_IpAddress.SetWindowText(m_bstrDomainName);
  1007. break;
  1008. }
  1009. }
  1010. //
  1011. // Message Handlers
  1012. //
  1013. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1014. BOOL
  1015. CIPAccessDlg::OnInitDialog()
  1016. /*++
  1017. Routine Description:
  1018. WM_INITDIALOG handler. Initialize the dialog.
  1019. Arguments:
  1020. None.
  1021. Return Value:
  1022. TRUE if no focus is to be set automatically, FALSE if the focus
  1023. is already set.
  1024. --*/
  1025. {
  1026. CDialog::OnInitDialog();
  1027. ASSERT_READ_PTR(m_pAccess);
  1028. if (m_pAccess == NULL)
  1029. {
  1030. CError err(ERROR_NOT_ENOUGH_MEMORY);
  1031. TRACEEOLID("access descriptor is NULL -- aborting dialog");
  1032. err.MessageBox();
  1033. EndDialog(IDCANCEL);
  1034. return FALSE;
  1035. }
  1036. //
  1037. // Domain selection not always available
  1038. //
  1039. ASSERT(!(!m_fAllowDomains && m_pAccess->IsDomainName()));
  1040. ActivateControl(m_radio_Domain, m_fAllowDomains);
  1041. //
  1042. // Use an appropriate title for the dialog depending on
  1043. // whether we're editing a 'grant' item or a 'deny' item
  1044. //
  1045. CComBSTR bstrTitle;
  1046. VERIFY(bstrTitle.LoadString(m_fDenyAccessMode ? IDS_DENY : IDS_GRANT));
  1047. SetWindowText(bstrTitle);
  1048. //
  1049. // Set fields to be edited
  1050. //
  1051. if (m_pAccess->IsDomainName())
  1052. {
  1053. m_edit_Domain.SetWindowText(m_pAccess->QueryDomainName());
  1054. }
  1055. else
  1056. {
  1057. DWORD dwIP = m_pAccess->QueryIPAddress();
  1058. if (dwIP != 0L)
  1059. {
  1060. m_ipa_IPAddress.SetAddress(m_pAccess->QueryIPAddress());
  1061. }
  1062. if (!m_pAccess->IsSingle())
  1063. {
  1064. m_ipa_SubnetMask.SetAddress(m_pAccess->QuerySubnetMask());
  1065. }
  1066. }
  1067. //
  1068. // Configure the dialog appropriately
  1069. //
  1070. SetControlStates(m_nStyle);
  1071. //
  1072. // No changes made yet
  1073. //
  1074. m_button_OK.EnableWindow(FALSE);
  1075. return TRUE;
  1076. }
  1077. void
  1078. CIPAccessDlg::OnRadioSingle()
  1079. /*++
  1080. Routine Description:
  1081. 'Single' radio button has been pressed. Change dialog style
  1082. appropriately.
  1083. Arguments:
  1084. None
  1085. Return Value:
  1086. None
  1087. --*/
  1088. {
  1089. SetControlStates(RADIO_SINGLE);
  1090. OnItemChanged();
  1091. }
  1092. void
  1093. CIPAccessDlg::OnRadioMultiple()
  1094. /*++
  1095. Routine Description:
  1096. 'Multiple' radio button has been pressed. Change dialog style
  1097. appropriately.
  1098. Arguments:
  1099. None
  1100. Return Value:
  1101. None
  1102. --*/
  1103. {
  1104. SetControlStates(RADIO_MULTIPLE);
  1105. OnItemChanged();
  1106. }
  1107. void
  1108. CIPAccessDlg::OnRadioDomain()
  1109. /*++
  1110. Routine Description:
  1111. 'Domain' radio button has been pressed. Change dialog style
  1112. appropriately. If this the first time domain has been pressed,
  1113. put up a warning about the performance implications of using
  1114. domain filtering.
  1115. Arguments:
  1116. None
  1117. Return Value:
  1118. None
  1119. --*/
  1120. {
  1121. ASSERT(m_fAllowDomains);
  1122. static BOOL fShownWarning = FALSE;
  1123. if (!fShownWarning)
  1124. {
  1125. fShownWarning = TRUE;
  1126. ::AfxMessageBox(IDS_DOMAIN_PERF);
  1127. }
  1128. SetControlStates(RADIO_DOMAIN);
  1129. OnItemChanged();
  1130. }
  1131. void
  1132. CIPAccessDlg::OnItemChanged()
  1133. /*++
  1134. Routine Description:
  1135. Control data has changed. Check to see if sufficient data have been
  1136. entered given the type of access descriptor being edited, and enable
  1137. or disable the OK button based on that result.
  1138. Arguments:
  1139. None
  1140. Return Value:
  1141. None
  1142. --*/
  1143. {
  1144. DWORD dwIP;
  1145. DWORD dwMask;
  1146. BOOL fOK = FALSE;
  1147. CString strDomain;
  1148. switch(m_nStyle)
  1149. {
  1150. case RADIO_DOMAIN:
  1151. m_edit_Domain.GetWindowText(strDomain);
  1152. fOK = !strDomain.IsEmpty();
  1153. break;
  1154. case RADIO_SINGLE:
  1155. m_ipa_IPAddress.GetAddress(dwIP);
  1156. fOK = (dwIP != 0L);
  1157. break;
  1158. case RADIO_MULTIPLE:
  1159. m_ipa_IPAddress.GetAddress(dwIP);
  1160. m_ipa_SubnetMask.GetAddress(dwMask);
  1161. fOK = (dwIP != 0L && dwMask != 0L);
  1162. break;
  1163. }
  1164. m_button_OK.EnableWindow(fOK);
  1165. }
  1166. void
  1167. CIPAccessDlg::OnButtonDns()
  1168. /*++
  1169. Routine Description:
  1170. 'DNS' Button was pressed. Bring up the DNS name resolver dialog
  1171. which will set the value in the associated IP address control.
  1172. Arguments:
  1173. None
  1174. Return Value:
  1175. None
  1176. --*/
  1177. {
  1178. //
  1179. // Ask for a DNS name to resolve to an IP address. The ip address
  1180. // control is passed along to the dns name dialog which will manage
  1181. // the ip addresses in it automatically.
  1182. //
  1183. CDnsNameDlg dlg(&m_ipa_IPAddress);
  1184. dlg.DoModal();
  1185. }
  1186. void
  1187. CIPAccessDlg::OnCancel()
  1188. /*++
  1189. Routine Description:
  1190. IDCANCEL handler. If we had allocated the access descriptor, throw it
  1191. away now.
  1192. Arguments:
  1193. None
  1194. Return Value:
  1195. None
  1196. --*/
  1197. {
  1198. if (m_fNew && m_pAccess != NULL)
  1199. {
  1200. delete m_pAccess;
  1201. m_pAccess = NULL;
  1202. }
  1203. CDialog::OnCancel();
  1204. }
  1205. void
  1206. CIPAccessDlg::OnOK()
  1207. /*++
  1208. Routine Description:
  1209. Handler for IDOK. Save control data to the access descriptor object
  1210. being edited. If we have a list of access descriptors, check for
  1211. duplicates.
  1212. Arguments:
  1213. None
  1214. Return Value:
  1215. None
  1216. --*/
  1217. {
  1218. //
  1219. // Must have been allocated by now.
  1220. //
  1221. ASSERT_READ_PTR(m_pAccess);
  1222. UpdateData(TRUE);
  1223. if (m_nStyle == RADIO_DOMAIN)
  1224. {
  1225. CString strDomain;
  1226. m_edit_Domain.GetWindowText(strDomain);
  1227. //
  1228. // Ensure that wildcards are used only in the first char
  1229. // of the name, or not at all.
  1230. //
  1231. int nWildCard;
  1232. if ((nWildCard = strDomain.ReverseFind(_T('*'))) != -1)
  1233. {
  1234. if (nWildCard != 0
  1235. || strDomain.GetLength() < 3
  1236. || strDomain[1] != _T('.'))
  1237. {
  1238. //
  1239. // Don't dismiss
  1240. //
  1241. m_edit_Domain.SetFocus();
  1242. m_edit_Domain.SetSel(0,-1);
  1243. ::AfxMessageBox(IDS_INVALID_DOMAIN_NAME);
  1244. return;
  1245. }
  1246. }
  1247. m_pAccess->SetValues(!m_fDenyAccessMode, strDomain);
  1248. }
  1249. else
  1250. {
  1251. DWORD dwIP;
  1252. m_ipa_IPAddress.GetAddress(dwIP);
  1253. //
  1254. // Filter out bogus ip addresses
  1255. //
  1256. if (dwIP == 0L || dwIP == (DWORD)-1L)
  1257. {
  1258. //
  1259. // Don't dismiss the dialog
  1260. //
  1261. m_ipa_IPAddress.SetFocus();
  1262. ::AfxMessageBox(IDS_IP_INVALID);
  1263. return;
  1264. }
  1265. if (m_nStyle == RADIO_SINGLE)
  1266. {
  1267. m_pAccess->SetValues(!m_fDenyAccessMode, dwIP);
  1268. }
  1269. else // Multiple
  1270. {
  1271. DWORD dwMask;
  1272. m_ipa_SubnetMask.GetAddress(dwMask);
  1273. m_pAccess->SetValues(!m_fDenyAccessMode, dwIP, dwMask);
  1274. }
  1275. }
  1276. //
  1277. // Check for duplicates in the list
  1278. //
  1279. if (m_poblAccessList)
  1280. {
  1281. if (m_pAccess->DuplicateInList(*m_poblAccessList))
  1282. {
  1283. //
  1284. // Found duplicate; don't dismiss the dialog
  1285. //
  1286. ::AfxMessageBox(IDS_DUPLICATE_ENTRY);
  1287. return;
  1288. }
  1289. }
  1290. //
  1291. // Everything ok -- dismiss the dialog.
  1292. //
  1293. EndDialog(IDOK);
  1294. }
  1295. void CALLBACK MsgBoxCallback(LPHELPINFO lpHelpInfo)
  1296. {
  1297. #ifdef _DEBUG
  1298. TCHAR szBuffer[30];
  1299. _stprintf(szBuffer,_T("AfxGetApp()->WinHelp:0x%x\n"),lpHelpInfo->dwContextId);OutputDebugString(szBuffer);
  1300. #endif
  1301. AfxGetApp()->WinHelp(lpHelpInfo->dwContextId);
  1302. }
  1303. // this version accepts a text string
  1304. UINT IisMessageBox(HWND hWnd, LPCTSTR szText, UINT nType, UINT nIDHelp = 0)
  1305. {
  1306. MSGBOXPARAMS mbp;
  1307. memset(&mbp, 0, sizeof mbp);
  1308. mbp.cbSize = sizeof MSGBOXPARAMS;
  1309. mbp.hwndOwner = hWnd;
  1310. mbp.hInstance = AfxGetInstanceHandle();
  1311. mbp.lpszText = szText;
  1312. // if you wanted to specify a different caption, here is where you do it
  1313. CString cap;
  1314. cap.LoadString(IDS_APP_NAME);
  1315. mbp.lpszCaption = cap;
  1316. // if Help ID is not 0, then add a help button
  1317. if (nIDHelp != 0)
  1318. {
  1319. mbp.dwStyle = nType | MB_HELP;
  1320. }
  1321. else
  1322. {
  1323. mbp.dwStyle = nType;
  1324. }
  1325. // mbp.lpszIcon = ; // note, you could provide your own custom ICON here!
  1326. mbp.dwContextHelpId = nIDHelp;
  1327. mbp.lpfnMsgBoxCallback = &MsgBoxCallback;
  1328. // mbp.dwLanguageId = 0x0409;
  1329. return ::MessageBoxIndirect(&mbp);
  1330. }
  1331. // this version accepts a resource string identifier
  1332. UINT IisMessageBox(HWND hWnd, UINT nIDText, UINT nType, UINT nIDHelp = 0)
  1333. {
  1334. CString s;
  1335. s.LoadString(nIDText);
  1336. return IisMessageBox(hWnd, s, nType, nIDHelp);
  1337. }