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.

855 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. facc.cpp
  5. Abstract:
  6. FTP Accounts Property Page
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #include "inetprop.h"
  19. #include "InetMgrApp.h"
  20. #include "supdlgs.h"
  21. #include "shts.h"
  22. #include "ftpsht.h"
  23. #include "facc.h"
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char BASED_CODE THIS_FILE[] = __FILE__;
  27. #endif
  28. IMPLEMENT_DYNCREATE(CFtpAccountsPage, CInetPropertyPage)
  29. CFtpAccountsPage::CFtpAccountsPage(
  30. IN CInetPropertySheet * pSheet
  31. )
  32. /*++
  33. Routine Description:
  34. Constructor for FTP service property page
  35. Arguments:
  36. CInetPropertySheet * pSheet : Associated property sheet
  37. Return Value:
  38. N/A
  39. --*/
  40. : CInetPropertyPage(CFtpAccountsPage::IDD, pSheet),
  41. m_ListBoxRes(
  42. IDB_ACLUSERS,
  43. CAccessEntryListBox::nBitmaps
  44. ),
  45. m_oblSID(),
  46. m_fPasswordSyncChanged(FALSE),
  47. m_fUserNameChanged(FALSE),
  48. m_fPasswordSyncMsgShown(FALSE)
  49. {
  50. #ifdef _DEBUG
  51. afxMemDF |= checkAlwaysMemDF;
  52. #endif // _DEBUG
  53. #if 0 // Keep Class Wizard happy
  54. //{{AFX_DATA_INIT(CFtpAccountsPage)
  55. m_strUserName = _T("");
  56. m_fAllowAnonymous = TRUE;
  57. m_fOnlyAnonymous = FALSE;
  58. m_fPasswordSync = FALSE;
  59. //}}AFX_DATA_INIT
  60. #endif // 0
  61. m_list_Administrators.AttachResources(&m_ListBoxRes);
  62. }
  63. CFtpAccountsPage::~CFtpAccountsPage()
  64. /*++
  65. Routine Description:
  66. Destructor
  67. Arguments:
  68. N/A
  69. Return Value:
  70. N/A
  71. --*/
  72. {
  73. }
  74. void
  75. CFtpAccountsPage::DoDataExchange(
  76. IN CDataExchange * pDX
  77. )
  78. /*++
  79. Routine Description:
  80. Initialise/Store control data
  81. Arguments:
  82. CDataExchange * pDX - DDX/DDV control structure
  83. Return Value:
  84. None
  85. --*/
  86. {
  87. CInetPropertyPage::DoDataExchange(pDX);
  88. //{{AFX_DATA_MAP(CFtpAccountsPage)
  89. DDX_Check(pDX, IDC_CHECK_ALLOW_ANONYMOUS, m_fAllowAnonymous);
  90. DDX_Check(pDX, IDC_CHECK_ONLY_ANYMOUS, m_fOnlyAnonymous);
  91. DDX_Check(pDX, IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, m_fPasswordSync);
  92. DDX_Control(pDX, IDC_BUTTON_ADD, m_button_Add);
  93. DDX_Control(pDX, IDC_EDIT_PASSWORD, m_edit_Password);
  94. DDX_Control(pDX, IDC_EDIT_USERNAME, m_edit_UserName);
  95. DDX_Control(pDX, IDC_STATIC_PW, m_static_Password);
  96. DDX_Control(pDX, IDC_STATIC_USERNAME, m_static_UserName);
  97. DDX_Control(pDX, IDC_STATIC_ACCOUNT_PROMPT, m_static_AccountPrompt);
  98. DDX_Control(pDX, IDC_BUTTON_CHECK_PASSWORD, m_button_CheckPassword);
  99. DDX_Control(pDX, IDC_BUTTON_BROWSE_USER, m_button_Browse);
  100. DDX_Control(pDX, IDC_BUTTON_DELETE, m_button_RemoveAdministrator);
  101. DDX_Control(pDX, IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, m_chk_PasswordSync);
  102. DDX_Control(pDX, IDC_CHECK_ALLOW_ANONYMOUS, m_chk_AllowAnymous);
  103. DDX_Control(pDX, IDC_CHECK_ONLY_ANYMOUS, m_chk_OnlyAnonymous);
  104. //}}AFX_DATA_MAP
  105. //
  106. // Private DDX/DDV Routines
  107. //
  108. DDX_Control(pDX, IDC_LIST_ADMINISTRATORS, m_list_Administrators);
  109. //
  110. // Set password/username only during load stage,
  111. // or if saving when allowing anonymous logons
  112. //
  113. if (!pDX->m_bSaveAndValidate || m_fAllowAnonymous)
  114. {
  115. DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUserName);
  116. DDV_MinMaxChars(pDX, m_strUserName, 1, UNLEN);
  117. //
  118. // Some people have a tendency to add "\\" before
  119. // the computer name in user accounts. Fix this here.
  120. //
  121. m_strUserName.TrimLeft();
  122. while (*m_strUserName == '\\')
  123. {
  124. m_strUserName = m_strUserName.Mid(2);
  125. }
  126. //
  127. // Display the remote password sync message if
  128. // password sync is on, the account is not local,
  129. // password sync has changed or username has changed
  130. // and the message hasn't already be shown.
  131. //
  132. if (pDX->m_bSaveAndValidate && m_fPasswordSync
  133. && !IsLocalAccount(m_strUserName)
  134. && (m_fPasswordSyncChanged || m_fUserNameChanged)
  135. && !m_fPasswordSyncMsgShown
  136. )
  137. {
  138. if (!NoYesMessageBox(IDS_WRN_PWSYNC))
  139. {
  140. pDX->Fail();
  141. }
  142. //
  143. // Don't show it again
  144. //
  145. m_fPasswordSyncMsgShown = TRUE;
  146. }
  147. if (!m_fPasswordSync || !pDX->m_bSaveAndValidate)
  148. {
  149. DDX_Password(
  150. pDX,
  151. IDC_EDIT_PASSWORD,
  152. m_strPassword,
  153. g_lpszDummyPassword
  154. );
  155. }
  156. if (!m_fPasswordSync)
  157. {
  158. DDV_MaxChars(pDX, m_strPassword, PWLEN);
  159. }
  160. }
  161. }
  162. //
  163. // Message Map
  164. //
  165. BEGIN_MESSAGE_MAP(CFtpAccountsPage, CInetPropertyPage)
  166. //{{AFX_MSG_MAP(CFtpAccountsPage)
  167. ON_BN_CLICKED(IDC_BUTTON_CHECK_PASSWORD, OnButtonCheckPassword)
  168. ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAdd)
  169. ON_CBN_SELCHANGE(IDC_LIST_ADMINISTRATORS, OnSelchangeListAdministrators)
  170. ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
  171. ON_BN_CLICKED(IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, OnCheckEnablePwSynchronization)
  172. ON_EN_CHANGE(IDC_EDIT_USERNAME, OnChangeEditUsername)
  173. //}}AFX_MSG_MAP
  174. ON_EN_CHANGE(IDC_EDIT_PASSWORD, OnItemChanged)
  175. ON_BN_CLICKED(IDC_CHECK_ALLOW_ANONYMOUS, OnCheckAllowAnonymous)
  176. ON_BN_CLICKED(IDC_CHECK_ONLY_ANYMOUS, OnCheckAllowOnlyAnonymous)
  177. ON_BN_CLICKED(IDC_BUTTON_BROWSE_USER, OnButtonBrowseUser)
  178. END_MESSAGE_MAP()
  179. void
  180. CFtpAccountsPage::SetControlStates(
  181. IN BOOL fAllowAnonymous
  182. )
  183. /*++
  184. Routine Description:
  185. Set the states of the dialog control depending on its current
  186. values.
  187. Arguments:
  188. BOOL fAllowAnonymous : If TRUE, 'allow anonymous' is on.
  189. Return Value:
  190. None
  191. --*/
  192. {
  193. m_static_Password.EnableWindow(
  194. fAllowAnonymous
  195. && !m_fPasswordSync
  196. && HasAdminAccess()
  197. );
  198. m_edit_Password.EnableWindow(
  199. fAllowAnonymous
  200. && !m_fPasswordSync
  201. && HasAdminAccess()
  202. );
  203. m_button_CheckPassword.EnableWindow(
  204. fAllowAnonymous
  205. && !m_fPasswordSync
  206. && HasAdminAccess()
  207. );
  208. m_static_AccountPrompt.EnableWindow(fAllowAnonymous);
  209. m_static_UserName.EnableWindow(fAllowAnonymous && HasAdminAccess());
  210. m_edit_UserName.EnableWindow(fAllowAnonymous && HasAdminAccess());
  211. m_button_Browse.EnableWindow(fAllowAnonymous && HasAdminAccess());
  212. m_chk_PasswordSync.EnableWindow(fAllowAnonymous && HasAdminAccess());
  213. m_chk_OnlyAnonymous.EnableWindow(fAllowAnonymous);
  214. }
  215. BOOL
  216. CFtpAccountsPage::SetAdminRemoveState()
  217. /*++
  218. Routine Description:
  219. Set the state of the remove button depending on the selection in the
  220. administrators listbox. Remove is only enabled if ALL selected
  221. items are removable.
  222. Arguments:
  223. None
  224. Return Value:
  225. TRUE if the remove button is enabled.
  226. --*/
  227. {
  228. int nSel = 0;
  229. int cSelectedItems = 0;
  230. BOOL fAllDeletable = TRUE;
  231. CAccessEntry * pAccess;
  232. while ((pAccess = m_list_Administrators.GetNextSelectedItem(&nSel)) != NULL)
  233. {
  234. ++cSelectedItems;
  235. if (!pAccess->IsDeletable())
  236. {
  237. fAllDeletable = FALSE;
  238. break;
  239. }
  240. ++nSel;
  241. }
  242. fAllDeletable = fAllDeletable && (cSelectedItems > 0);
  243. m_button_RemoveAdministrator.EnableWindow(
  244. fAllDeletable
  245. && HasOperatorList()
  246. && HasAdminAccess()
  247. );
  248. return fAllDeletable;
  249. }
  250. //
  251. // Message Handlers
  252. //
  253. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  254. BOOL
  255. CFtpAccountsPage::OnInitDialog()
  256. /*++
  257. Routine Description:
  258. WM_INITDIALOG handler. Initialize the dialog.
  259. Arguments:
  260. None.
  261. Return Value:
  262. TRUE if no focus is to be set automatically, FALSE if the focus
  263. is already set.
  264. --*/
  265. {
  266. CInetPropertyPage::OnInitDialog();
  267. m_list_Administrators.Initialize();
  268. CWaitCursor wait;
  269. //
  270. // Build the ACL list
  271. //
  272. CError err(BuildAclOblistFromBlob(
  273. ((CFtpSheet *)GetSheet())->GetInstanceProperties().m_acl,
  274. m_oblSID
  275. ));
  276. err.MessageBoxOnFailure();
  277. m_list_Administrators.FillAccessListBox(m_oblSID);
  278. //
  279. // check if the operators controls are accessible
  280. //
  281. m_button_Add.EnableWindow(HasOperatorList() && HasAdminAccess());
  282. m_list_Administrators.EnableWindow(HasOperatorList() && HasAdminAccess());
  283. GetDlgItem(IDC_STATIC_OPERATOR_PROMPT1)->EnableWindow(
  284. HasOperatorList()
  285. && HasAdminAccess()
  286. );
  287. GetDlgItem(IDC_STATIC_OPERATOR_PROMPT2)->EnableWindow(
  288. HasOperatorList()
  289. && HasAdminAccess()
  290. );
  291. SetControlStates(m_fAllowAnonymous);
  292. SetAdminRemoveState();
  293. return TRUE;
  294. }
  295. /* virtual */
  296. HRESULT
  297. CFtpAccountsPage::FetchLoadedValues()
  298. /*++
  299. Routine Description:
  300. Move configuration data from sheet to dialog controls
  301. Arguments:
  302. None
  303. Return Value:
  304. HRESULT
  305. --*/
  306. {
  307. CError err;
  308. BEGIN_META_INST_READ(CFtpSheet)
  309. FETCH_INST_DATA_FROM_SHEET(m_strUserName);
  310. FETCH_INST_DATA_FROM_SHEET(m_strPassword);
  311. FETCH_INST_DATA_FROM_SHEET(m_fAllowAnonymous);
  312. FETCH_INST_DATA_FROM_SHEET(m_fOnlyAnonymous);
  313. FETCH_INST_DATA_FROM_SHEET(m_fPasswordSync);
  314. END_META_INST_READ(err)
  315. return err;
  316. }
  317. /* virtual */
  318. HRESULT
  319. CFtpAccountsPage::SaveInfo()
  320. /*++
  321. Routine Description:
  322. Save the information on this property page
  323. Arguments:
  324. None
  325. Return Value:
  326. Error return code
  327. --*/
  328. {
  329. ASSERT(IsDirty());
  330. TRACEEOLID("Saving FTP service page now...");
  331. //
  332. // Use m_ notation because the message crackers require it
  333. //
  334. CBlob m_acl;
  335. BOOL fAclDirty = BuildAclBlob(m_oblSID, m_acl);
  336. CError err;
  337. BeginWaitCursor();
  338. BEGIN_META_INST_WRITE(CFtpSheet)
  339. STORE_INST_DATA_ON_SHEET(m_strUserName)
  340. STORE_INST_DATA_ON_SHEET(m_fOnlyAnonymous)
  341. STORE_INST_DATA_ON_SHEET(m_fAllowAnonymous)
  342. STORE_INST_DATA_ON_SHEET(m_fPasswordSync)
  343. if (fAclDirty)
  344. {
  345. STORE_INST_DATA_ON_SHEET(m_acl)
  346. }
  347. if (m_fPasswordSync)
  348. {
  349. //
  350. // Delete password
  351. //
  352. // CODEWORK: Shouldn't need to know ID number.
  353. // Implement m_fDelete flag in CMP template maybe?
  354. //
  355. FLAG_INST_DATA_FOR_DELETION(MD_ANONYMOUS_PWD);
  356. }
  357. else
  358. {
  359. STORE_INST_DATA_ON_SHEET(m_strPassword);
  360. }
  361. END_META_INST_WRITE(err)
  362. EndWaitCursor();
  363. return err;
  364. }
  365. void
  366. CFtpAccountsPage::OnItemChanged()
  367. /*++
  368. Routine Description:
  369. Register a change in control value on this page. Mark the page as dirty.
  370. All change messages map to this function
  371. Arguments:
  372. None
  373. Return Value:
  374. None
  375. --*/
  376. {
  377. SetModified(TRUE);
  378. SetControlStates(m_chk_AllowAnymous.GetCheck() > 0);
  379. }
  380. void
  381. CFtpAccountsPage::OnCheckAllowAnonymous()
  382. /*++
  383. Routine Description:
  384. Respond to 'allow anonymous' checkbox being pressed
  385. Arguments:
  386. None
  387. Return Value:
  388. None
  389. --*/
  390. {
  391. if (m_chk_AllowAnymous.GetCheck() == 0)
  392. {
  393. //
  394. // Show security warning
  395. //
  396. CClearTxtDlg dlg;
  397. if (dlg.DoModal() != IDOK)
  398. {
  399. m_chk_AllowAnymous.SetCheck(1);
  400. return;
  401. }
  402. }
  403. SetControlStates(m_chk_AllowAnymous.GetCheck() > 0);
  404. OnItemChanged();
  405. }
  406. void
  407. CFtpAccountsPage::OnCheckAllowOnlyAnonymous()
  408. /*++
  409. Routine Description:
  410. Respond to 'allow only anonymous' checkbox being pressed
  411. Arguments:
  412. None
  413. Return Value:
  414. None
  415. --*/
  416. {
  417. if (m_chk_OnlyAnonymous.GetCheck() == 0)
  418. {
  419. //
  420. // Show security warning
  421. //
  422. CClearTxtDlg dlg;
  423. if (dlg.DoModal() != IDOK)
  424. {
  425. m_chk_OnlyAnonymous.SetCheck(1);
  426. return;
  427. }
  428. }
  429. OnItemChanged();
  430. }
  431. void
  432. CFtpAccountsPage::OnButtonBrowseUser()
  433. /*++
  434. Routine Description:
  435. User browser button has been pressed. Browse for IUSR account name
  436. Arguments:
  437. None
  438. Return Value:
  439. None
  440. --*/
  441. {
  442. CString str;
  443. if (GetIUsrAccount(str))
  444. {
  445. //
  446. // If the name is non-local (determined by having
  447. // a slash in the name, password sync is disabled,
  448. // and a password should be entered.
  449. //
  450. m_edit_UserName.SetWindowText(str);
  451. if (!(m_fPasswordSync = IsLocalAccount(str)))
  452. {
  453. m_edit_Password.SetWindowText(_T(""));
  454. m_edit_Password.SetFocus();
  455. }
  456. m_chk_PasswordSync.SetCheck(m_fPasswordSync);
  457. OnItemChanged();
  458. }
  459. }
  460. void
  461. CFtpAccountsPage::OnButtonCheckPassword()
  462. /*++
  463. Routine Description:
  464. Check password button has been pressed.
  465. Arguments:
  466. None
  467. Return Value:
  468. None
  469. --*/
  470. {
  471. if (!UpdateData(TRUE))
  472. {
  473. return;
  474. }
  475. CError err(CComAuthInfo::VerifyUserPassword(m_strUserName, m_strPassword));
  476. if (!err.MessageBoxOnFailure())
  477. {
  478. ::AfxMessageBox(IDS_PASSWORD_OK);
  479. }
  480. }
  481. void
  482. CFtpAccountsPage::OnButtonAdd()
  483. /*++
  484. Routine Description:
  485. 'Add' button has been pressed
  486. Arguments:
  487. None
  488. Return Value:
  489. None
  490. --*/
  491. {
  492. if (m_list_Administrators.AddToAccessList(
  493. this,
  494. QueryServerName(),
  495. m_oblSID
  496. ))
  497. {
  498. OnItemChanged();
  499. }
  500. SetAdminRemoveState();
  501. }
  502. void
  503. CFtpAccountsPage::OnSelchangeListAdministrators()
  504. /*++
  505. Routine Description:
  506. Selection Change in admin list box handler
  507. Arguments:
  508. None.
  509. Return Value:
  510. None
  511. --*/
  512. {
  513. SetAdminRemoveState();
  514. }
  515. void
  516. CFtpAccountsPage::OnButtonDelete()
  517. /*++
  518. Routine Description:
  519. Delete all selected items in the list box
  520. Arguments:
  521. None.
  522. Return Value:
  523. None
  524. --*/
  525. {
  526. int nSel = 0;
  527. int cChanges = 0;
  528. CAccessEntry * pAccess;
  529. while ((pAccess = m_list_Administrators.GetNextSelectedItem(&nSel)) != NULL)
  530. {
  531. //
  532. // Remove button should be disabled unless all selected
  533. // items are deletable
  534. //
  535. ASSERT(pAccess->IsDeletable());
  536. if (pAccess->IsDeletable())
  537. {
  538. ++cChanges;
  539. pAccess->FlagForDeletion();
  540. m_list_Administrators.DeleteString(nSel);
  541. //
  542. // Don't advance counter to account for shift
  543. //
  544. continue;
  545. }
  546. ++nSel;
  547. }
  548. if (cChanges)
  549. {
  550. OnItemChanged();
  551. }
  552. if (!SetAdminRemoveState())
  553. {
  554. m_button_Add.SetFocus();
  555. }
  556. }
  557. void
  558. CFtpAccountsPage::OnCheckEnablePwSynchronization()
  559. /*++
  560. Routine Description:
  561. Handler for 'enable password synchronization' checkbox press
  562. Arguments:
  563. None
  564. Return Value:
  565. None
  566. --*/
  567. {
  568. m_fPasswordSyncChanged = TRUE;
  569. m_fPasswordSync = !m_fPasswordSync;
  570. OnItemChanged();
  571. SetControlStates(m_chk_AllowAnymous.GetCheck() > 0);
  572. if (!m_fPasswordSync )
  573. {
  574. m_edit_Password.SetSel(0,-1);
  575. m_edit_Password.SetFocus();
  576. }
  577. }
  578. void
  579. CFtpAccountsPage::OnChangeEditUsername()
  580. /*++
  581. Routine description:
  582. Handler for 'username' edit box change messages
  583. Arguments:
  584. None
  585. Return Value:
  586. None
  587. --*/
  588. {
  589. m_fUserNameChanged = TRUE;
  590. OnItemChanged();
  591. }