Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

664 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. errordlg.cpp
  5. Abstract:
  6. Error dialog
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #include "inetprop.h"
  19. #include "InetMgrapp.h"
  20. #include "shts.h"
  21. #include "w3sht.h"
  22. #include "resource.h"
  23. #include "fltdlg.h"
  24. #include "errordlg.h"
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. //
  31. // HTTP Custom Error Definition
  32. //
  33. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  34. //
  35. // Static Initialization
  36. //
  37. LPCTSTR CCustomError::s_szSep = _T(",");
  38. LPCTSTR CCustomError::s_szURL = _T("URL");
  39. LPCTSTR CCustomError::s_szFile = _T("FILE");
  40. LPCTSTR CCustomError::s_szNoSubError = _T("*");
  41. #define GET_FIELD()\
  42. end = strError.Find(s_szSep, start);\
  43. if (end == -1) \
  44. break
  45. #define SKIP()\
  46. start = end + skip
  47. #define GET_INT_FIELD(n)\
  48. GET_FIELD();\
  49. (n) = StrToInt(strError.Mid(start, end - start));\
  50. SKIP()
  51. /* static */
  52. BOOL
  53. CCustomError::CrackErrorString(
  54. IN LPCTSTR lpstrErrorString,
  55. OUT UINT & nError,
  56. OUT UINT & nSubError,
  57. OUT ERT & nType,
  58. OUT CString & str
  59. )
  60. /*++
  61. Routine Description
  62. Helper function to parse error string into component parts
  63. Arguments:
  64. LPCTSTR lpstrErrorString : Error input string
  65. UINT & nError : Error
  66. UINT & nSubError : Sub Error
  67. int & nType : Error type
  68. CString & str : Text parameter
  69. Return Value:
  70. TRUE for success, FALSE for failure
  71. --*/
  72. {
  73. BOOL fSuccess = FALSE;
  74. do
  75. {
  76. CString strError(lpstrErrorString);
  77. TRACEEOLID(strError);
  78. int start = 0, end, skip = lstrlen(s_szSep);
  79. GET_INT_FIELD(nError);
  80. ASSERT(nError > 0);
  81. GET_INT_FIELD(nSubError);
  82. GET_FIELD();
  83. nType = strError.Mid(start, end - start).CompareNoCase(s_szURL) == 0
  84. ? ERT_URL : ERT_FILE;
  85. SKIP();
  86. if (-1 != (end = strError.Find(s_szSep, start)))
  87. str = strError.Mid(start, end - start);
  88. else
  89. str = strError.Right(strError.GetLength() - start);
  90. fSuccess = TRUE;
  91. }
  92. while(FALSE);
  93. return fSuccess;
  94. }
  95. /* static */
  96. void
  97. CCustomError::CrackErrorDescription(
  98. IN LPCTSTR lpstrErrorString,
  99. OUT UINT & nError,
  100. OUT UINT & nSubError,
  101. OUT BOOL & fURLSupported,
  102. OUT CString & str
  103. )
  104. /*++
  105. Routine Description
  106. Helper function to parse error description into component parts
  107. Arguments:
  108. LPCTSTR lpstrErrorString : Error input string
  109. UINT & nError : Error
  110. UINT & nSubError : Sub Error
  111. BOOL & fURLSupported : Return TRUE if urls are allowed
  112. CString & str : Text parameter
  113. Return Value:
  114. None.
  115. --*/
  116. {
  117. try
  118. {
  119. CString strError(lpstrErrorString);
  120. TRACEEOLID(strError);
  121. int start = 0, end, skip = lstrlen(s_szSep);
  122. do
  123. {
  124. GET_INT_FIELD(nError);
  125. ASSERT(nError > 0);
  126. GET_INT_FIELD(nSubError);
  127. GET_FIELD();
  128. str = strError.Mid(start, end - start);
  129. SKIP();
  130. GET_FIELD();
  131. if (nSubError > 0)
  132. {
  133. str += _T(" - ");
  134. str += strError.Mid(start, end - start);
  135. SKIP();
  136. GET_FIELD();
  137. }
  138. fURLSupported = end != -1 ?
  139. 0 == StrToInt(strError.Mid(start, end - start)) : FALSE;
  140. }
  141. while (FALSE);
  142. /*
  143. LPTSTR lp = strError.GetBuffer(0);
  144. LPTSTR lpField = StringTok(lp, s_szSep);
  145. nError = _ttoi(lpField);
  146. ASSERT(nError > 0);
  147. lpField = StringTok(NULL, s_szSep);
  148. ASSERT(lpField != NULL);
  149. nSubError = lpField != NULL ? _ttoi(lpField) : 0;
  150. lpField = StringTok(NULL, s_szSep);
  151. ASSERT(lpField != NULL);
  152. str = lpField;
  153. lpField = StringTok(NULL, s_szSep);
  154. ASSERT(lpField != NULL);
  155. if (nSubError > 0)
  156. {
  157. //
  158. // Add sub error text
  159. //
  160. ASSERT(nSubError > 0);
  161. str += _T(" - ");
  162. str += lpField;
  163. lpField = StringTok(NULL, s_szSep);
  164. }
  165. ASSERT(lpField != NULL);
  166. fURLSupported = lpField != NULL ? (_ttoi(lpField) == 0) : FALSE;
  167. */
  168. }
  169. catch(CException * e)
  170. {
  171. e->ReportError();
  172. e->Delete();
  173. }
  174. }
  175. CCustomError::CCustomError(
  176. IN LPCTSTR lpstrErrorString
  177. )
  178. /*++
  179. Routine Description:
  180. Construct error definition from metabase string
  181. Arguments:
  182. LPCTSTR lpstrErrorString : Error string
  183. Return Value:
  184. N/A
  185. --*/
  186. : m_nType(ERT_DEFAULT)
  187. {
  188. CrackErrorDescription(
  189. lpstrErrorString,
  190. m_nError,
  191. m_nSubError,
  192. m_fURLSupported,
  193. m_strDefault
  194. );
  195. }
  196. void
  197. CCustomError::BuildErrorString(
  198. OUT CString & str
  199. )
  200. /*++
  201. Routine Description:
  202. Build metabase-ready error string out of the current values
  203. Arguments:
  204. CString & str : String
  205. Return Value:
  206. None
  207. --*/
  208. {
  209. ASSERT(!IsDefault());
  210. try
  211. {
  212. if (m_nSubError > 0)
  213. {
  214. str.Format(_T("%d,%d,%s,%s"),
  215. m_nError,
  216. m_nSubError,
  217. IsFile() ? s_szFile : s_szURL,
  218. (LPCTSTR)m_str
  219. );
  220. }
  221. else
  222. {
  223. str.Format(
  224. _T("%d,%s,%s,%s"),
  225. m_nError,
  226. s_szNoSubError,
  227. IsFile() ? s_szFile : s_szURL,
  228. (LPCTSTR)m_str
  229. );
  230. }
  231. }
  232. catch(CMemoryException * e)
  233. {
  234. e->ReportError();
  235. e->Delete();
  236. }
  237. }
  238. //
  239. // Custom Errors property page
  240. //
  241. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  242. CCustomErrorDlg::CCustomErrorDlg(
  243. IN OUT CCustomError * pErr,
  244. IN BOOL fLocal,
  245. IN CWnd * pParent OPTIONAL
  246. )
  247. /*++
  248. Routine Description:
  249. Error editing dialog
  250. Arguments:
  251. CCustomError * pErr : Error definition to be edited
  252. BOOL fLocal : TRUE if the current computer is local
  253. CWnd * pParent : Optional parent window or NULL
  254. Return Value:
  255. N/A
  256. --*/
  257. : CDialog(CCustomErrorDlg::IDD, pParent),
  258. m_fLocal(fLocal),
  259. m_pErr(pErr),
  260. m_nMessageType(pErr->m_nType),
  261. m_strTextFile(pErr->m_str),
  262. m_strDefText(pErr->m_strDefault)
  263. {
  264. #if 0 // Keep Class Wizard Happy
  265. //{{AFX_DATA_INIT(CCustomErrorDlg)
  266. m_nMessageType = -1;
  267. m_strTextFile = _T("");
  268. m_strDefText = _T("");
  269. //}}AFX_DATA_INIT
  270. #endif // 0
  271. VERIFY(m_strFile.LoadString(IDS_FILE_PROMPT));
  272. VERIFY(m_strURL.LoadString(IDS_URL_PROMPT));
  273. }
  274. void
  275. CCustomErrorDlg::DoDataExchange(
  276. IN CDataExchange * pDX
  277. )
  278. /*++
  279. Routine Description:
  280. Initialise/Store control data
  281. Arguments:
  282. CDataExchange * pDX - DDX/DDV control structure
  283. Return Value:
  284. None
  285. --*/
  286. {
  287. CDialog::DoDataExchange(pDX);
  288. //{{AFX_DATA_MAP(CCustomErrorDlg)
  289. DDX_CBIndex(pDX, IDC_COMBO_MESSAGE_TYPE, m_nMessageType);
  290. DDX_Text(pDX, IDC_STATIC_DEF_TEXT, m_strDefText);
  291. DDX_Control(pDX, IDC_EDIT_TEXT_FILE, m_edit_TextFile);
  292. DDX_Control(pDX, IDC_STATIC_SUB_PROMPT, m_static_SubErrorPrompt);
  293. DDX_Control(pDX, IDC_STATIC_SUB_ERROR_CODE, m_static_SubError);
  294. DDX_Control(pDX, IDC_STATIC_TEXT_FILE_PROMT, m_static_TextFilePrompt);
  295. DDX_Control(pDX, IDC_BUTTON_BROWSE, m_button_Browse);
  296. DDX_Control(pDX, IDC_COMBO_MESSAGE_TYPE, m_combo_MessageType);
  297. DDX_Control(pDX, IDOK, m_button_OK);
  298. //}}AFX_DATA_MAP
  299. DDX_Text(pDX, IDC_STATIC_ERROR_CODE, m_pErr->m_nError);
  300. DDX_Text(pDX, IDC_STATIC_SUB_ERROR_CODE, m_pErr->m_nSubError);
  301. DDX_Text(pDX, IDC_EDIT_TEXT_FILE, m_strTextFile);
  302. m_strTextFile.TrimLeft();
  303. m_strTextFile.TrimRight();
  304. if (pDX->m_bSaveAndValidate)
  305. {
  306. if (m_nMessageType == CCustomError::ERT_FILE)
  307. {
  308. if (PathIsRelative(m_strTextFile)
  309. || (m_fLocal && PathIsNetworkPath(m_strTextFile))
  310. )
  311. {
  312. ::AfxMessageBox(IDS_ERR_BAD_PATH);
  313. pDX->Fail();
  314. }
  315. if (m_fLocal &&
  316. (::GetFileAttributes(m_strTextFile) & FILE_ATTRIBUTE_DIRECTORY))
  317. {
  318. ::AfxMessageBox(IDS_ERR_FILE_NOT_FOUND);
  319. pDX->Fail();
  320. }
  321. }
  322. else if (m_nMessageType == CCustomError::ERT_URL)
  323. {
  324. if (!IsRelURLPath(m_strTextFile))
  325. {
  326. ::AfxMessageBox(IDS_NOT_REL_URL);
  327. pDX->Fail();
  328. }
  329. }
  330. }
  331. }
  332. //
  333. // Message Map
  334. //
  335. BEGIN_MESSAGE_MAP(CCustomErrorDlg, CDialog)
  336. //{{AFX_MSG_MAP(CCustomErrorDlg)
  337. ON_CBN_SELCHANGE(IDC_COMBO_MESSAGE_TYPE, OnSelchangeComboMessageType)
  338. ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse)
  339. ON_EN_CHANGE(IDC_EDIT_TEXT_FILE, OnChangeEditTextFile)
  340. //}}AFX_MSG_MAP
  341. END_MESSAGE_MAP()
  342. BOOL
  343. CCustomErrorDlg::SetControlStates()
  344. /*++
  345. Routine Description:
  346. Set the enabled states of the dialog controls depending on the current
  347. state of the dialog
  348. Arguments:
  349. None
  350. Return Value:
  351. TRUE if file/url is selected, FALSE otherwise
  352. --*/
  353. {
  354. int nCurSel = m_combo_MessageType.GetCurSel();
  355. BOOL fFile = nCurSel == CCustomError::ERT_FILE;
  356. BOOL fDefault = nCurSel == CCustomError::ERT_DEFAULT;
  357. ActivateControl(m_button_Browse, m_fLocal && fFile);
  358. ActivateControl(m_edit_TextFile, !fDefault);
  359. ActivateControl(m_static_TextFilePrompt, !fDefault);
  360. m_static_TextFilePrompt.SetWindowText(fFile ? m_strFile : m_strURL);
  361. m_button_OK.EnableWindow(fDefault
  362. || m_edit_TextFile.GetWindowTextLength() > 0);
  363. return !fDefault;
  364. }
  365. //
  366. // Message Handlers
  367. //
  368. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  369. BOOL
  370. CCustomErrorDlg::OnInitDialog()
  371. /*++
  372. Routine Description:
  373. WM_INITDIALOG handler. Initialize the dialog.
  374. Arguments:
  375. None.
  376. Return Value:
  377. TRUE if focus is to be set automatically, FALSE if the focus
  378. is already set.
  379. --*/
  380. {
  381. CDialog::OnInitDialog();
  382. //
  383. // Browsing available locally only
  384. //
  385. m_button_Browse.EnableWindow(m_fLocal);
  386. CString str;
  387. VERIFY(str.LoadString(IDS_DEFAULT_ERROR));
  388. m_combo_MessageType.AddString(str);
  389. VERIFY(str.LoadString(IDS_FILE));
  390. m_combo_MessageType.AddString(str);
  391. if (m_pErr->URLSupported() || m_nMessageType == CCustomError::ERT_URL)
  392. {
  393. VERIFY(str.LoadString(IDS_URL));
  394. m_combo_MessageType.AddString(str);
  395. }
  396. m_combo_MessageType.SetCurSel(m_nMessageType);
  397. if (m_pErr->m_nSubError == 0)
  398. {
  399. DeActivateControl(m_static_SubErrorPrompt);
  400. DeActivateControl(m_static_SubError);
  401. }
  402. SetControlStates();
  403. return TRUE;
  404. }
  405. void
  406. CCustomErrorDlg::OnSelchangeComboMessageType()
  407. /*++
  408. Routine Description:
  409. Handle change in message type combo box
  410. Arguments:
  411. None
  412. Return Value:
  413. None
  414. --*/
  415. {
  416. int nSel = m_combo_MessageType.GetCurSel();
  417. if (m_nMessageType == nSel)
  418. {
  419. //
  420. // Selection didn't change
  421. //
  422. return;
  423. }
  424. m_nMessageType = nSel;
  425. if (SetControlStates())
  426. {
  427. m_edit_TextFile.SetWindowText(_T(""));
  428. m_edit_TextFile.SetFocus();
  429. }
  430. }
  431. void
  432. CCustomErrorDlg::OnChangeEditTextFile()
  433. /*++
  434. Routine Description:
  435. Handle change in text/file edit box
  436. Arguments:
  437. None
  438. Return Value:
  439. None
  440. --*/
  441. {
  442. SetControlStates();
  443. }
  444. void
  445. CCustomErrorDlg::OnOK()
  446. /*++
  447. Routine Description:
  448. Handle the OK button being pressed
  449. Arguments:
  450. None
  451. Return Value:
  452. None
  453. --*/
  454. {
  455. if (UpdateData(TRUE))
  456. {
  457. m_pErr->m_nType = (CCustomError::ERT)m_nMessageType;
  458. m_pErr->m_str = m_strTextFile;
  459. CDialog::OnOK();
  460. }
  461. }
  462. void
  463. CCustomErrorDlg::OnButtonBrowse()
  464. /*++
  465. Routine Description:
  466. Browse for HTML File
  467. Arguments:
  468. None
  469. Return Value:
  470. None
  471. --*/
  472. {
  473. ASSERT(m_fLocal);
  474. //
  475. // popup the file dialog and let the user select the error htm file
  476. //
  477. CString str;
  478. str.LoadString(IDS_HTML_MASK);
  479. CFileDialog dlgBrowse(TRUE, NULL, NULL, OFN_HIDEREADONLY, str, this);
  480. // Disable hook to get Windows 2000 style dialog
  481. dlgBrowse.m_ofn.Flags &= ~(OFN_ENABLEHOOK);
  482. dlgBrowse.m_ofn.Flags |= OFN_DONTADDTORECENT|OFN_FILEMUSTEXIST;
  483. if (dlgBrowse.DoModal() == IDOK)
  484. {
  485. m_pErr->m_str = dlgBrowse.GetPathName();
  486. m_edit_TextFile.SetWindowText(m_pErr->m_str);
  487. }
  488. }