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

928 lines
14 KiB
C++

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
errors.cpp
Abstract:
HTTP errors 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 "w3sht.h"
#include "resource.h"
#include "fltdlg.h"
#include "errors.h"
#include "errordlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// CCustomErrorsListBox : a listbox of CCustomError objects
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//
// Column width relative weights
//
#define WT_HTTP_ERROR 3
#define WT_OUTPUT_TYPE 2
#define WT_CONTENTS 8
//
// Registry key name for this dialog
//
const TCHAR g_szRegKey[] = _T("Errors");
//
// Key under w3svc where the error descriptions live
//
const TCHAR g_cszErrorLocation[] = _T("Info");
IMPLEMENT_DYNAMIC(CCustomErrorsListBox, CHeaderListBox);
const int CCustomErrorsListBox::nBitmaps = 3;
CCustomErrorsListBox::CCustomErrorsListBox(
IN UINT nIDDefault,
IN UINT nIDFile,
IN UINT nIDURL
)
/*++
Routine Description:
Error listbox constructor
Arguments:
UINT nIDDefault : String ID for 'default'
UINT nIDFile : String ID for 'file'
UINT nIDURL : String ID for 'URL'
--*/
: CHeaderListBox(HLS_STRETCH, g_szRegKey)
{
VERIFY(m_str[CCustomError::ERT_DEFAULT].LoadString(nIDDefault));
VERIFY(m_str[CCustomError::ERT_FILE].LoadString(nIDFile));
VERIFY(m_str[CCustomError::ERT_URL].LoadString(nIDURL));
}
void
CCustomErrorsListBox::DrawItemEx(
IN CRMCListBoxDrawStruct & ds
)
/*++
Routine Description:
Draw item in the listbox
Arguments:
CRMCListBoxDrawStruct & ds : Input data structure
Return Value:
N/A
--*/
{
CCustomError * p = (CCustomError *)ds.m_ItemData;
ASSERT(p != NULL);
DrawBitmap(ds, 0, p->m_nType);
CString strError, strText;
if (p->m_nSubError > 0)
{
strError.Format(_T("%d;%d"), p->m_nError, p->m_nSubError);
}
else
{
strError.Format(_T("%d"), p->m_nError);
}
ColumnText(ds, 0, TRUE, strError);
ColumnText(ds, 1, FALSE, m_str[p->m_nType] );
if (p->IsDefault())
{
strText.Format(_T("\"%s\""), p->m_strDefault);
}
else
{
strText = p->m_str;
}
ColumnText(ds, 2, FALSE, strText);
}
/* virtual */
BOOL
CCustomErrorsListBox::Initialize()
/*++
Routine Description:
initialize the listbox. Insert the columns
as requested, and lay them out appropriately
Arguments:
None
Return Value:
TRUE if initialized successfully, FALSE otherwise
--*/
{
if (!CHeaderListBox::Initialize())
{
return FALSE;
}
HINSTANCE hInst = AfxGetResourceHandle();
InsertColumn(0, WT_HTTP_ERROR, IDS_HTTP_ERROR, hInst);
InsertColumn(1, WT_OUTPUT_TYPE, IDS_OUTPUT_TYPE, hInst);
InsertColumn(2, WT_CONTENTS, IDS_CONTENTS, hInst);
//
// Try to set the widths from the stored registry value,
// otherwise distribute according to column weights specified
//
// if (!SetWidthsFromReg())
// {
DistributeColumns();
// }
SetRedraw(TRUE);
return TRUE;
}
CHTTPErrorDescriptions::CHTTPErrorDescriptions(
IN LPCTSTR lpszServer
)
/*++
Routine Description:
Constructor for default errors object. This fetches the default
error definitions
Arguments:
LPCTSTR lpServerName : Server name
Return Value:
None
--*/
: CMetaProperties(
QueryAuthInfo(),
CMetabasePath(g_cszSvc, MASTER_INSTANCE, g_cszErrorLocation)
)
{
m_dwMDUserType = IIS_MD_UT_SERVER;
m_dwMDDataType = MULTISZ_METADATA;
}
/* virtual */
void
CHTTPErrorDescriptions::ParseFields()
/*++
Routine Description:
Parse the fetched data into fields
Arguments:
None
Return Value:
None
--*/
{
BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
HANDLE_META_RECORD(MD_CUSTOM_ERROR_DESC, m_strlErrorDescriptions)
END_PARSE_META_RECORDS
}
//
// Errors property page
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
IMPLEMENT_DYNCREATE(CW3ErrorsPage, CInetPropertyPage)
CW3ErrorsPage::CW3ErrorsPage(
IN CInetPropertySheet * pSheet
)
/*++
Routine Description:
Constructor for WWW error property page
Arguments:
CInetPropertySheet * pSheet : Sheet object
Return Value:
N/A
--*/
: CInetPropertyPage(CW3ErrorsPage::IDD, pSheet),
m_list_Errors(IDS_DEFAULT_ERROR, IDS_FILE, IDS_URL),
m_ListBoxRes(IDB_ERRORS, m_list_Errors.nBitmaps),
m_strlCustomErrors(),
m_strlErrorDescriptions(),
m_oblErrors()
{
//{{AFX_DATA_INIT(CW3ErrorsPage)
//}}AFX_DATA_INIT
m_list_Errors.AttachResources(&m_ListBoxRes);
}
CW3ErrorsPage::~CW3ErrorsPage()
/*++
Routine Description:
Destructor
Arguments:
N/A
Return Value:
N/A
--*/
{
}
void
CW3ErrorsPage::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(CW3ErrorsPage)
DDX_Control(pDX, IDC_BUTTON_SET_TO_DEFAULT, m_button_SetDefault);
DDX_Control(pDX, IDC_BUTTON_EDIT, m_button_Edit);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_LIST_ERRORS, m_list_Errors);
if (pDX->m_bSaveAndValidate)
{
CError err(StoreErrors());
if (err.MessageBoxOnFailure())
{
pDX->Fail();
}
}
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CW3ErrorsPage, CInetPropertyPage)
//{{AFX_MSG_MAP(CW3ErrorsPage)
ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit)
ON_BN_CLICKED(IDC_BUTTON_SET_TO_DEFAULT, OnButtonSetToDefault)
ON_LBN_DBLCLK(IDC_LIST_ERRORS, OnDblclkListErrors)
ON_LBN_SELCHANGE(IDC_LIST_ERRORS, OnSelchangeListErrors)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void
CW3ErrorsPage::FillListBox()
/*++
Routine Description:
Populate the listbox with the directory entries
Arguments:
None
Return Value:
None
--*/
{
CObListIter obli(m_oblErrors);
CCustomError * pError;
//
// Remember the selection.
//
int nCurSel = m_list_Errors.GetCurSel();
m_list_Errors.SetRedraw(FALSE);
m_list_Errors.ResetContent();
int cItems = 0;
for (/**/; pError = (CCustomError *)obli.Next(); ++cItems)
{
m_list_Errors.AddItem(pError);
}
m_list_Errors.SetRedraw(TRUE);
m_list_Errors.SetCurSel(nCurSel);
}
HRESULT
CW3ErrorsPage::StoreErrors()
/*++
Routine Description:
Build errors stringlist from the error oblist built up.
Arguments:
None
Return Value:
Error return code
--*/
{
CError err;
try
{
m_strlCustomErrors.RemoveAll();
POSITION pos = m_oblErrors.GetHeadPosition();
while(pos)
{
CCustomError * pErr = (CCustomError *)m_oblErrors.GetNext(pos);
if (!pErr->IsDefault())
{
CString str;
pErr->BuildErrorString(str);
m_strlCustomErrors.AddTail(str);
}
}
}
catch(CMemoryException * e)
{
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
return err;
}
CCustomError *
CW3ErrorsPage::FindError(
IN UINT nError,
IN UINT nSubError
)
/*++
Routine Description:
Find error in the list with the given error code and suberror code
Arguments:
UINT nError : Error code
UINT nSubError : Sub error code
Return Value:
Pointer to the error or NULL if not found.
--*/
{
CCustomError * pErr = NULL;
POSITION pos = m_oblErrors.GetHeadPosition();
while(pos)
{
pErr = (CCustomError *)m_oblErrors.GetNext(pos);
ASSERT(pErr != NULL);
if (pErr->m_nError == nError && pErr->m_nSubError == nSubError)
{
//
// Found it!
//
return pErr;
}
}
//
// Not found!
//
return NULL;
}
HRESULT
CW3ErrorsPage::FetchErrors()
/*++
Routine Description:
Build up the errors list
Arguments:
None
Return Value:
Error return code
--*/
{
CError err;
CWaitCursor wait;
do
{
try
{
//
// First get the default descriptions
//
CHTTPErrorDescriptions ed(QueryServerName());
err = ed.LoadData();
if (err.Failed())
{
break;
}
if (!ed.GetErrorDescriptions().IsEmpty())
{
POSITION pos = ed.GetErrorDescriptions().GetHeadPosition();
while(pos)
{
CString & str = ed.GetErrorDescriptions().GetNext(pos);
m_oblErrors.AddTail(new CCustomError(str));
}
}
else
{
::AfxMessageBox(IDS_NO_DEF_ERRORS);
break;
}
//
// Now match up the overrides if any
//
POSITION pos = m_strlCustomErrors.GetHeadPosition();
while(pos)
{
CString & strError = m_strlCustomErrors.GetNext(pos);
TRACEEOLID(strError);
UINT nError;
UINT nSubError;
CCustomError::ERT nType;
CString str;
CCustomError * pErr = NULL;
if (CCustomError::CrackErrorString(
strError,
nError,
nSubError,
nType,
str
))
{
pErr = FindError(nError, nSubError);
}
if (pErr != NULL)
{
pErr->SetValue(nType, str);
}
else
{
CString strFmt;
strFmt.LoadString(IDS_BAD_ERROR);
str.Format(strFmt, nError, nSubError);
::AfxMessageBox(str);
break;
}
}
FillListBox();
}
catch(CMemoryException * e)
{
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
}
while(FALSE);
return err;
}
void
CW3ErrorsPage::SetControlStates()
/*++
Routine Description:
Enable/disable controls depending on the state of
the dialog
Arguments:
None
Return Value:
None
--*/
{
CCustomError * pErr = GetSelectedListItem();
m_button_Edit.EnableWindow(pErr != NULL);
m_button_SetDefault.EnableWindow(m_list_Errors.GetSelCount() > 0);
}
INT_PTR
CW3ErrorsPage::ShowPropertyDialog()
/*++
Routine Description:
Display the add/edit dialog. The return
value is the value returned by the dialog
Arguments:
None
Return Value:
None
--*/
{
int nCurSel;
CCustomError * pErr = GetSelectedListItem(&nCurSel);
if (pErr == NULL)
{
//
// Must be from a double click on extended selection
//
return IDCANCEL;
}
CCustomErrorDlg dlgError(pErr, IsLocal(), this);
INT_PTR nReturn = dlgError.DoModal();
if (nReturn == IDOK)
{
//
// Re-display the text
//
m_list_Errors.InvalidateSelection(nCurSel);
SetModified(TRUE);
}
return nReturn;
}
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BOOL
CW3ErrorsPage::OnInitDialog()
/*++
Routine Description:
WM_INITDIALOG handler. Initialize the dialog.
Arguments:
None.
Return Value:
TRUE if focus is to be set automatically, FALSE if the focus
is already set.
--*/
{
CInetPropertyPage::OnInitDialog();
m_list_Errors.Initialize();
//
// Build filters oblist
//
CError err(FetchErrors());
err.MessageBoxOnFailure();
SetControlStates();
return TRUE;
}
void
CW3ErrorsPage::OnButtonEdit()
/*++
Routine Description:
'edit' button handler
Arguments:
None
Return Value:
None
--*/
{
if (ShowPropertyDialog() == IDOK)
{
SetControlStates();
SetModified(TRUE);
}
}
void
CW3ErrorsPage::OnButtonSetToDefault()
/*++
Routine Description:
'set to default' button handler
Arguments:
None
Return Value:
None
--*/
{
//
// Apply to each selected item
//
m_list_Errors.SetRedraw(FALSE);
int nSel = 0;
int cChanges = 0;
CCustomError * pErr;
while ((pErr = GetNextSelectedItem(&nSel)) != NULL)
{
if (!pErr->IsDefault())
{
//
// Force a redraw of the current item
//
pErr->MakeDefault();
m_list_Errors.InvalidateSelection(nSel);
++cChanges;
}
++nSel;
}
if (cChanges)
{
SetModified(TRUE);
}
m_list_Errors.SetRedraw(TRUE);
SetControlStates();
}
void
CW3ErrorsPage::OnDblclkListErrors()
/*++
Routine Description:
error list 'double click' handler
Arguments:
None
Return Value:
None
--*/
{
OnButtonEdit();
}
void
CW3ErrorsPage::OnSelchangeListErrors()
/*++
Routine Description:
error list selection change handler
Arguments:
None
Return Value:
None
--*/
{
SetControlStates();
}
/* virtual */
HRESULT
CW3ErrorsPage::FetchLoadedValues()
/*++
Routine Description:
Move configuration data from sheet to dialog controls
Arguments:
None
Return Value:
HRESULT
--*/
{
CError err;
BEGIN_META_DIR_READ(CW3Sheet)
FETCH_DIR_DATA_FROM_SHEET(m_strlCustomErrors);
END_META_DIR_READ(err)
return err;
}
/* virtual */
HRESULT
CW3ErrorsPage::SaveInfo()
/*++
Routine Description:
Save the information on this property page
Arguments:
None
Return Value:
Error return code
--*/
{
ASSERT(IsDirty());
TRACEEOLID("Saving W3 errors page now...");
CError err;
BeginWaitCursor();
BEGIN_META_DIR_WRITE(CW3Sheet)
STORE_DIR_DATA_ON_SHEET(m_strlCustomErrors)
END_META_DIR_WRITE(err)
if (err.Succeeded())
{
err = ((CW3Sheet *)GetSheet())->SetKeyType();
}
EndWaitCursor();
return err;
}