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

760 lines
14 KiB
C++

/*++
Copyright (c) 1994-1999 Microsoft Corporation
Module Name :
fservic.cpp
Abstract:
FTP Service 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 "shts.h"
#include "ftpsht.h"
#include "fservic.h"
#include "usersess.h"
#include "iisobj.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
//
// Some sanity values on max connections
//
#define MAX_MAX_CONNECTIONS (1999999999L)
#define INITIAL_MAX_CONNECTIONS ( 1000L)
#define UNLIMITED_CONNECTIONS (2000000000L)
#define MAX_TIMEOUT (0x7FFFFFFF)
#define LIMITED_CONNECTIONS_MIN (10)
#define LIMITED_CONNECTIONS_MAX (40)
IMPLEMENT_DYNCREATE(CFtpServicePage, CInetPropertyPage)
CFtpServicePage::CFtpServicePage(
IN CInetPropertySheet * pSheet
)
/*++
Routine Description:
Constructor for FTP service property page
Arguments:
CInetPropertySheet * pSheet : Associated property sheet
Return Value:
N/A
--*/
: CInetPropertyPage(CFtpServicePage::IDD, pSheet)
{
#ifdef _DEBUG
afxMemDF |= checkAlwaysMemDF;
#endif // _DEBUG
#if 0 // Keep Class Wizard happy
//{{AFX_DATA_INIT(CFtpServicePage)
m_strComment = _T("");
m_nTCPPort = 20;
m_nUnlimited = RADIO_LIMITED;
m_nIpAddressSel = -1;
m_fEnableLogging = FALSE;
//}}AFX_DATA_INIT
m_nMaxConnections = 50;
m_nVisibleMaxConnections = 50;
m_nConnectionTimeOut = 600;
m_iaIpAddress = (LONG)0L;
m_strDomainName = _T("");
#endif // 0
}
CFtpServicePage::~CFtpServicePage()
/*++
Routine Description:
Destructor
Arguments:
N/A
Return Value:
N/A
--*/
{
}
void
CFtpServicePage::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
CInetPropertyPage::DoDataExchange(pDX);
if (!pDX->m_bSaveAndValidate)
{
m_fEnableLogging = LoggingEnabled(m_dwLogType);
}
//{{AFX_DATA_MAP(CFtpServicePage)
DDX_Radio(pDX, IDC_RADIO_UNLIMITED, m_nUnlimited);
DDX_Check(pDX, IDC_CHECK_ENABLE_LOGGING, m_fEnableLogging);
DDX_Text(pDX, IDC_EDIT_COMMENT, m_strComment);
DDV_MinMaxChars(pDX, m_strComment, 0, MAX_PATH);
DDX_Control(pDX, IDC_EDIT_MAX_CONNECTIONS, m_edit_MaxConnections);
DDX_Control(pDX, IDC_STATIC_LOG_PROMPT, m_static_LogPrompt);
DDX_Control(pDX, IDC_STATIC_CONNECTIONS, m_static_Connections);
DDX_Control(pDX, IDC_BUTTON_PROPERTIES, m_button_LogProperties);
DDX_Control(pDX, IDC_COMBO_IP_ADDRESS, m_combo_IpAddresses);
DDX_Control(pDX, IDC_COMBO_LOG_FORMATS, m_combo_LogFormats);
//}}AFX_DATA_MAP
DDX_Text(pDX, IDC_EDIT_TCP_PORT, m_nTCPPort);
if (!IsMasterInstance())
{
DDV_MinMaxUInt(pDX, m_nTCPPort, 1, 65535);
}
if (pDX->m_bSaveAndValidate && !FetchIpAddressFromCombo(
m_combo_IpAddresses,
m_oblIpAddresses,
m_iaIpAddress
))
{
pDX->Fail();
}
//
// Private DDX/DDV Routines
//
int nMin = IsMasterInstance() ? 0 : 1;
if (!pDX->m_bSaveAndValidate || !m_fUnlimitedConnections )
{
DDX_Text(pDX, IDC_EDIT_MAX_CONNECTIONS, m_nVisibleMaxConnections);
}
if (m_f10ConnectionLimit)
{
//
// Special validation for unlimited connections. We use a bogus
// numeric check for data validation. Number adjustment happens
// later.
//
if (pDX->m_bSaveAndValidate &&
(m_nVisibleMaxConnections < 0 ||
m_nVisibleMaxConnections > UNLIMITED_CONNECTIONS))
{
TCHAR szMin[32];
TCHAR szMax[32];
wsprintf(szMin, _T("%ld"), 0);
wsprintf(szMax, _T("%ld"), 40);
CString prompt;
AfxFormatString2(prompt, AFX_IDP_PARSE_INT_RANGE, szMin, szMax);
AfxMessageBox(prompt, MB_ICONEXCLAMATION);
prompt.Empty(); // exception prep
pDX->Fail();
}
}
else
{
DDV_MinMaxLong(pDX, m_nVisibleMaxConnections, 0, UNLIMITED_CONNECTIONS);
}
DDX_Text(pDX, IDC_EDIT_CONNECTION_TIMEOUT, m_nConnectionTimeOut);
DDV_MinMaxLong(pDX, m_nConnectionTimeOut, nMin, MAX_TIMEOUT);
if (pDX->m_bSaveAndValidate)
{
EnableLogging(m_dwLogType, m_fEnableLogging);
}
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CFtpServicePage, CInetPropertyPage)
//{{AFX_MSG_MAP(CFtpServicePage)
ON_BN_CLICKED(IDC_CHECK_ENABLE_LOGGING, OnCheckEnableLogging)
ON_BN_CLICKED(IDC_RADIO_LIMITED, OnRadioLimited)
ON_BN_CLICKED(IDC_RADIO_UNLIMITED, OnRadioUnlimited)
ON_BN_CLICKED(IDC_BUTTON_CURRENT_SESSIONS, OnButtonCurrentSessions)
ON_BN_CLICKED(IDC_BUTTON_PROPERTIES, OnButtonProperties)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_EN_CHANGE(IDC_EDIT_TCP_PORT, OnItemChanged)
ON_EN_CHANGE(IDC_EDIT_COMMENT, OnItemChanged)
ON_EN_CHANGE(IDC_EDIT_MAX_CONNECTIONS, OnItemChanged)
ON_EN_CHANGE(IDC_EDIT_CONNECTION_TIMEOUT, OnItemChanged)
ON_CBN_EDITCHANGE(IDC_COMBO_IP_ADDRESS, OnItemChanged)
ON_CBN_SELCHANGE(IDC_COMBO_IP_ADDRESS, OnItemChanged)
ON_CBN_SELCHANGE(IDC_COMBO_LOG_FORMATS, OnItemChanged)
END_MESSAGE_MAP()
void
CFtpServicePage::SetControlStates()
/*++
Routine Description:
Set the states of the dialog control depending on its current
values.
Arguments:
None
Return Value:
None
--*/
{
if (m_edit_MaxConnections.m_hWnd)
{
m_edit_MaxConnections.EnableWindow(!m_fUnlimitedConnections);
m_static_Connections.EnableWindow(!m_fUnlimitedConnections);
}
}
void
CFtpServicePage::PopulateKnownIpAddresses()
/*++
Routine Description:
Fill the combo box with known ip addresses
Arguments:
None
Return Value:
None
--*/
{
BeginWaitCursor();
PopulateComboWithKnownIpAddresses(
QueryServerName(),
m_combo_IpAddresses,
m_iaIpAddress,
m_oblIpAddresses,
m_nIpAddressSel
);
EndWaitCursor();
}
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BOOL
CFtpServicePage::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.
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CInetPropertyPage::OnInitDialog();
//
// Take our direction from a phony button
//
CRect rc(0, 0, 0, 0);
m_ocx_LogProperties.Create(
_T("LogUI"),
WS_BORDER,
rc,
this,
IDC_LOGUICTRL
);
//
// Initialize the logging ocx; pass it the metabase path of the
// virtual server.
// TODO: Rewrite this crappy logui control to make it more predictable.
// Here metabase path should not contain leading / and trailing Root
//
CString path_inst = QueryMetaPath();
CString path;
if (IsMasterInstance())
{
CMetabasePath::GetServicePath(path_inst, path);
}
else
{
CMetabasePath::GetInstancePath(path_inst, path);
}
if (path[0] == _T('/'))
{
path = path.Right(path.GetLength() - 1);
}
m_ocx_LogProperties.SetAdminTarget(QueryServerName(), path);
m_ocx_LogProperties.SetComboBox(m_combo_LogFormats.m_hWnd);
GetDlgItem(IDC_RADIO_UNLIMITED)->EnableWindow(!m_f10ConnectionLimit);
if (IsMasterInstance() || !HasAdminAccess())
{
GetDlgItem(IDC_STATIC_IPADDRESS)->EnableWindow(FALSE);
GetDlgItem(IDC_STATIC_TCP_PORT)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_TCP_PORT)->EnableWindow(FALSE);
m_combo_IpAddresses.EnableWindow(FALSE);
GetDlgItem(IDC_STATIC_DESCRIPTION)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_COMMENT)->EnableWindow(FALSE);
}
PopulateKnownIpAddresses();
SetControlStates();
SetLogState();
GetDlgItem(IDC_BUTTON_CURRENT_SESSIONS)->EnableWindow(!IsMasterInstance());
return TRUE;
}
/* virtual */
HRESULT
CFtpServicePage::FetchLoadedValues()
/*++
Routine Description:
Move configuration data from sheet to dialog controls
Arguments:
None
Return Value:
HRESULT
--*/
{
CError err;
m_f10ConnectionLimit = Has10ConnectionLimit();
BEGIN_META_INST_READ(CFtpSheet)
FETCH_INST_DATA_FROM_SHEET(m_nMaxConnections);
FETCH_INST_DATA_FROM_SHEET(m_nConnectionTimeOut);
FETCH_INST_DATA_FROM_SHEET(m_iaIpAddress);
FETCH_INST_DATA_FROM_SHEET(m_nTCPPort);
FETCH_INST_DATA_FROM_SHEET(m_strDomainName);
FETCH_INST_DATA_FROM_SHEET(m_strComment);
FETCH_INST_DATA_FROM_SHEET(m_dwLogType);
m_fUnlimitedConnections = m_nMaxConnections >= MAX_MAX_CONNECTIONS;
if (m_f10ConnectionLimit)
{
m_fUnlimitedConnections = FALSE;
if ((LONG)m_nMaxConnections > LIMITED_CONNECTIONS_MAX)
{
m_nMaxConnections = LIMITED_CONNECTIONS_MAX;
}
}
m_nVisibleMaxConnections = m_fUnlimitedConnections
? INITIAL_MAX_CONNECTIONS
: m_nMaxConnections;
//
// Set radio value
//
m_nUnlimited = m_fUnlimitedConnections ? RADIO_UNLIMITED : RADIO_LIMITED;
m_nOldTCPPort = m_nTCPPort;
END_META_INST_READ(err)
return err;
}
HRESULT
CFtpServicePage::SaveInfo()
/*++
Routine Description:
Save the information on this property page
Arguments:
None
Return Value:
Error return code
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
ASSERT(IsDirty());
TRACEEOLID("Saving FTP service page now...");
CError err;
m_nMaxConnections = m_fUnlimitedConnections
? UNLIMITED_CONNECTIONS
: m_nVisibleMaxConnections;
//
// Check to make sure we're not violating the license
// agreement
//
if (m_f10ConnectionLimit)
{
if (m_nMaxConnections > LIMITED_CONNECTIONS_MAX)
{
::AfxMessageBox(IDS_CONNECTION_LIMIT);
m_nMaxConnections = LIMITED_CONNECTIONS_MIN;
}
else if (m_nMaxConnections > LIMITED_CONNECTIONS_MIN
&& m_nMaxConnections <= LIMITED_CONNECTIONS_MAX)
{
::AfxMessageBox(IDS_WRN_CONNECTION_LIMIT);
}
}
CString strBinding;
CStringListEx m_strlBindings;
CInstanceProps::BuildBinding(
strBinding,
m_iaIpAddress,
m_nTCPPort,
m_strDomainName
);
m_strlBindings.AddTail(strBinding);
m_ocx_LogProperties.ApplyLogSelection();
BeginWaitCursor();
BEGIN_META_INST_WRITE(CFtpSheet)
STORE_INST_DATA_ON_SHEET(m_nMaxConnections);
STORE_INST_DATA_ON_SHEET(m_nMaxConnections);
STORE_INST_DATA_ON_SHEET(m_nConnectionTimeOut);
STORE_INST_DATA_ON_SHEET(m_dwLogType);
STORE_INST_DATA_ON_SHEET(m_strComment);
STORE_INST_DATA_ON_SHEET(m_strlBindings);
END_META_INST_WRITE(err)
EndWaitCursor();
if (err.Succeeded())
{
CIISMBNode * pNode = (CIISMBNode *)GetSheet()->GetParameter();
ASSERT(pNode != NULL);
pNode->Refresh(FALSE);
}
return err;
}
void
CFtpServicePage::OnRadioLimited()
/*++
Routine Description:
'limited' radio button handler
Arguments:
None
Return Value:
None
--*/
{
m_fUnlimitedConnections = FALSE;
SetControlStates();
m_edit_MaxConnections.SetSel(0, -1);
m_edit_MaxConnections.SetFocus();
OnItemChanged();
}
void
CFtpServicePage::OnRadioUnlimited()
/*++
Routine Description:
'unlimited' radio button handler
Arguments:
None
Return Value:
None
--*/
{
m_fUnlimitedConnections = TRUE;
OnItemChanged();
}
void
CFtpServicePage::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
--*/
{
SetControlStates();
SetModified(TRUE);
}
void
CFtpServicePage::SetLogState()
/*++
Routine Description:
Set the enabled state of the logging controls depending on
whether logging is currently enabled
Arguments:
None
Return Value:
None
--*/
{
m_static_LogPrompt.EnableWindow(m_fEnableLogging);
m_combo_LogFormats.EnableWindow(m_fEnableLogging);
m_button_LogProperties.EnableWindow(m_fEnableLogging);
}
void
CFtpServicePage::OnCheckEnableLogging()
/*++
Routine Description:
'Enable logging' checkbox has been toggled. Reset the state
of the dialog
Arguments:
None
Return Value:
None
--*/
{
m_fEnableLogging = !m_fEnableLogging;
SetLogState();
OnItemChanged();
}
void
CFtpServicePage::OnButtonProperties()
/*++
Routine Description:
Pass on "log properties" button click to the ocx.
Arguments:
None
Return Value:
None
--*/
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
m_ocx_LogProperties.DoClick();
}
void
CFtpServicePage::OnButtonCurrentSessions()
/*++
Routine Description:
'Current Sessions' button has been pressed. Bring up the current
sessions dialog
Arguments:
None
Return Value:
None
-*/
{
CComAuthInfo * pAuth = GetSheet()->QueryAuthInfo();
ASSERT(pAuth != NULL);
CUserSessionsDlg dlg(
pAuth->QueryServerName(),
QueryInstance(),
pAuth->QueryUserName(),
pAuth->QueryPassword(),
this);
dlg.DoModal();
}
void
CFtpServicePage::OnDestroy()
/*++
Routine Description:
WM_DESTROY handler. Clean up internal data
Arguments:
None
Return Value:
None
--*/
{
CInetPropertyPage::OnDestroy();
if (m_ocx_LogProperties.m_hWnd)
{
m_ocx_LogProperties.Terminate();
}
}