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

665 lines
13 KiB
C++

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
errordlg.cpp
Abstract:
Error dialog
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 "errordlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// HTTP Custom Error Definition
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//
// Static Initialization
//
LPCTSTR CCustomError::s_szSep = _T(",");
LPCTSTR CCustomError::s_szURL = _T("URL");
LPCTSTR CCustomError::s_szFile = _T("FILE");
LPCTSTR CCustomError::s_szNoSubError = _T("*");
#define GET_FIELD()\
end = strError.Find(s_szSep, start);\
if (end == -1) \
break
#define SKIP()\
start = end + skip
#define GET_INT_FIELD(n)\
GET_FIELD();\
(n) = StrToInt(strError.Mid(start, end - start));\
SKIP()
/* static */
BOOL
CCustomError::CrackErrorString(
IN LPCTSTR lpstrErrorString,
OUT UINT & nError,
OUT UINT & nSubError,
OUT ERT & nType,
OUT CString & str
)
/*++
Routine Description
Helper function to parse error string into component parts
Arguments:
LPCTSTR lpstrErrorString : Error input string
UINT & nError : Error
UINT & nSubError : Sub Error
int & nType : Error type
CString & str : Text parameter
Return Value:
TRUE for success, FALSE for failure
--*/
{
BOOL fSuccess = FALSE;
do
{
CString strError(lpstrErrorString);
TRACEEOLID(strError);
int start = 0, end, skip = lstrlen(s_szSep);
GET_INT_FIELD(nError);
ASSERT(nError > 0);
GET_INT_FIELD(nSubError);
GET_FIELD();
nType = strError.Mid(start, end - start).CompareNoCase(s_szURL) == 0
? ERT_URL : ERT_FILE;
SKIP();
if (-1 != (end = strError.Find(s_szSep, start)))
str = strError.Mid(start, end - start);
else
str = strError.Right(strError.GetLength() - start);
fSuccess = TRUE;
}
while(FALSE);
return fSuccess;
}
/* static */
void
CCustomError::CrackErrorDescription(
IN LPCTSTR lpstrErrorString,
OUT UINT & nError,
OUT UINT & nSubError,
OUT BOOL & fURLSupported,
OUT CString & str
)
/*++
Routine Description
Helper function to parse error description into component parts
Arguments:
LPCTSTR lpstrErrorString : Error input string
UINT & nError : Error
UINT & nSubError : Sub Error
BOOL & fURLSupported : Return TRUE if urls are allowed
CString & str : Text parameter
Return Value:
None.
--*/
{
try
{
CString strError(lpstrErrorString);
TRACEEOLID(strError);
int start = 0, end, skip = lstrlen(s_szSep);
do
{
GET_INT_FIELD(nError);
ASSERT(nError > 0);
GET_INT_FIELD(nSubError);
GET_FIELD();
str = strError.Mid(start, end - start);
SKIP();
GET_FIELD();
if (nSubError > 0)
{
str += _T(" - ");
str += strError.Mid(start, end - start);
SKIP();
GET_FIELD();
}
fURLSupported = end != -1 ?
0 == StrToInt(strError.Mid(start, end - start)) : FALSE;
}
while (FALSE);
/*
LPTSTR lp = strError.GetBuffer(0);
LPTSTR lpField = StringTok(lp, s_szSep);
nError = _ttoi(lpField);
ASSERT(nError > 0);
lpField = StringTok(NULL, s_szSep);
ASSERT(lpField != NULL);
nSubError = lpField != NULL ? _ttoi(lpField) : 0;
lpField = StringTok(NULL, s_szSep);
ASSERT(lpField != NULL);
str = lpField;
lpField = StringTok(NULL, s_szSep);
ASSERT(lpField != NULL);
if (nSubError > 0)
{
//
// Add sub error text
//
ASSERT(nSubError > 0);
str += _T(" - ");
str += lpField;
lpField = StringTok(NULL, s_szSep);
}
ASSERT(lpField != NULL);
fURLSupported = lpField != NULL ? (_ttoi(lpField) == 0) : FALSE;
*/
}
catch(CException * e)
{
e->ReportError();
e->Delete();
}
}
CCustomError::CCustomError(
IN LPCTSTR lpstrErrorString
)
/*++
Routine Description:
Construct error definition from metabase string
Arguments:
LPCTSTR lpstrErrorString : Error string
Return Value:
N/A
--*/
: m_nType(ERT_DEFAULT)
{
CrackErrorDescription(
lpstrErrorString,
m_nError,
m_nSubError,
m_fURLSupported,
m_strDefault
);
}
void
CCustomError::BuildErrorString(
OUT CString & str
)
/*++
Routine Description:
Build metabase-ready error string out of the current values
Arguments:
CString & str : String
Return Value:
None
--*/
{
ASSERT(!IsDefault());
try
{
if (m_nSubError > 0)
{
str.Format(_T("%d,%d,%s,%s"),
m_nError,
m_nSubError,
IsFile() ? s_szFile : s_szURL,
(LPCTSTR)m_str
);
}
else
{
str.Format(
_T("%d,%s,%s,%s"),
m_nError,
s_szNoSubError,
IsFile() ? s_szFile : s_szURL,
(LPCTSTR)m_str
);
}
}
catch(CMemoryException * e)
{
e->ReportError();
e->Delete();
}
}
//
// Custom Errors property page
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CCustomErrorDlg::CCustomErrorDlg(
IN OUT CCustomError * pErr,
IN BOOL fLocal,
IN CWnd * pParent OPTIONAL
)
/*++
Routine Description:
Error editing dialog
Arguments:
CCustomError * pErr : Error definition to be edited
BOOL fLocal : TRUE if the current computer is local
CWnd * pParent : Optional parent window or NULL
Return Value:
N/A
--*/
: CDialog(CCustomErrorDlg::IDD, pParent),
m_fLocal(fLocal),
m_pErr(pErr),
m_nMessageType(pErr->m_nType),
m_strTextFile(pErr->m_str),
m_strDefText(pErr->m_strDefault)
{
#if 0 // Keep Class Wizard Happy
//{{AFX_DATA_INIT(CCustomErrorDlg)
m_nMessageType = -1;
m_strTextFile = _T("");
m_strDefText = _T("");
//}}AFX_DATA_INIT
#endif // 0
VERIFY(m_strFile.LoadString(IDS_FILE_PROMPT));
VERIFY(m_strURL.LoadString(IDS_URL_PROMPT));
}
void
CCustomErrorDlg::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCustomErrorDlg)
DDX_CBIndex(pDX, IDC_COMBO_MESSAGE_TYPE, m_nMessageType);
DDX_Text(pDX, IDC_STATIC_DEF_TEXT, m_strDefText);
DDX_Control(pDX, IDC_EDIT_TEXT_FILE, m_edit_TextFile);
DDX_Control(pDX, IDC_STATIC_SUB_PROMPT, m_static_SubErrorPrompt);
DDX_Control(pDX, IDC_STATIC_SUB_ERROR_CODE, m_static_SubError);
DDX_Control(pDX, IDC_STATIC_TEXT_FILE_PROMT, m_static_TextFilePrompt);
DDX_Control(pDX, IDC_BUTTON_BROWSE, m_button_Browse);
DDX_Control(pDX, IDC_COMBO_MESSAGE_TYPE, m_combo_MessageType);
DDX_Control(pDX, IDOK, m_button_OK);
//}}AFX_DATA_MAP
DDX_Text(pDX, IDC_STATIC_ERROR_CODE, m_pErr->m_nError);
DDX_Text(pDX, IDC_STATIC_SUB_ERROR_CODE, m_pErr->m_nSubError);
DDX_Text(pDX, IDC_EDIT_TEXT_FILE, m_strTextFile);
m_strTextFile.TrimLeft();
m_strTextFile.TrimRight();
if (pDX->m_bSaveAndValidate)
{
if (m_nMessageType == CCustomError::ERT_FILE)
{
if (PathIsRelative(m_strTextFile)
|| (m_fLocal && PathIsNetworkPath(m_strTextFile))
)
{
::AfxMessageBox(IDS_ERR_BAD_PATH);
pDX->Fail();
}
if (m_fLocal &&
(::GetFileAttributes(m_strTextFile) & FILE_ATTRIBUTE_DIRECTORY))
{
::AfxMessageBox(IDS_ERR_FILE_NOT_FOUND);
pDX->Fail();
}
}
else if (m_nMessageType == CCustomError::ERT_URL)
{
if (!IsRelURLPath(m_strTextFile))
{
::AfxMessageBox(IDS_NOT_REL_URL);
pDX->Fail();
}
}
}
}
//
// Message Map
//
BEGIN_MESSAGE_MAP(CCustomErrorDlg, CDialog)
//{{AFX_MSG_MAP(CCustomErrorDlg)
ON_CBN_SELCHANGE(IDC_COMBO_MESSAGE_TYPE, OnSelchangeComboMessageType)
ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse)
ON_EN_CHANGE(IDC_EDIT_TEXT_FILE, OnChangeEditTextFile)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL
CCustomErrorDlg::SetControlStates()
/*++
Routine Description:
Set the enabled states of the dialog controls depending on the current
state of the dialog
Arguments:
None
Return Value:
TRUE if file/url is selected, FALSE otherwise
--*/
{
int nCurSel = m_combo_MessageType.GetCurSel();
BOOL fFile = nCurSel == CCustomError::ERT_FILE;
BOOL fDefault = nCurSel == CCustomError::ERT_DEFAULT;
ActivateControl(m_button_Browse, m_fLocal && fFile);
ActivateControl(m_edit_TextFile, !fDefault);
ActivateControl(m_static_TextFilePrompt, !fDefault);
m_static_TextFilePrompt.SetWindowText(fFile ? m_strFile : m_strURL);
m_button_OK.EnableWindow(fDefault
|| m_edit_TextFile.GetWindowTextLength() > 0);
return !fDefault;
}
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BOOL
CCustomErrorDlg::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.
--*/
{
CDialog::OnInitDialog();
//
// Browsing available locally only
//
m_button_Browse.EnableWindow(m_fLocal);
CString str;
VERIFY(str.LoadString(IDS_DEFAULT_ERROR));
m_combo_MessageType.AddString(str);
VERIFY(str.LoadString(IDS_FILE));
m_combo_MessageType.AddString(str);
if (m_pErr->URLSupported() || m_nMessageType == CCustomError::ERT_URL)
{
VERIFY(str.LoadString(IDS_URL));
m_combo_MessageType.AddString(str);
}
m_combo_MessageType.SetCurSel(m_nMessageType);
if (m_pErr->m_nSubError == 0)
{
DeActivateControl(m_static_SubErrorPrompt);
DeActivateControl(m_static_SubError);
}
SetControlStates();
return TRUE;
}
void
CCustomErrorDlg::OnSelchangeComboMessageType()
/*++
Routine Description:
Handle change in message type combo box
Arguments:
None
Return Value:
None
--*/
{
int nSel = m_combo_MessageType.GetCurSel();
if (m_nMessageType == nSel)
{
//
// Selection didn't change
//
return;
}
m_nMessageType = nSel;
if (SetControlStates())
{
m_edit_TextFile.SetWindowText(_T(""));
m_edit_TextFile.SetFocus();
}
}
void
CCustomErrorDlg::OnChangeEditTextFile()
/*++
Routine Description:
Handle change in text/file edit box
Arguments:
None
Return Value:
None
--*/
{
SetControlStates();
}
void
CCustomErrorDlg::OnOK()
/*++
Routine Description:
Handle the OK button being pressed
Arguments:
None
Return Value:
None
--*/
{
if (UpdateData(TRUE))
{
m_pErr->m_nType = (CCustomError::ERT)m_nMessageType;
m_pErr->m_str = m_strTextFile;
CDialog::OnOK();
}
}
void
CCustomErrorDlg::OnButtonBrowse()
/*++
Routine Description:
Browse for HTML File
Arguments:
None
Return Value:
None
--*/
{
ASSERT(m_fLocal);
//
// popup the file dialog and let the user select the error htm file
//
CString str;
str.LoadString(IDS_HTML_MASK);
CFileDialog dlgBrowse(TRUE, NULL, NULL, OFN_HIDEREADONLY, str, this);
// Disable hook to get Windows 2000 style dialog
dlgBrowse.m_ofn.Flags &= ~(OFN_ENABLEHOOK);
dlgBrowse.m_ofn.Flags |= OFN_DONTADDTORECENT|OFN_FILEMUSTEXIST;
if (dlgBrowse.DoModal() == IDOK)
{
m_pErr->m_str = dlgBrowse.GetPathName();
m_edit_TextFile.SetWindowText(m_pErr->m_str);
}
}