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.

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