windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/snapin/facc.cpp
2020-09-26 16:20:57 +08:00

856 lines
15 KiB
C++

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
facc.cpp
Abstract:
FTP Accounts Property Page
Author:
Ronald Meijer (ronaldm)
Project:
Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#include "stdafx.h"
#include "common.h"
#include "inetprop.h"
#include "InetMgrApp.h"
#include "supdlgs.h"
#include "shts.h"
#include "ftpsht.h"
#include "facc.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CFtpAccountsPage, CInetPropertyPage)
CFtpAccountsPage::CFtpAccountsPage(
IN CInetPropertySheet * pSheet
)
/*++
Routine Description:
Constructor for FTP service property page
Arguments:
CInetPropertySheet * pSheet : Associated property sheet
Return Value:
N/A
--*/
: CInetPropertyPage(CFtpAccountsPage::IDD, pSheet),
m_ListBoxRes(
IDB_ACLUSERS,
CAccessEntryListBox::nBitmaps
),
m_oblSID(),
m_fPasswordSyncChanged(FALSE),
m_fUserNameChanged(FALSE),
m_fPasswordSyncMsgShown(FALSE)
{
#ifdef _DEBUG
afxMemDF |= checkAlwaysMemDF;
#endif // _DEBUG
#if 0 // Keep Class Wizard happy
//{{AFX_DATA_INIT(CFtpAccountsPage)
m_strUserName = _T("");
m_fAllowAnonymous = TRUE;
m_fOnlyAnonymous = FALSE;
m_fPasswordSync = FALSE;
//}}AFX_DATA_INIT
#endif // 0
m_list_Administrators.AttachResources(&m_ListBoxRes);
}
CFtpAccountsPage::~CFtpAccountsPage()
/*++
Routine Description:
Destructor
Arguments:
N/A
Return Value:
N/A
--*/
{
}
void
CFtpAccountsPage::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
CInetPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFtpAccountsPage)
DDX_Check(pDX, IDC_CHECK_ALLOW_ANONYMOUS, m_fAllowAnonymous);
DDX_Check(pDX, IDC_CHECK_ONLY_ANYMOUS, m_fOnlyAnonymous);
DDX_Check(pDX, IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, m_fPasswordSync);
DDX_Control(pDX, IDC_BUTTON_ADD, m_button_Add);
DDX_Control(pDX, IDC_EDIT_PASSWORD, m_edit_Password);
DDX_Control(pDX, IDC_EDIT_USERNAME, m_edit_UserName);
DDX_Control(pDX, IDC_STATIC_PW, m_static_Password);
DDX_Control(pDX, IDC_STATIC_USERNAME, m_static_UserName);
DDX_Control(pDX, IDC_STATIC_ACCOUNT_PROMPT, m_static_AccountPrompt);
DDX_Control(pDX, IDC_BUTTON_CHECK_PASSWORD, m_button_CheckPassword);
DDX_Control(pDX, IDC_BUTTON_BROWSE_USER, m_button_Browse);
DDX_Control(pDX, IDC_BUTTON_DELETE, m_button_RemoveAdministrator);
DDX_Control(pDX, IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, m_chk_PasswordSync);
DDX_Control(pDX, IDC_CHECK_ALLOW_ANONYMOUS, m_chk_AllowAnymous);
DDX_Control(pDX, IDC_CHECK_ONLY_ANYMOUS, m_chk_OnlyAnonymous);
//}}AFX_DATA_MAP
//
// Private DDX/DDV Routines
//
DDX_Control(pDX, IDC_LIST_ADMINISTRATORS, m_list_Administrators);
//
// Set password/username only during load stage,
// or if saving when allowing anonymous logons
//
if (!pDX->m_bSaveAndValidate || m_fAllowAnonymous)
{
DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUserName);
DDV_MinMaxChars(pDX, m_strUserName, 1, UNLEN);
//
// Some people have a tendency to add "\\" before
// the computer name in user accounts. Fix this here.
//
m_strUserName.TrimLeft();
while (*m_strUserName == '\\')
{
m_strUserName = m_strUserName.Mid(2);
}
//
// Display the remote password sync message if
// password sync is on, the account is not local,
// password sync has changed or username has changed
// and the message hasn't already be shown.
//
if (pDX->m_bSaveAndValidate && m_fPasswordSync
&& !IsLocalAccount(m_strUserName)
&& (m_fPasswordSyncChanged || m_fUserNameChanged)
&& !m_fPasswordSyncMsgShown
)
{
if (!NoYesMessageBox(IDS_WRN_PWSYNC))
{
pDX->Fail();
}
//
// Don't show it again
//
m_fPasswordSyncMsgShown = TRUE;
}
if (!m_fPasswordSync || !pDX->m_bSaveAndValidate)
{
DDX_Password(
pDX,
IDC_EDIT_PASSWORD,
m_strPassword,
g_lpszDummyPassword
);
}
if (!m_fPasswordSync)
{
DDV_MaxChars(pDX, m_strPassword, PWLEN);
}
}
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CFtpAccountsPage, CInetPropertyPage)
//{{AFX_MSG_MAP(CFtpAccountsPage)
ON_BN_CLICKED(IDC_BUTTON_CHECK_PASSWORD, OnButtonCheckPassword)
ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAdd)
ON_CBN_SELCHANGE(IDC_LIST_ADMINISTRATORS, OnSelchangeListAdministrators)
ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
ON_BN_CLICKED(IDC_CHECK_ENABLE_PW_SYNCHRONIZATION, OnCheckEnablePwSynchronization)
ON_EN_CHANGE(IDC_EDIT_USERNAME, OnChangeEditUsername)
//}}AFX_MSG_MAP
ON_EN_CHANGE(IDC_EDIT_PASSWORD, OnItemChanged)
ON_BN_CLICKED(IDC_CHECK_ALLOW_ANONYMOUS, OnCheckAllowAnonymous)
ON_BN_CLICKED(IDC_CHECK_ONLY_ANYMOUS, OnCheckAllowOnlyAnonymous)
ON_BN_CLICKED(IDC_BUTTON_BROWSE_USER, OnButtonBrowseUser)
END_MESSAGE_MAP()
void
CFtpAccountsPage::SetControlStates(
IN BOOL fAllowAnonymous
)
/*++
Routine Description:
Set the states of the dialog control depending on its current
values.
Arguments:
BOOL fAllowAnonymous : If TRUE, 'allow anonymous' is on.
Return Value:
None
--*/
{
m_static_Password.EnableWindow(
fAllowAnonymous
&& !m_fPasswordSync
&& HasAdminAccess()
);
m_edit_Password.EnableWindow(
fAllowAnonymous
&& !m_fPasswordSync
&& HasAdminAccess()
);
m_button_CheckPassword.EnableWindow(
fAllowAnonymous
&& !m_fPasswordSync
&& HasAdminAccess()
);
m_static_AccountPrompt.EnableWindow(fAllowAnonymous);
m_static_UserName.EnableWindow(fAllowAnonymous && HasAdminAccess());
m_edit_UserName.EnableWindow(fAllowAnonymous && HasAdminAccess());
m_button_Browse.EnableWindow(fAllowAnonymous && HasAdminAccess());
m_chk_PasswordSync.EnableWindow(fAllowAnonymous && HasAdminAccess());
m_chk_OnlyAnonymous.EnableWindow(fAllowAnonymous);
}
BOOL
CFtpAccountsPage::SetAdminRemoveState()
/*++
Routine Description:
Set the state of the remove button depending on the selection in the
administrators listbox. Remove is only enabled if ALL selected
items are removable.
Arguments:
None
Return Value:
TRUE if the remove button is enabled.
--*/
{
int nSel = 0;
int cSelectedItems = 0;
BOOL fAllDeletable = TRUE;
CAccessEntry * pAccess;
while ((pAccess = m_list_Administrators.GetNextSelectedItem(&nSel)) != NULL)
{
++cSelectedItems;
if (!pAccess->IsDeletable())
{
fAllDeletable = FALSE;
break;
}
++nSel;
}
fAllDeletable = fAllDeletable && (cSelectedItems > 0);
m_button_RemoveAdministrator.EnableWindow(
fAllDeletable
&& HasOperatorList()
&& HasAdminAccess()
);
return fAllDeletable;
}
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BOOL
CFtpAccountsPage::OnInitDialog()
/*++
Routine Description:
WM_INITDIALOG handler. Initialize the dialog.
Arguments:
None.
Return Value:
TRUE if no focus is to be set automatically, FALSE if the focus
is already set.
--*/
{
CInetPropertyPage::OnInitDialog();
m_list_Administrators.Initialize();
CWaitCursor wait;
//
// Build the ACL list
//
CError err(BuildAclOblistFromBlob(
((CFtpSheet *)GetSheet())->GetInstanceProperties().m_acl,
m_oblSID
));
err.MessageBoxOnFailure();
m_list_Administrators.FillAccessListBox(m_oblSID);
//
// check if the operators controls are accessible
//
m_button_Add.EnableWindow(HasOperatorList() && HasAdminAccess());
m_list_Administrators.EnableWindow(HasOperatorList() && HasAdminAccess());
GetDlgItem(IDC_STATIC_OPERATOR_PROMPT1)->EnableWindow(
HasOperatorList()
&& HasAdminAccess()
);
GetDlgItem(IDC_STATIC_OPERATOR_PROMPT2)->EnableWindow(
HasOperatorList()
&& HasAdminAccess()
);
SetControlStates(m_fAllowAnonymous);
SetAdminRemoveState();
return TRUE;
}
/* virtual */
HRESULT
CFtpAccountsPage::FetchLoadedValues()
/*++
Routine Description:
Move configuration data from sheet to dialog controls
Arguments:
None
Return Value:
HRESULT
--*/
{
CError err;
BEGIN_META_INST_READ(CFtpSheet)
FETCH_INST_DATA_FROM_SHEET(m_strUserName);
FETCH_INST_DATA_FROM_SHEET(m_strPassword);
FETCH_INST_DATA_FROM_SHEET(m_fAllowAnonymous);
FETCH_INST_DATA_FROM_SHEET(m_fOnlyAnonymous);
FETCH_INST_DATA_FROM_SHEET(m_fPasswordSync);
END_META_INST_READ(err)
return err;
}
/* virtual */
HRESULT
CFtpAccountsPage::SaveInfo()
/*++
Routine Description:
Save the information on this property page
Arguments:
None
Return Value:
Error return code
--*/
{
ASSERT(IsDirty());
TRACEEOLID("Saving FTP service page now...");
//
// Use m_ notation because the message crackers require it
//
CBlob m_acl;
BOOL fAclDirty = BuildAclBlob(m_oblSID, m_acl);
CError err;
BeginWaitCursor();
BEGIN_META_INST_WRITE(CFtpSheet)
STORE_INST_DATA_ON_SHEET(m_strUserName)
STORE_INST_DATA_ON_SHEET(m_fOnlyAnonymous)
STORE_INST_DATA_ON_SHEET(m_fAllowAnonymous)
STORE_INST_DATA_ON_SHEET(m_fPasswordSync)
if (fAclDirty)
{
STORE_INST_DATA_ON_SHEET(m_acl)
}
if (m_fPasswordSync)
{
//
// Delete password
//
// CODEWORK: Shouldn't need to know ID number.
// Implement m_fDelete flag in CMP template maybe?
//
FLAG_INST_DATA_FOR_DELETION(MD_ANONYMOUS_PWD);
}
else
{
STORE_INST_DATA_ON_SHEET(m_strPassword);
}
END_META_INST_WRITE(err)
EndWaitCursor();
return err;
}
void
CFtpAccountsPage::OnItemChanged()
/*++
Routine Description:
Register a change in control value on this page. Mark the page as dirty.
All change messages map to this function
Arguments:
None
Return Value:
None
--*/
{
SetModified(TRUE);
SetControlStates(m_chk_AllowAnymous.GetCheck() > 0);
}
void
CFtpAccountsPage::OnCheckAllowAnonymous()
/*++
Routine Description:
Respond to 'allow anonymous' checkbox being pressed
Arguments:
None
Return Value:
None
--*/
{
if (m_chk_AllowAnymous.GetCheck() == 0)
{
//
// Show security warning
//
CClearTxtDlg dlg;
if (dlg.DoModal() != IDOK)
{
m_chk_AllowAnymous.SetCheck(1);
return;
}
}
SetControlStates(m_chk_AllowAnymous.GetCheck() > 0);
OnItemChanged();
}
void
CFtpAccountsPage::OnCheckAllowOnlyAnonymous()
/*++
Routine Description:
Respond to 'allow only anonymous' checkbox being pressed
Arguments:
None
Return Value:
None
--*/
{
if (m_chk_OnlyAnonymous.GetCheck() == 0)
{
//
// Show security warning
//
CClearTxtDlg dlg;
if (dlg.DoModal() != IDOK)
{
m_chk_OnlyAnonymous.SetCheck(1);
return;
}
}
OnItemChanged();
}
void
CFtpAccountsPage::OnButtonBrowseUser()
/*++
Routine Description:
User browser button has been pressed. Browse for IUSR account name
Arguments:
None
Return Value:
None
--*/
{
CString str;
if (GetIUsrAccount(str))
{
//
// If the name is non-local (determined by having
// a slash in the name, password sync is disabled,
// and a password should be entered.
//
m_edit_UserName.SetWindowText(str);
if (!(m_fPasswordSync = IsLocalAccount(str)))
{
m_edit_Password.SetWindowText(_T(""));
m_edit_Password.SetFocus();
}
m_chk_PasswordSync.SetCheck(m_fPasswordSync);
OnItemChanged();
}
}
void
CFtpAccountsPage::OnButtonCheckPassword()
/*++
Routine Description:
Check password button has been pressed.
Arguments:
None
Return Value:
None
--*/
{
if (!UpdateData(TRUE))
{
return;
}
CError err(CComAuthInfo::VerifyUserPassword(m_strUserName, m_strPassword));
if (!err.MessageBoxOnFailure())
{
::AfxMessageBox(IDS_PASSWORD_OK);
}
}
void
CFtpAccountsPage::OnButtonAdd()
/*++
Routine Description:
'Add' button has been pressed
Arguments:
None
Return Value:
None
--*/
{
if (m_list_Administrators.AddToAccessList(
this,
QueryServerName(),
m_oblSID
))
{
OnItemChanged();
}
SetAdminRemoveState();
}
void
CFtpAccountsPage::OnSelchangeListAdministrators()
/*++
Routine Description:
Selection Change in admin list box handler
Arguments:
None.
Return Value:
None
--*/
{
SetAdminRemoveState();
}
void
CFtpAccountsPage::OnButtonDelete()
/*++
Routine Description:
Delete all selected items in the list box
Arguments:
None.
Return Value:
None
--*/
{
int nSel = 0;
int cChanges = 0;
CAccessEntry * pAccess;
while ((pAccess = m_list_Administrators.GetNextSelectedItem(&nSel)) != NULL)
{
//
// Remove button should be disabled unless all selected
// items are deletable
//
ASSERT(pAccess->IsDeletable());
if (pAccess->IsDeletable())
{
++cChanges;
pAccess->FlagForDeletion();
m_list_Administrators.DeleteString(nSel);
//
// Don't advance counter to account for shift
//
continue;
}
++nSel;
}
if (cChanges)
{
OnItemChanged();
}
if (!SetAdminRemoveState())
{
m_button_Add.SetFocus();
}
}
void
CFtpAccountsPage::OnCheckEnablePwSynchronization()
/*++
Routine Description:
Handler for 'enable password synchronization' checkbox press
Arguments:
None
Return Value:
None
--*/
{
m_fPasswordSyncChanged = TRUE;
m_fPasswordSync = !m_fPasswordSync;
OnItemChanged();
SetControlStates(m_chk_AllowAnymous.GetCheck() > 0);
if (!m_fPasswordSync )
{
m_edit_Password.SetSel(0,-1);
m_edit_Password.SetFocus();
}
}
void
CFtpAccountsPage::OnChangeEditUsername()
/*++
Routine description:
Handler for 'username' edit box change messages
Arguments:
None
Return Value:
None
--*/
{
m_fUserNameChanged = TRUE;
OnItemChanged();
}