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.

927 lines
14 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. errors.cpp
  5. Abstract:
  6. HTTP errors property page
  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 "errors.h"
  25. #include "errordlg.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. //
  32. // CCustomErrorsListBox : a listbox of CCustomError objects
  33. //
  34. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  35. //
  36. // Column width relative weights
  37. //
  38. #define WT_HTTP_ERROR 3
  39. #define WT_OUTPUT_TYPE 2
  40. #define WT_CONTENTS 8
  41. //
  42. // Registry key name for this dialog
  43. //
  44. const TCHAR g_szRegKey[] = _T("Errors");
  45. //
  46. // Key under w3svc where the error descriptions live
  47. //
  48. const TCHAR g_cszErrorLocation[] = _T("Info");
  49. IMPLEMENT_DYNAMIC(CCustomErrorsListBox, CHeaderListBox);
  50. const int CCustomErrorsListBox::nBitmaps = 3;
  51. CCustomErrorsListBox::CCustomErrorsListBox(
  52. IN UINT nIDDefault,
  53. IN UINT nIDFile,
  54. IN UINT nIDURL
  55. )
  56. /*++
  57. Routine Description:
  58. Error listbox constructor
  59. Arguments:
  60. UINT nIDDefault : String ID for 'default'
  61. UINT nIDFile : String ID for 'file'
  62. UINT nIDURL : String ID for 'URL'
  63. --*/
  64. : CHeaderListBox(HLS_STRETCH, g_szRegKey)
  65. {
  66. VERIFY(m_str[CCustomError::ERT_DEFAULT].LoadString(nIDDefault));
  67. VERIFY(m_str[CCustomError::ERT_FILE].LoadString(nIDFile));
  68. VERIFY(m_str[CCustomError::ERT_URL].LoadString(nIDURL));
  69. }
  70. void
  71. CCustomErrorsListBox::DrawItemEx(
  72. IN CRMCListBoxDrawStruct & ds
  73. )
  74. /*++
  75. Routine Description:
  76. Draw item in the listbox
  77. Arguments:
  78. CRMCListBoxDrawStruct & ds : Input data structure
  79. Return Value:
  80. N/A
  81. --*/
  82. {
  83. CCustomError * p = (CCustomError *)ds.m_ItemData;
  84. ASSERT(p != NULL);
  85. DrawBitmap(ds, 0, p->m_nType);
  86. CString strError, strText;
  87. if (p->m_nSubError > 0)
  88. {
  89. strError.Format(_T("%d;%d"), p->m_nError, p->m_nSubError);
  90. }
  91. else
  92. {
  93. strError.Format(_T("%d"), p->m_nError);
  94. }
  95. ColumnText(ds, 0, TRUE, strError);
  96. ColumnText(ds, 1, FALSE, m_str[p->m_nType] );
  97. if (p->IsDefault())
  98. {
  99. strText.Format(_T("\"%s\""), p->m_strDefault);
  100. }
  101. else
  102. {
  103. strText = p->m_str;
  104. }
  105. ColumnText(ds, 2, FALSE, strText);
  106. }
  107. /* virtual */
  108. BOOL
  109. CCustomErrorsListBox::Initialize()
  110. /*++
  111. Routine Description:
  112. initialize the listbox. Insert the columns
  113. as requested, and lay them out appropriately
  114. Arguments:
  115. None
  116. Return Value:
  117. TRUE if initialized successfully, FALSE otherwise
  118. --*/
  119. {
  120. if (!CHeaderListBox::Initialize())
  121. {
  122. return FALSE;
  123. }
  124. HINSTANCE hInst = AfxGetResourceHandle();
  125. InsertColumn(0, WT_HTTP_ERROR, IDS_HTTP_ERROR, hInst);
  126. InsertColumn(1, WT_OUTPUT_TYPE, IDS_OUTPUT_TYPE, hInst);
  127. InsertColumn(2, WT_CONTENTS, IDS_CONTENTS, hInst);
  128. //
  129. // Try to set the widths from the stored registry value,
  130. // otherwise distribute according to column weights specified
  131. //
  132. // if (!SetWidthsFromReg())
  133. // {
  134. DistributeColumns();
  135. // }
  136. SetRedraw(TRUE);
  137. return TRUE;
  138. }
  139. CHTTPErrorDescriptions::CHTTPErrorDescriptions(
  140. IN LPCTSTR lpszServer
  141. )
  142. /*++
  143. Routine Description:
  144. Constructor for default errors object. This fetches the default
  145. error definitions
  146. Arguments:
  147. LPCTSTR lpServerName : Server name
  148. Return Value:
  149. None
  150. --*/
  151. : CMetaProperties(
  152. QueryAuthInfo(),
  153. CMetabasePath(g_cszSvc, MASTER_INSTANCE, g_cszErrorLocation)
  154. )
  155. {
  156. m_dwMDUserType = IIS_MD_UT_SERVER;
  157. m_dwMDDataType = MULTISZ_METADATA;
  158. }
  159. /* virtual */
  160. void
  161. CHTTPErrorDescriptions::ParseFields()
  162. /*++
  163. Routine Description:
  164. Parse the fetched data into fields
  165. Arguments:
  166. None
  167. Return Value:
  168. None
  169. --*/
  170. {
  171. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  172. HANDLE_META_RECORD(MD_CUSTOM_ERROR_DESC, m_strlErrorDescriptions)
  173. END_PARSE_META_RECORDS
  174. }
  175. //
  176. // Errors property page
  177. //
  178. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  179. IMPLEMENT_DYNCREATE(CW3ErrorsPage, CInetPropertyPage)
  180. CW3ErrorsPage::CW3ErrorsPage(
  181. IN CInetPropertySheet * pSheet
  182. )
  183. /*++
  184. Routine Description:
  185. Constructor for WWW error property page
  186. Arguments:
  187. CInetPropertySheet * pSheet : Sheet object
  188. Return Value:
  189. N/A
  190. --*/
  191. : CInetPropertyPage(CW3ErrorsPage::IDD, pSheet),
  192. m_list_Errors(IDS_DEFAULT_ERROR, IDS_FILE, IDS_URL),
  193. m_ListBoxRes(IDB_ERRORS, m_list_Errors.nBitmaps),
  194. m_strlCustomErrors(),
  195. m_strlErrorDescriptions(),
  196. m_oblErrors()
  197. {
  198. //{{AFX_DATA_INIT(CW3ErrorsPage)
  199. //}}AFX_DATA_INIT
  200. m_list_Errors.AttachResources(&m_ListBoxRes);
  201. }
  202. CW3ErrorsPage::~CW3ErrorsPage()
  203. /*++
  204. Routine Description:
  205. Destructor
  206. Arguments:
  207. N/A
  208. Return Value:
  209. N/A
  210. --*/
  211. {
  212. }
  213. void
  214. CW3ErrorsPage::DoDataExchange(
  215. IN CDataExchange * pDX
  216. )
  217. /*++
  218. Routine Description:
  219. Initialise/Store control data
  220. Arguments:
  221. CDataExchange * pDX - DDX/DDV control structure
  222. Return Value:
  223. None
  224. --*/
  225. {
  226. CInetPropertyPage::DoDataExchange(pDX);
  227. //{{AFX_DATA_MAP(CW3ErrorsPage)
  228. DDX_Control(pDX, IDC_BUTTON_SET_TO_DEFAULT, m_button_SetDefault);
  229. DDX_Control(pDX, IDC_BUTTON_EDIT, m_button_Edit);
  230. //}}AFX_DATA_MAP
  231. DDX_Control(pDX, IDC_LIST_ERRORS, m_list_Errors);
  232. if (pDX->m_bSaveAndValidate)
  233. {
  234. CError err(StoreErrors());
  235. if (err.MessageBoxOnFailure())
  236. {
  237. pDX->Fail();
  238. }
  239. }
  240. }
  241. //
  242. // Message Map
  243. //
  244. BEGIN_MESSAGE_MAP(CW3ErrorsPage, CInetPropertyPage)
  245. //{{AFX_MSG_MAP(CW3ErrorsPage)
  246. ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit)
  247. ON_BN_CLICKED(IDC_BUTTON_SET_TO_DEFAULT, OnButtonSetToDefault)
  248. ON_LBN_DBLCLK(IDC_LIST_ERRORS, OnDblclkListErrors)
  249. ON_LBN_SELCHANGE(IDC_LIST_ERRORS, OnSelchangeListErrors)
  250. //}}AFX_MSG_MAP
  251. END_MESSAGE_MAP()
  252. void
  253. CW3ErrorsPage::FillListBox()
  254. /*++
  255. Routine Description:
  256. Populate the listbox with the directory entries
  257. Arguments:
  258. None
  259. Return Value:
  260. None
  261. --*/
  262. {
  263. CObListIter obli(m_oblErrors);
  264. CCustomError * pError;
  265. //
  266. // Remember the selection.
  267. //
  268. int nCurSel = m_list_Errors.GetCurSel();
  269. m_list_Errors.SetRedraw(FALSE);
  270. m_list_Errors.ResetContent();
  271. int cItems = 0;
  272. for (/**/; pError = (CCustomError *)obli.Next(); ++cItems)
  273. {
  274. m_list_Errors.AddItem(pError);
  275. }
  276. m_list_Errors.SetRedraw(TRUE);
  277. m_list_Errors.SetCurSel(nCurSel);
  278. }
  279. HRESULT
  280. CW3ErrorsPage::StoreErrors()
  281. /*++
  282. Routine Description:
  283. Build errors stringlist from the error oblist built up.
  284. Arguments:
  285. None
  286. Return Value:
  287. Error return code
  288. --*/
  289. {
  290. CError err;
  291. try
  292. {
  293. m_strlCustomErrors.RemoveAll();
  294. POSITION pos = m_oblErrors.GetHeadPosition();
  295. while(pos)
  296. {
  297. CCustomError * pErr = (CCustomError *)m_oblErrors.GetNext(pos);
  298. if (!pErr->IsDefault())
  299. {
  300. CString str;
  301. pErr->BuildErrorString(str);
  302. m_strlCustomErrors.AddTail(str);
  303. }
  304. }
  305. }
  306. catch(CMemoryException * e)
  307. {
  308. err = ERROR_NOT_ENOUGH_MEMORY;
  309. e->Delete();
  310. }
  311. return err;
  312. }
  313. CCustomError *
  314. CW3ErrorsPage::FindError(
  315. IN UINT nError,
  316. IN UINT nSubError
  317. )
  318. /*++
  319. Routine Description:
  320. Find error in the list with the given error code and suberror code
  321. Arguments:
  322. UINT nError : Error code
  323. UINT nSubError : Sub error code
  324. Return Value:
  325. Pointer to the error or NULL if not found.
  326. --*/
  327. {
  328. CCustomError * pErr = NULL;
  329. POSITION pos = m_oblErrors.GetHeadPosition();
  330. while(pos)
  331. {
  332. pErr = (CCustomError *)m_oblErrors.GetNext(pos);
  333. ASSERT(pErr != NULL);
  334. if (pErr->m_nError == nError && pErr->m_nSubError == nSubError)
  335. {
  336. //
  337. // Found it!
  338. //
  339. return pErr;
  340. }
  341. }
  342. //
  343. // Not found!
  344. //
  345. return NULL;
  346. }
  347. HRESULT
  348. CW3ErrorsPage::FetchErrors()
  349. /*++
  350. Routine Description:
  351. Build up the errors list
  352. Arguments:
  353. None
  354. Return Value:
  355. Error return code
  356. --*/
  357. {
  358. CError err;
  359. CWaitCursor wait;
  360. do
  361. {
  362. try
  363. {
  364. //
  365. // First get the default descriptions
  366. //
  367. CHTTPErrorDescriptions ed(QueryServerName());
  368. err = ed.LoadData();
  369. if (err.Failed())
  370. {
  371. break;
  372. }
  373. if (!ed.GetErrorDescriptions().IsEmpty())
  374. {
  375. POSITION pos = ed.GetErrorDescriptions().GetHeadPosition();
  376. while(pos)
  377. {
  378. CString & str = ed.GetErrorDescriptions().GetNext(pos);
  379. m_oblErrors.AddTail(new CCustomError(str));
  380. }
  381. }
  382. else
  383. {
  384. ::AfxMessageBox(IDS_NO_DEF_ERRORS);
  385. break;
  386. }
  387. //
  388. // Now match up the overrides if any
  389. //
  390. POSITION pos = m_strlCustomErrors.GetHeadPosition();
  391. while(pos)
  392. {
  393. CString & strError = m_strlCustomErrors.GetNext(pos);
  394. TRACEEOLID(strError);
  395. UINT nError;
  396. UINT nSubError;
  397. CCustomError::ERT nType;
  398. CString str;
  399. CCustomError * pErr = NULL;
  400. if (CCustomError::CrackErrorString(
  401. strError,
  402. nError,
  403. nSubError,
  404. nType,
  405. str
  406. ))
  407. {
  408. pErr = FindError(nError, nSubError);
  409. }
  410. if (pErr != NULL)
  411. {
  412. pErr->SetValue(nType, str);
  413. }
  414. else
  415. {
  416. CString strFmt;
  417. strFmt.LoadString(IDS_BAD_ERROR);
  418. str.Format(strFmt, nError, nSubError);
  419. ::AfxMessageBox(str);
  420. break;
  421. }
  422. }
  423. FillListBox();
  424. }
  425. catch(CMemoryException * e)
  426. {
  427. err = ERROR_NOT_ENOUGH_MEMORY;
  428. e->Delete();
  429. }
  430. }
  431. while(FALSE);
  432. return err;
  433. }
  434. void
  435. CW3ErrorsPage::SetControlStates()
  436. /*++
  437. Routine Description:
  438. Enable/disable controls depending on the state of
  439. the dialog
  440. Arguments:
  441. None
  442. Return Value:
  443. None
  444. --*/
  445. {
  446. CCustomError * pErr = GetSelectedListItem();
  447. m_button_Edit.EnableWindow(pErr != NULL);
  448. m_button_SetDefault.EnableWindow(m_list_Errors.GetSelCount() > 0);
  449. }
  450. INT_PTR
  451. CW3ErrorsPage::ShowPropertyDialog()
  452. /*++
  453. Routine Description:
  454. Display the add/edit dialog. The return
  455. value is the value returned by the dialog
  456. Arguments:
  457. None
  458. Return Value:
  459. None
  460. --*/
  461. {
  462. int nCurSel;
  463. CCustomError * pErr = GetSelectedListItem(&nCurSel);
  464. if (pErr == NULL)
  465. {
  466. //
  467. // Must be from a double click on extended selection
  468. //
  469. return IDCANCEL;
  470. }
  471. CCustomErrorDlg dlgError(pErr, IsLocal(), this);
  472. INT_PTR nReturn = dlgError.DoModal();
  473. if (nReturn == IDOK)
  474. {
  475. //
  476. // Re-display the text
  477. //
  478. m_list_Errors.InvalidateSelection(nCurSel);
  479. SetModified(TRUE);
  480. }
  481. return nReturn;
  482. }
  483. //
  484. // Message Handlers
  485. //
  486. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  487. BOOL
  488. CW3ErrorsPage::OnInitDialog()
  489. /*++
  490. Routine Description:
  491. WM_INITDIALOG handler. Initialize the dialog.
  492. Arguments:
  493. None.
  494. Return Value:
  495. TRUE if focus is to be set automatically, FALSE if the focus
  496. is already set.
  497. --*/
  498. {
  499. CInetPropertyPage::OnInitDialog();
  500. m_list_Errors.Initialize();
  501. //
  502. // Build filters oblist
  503. //
  504. CError err(FetchErrors());
  505. err.MessageBoxOnFailure();
  506. SetControlStates();
  507. return TRUE;
  508. }
  509. void
  510. CW3ErrorsPage::OnButtonEdit()
  511. /*++
  512. Routine Description:
  513. 'edit' button handler
  514. Arguments:
  515. None
  516. Return Value:
  517. None
  518. --*/
  519. {
  520. if (ShowPropertyDialog() == IDOK)
  521. {
  522. SetControlStates();
  523. SetModified(TRUE);
  524. }
  525. }
  526. void
  527. CW3ErrorsPage::OnButtonSetToDefault()
  528. /*++
  529. Routine Description:
  530. 'set to default' button handler
  531. Arguments:
  532. None
  533. Return Value:
  534. None
  535. --*/
  536. {
  537. //
  538. // Apply to each selected item
  539. //
  540. m_list_Errors.SetRedraw(FALSE);
  541. int nSel = 0;
  542. int cChanges = 0;
  543. CCustomError * pErr;
  544. while ((pErr = GetNextSelectedItem(&nSel)) != NULL)
  545. {
  546. if (!pErr->IsDefault())
  547. {
  548. //
  549. // Force a redraw of the current item
  550. //
  551. pErr->MakeDefault();
  552. m_list_Errors.InvalidateSelection(nSel);
  553. ++cChanges;
  554. }
  555. ++nSel;
  556. }
  557. if (cChanges)
  558. {
  559. SetModified(TRUE);
  560. }
  561. m_list_Errors.SetRedraw(TRUE);
  562. SetControlStates();
  563. }
  564. void
  565. CW3ErrorsPage::OnDblclkListErrors()
  566. /*++
  567. Routine Description:
  568. error list 'double click' handler
  569. Arguments:
  570. None
  571. Return Value:
  572. None
  573. --*/
  574. {
  575. OnButtonEdit();
  576. }
  577. void
  578. CW3ErrorsPage::OnSelchangeListErrors()
  579. /*++
  580. Routine Description:
  581. error list selection change handler
  582. Arguments:
  583. None
  584. Return Value:
  585. None
  586. --*/
  587. {
  588. SetControlStates();
  589. }
  590. /* virtual */
  591. HRESULT
  592. CW3ErrorsPage::FetchLoadedValues()
  593. /*++
  594. Routine Description:
  595. Move configuration data from sheet to dialog controls
  596. Arguments:
  597. None
  598. Return Value:
  599. HRESULT
  600. --*/
  601. {
  602. CError err;
  603. BEGIN_META_DIR_READ(CW3Sheet)
  604. FETCH_DIR_DATA_FROM_SHEET(m_strlCustomErrors);
  605. END_META_DIR_READ(err)
  606. return err;
  607. }
  608. /* virtual */
  609. HRESULT
  610. CW3ErrorsPage::SaveInfo()
  611. /*++
  612. Routine Description:
  613. Save the information on this property page
  614. Arguments:
  615. None
  616. Return Value:
  617. Error return code
  618. --*/
  619. {
  620. ASSERT(IsDirty());
  621. TRACEEOLID("Saving W3 errors page now...");
  622. CError err;
  623. BeginWaitCursor();
  624. BEGIN_META_DIR_WRITE(CW3Sheet)
  625. STORE_DIR_DATA_ON_SHEET(m_strlCustomErrors)
  626. END_META_DIR_WRITE(err)
  627. if (err.Succeeded())
  628. {
  629. err = ((CW3Sheet *)GetSheet())->SetKeyType();
  630. }
  631. EndWaitCursor();
  632. return err;
  633. }