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.

770 lines
12 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. shts.cpp
  5. Abstract:
  6. IIS Property sheet classes
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager (cluster edition)
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "common.h"
  15. #include "inetprop.h"
  16. #include "InetMgrApp.h"
  17. #include "shts.h"
  18. #include "mime.h"
  19. #include "iisobj.h"
  20. #include "shutdown.h"
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25. #define new DEBUG_NEW
  26. //
  27. // CInetPropertySheet class
  28. //
  29. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  30. IMPLEMENT_DYNAMIC(CInetPropertySheet, CPropertySheet)
  31. CInetPropertySheet::CInetPropertySheet(
  32. CComAuthInfo * pAuthInfo,
  33. LPCTSTR lpszMetaPath,
  34. CWnd * pParentWnd,
  35. LPARAM lParam,
  36. LONG_PTR handle,
  37. UINT iSelectPage
  38. )
  39. /*++
  40. Routine Description:
  41. IIS Property Sheet constructor
  42. Arguments:
  43. CComAuthInfo * pAuthInfo : Authentication information
  44. LPCTSTR lpszMetPath : Metabase path
  45. CWnd * pParentWnd : Optional parent window
  46. LPARAM lParam : MMC Console parameter
  47. LONG_PTR handle : MMC Console handle
  48. UINT iSelectPage : Initial page to be selected
  49. Return Value:
  50. N/A
  51. --*/
  52. : CPropertySheet(_T(""), pParentWnd, iSelectPage),
  53. m_auth(pAuthInfo),
  54. m_strMetaPath(lpszMetaPath),
  55. m_dwInstance(0L),
  56. m_bModeless(FALSE),
  57. m_hConsole(handle),
  58. m_lParam(lParam),
  59. m_fHasAdminAccess(TRUE), // Assumed by default
  60. m_pCap(NULL),
  61. m_refcount(0),
  62. m_fRestartRequired(FALSE),
  63. m_fChanged(FALSE)
  64. {
  65. m_fIsMasterPath = CMetabasePath::IsMasterInstance(lpszMetaPath);
  66. TRACEEOLID("Metabase path is master? " << m_fIsMasterPath);
  67. }
  68. void
  69. CInetPropertySheet::NotifyMMC()
  70. /*++
  71. Routine Description:
  72. Notify MMC that changes have been made, so that the changes are
  73. reflected.
  74. Arguments:
  75. None
  76. Return Value:
  77. None
  78. --*/
  79. {
  80. //
  81. // Notify MMC to update changes.
  82. //
  83. if (m_hConsole != NULL)
  84. {
  85. ASSERT(m_lParam != 0L);
  86. MMCPropertyChangeNotify(m_hConsole, m_lParam);
  87. }
  88. }
  89. CInetPropertySheet::~CInetPropertySheet()
  90. /*++
  91. Routine Description:
  92. IIS Property Sheet destructor
  93. Arguments:
  94. N/A
  95. Return Value:
  96. N/A
  97. --*/
  98. {
  99. // At this moment we should have in m_pages only pages that were not activated
  100. // in this session.
  101. while (!m_pages.IsEmpty())
  102. {
  103. CInetPropertyPage * pPage = m_pages.RemoveHead();
  104. delete pPage;
  105. }
  106. if (m_fChanged)
  107. {
  108. NotifyMMC();
  109. }
  110. if (m_hConsole != NULL)
  111. {
  112. MMCFreeNotifyHandle(m_hConsole);
  113. }
  114. }
  115. void
  116. CInetPropertySheet::AttachPage(CInetPropertyPage * pPage)
  117. {
  118. m_pages.AddTail(pPage);
  119. }
  120. void
  121. CInetPropertySheet::DetachPage(CInetPropertyPage * pPage)
  122. {
  123. POSITION pos = m_pages.Find(pPage);
  124. ASSERT(pos != NULL);
  125. if (pos != NULL)
  126. {
  127. m_fChanged |= pPage->IsDirty();
  128. m_pages.RemoveAt(pos);
  129. }
  130. }
  131. WORD
  132. CInetPropertySheet::QueryMajorVersion() const
  133. {
  134. CIISMBNode * pNode = (CIISMBNode *)m_lParam;
  135. ASSERT(pNode != NULL);
  136. return pNode->QueryMajorVersion();
  137. }
  138. WORD
  139. CInetPropertySheet::QueryMinorVersion() const
  140. {
  141. CIISMBNode * pNode = (CIISMBNode *)m_lParam;
  142. ASSERT(pNode != NULL);
  143. return pNode->QueryMinorVersion();
  144. }
  145. /* virtual */
  146. HRESULT
  147. CInetPropertySheet::LoadConfigurationParameters()
  148. /*++
  149. Routine Description:
  150. Load configuration parameters information
  151. Arguments:
  152. None
  153. Return Value:
  154. HRESULT
  155. --*/
  156. {
  157. //
  158. // Load base values
  159. //
  160. CError err;
  161. if (m_pCap == NULL)
  162. {
  163. TRACEEOLID("Determining path locations for " << m_strMetaPath);
  164. //
  165. // Capability info stored off the service path ("lm/w3svc").
  166. //
  167. ASSERT(m_strInfoPath.IsEmpty());
  168. //
  169. // Building path components
  170. //
  171. CMetabasePath::GetServiceInfoPath(m_strMetaPath, m_strInfoPath);
  172. TRACEEOLID("Storing info path: " << m_strInfoPath);
  173. //
  174. // Split into instance and directory paths
  175. //
  176. if (IsMasterInstance())
  177. {
  178. m_strServicePath = m_strInstancePath = QueryMetaPath();
  179. }
  180. else
  181. {
  182. VERIFY(CMetabasePath::GetInstancePath(
  183. QueryMetaPath(),
  184. m_strInstancePath,
  185. &m_strDirectoryPath
  186. ));
  187. VERIFY(CMetabasePath::GetServicePath(
  188. QueryMetaPath(),
  189. m_strServicePath
  190. ));
  191. }
  192. TRACEEOLID("Service path " << m_strServicePath);
  193. TRACEEOLID("Instance path " << m_strInstancePath);
  194. if (m_strDirectoryPath.IsEmpty() && !IsMasterInstance())
  195. {
  196. m_strDirectoryPath = CMetabasePath(FALSE, QueryMetaPath(), g_cszRoot);
  197. }
  198. else
  199. {
  200. m_strDirectoryPath = QueryMetaPath();
  201. }
  202. TRACEEOLID("Directory path " << m_strDirectoryPath);
  203. m_dwInstance = CMetabasePath::GetInstanceNumber(m_strMetaPath);
  204. TRACEEOLID("Instance number " << m_dwInstance);
  205. m_pCap = new CServerCapabilities(QueryAuthInfo(), m_strInfoPath);
  206. if (!m_pCap)
  207. {
  208. err = ERROR_NOT_ENOUGH_MEMORY;
  209. return err;
  210. }
  211. err = m_pCap->LoadData();
  212. if (err.Succeeded())
  213. {
  214. err = DetermineAdminAccess();
  215. }
  216. }
  217. return err;
  218. }
  219. /* virtual */
  220. void
  221. CInetPropertySheet::FreeConfigurationParameters()
  222. /*++
  223. Routine Description:
  224. Clean up configuration data
  225. Arguments:
  226. None
  227. Return Value:
  228. None
  229. --*/
  230. {
  231. // ASSERT_PTR(m_pCap);
  232. SAFE_DELETE(m_pCap);
  233. }
  234. void
  235. CInetPropertySheet::WinHelp(
  236. IN DWORD dwData,
  237. IN UINT nCmd
  238. )
  239. /*++
  240. Routine Description:
  241. WinHelp override. We can't use the base class, because our
  242. 'sheet' doesn't usually have a window handle
  243. Arguments:
  244. DWORD dwData : Help data
  245. UINT nCmd : Help command
  246. Return Value:
  247. None
  248. --*/
  249. {
  250. #ifdef _DEBUG
  251. TCHAR szBuffer[20];
  252. _stprintf(szBuffer,_T("WinHelp:0x%x\n"),dwData);OutputDebugString(szBuffer);
  253. #endif
  254. if (m_hWnd == NULL)
  255. {
  256. /*
  257. //
  258. // Special case
  259. //
  260. ::WinHelp(
  261. HWND hWndMain,
  262. LPCWSTR lpszHelp,
  263. UINT uCommand,
  264. DWORD dwData
  265. );
  266. */
  267. CWnd * pWnd = ::AfxGetMainWnd();
  268. if (pWnd != NULL)
  269. {
  270. pWnd->WinHelp(dwData, nCmd);
  271. }
  272. return;
  273. }
  274. CPropertySheet::WinHelp(dwData, nCmd);
  275. }
  276. //
  277. // Message Map
  278. //
  279. BEGIN_MESSAGE_MAP(CInetPropertySheet, CPropertySheet)
  280. //{{AFX_MSG_MAP(CInetPropertySheet)
  281. //}}AFX_MSG_MAP
  282. END_MESSAGE_MAP()
  283. //
  284. // CInetPropertyPage class
  285. //
  286. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  287. //
  288. // CInetPropertyPage property page
  289. //
  290. IMPLEMENT_DYNAMIC(CInetPropertyPage, CPropertyPage)
  291. #ifdef _DEBUG
  292. /* virtual */
  293. void
  294. CInetPropertyPage::AssertValid() const
  295. {
  296. }
  297. /* virtual */
  298. void
  299. CInetPropertyPage::Dump(CDumpContext& dc) const
  300. {
  301. }
  302. #endif // _DEBUG
  303. CInetPropertyPage::CInetPropertyPage(
  304. IN UINT nIDTemplate,
  305. IN CInetPropertySheet * pSheet,
  306. IN UINT nIDCaption,
  307. IN BOOL fEnableEnhancedFonts OPTIONAL
  308. )
  309. /*++
  310. Routine Description:
  311. IIS Property Page Constructor
  312. Arguments:
  313. UINT nIDTemplate : Resource template
  314. CInetPropertySheet * pSheet : Associated property sheet
  315. UINT nIDCaption : Caption ID
  316. BOOL fEnableEnhancedFonts : Enable enhanced fonts
  317. Return Value:
  318. N/A
  319. --*/
  320. : CPropertyPage(nIDTemplate, nIDCaption),
  321. m_nHelpContext(nIDTemplate + 0x20000),
  322. m_fEnableEnhancedFonts(fEnableEnhancedFonts),
  323. m_bChanged(FALSE),
  324. m_pSheet(pSheet)
  325. {
  326. //{{AFX_DATA_INIT(CInetPropertyPage)
  327. //}}AFX_DATA_INIT
  328. m_psp.dwFlags |= PSP_HASHELP;
  329. ASSERT(m_pSheet != NULL);
  330. m_pSheet->AttachPage(this);
  331. }
  332. CInetPropertyPage::~CInetPropertyPage()
  333. /*++
  334. Routine Description:
  335. IIS Property Page Destructor
  336. Arguments:
  337. N/A
  338. Return Value:
  339. N/A
  340. --*/
  341. {
  342. }
  343. void
  344. CInetPropertyPage::DoDataExchange(
  345. IN CDataExchange * pDX
  346. )
  347. /*++
  348. Routine Description:
  349. Initialise/Store control data
  350. Arguments:
  351. CDataExchange * pDX - DDX/DDV control structure
  352. Return Value:
  353. None
  354. --*/
  355. {
  356. CPropertyPage::DoDataExchange(pDX);
  357. //{{AFX_DATA_MAP(CInetPropertyPage)
  358. //}}AFX_DATA_MAP
  359. }
  360. /* virtual */
  361. void
  362. CInetPropertyPage::PostNcDestroy()
  363. /*++
  364. Routine Description:
  365. handle destruction of the window by freeing the this
  366. pointer (as this modeless dialog must have been created
  367. on the heap)
  368. Arguments:
  369. None.
  370. Return Value:
  371. None
  372. --*/
  373. {
  374. m_pSheet->Release(this);
  375. delete this;
  376. }
  377. //
  378. // Message Map
  379. //
  380. BEGIN_MESSAGE_MAP(CInetPropertyPage, CPropertyPage)
  381. //{{AFX_MSG_MAP(CInetPropertyPage)
  382. ON_COMMAND(ID_HELP, OnHelp)
  383. ON_WM_HELPINFO()
  384. //}}AFX_MSG_MAP
  385. END_MESSAGE_MAP()
  386. //
  387. // Message Handlers
  388. //
  389. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  390. /* virtual */
  391. BOOL
  392. CInetPropertyPage::OnInitDialog()
  393. /*++
  394. Routine Description:
  395. WM_INITDIALOG handler. Initialize the dialog. Reset changed
  396. status (sometimes gets set by e.g. spinboxes when the dialog is
  397. constructed), so make sure the dialog is considered clean.
  398. Arguments:
  399. None
  400. Return Value:
  401. TRUE if no focus is to be set automatically, FALSE if the focus
  402. is already set.
  403. --*/
  404. {
  405. m_bChanged = FALSE;
  406. //
  407. // Tell derived class to load its configuration parameters
  408. //
  409. CError err(LoadConfigurationParameters());
  410. if (err.Succeeded())
  411. {
  412. err = FetchLoadedValues();
  413. }
  414. BOOL bResult = CPropertyPage::OnInitDialog();
  415. err.MessageBoxOnFailure();
  416. if (m_fEnableEnhancedFonts)
  417. {
  418. CFont * pFont = &m_fontBold;
  419. if (CreateSpecialDialogFont(this, pFont))
  420. {
  421. ApplyFontToControls(this, pFont, IDC_ED_BOLD1, IDC_ED_BOLD5);
  422. }
  423. }
  424. // We should call AddRef here, not in page constructor, because PostNCDestroy()
  425. // is getting called only for pages that were activated, not for all created pages.
  426. // OnInitDialog is also called for activated pages only -- so we will get parity
  427. // and delete property sheet.
  428. //
  429. ASSERT(m_pSheet != NULL);
  430. m_pSheet->AddRef();
  431. return bResult;
  432. }
  433. void
  434. CInetPropertyPage::OnHelp()
  435. /*++
  436. Routine Description:
  437. 'Help' button handler
  438. Arguments:
  439. None
  440. Return Value:
  441. None
  442. --*/
  443. {
  444. ASSERT_PTR(m_pSheet);
  445. #ifdef _DEBUG
  446. TCHAR szBuffer[20];
  447. _stprintf(szBuffer,_T("WinHelp:0x%x\n"),m_nHelpContext);OutputDebugString(szBuffer);
  448. #endif
  449. m_pSheet->WinHelp(m_nHelpContext);
  450. }
  451. BOOL
  452. CInetPropertyPage::OnHelpInfo(
  453. IN HELPINFO * pHelpInfo
  454. )
  455. /*++
  456. Routine Description:
  457. Eat "help info" command
  458. Arguments:
  459. None
  460. Return Value:
  461. None
  462. --*/
  463. {
  464. OnHelp();
  465. return TRUE;
  466. }
  467. BOOL
  468. CInetPropertyPage::OnApply()
  469. /*++
  470. Routine Description:
  471. Handle "OK" or "APPLY". Call the derived class to save its stuff,
  472. and set the dirty state depending on whether saving succeeded or
  473. failed.
  474. Arguments:
  475. None
  476. Return Value:
  477. None
  478. --*/
  479. {
  480. BOOL bSuccess = TRUE;
  481. if (IsDirty())
  482. {
  483. CError err(SaveInfo());
  484. if (err.MessageBoxOnFailure())
  485. {
  486. //
  487. // Failed, sheet will not be dismissed.
  488. //
  489. // CODEWORK: This page should be activated.
  490. //
  491. bSuccess = FALSE;
  492. }
  493. SetModified(!bSuccess);
  494. if (bSuccess && GetSheet()->RestartRequired())
  495. {
  496. // ask user about immediate restart
  497. if (IDYES == ::AfxMessageBox(IDS_ASK_TO_RESTART, MB_YESNO | MB_ICONQUESTION))
  498. {
  499. // restart IIS
  500. CIISMachine * pMachine = new CIISMachine(QueryAuthInfo());
  501. if (pMachine != NULL)
  502. {
  503. CIISShutdownDlg dlg(pMachine, this);
  504. dlg.PerformCommand(ISC_RESTART);
  505. bSuccess = dlg.ServicesWereRestarted();
  506. delete pMachine;
  507. }
  508. }
  509. // mark restart required false to suppress it on other pages
  510. GetSheet()->SetRestartRequired(FALSE);
  511. }
  512. }
  513. return bSuccess;
  514. }
  515. void
  516. CInetPropertyPage::SetModified(
  517. IN BOOL bChanged
  518. )
  519. /*++
  520. Routine Description:
  521. Keep private check on dirty state of the property page.
  522. Arguments:
  523. BOOL bChanged : Dirty flag
  524. Return Value:
  525. None
  526. --*/
  527. {
  528. CPropertyPage::SetModified(bChanged);
  529. m_bChanged = bChanged;
  530. }