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.

938 lines
16 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(m_hWnd))
  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. DWORD
  280. CW3ErrorsPage::SortCustomErrorsList()
  281. {
  282. BeginWaitCursor();
  283. DWORD dw = m_oblErrors.Sort(
  284. (CObjectPlus::PCOBJPLUS_ORDER_FUNC)&CCustomError::OrderByErrorNum);
  285. EndWaitCursor();
  286. return dw;
  287. }
  288. HRESULT
  289. CW3ErrorsPage::StoreErrors()
  290. /*++
  291. Routine Description:
  292. Build errors stringlist from the error oblist built up.
  293. Arguments:
  294. None
  295. Return Value:
  296. Error return code
  297. --*/
  298. {
  299. CError err;
  300. try
  301. {
  302. m_strlCustomErrors.RemoveAll();
  303. POSITION pos = m_oblErrors.GetHeadPosition();
  304. while(pos)
  305. {
  306. CCustomError * pErr = (CCustomError *)m_oblErrors.GetNext(pos);
  307. if (!pErr->IsDefault())
  308. {
  309. CString str;
  310. pErr->BuildErrorString(str);
  311. m_strlCustomErrors.AddTail(str);
  312. }
  313. }
  314. }
  315. catch(CMemoryException * e)
  316. {
  317. err = ERROR_NOT_ENOUGH_MEMORY;
  318. e->Delete();
  319. }
  320. return err;
  321. }
  322. CCustomError *
  323. CW3ErrorsPage::FindError(
  324. IN UINT nError,
  325. IN UINT nSubError
  326. )
  327. /*++
  328. Routine Description:
  329. Find error in the list with the given error code and suberror code
  330. Arguments:
  331. UINT nError : Error code
  332. UINT nSubError : Sub error code
  333. Return Value:
  334. Pointer to the error or NULL if not found.
  335. --*/
  336. {
  337. CCustomError * pErr = NULL;
  338. POSITION pos = m_oblErrors.GetHeadPosition();
  339. while(pos)
  340. {
  341. pErr = (CCustomError *)m_oblErrors.GetNext(pos);
  342. ASSERT(pErr != NULL);
  343. if (pErr->m_nError == nError && pErr->m_nSubError == nSubError)
  344. {
  345. //
  346. // Found it!
  347. //
  348. return pErr;
  349. }
  350. }
  351. //
  352. // Not found!
  353. //
  354. return NULL;
  355. }
  356. HRESULT
  357. CW3ErrorsPage::FetchErrors()
  358. /*++
  359. Routine Description:
  360. Build up the errors list
  361. Arguments:
  362. None
  363. Return Value:
  364. Error return code
  365. --*/
  366. {
  367. CError err;
  368. CWaitCursor wait;
  369. do
  370. {
  371. try
  372. {
  373. //
  374. // First get the default descriptions
  375. //
  376. CHTTPErrorDescriptions ed(QueryServerName());
  377. err = ed.LoadData();
  378. if (err.Failed())
  379. {
  380. break;
  381. }
  382. if (!ed.GetErrorDescriptions().IsEmpty())
  383. {
  384. POSITION pos = ed.GetErrorDescriptions().GetHeadPosition();
  385. while(pos)
  386. {
  387. CString & str = ed.GetErrorDescriptions().GetNext(pos);
  388. m_oblErrors.AddTail(new CCustomError(str));
  389. }
  390. }
  391. else
  392. {
  393. DoHelpMessageBox(m_hWnd,IDS_NO_DEF_ERRORS, MB_APPLMODAL | MB_OK | MB_ICONINFORMATION, 0);
  394. break;
  395. }
  396. //
  397. // Now match up the overrides if any
  398. //
  399. POSITION pos = m_strlCustomErrors.GetHeadPosition();
  400. while(pos)
  401. {
  402. CString & strError = m_strlCustomErrors.GetNext(pos);
  403. TRACEEOLID(strError);
  404. UINT nError;
  405. UINT nSubError;
  406. CCustomError::ERT nType;
  407. CString str;
  408. CCustomError * pErr = NULL;
  409. if (CCustomError::CrackErrorString(
  410. strError,
  411. nError,
  412. nSubError,
  413. nType,
  414. str
  415. ))
  416. {
  417. pErr = FindError(nError, nSubError);
  418. }
  419. if (pErr != NULL)
  420. {
  421. pErr->SetValue(nType, str);
  422. }
  423. else
  424. {
  425. CString strFmt;
  426. strFmt.LoadString(IDS_BAD_ERROR);
  427. str.Format(strFmt, nError, nSubError);
  428. ::AfxMessageBox(str);
  429. break;
  430. }
  431. }
  432. SortCustomErrorsList();
  433. FillListBox();
  434. }
  435. catch(CMemoryException * e)
  436. {
  437. err = ERROR_NOT_ENOUGH_MEMORY;
  438. e->Delete();
  439. }
  440. }
  441. while(FALSE);
  442. return err;
  443. }
  444. void
  445. CW3ErrorsPage::SetControlStates()
  446. /*++
  447. Routine Description:
  448. Enable/disable controls depending on the state of
  449. the dialog
  450. Arguments:
  451. None
  452. Return Value:
  453. None
  454. --*/
  455. {
  456. CCustomError * pErr = GetSelectedListItem();
  457. m_button_Edit.EnableWindow(pErr != NULL);
  458. m_button_SetDefault.EnableWindow(m_list_Errors.GetSelCount() > 0);
  459. }
  460. INT_PTR
  461. CW3ErrorsPage::ShowPropertyDialog()
  462. /*++
  463. Routine Description:
  464. Display the add/edit dialog. The return
  465. value is the value returned by the dialog
  466. Arguments:
  467. None
  468. Return Value:
  469. None
  470. --*/
  471. {
  472. int nCurSel;
  473. CCustomError * pErr = GetSelectedListItem(&nCurSel);
  474. if (pErr == NULL)
  475. {
  476. //
  477. // Must be from a double click on extended selection
  478. //
  479. return IDCANCEL;
  480. }
  481. CCustomErrorDlg dlgError(pErr, IsLocal(), this);
  482. INT_PTR nReturn = dlgError.DoModal();
  483. if (nReturn == IDOK)
  484. {
  485. //
  486. // Re-display the text
  487. //
  488. m_list_Errors.InvalidateSelection(nCurSel);
  489. SetModified(TRUE);
  490. }
  491. return nReturn;
  492. }
  493. //
  494. // Message Handlers
  495. //
  496. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  497. BOOL
  498. CW3ErrorsPage::OnInitDialog()
  499. /*++
  500. Routine Description:
  501. WM_INITDIALOG handler. Initialize the dialog.
  502. Arguments:
  503. None.
  504. Return Value:
  505. TRUE if focus is to be set automatically, FALSE if the focus
  506. is already set.
  507. --*/
  508. {
  509. CInetPropertyPage::OnInitDialog();
  510. m_list_Errors.Initialize();
  511. //
  512. // Build filters oblist
  513. //
  514. CError err(FetchErrors());
  515. err.MessageBoxOnFailure(m_hWnd);
  516. SetControlStates();
  517. return TRUE;
  518. }
  519. void
  520. CW3ErrorsPage::OnButtonEdit()
  521. /*++
  522. Routine Description:
  523. 'edit' button handler
  524. Arguments:
  525. None
  526. Return Value:
  527. None
  528. --*/
  529. {
  530. if (ShowPropertyDialog() == IDOK)
  531. {
  532. SetControlStates();
  533. SetModified(TRUE);
  534. }
  535. }
  536. void
  537. CW3ErrorsPage::OnButtonSetToDefault()
  538. /*++
  539. Routine Description:
  540. 'set to default' button handler
  541. Arguments:
  542. None
  543. Return Value:
  544. None
  545. --*/
  546. {
  547. //
  548. // Apply to each selected item
  549. //
  550. m_list_Errors.SetRedraw(FALSE);
  551. int nSel = 0;
  552. int cChanges = 0;
  553. CCustomError * pErr;
  554. while ((pErr = GetNextSelectedItem(&nSel)) != NULL)
  555. {
  556. if (!pErr->IsDefault())
  557. {
  558. //
  559. // Force a redraw of the current item
  560. //
  561. pErr->MakeDefault();
  562. m_list_Errors.InvalidateSelection(nSel);
  563. ++cChanges;
  564. }
  565. ++nSel;
  566. }
  567. if (cChanges)
  568. {
  569. SetModified(TRUE);
  570. }
  571. m_list_Errors.SetRedraw(TRUE);
  572. SetControlStates();
  573. }
  574. void
  575. CW3ErrorsPage::OnDblclkListErrors()
  576. /*++
  577. Routine Description:
  578. error list 'double click' handler
  579. Arguments:
  580. None
  581. Return Value:
  582. None
  583. --*/
  584. {
  585. OnButtonEdit();
  586. }
  587. void
  588. CW3ErrorsPage::OnSelchangeListErrors()
  589. /*++
  590. Routine Description:
  591. error list selection change handler
  592. Arguments:
  593. None
  594. Return Value:
  595. None
  596. --*/
  597. {
  598. SetControlStates();
  599. }
  600. /* virtual */
  601. HRESULT
  602. CW3ErrorsPage::FetchLoadedValues()
  603. /*++
  604. Routine Description:
  605. Move configuration data from sheet to dialog controls
  606. Arguments:
  607. None
  608. Return Value:
  609. HRESULT
  610. --*/
  611. {
  612. CError err;
  613. BEGIN_META_DIR_READ(CW3Sheet)
  614. FETCH_DIR_DATA_FROM_SHEET(m_strlCustomErrors);
  615. END_META_DIR_READ(err)
  616. return err;
  617. }
  618. /* virtual */
  619. HRESULT
  620. CW3ErrorsPage::SaveInfo()
  621. /*++
  622. Routine Description:
  623. Save the information on this property page
  624. Arguments:
  625. None
  626. Return Value:
  627. Error return code
  628. --*/
  629. {
  630. ASSERT(IsDirty());
  631. TRACEEOLID("Saving W3 errors page now...");
  632. CError err;
  633. BeginWaitCursor();
  634. BEGIN_META_DIR_WRITE(CW3Sheet)
  635. STORE_DIR_DATA_ON_SHEET(m_strlCustomErrors)
  636. END_META_DIR_WRITE(err)
  637. if (err.Succeeded())
  638. {
  639. err = ((CW3Sheet *)GetSheet())->SetKeyType();
  640. }
  641. EndWaitCursor();
  642. return err;
  643. }