Leaked source code of windows server 2003
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.

692 lines
14 KiB

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