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

828 lines
14 KiB
C++

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
machine.cpp
Abstract:
IIS Machine properties page
Author:
Ronald Meijer (ronaldm)
Project:
Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#include "stdafx.h"
#include "comprop.h"
#include "mime.h"
#define DLL_BASED __declspec(dllimport)
#include "mmc.h"
#include "machine.h"
#include "inetprop.h"
#include "..\mmc\constr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CIISMachinePage, CPropertyPage)
typedef struct tagMASTER_DLL
{
LPCTSTR lpszDllName;
UINT nID;
} MASTER_DLL;
MASTER_DLL rgMasters[] =
{
//
// Note: path should not be neccesary for these
// config DLLs, because they should really already
// be loaded by inetmgr at this point.
//
{ _T("W3SCFG.DLL"), IDS_WWW_MASTER },
{ _T("FSCFG.DLL"), IDS_FTP_MASTER },
};
#define NUM_MASTER_DLL ARRAY_SIZE(rgMasters)
CMasterDll::CMasterDll(
IN UINT nID,
IN LPCTSTR lpszDllName,
IN LPCTSTR lpszMachineName
)
/*++
Routine Description:
Construct master dll object
Arguments:
UINT nID : Resource ID
LPCTSTR lpszDllName : Dll filename and path
LPCTSTR lpszMachineName : Current machine name
Return Value:
N/A
--*/
: m_hDll(NULL),
m_pfnConfig(NULL),
m_strText()
{
m_hDll = ::AfxLoadLibrary(lpszDllName);
if (m_hDll != NULL)
{
//
// Check to see if this service is installed
//
pfnQueryServerInfo pfnInfo = (pfnQueryServerInfo)
::GetProcAddress(m_hDll, SZ_SERVERINFO_PROC);
if (pfnInfo != NULL)
{
ISMSERVERINFO ism;
ism.dwSize = ISMSERVERINFO_SIZE;
CError err((*pfnInfo)(lpszMachineName, &ism));
if (err.Succeeded())
{
m_pfnConfig = (pfnConfigure)::GetProcAddress(
m_hDll,
SZ_CONFIGURE_PROC
);
if (m_pfnConfig != NULL)
{
HINSTANCE hOld = AfxGetResourceHandle();
AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
VERIFY(m_strText.LoadString(nID));
AfxSetResourceHandle(hOld);
//
// Success!
//
return;
}
}
}
}
//
// Library didn't exist, was bogus, or unable to provide information
// about itself.
//
SAFE_AFXFREELIBRARY(m_hDll);
}
CMasterDll::~CMasterDll()
/*++
Routine Description:
Destructor -- decrement library reference count
Arguments:
N/A
Return Value:
N/A
--*/
{
TRACEEOLID("Deleting: " << m_strText);
SAFE_AFXFREELIBRARY(m_hDll);
}
/* static */
void
CIISMachinePage::ParseMaxNetworkUse(
IN OUT CILong & nMaxNetworkUse,
OUT BOOL & fLimitNetworkUse
)
/*++
Routine Description:
Break out max network use function
Arguments:
CILong & nMaxNetworkUse : Maximum network value (will be changed)
BOOL & fLimitMaxNetworkUse : TRUE if max network is not infinite
Return Value
None/
--*/
{
fLimitNetworkUse = (nMaxNetworkUse != INFINITE_BANDWIDTH);
nMaxNetworkUse = fLimitNetworkUse
? (nMaxNetworkUse / KILOBYTE)
: (DEF_BANDWIDTH / KILOBYTE);
}
CIISMachinePage::CIISMachinePage(
IN LPCTSTR lpstrMachineName,
IN HINSTANCE hInstance
)
/*++
Routine Description:
Constructor for IIS Machine property page
Arguments:
LPCTSTR lpstrMachineName : Machine name
HINSTANCE hInstance : Instance handle
Return Value:
N/A
--*/
: CPropertyPage(CIISMachinePage::IDD),
m_strMachineName(lpstrMachineName),
m_fLocal(IsServerLocal(lpstrMachineName)),
m_ppropMimeTypes(NULL),
m_ppropMachine(NULL),
m_lstMasterDlls(),
m_hr(S_OK)
{
#if 0 // Keep class wizard happy
//{{AFX_DATA_INIT(CIISMachinePage)
m_fLimitNetworkUse = FALSE;
m_nMasterType = -1;
//}}AFX_DATA_INIT
m_nMaxNetworkUse = 0;
#endif
m_nMasterType = 0;
//
// Data will be fetched later to prevent marshalling across
// threads errors. The dialog is constructed in one thread,
// and operates in another.
//
}
CIISMachinePage::~CIISMachinePage()
/*++
Routine Description:
Destructor
Arguments:
N/A
Return Value:
N/A
--*/
{
}
//
// COMPILER ISSUE::: Inlining this function doesn't
// work on x86 using NT 5!
//
HRESULT CIISMachinePage::QueryResult() const
{
return m_hr;
}
void
CIISMachinePage::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
//
// Make sure data was fetched
//
ASSERT(m_ppropMachine != NULL);
ASSERT(m_ppropMimeTypes != NULL);
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CIISMachinePage)
DDX_CBIndex(pDX, IDC_COMBO_MASTER_TYPE, m_nMasterType);
DDX_Control(pDX, IDC_EDIT_MAX_NETWORK_USE, m_edit_MaxNetworkUse);
DDX_Control(pDX, IDC_STATIC_THROTTLE_PROMPT, m_static_ThrottlePrompt);
DDX_Control(pDX, IDC_STATIC_MAX_NETWORK_USE, m_static_MaxNetworkUse);
DDX_Control(pDX, IDC_STATIC_KBS, m_static_KBS);
DDX_Control(pDX, IDC_BUTTON_EDIT_DEFAULT, m_button_EditDefault);
DDX_Control(pDX, IDC_CHECK_LIMIT_NETWORK_USE, m_check_LimitNetworkUse);
DDX_Control(pDX, IDC_COMBO_MASTER_TYPE, m_combo_MasterType);
DDX_Check(pDX, IDC_CHECK_LIMIT_NETWORK_USE, m_fLimitNetworkUse);
//}}AFX_DATA_MAP
if (m_edit_MaxNetworkUse.IsWindowEnabled())
{
DDX_Text(pDX, IDC_EDIT_MAX_NETWORK_USE, m_nMaxNetworkUse);
DDV_MinMaxLong(pDX, m_nMaxNetworkUse, 1, UD_MAXVAL);
}
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CIISMachinePage, CPropertyPage)
//{{AFX_MSG_MAP(CIISMachinePage)
ON_BN_CLICKED(IDC_CHECK_LIMIT_NETWORK_USE, OnCheckLimitNetworkUse)
ON_BN_CLICKED(IDC_BUTTON_EDIT_DEFAULT, OnButtonEditDefault)
ON_BN_CLICKED(IDC_BUTTON_FILE_TYPES, OnButtonFileTypes)
ON_COMMAND(ID_HELP, OnHelp)
ON_COMMAND(ID_CONTEXT_HELP, OnHelp)
ON_WM_DESTROY()
ON_WM_HELPINFO()
//}}AFX_MSG_MAP
ON_EN_CHANGE(IDC_EDIT_MAX_NETWORK_USE, OnItemChanged)
END_MESSAGE_MAP()
BOOL
CIISMachinePage::SetControlStates()
/*++
Routine Description:
Set button states depending on contents of the controls.
Return whether or not "Limit network use" is on.
Arguments:
None
Return Value:
TRUE if "Limit network use" is checked
--*/
{
BOOL fLimitOn = m_check_LimitNetworkUse.GetCheck() > 0;
m_static_MaxNetworkUse.EnableWindow(fLimitOn);
m_static_ThrottlePrompt.EnableWindow(fLimitOn);
m_edit_MaxNetworkUse.EnableWindow(fLimitOn);
m_static_KBS.EnableWindow(fLimitOn);
return fLimitOn;
}
HRESULT
CIISMachinePage::LoadDelayedValues()
/*++
Routine Description:
Load the metabase parameters
Arguments:
None
Return Value:
HRESULT
--*/
{
//
// Fetch the properties from the metabase
//
ASSERT(m_ppropMachine == NULL);
ASSERT(m_ppropMimeTypes == NULL);
//
// Share interface between the objects here
//
m_ppropMachine = new CMachineProps(m_strMachineName);
if (NULL == m_ppropMachine)
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
else if (FAILED(m_ppropMachine->QueryResult()))
return m_ppropMachine->QueryResult();
m_ppropMimeTypes = new CMimeTypes(m_ppropMachine);
if (NULL == m_ppropMimeTypes)
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
else if (FAILED(m_ppropMimeTypes->QueryResult()))
return m_ppropMimeTypes->QueryResult();
m_hr = m_ppropMachine->LoadData();
if (SUCCEEDED(m_hr))
{
m_nMaxNetworkUse = m_ppropMachine->m_nMaxNetworkUse;
ParseMaxNetworkUse(m_nMaxNetworkUse, m_fLimitNetworkUse);
m_hr = m_ppropMimeTypes->LoadData();
if (SUCCEEDED(m_hr))
{
m_strlMimeTypes = m_ppropMimeTypes->m_strlMimeTypes;
}
}
return S_OK;
}
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void
CIISMachinePage::OnHelp()
/*++
Routine Description:
'Help' button handler
Arguments:
None
Return Value:
None
--*/
{
if (m_strHelpFile.IsEmpty())
{
CRMCRegKey rk(REG_KEY, SZ_PARAMETERS, KEY_READ);
rk.QueryValue(SZ_HELPPATH, m_strHelpFile, EXPANSION_ON);
m_strHelpFile += _T("\\inetmgr.hlp");
TRACEEOLID("Initialized help file " << m_strHelpFile);
}
CWnd * pWnd = ::AfxGetMainWnd();
HWND hWndParent = pWnd != NULL
? pWnd->m_hWnd
: NULL;
::WinHelp(m_hWnd, m_strHelpFile, HELP_CONTEXT, HIDD_IIS_MACHINE);
}
BOOL
CIISMachinePage::OnHelpInfo(HELPINFO * pHelpInfo)
{
OnHelp();
return FALSE;
}
void
CIISMachinePage::OnCheckLimitNetworkUse()
/*++
Routine Description:
The "limit network use" checkbox has been clicked
Enable/disable the "max network use" controls.
Arguments:
None
Return Value:
None
--*/
{
if (SetControlStates())
{
m_edit_MaxNetworkUse.SetSel(0,-1);
m_edit_MaxNetworkUse.SetFocus();
}
OnItemChanged();
}
void
CIISMachinePage::OnItemChanged()
/*++
Routine Description:
All EN_CHANGE messages map to this function
Arguments:
None
Return Value:
None
--*/
{
SetModified(TRUE);
}
void
CIISMachinePage::OnButtonEditDefault()
/*++
Routine Description:
'edit default' button handler
Arguments:
None
Return Value:
None
--*/
{
//
// Get selection, and convert to index into server table
// via associative array.
//
CError err;
int nSel = m_combo_MasterType.GetCurSel();
ASSERT(nSel >= 0 && nSel < NUM_MASTER_DLL);
POSITION pos = m_lstMasterDlls.FindIndex(nSel);
ASSERT(pos != NULL);
CMasterDll * pDll = m_lstMasterDlls.GetAt(pos);
ASSERT(pDll != NULL);
//
// Allocate string with 2 terminating NULLS
//
int nLen = m_strMachineName.GetLength();
LPTSTR lpServers = AllocTString(nLen + 2);
if (lpServers == NULL)
{
err = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
::lstrcpy(lpServers, m_strMachineName);
lpServers[nLen + 1] = _T('\0');
err = pDll->Config(m_hWnd, lpServers);
}
SAFE_FREEMEM(lpServers);
err.MessageBoxOnFailure();
}
void
CIISMachinePage::OnButtonFileTypes()
/*++
Routine Description:
'file types' button handler - bring up mime types dialog.
Arguments:
None
Return Value:
None
--*/
{
HINSTANCE hOld = AfxGetResourceHandle();
AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
CMimeDlg dlg(m_strlMimeTypes, this);
if (dlg.DoModal() == IDOK)
{
OnItemChanged();
}
AfxSetResourceHandle(hOld);
}
BOOL
CIISMachinePage::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.
--*/
{
CServerCapabilities caps(m_strMachineName, SZ_MBN_WEB);
BOOL fHasThrottling = caps.HasBwThrottling();
CError err(LoadDelayedValues());
if (err.Failed())
{
fHasThrottling = FALSE;
}
CPropertyPage::OnInitDialog();
//
// Fill the master combo box
//
int cServices = 0;
CMasterDll * pDll;
for (int n = 0; n < NUM_MASTER_DLL; ++n)
{
pDll = new CMasterDll(
rgMasters[n].nID,
rgMasters[n].lpszDllName,
m_strMachineName
);
if (pDll == NULL)
{
err = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if (pDll->IsLoaded())
{
m_combo_MasterType.AddString(*pDll);
m_lstMasterDlls.AddTail(pDll);
++cServices;
}
else
{
//
// Dll didn't load, toss it.
//
delete pDll;
}
}
if (cServices == 0)
{
//
// No master-programmable services installed, so disallow
// master editing.
//
GetDlgItem(IDC_BUTTON_EDIT_DEFAULT)->EnableWindow(FALSE);
GetDlgItem(IDC_GROUP_MASTER)->EnableWindow(FALSE);
GetDlgItem(IDC_STATIC_MASTER_PROMPT1)->EnableWindow(FALSE);
GetDlgItem(IDC_STATIC_MASTER_PROMPT2)->EnableWindow(FALSE);
m_combo_MasterType.EnableWindow(FALSE);
}
m_check_LimitNetworkUse.EnableWindow(fHasThrottling);
m_combo_MasterType.SetCurSel(0);
SetControlStates();
err.MessageBoxOnFailure();
return TRUE;
}
BOOL
CIISMachinePage::OnApply()
/*++
Routine Description:
'Apply' button handler. Called when OK or APPLY is pressed.
Arguments:
None.
Return Value:
TRUE to continue, FALSE otherwise
--*/
{
//
// Don't use m_nMaxNetworkUse, because it would
// alter the values on the screen when DDX happens next.
//
CILong nMaxNetworkUse = m_nMaxNetworkUse;
BuildMaxNetworkUse(nMaxNetworkUse, m_fLimitNetworkUse);
m_ppropMachine->m_nMaxNetworkUse = nMaxNetworkUse;
CError err(m_ppropMachine->WriteDirtyProps());
if (err.Succeeded())
{
m_ppropMimeTypes->m_strlMimeTypes = m_strlMimeTypes;
err = m_ppropMimeTypes->WriteDirtyProps();
}
if (err.Succeeded())
{
return CPropertyPage::OnApply();
}
//
// Failed
//
err.MessageBox();
return FALSE;
}
void
CIISMachinePage::OnDestroy()
/*++
Routine Description:
Window is being destroyed. Time to clean up
Arguments:
None.
Return Value:
None.
--*/
{
ASSERT(m_ppropMachine != NULL);
ASSERT(m_ppropMimeTypes != NULL);
SAFE_DELETE(m_ppropMachine);
SAFE_DELETE(m_ppropMimeTypes);
while (!m_lstMasterDlls.IsEmpty())
{
CMasterDll * pDll = m_lstMasterDlls.RemoveHead();
delete pDll;
}
//
// Remove the help window if it's currently open
//
::WinHelp(m_hWnd, NULL, HELP_QUIT, 0L);
CPropertyPage::OnDestroy();
}
void
CIISMachinePage::PostNcDestroy()
/*++
Routine Description:
handle destruction of the window by freeing the this
pointer (as this modeless dialog must have been created
on the heap)
Arguments:
None.
Return Value:
None
--*/
{
delete this;
}