/*++ Copyright (c) 1994-1999 Microsoft Corporation Module Name : shts.cpp Abstract: IIS Property sheet classes Author: Ronald Meijer (ronaldm) Project: Internet Services Manager (cluster edition) Revision History: --*/ #include "stdafx.h" #include "common.h" #include "inetprop.h" #include "InetMgrApp.h" #include "shts.h" #include "mime.h" #include "iisobj.h" #include "shutdown.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW // // CInetPropertySheet class // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< IMPLEMENT_DYNAMIC(CInetPropertySheet, CPropertySheet) CInetPropertySheet::CInetPropertySheet( CComAuthInfo * pAuthInfo, LPCTSTR lpszMetaPath, CWnd * pParentWnd, LPARAM lParam, LONG_PTR handle, UINT iSelectPage ) /*++ Routine Description: IIS Property Sheet constructor Arguments: CComAuthInfo * pAuthInfo : Authentication information LPCTSTR lpszMetPath : Metabase path CWnd * pParentWnd : Optional parent window LPARAM lParam : MMC Console parameter LONG_PTR handle : MMC Console handle UINT iSelectPage : Initial page to be selected Return Value: N/A --*/ : CPropertySheet(_T(""), pParentWnd, iSelectPage), m_auth(pAuthInfo), m_strMetaPath(lpszMetaPath), m_dwInstance(0L), m_bModeless(FALSE), m_hConsole(handle), m_lParam(lParam), m_fHasAdminAccess(TRUE), // Assumed by default m_pCap(NULL), m_refcount(0), m_fRestartRequired(FALSE), m_fChanged(FALSE) { m_fIsMasterPath = CMetabasePath::IsMasterInstance(lpszMetaPath); TRACEEOLID("Metabase path is master? " << m_fIsMasterPath); } void CInetPropertySheet::NotifyMMC() /*++ Routine Description: Notify MMC that changes have been made, so that the changes are reflected. Arguments: None Return Value: None --*/ { // // Notify MMC to update changes. // if (m_hConsole != NULL) { ASSERT(m_lParam != 0L); MMCPropertyChangeNotify(m_hConsole, m_lParam); } } CInetPropertySheet::~CInetPropertySheet() /*++ Routine Description: IIS Property Sheet destructor Arguments: N/A Return Value: N/A --*/ { // At this moment we should have in m_pages only pages that were not activated // in this session. while (!m_pages.IsEmpty()) { CInetPropertyPage * pPage = m_pages.RemoveHead(); delete pPage; } if (m_fChanged) { NotifyMMC(); } if (m_hConsole != NULL) { MMCFreeNotifyHandle(m_hConsole); } } void CInetPropertySheet::AttachPage(CInetPropertyPage * pPage) { m_pages.AddTail(pPage); } void CInetPropertySheet::DetachPage(CInetPropertyPage * pPage) { POSITION pos = m_pages.Find(pPage); ASSERT(pos != NULL); if (pos != NULL) { m_fChanged |= pPage->IsDirty(); m_pages.RemoveAt(pos); } } WORD CInetPropertySheet::QueryMajorVersion() const { CIISMBNode * pNode = (CIISMBNode *)m_lParam; ASSERT(pNode != NULL); return pNode->QueryMajorVersion(); } WORD CInetPropertySheet::QueryMinorVersion() const { CIISMBNode * pNode = (CIISMBNode *)m_lParam; ASSERT(pNode != NULL); return pNode->QueryMinorVersion(); } /* virtual */ HRESULT CInetPropertySheet::LoadConfigurationParameters() /*++ Routine Description: Load configuration parameters information Arguments: None Return Value: HRESULT --*/ { // // Load base values // CError err; if (m_pCap == NULL) { TRACEEOLID("Determining path locations for " << m_strMetaPath); // // Capability info stored off the service path ("lm/w3svc"). // ASSERT(m_strInfoPath.IsEmpty()); // // Building path components // CMetabasePath::GetServiceInfoPath(m_strMetaPath, m_strInfoPath); TRACEEOLID("Storing info path: " << m_strInfoPath); // // Split into instance and directory paths // if (IsMasterInstance()) { m_strServicePath = m_strInstancePath = QueryMetaPath(); } else { VERIFY(CMetabasePath::GetInstancePath( QueryMetaPath(), m_strInstancePath, &m_strDirectoryPath )); VERIFY(CMetabasePath::GetServicePath( QueryMetaPath(), m_strServicePath )); } TRACEEOLID("Service path " << m_strServicePath); TRACEEOLID("Instance path " << m_strInstancePath); if (m_strDirectoryPath.IsEmpty() && !IsMasterInstance()) { m_strDirectoryPath = CMetabasePath(FALSE, QueryMetaPath(), g_cszRoot); } else { m_strDirectoryPath = QueryMetaPath(); } TRACEEOLID("Directory path " << m_strDirectoryPath); m_dwInstance = CMetabasePath::GetInstanceNumber(m_strMetaPath); TRACEEOLID("Instance number " << m_dwInstance); m_pCap = new CServerCapabilities(QueryAuthInfo(), m_strInfoPath); if (!m_pCap) { err = ERROR_NOT_ENOUGH_MEMORY; return err; } err = m_pCap->LoadData(); if (err.Succeeded()) { err = DetermineAdminAccess(); } } return err; } /* virtual */ void CInetPropertySheet::FreeConfigurationParameters() /*++ Routine Description: Clean up configuration data Arguments: None Return Value: None --*/ { // ASSERT_PTR(m_pCap); SAFE_DELETE(m_pCap); } void CInetPropertySheet::WinHelp( IN DWORD dwData, IN UINT nCmd ) /*++ Routine Description: WinHelp override. We can't use the base class, because our 'sheet' doesn't usually have a window handle Arguments: DWORD dwData : Help data UINT nCmd : Help command Return Value: None --*/ { #ifdef _DEBUG TCHAR szBuffer[20]; _stprintf(szBuffer,_T("WinHelp:0x%x\n"),dwData);OutputDebugString(szBuffer); #endif if (m_hWnd == NULL) { /* // // Special case // ::WinHelp( HWND hWndMain, LPCWSTR lpszHelp, UINT uCommand, DWORD dwData ); */ CWnd * pWnd = ::AfxGetMainWnd(); if (pWnd != NULL) { pWnd->WinHelp(dwData, nCmd); } return; } CPropertySheet::WinHelp(dwData, nCmd); } // // Message Map // BEGIN_MESSAGE_MAP(CInetPropertySheet, CPropertySheet) //{{AFX_MSG_MAP(CInetPropertySheet) //}}AFX_MSG_MAP END_MESSAGE_MAP() // // CInetPropertyPage class // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // // CInetPropertyPage property page // IMPLEMENT_DYNAMIC(CInetPropertyPage, CPropertyPage) #ifdef _DEBUG /* virtual */ void CInetPropertyPage::AssertValid() const { } /* virtual */ void CInetPropertyPage::Dump(CDumpContext& dc) const { } #endif // _DEBUG CInetPropertyPage::CInetPropertyPage( IN UINT nIDTemplate, IN CInetPropertySheet * pSheet, IN UINT nIDCaption, IN BOOL fEnableEnhancedFonts OPTIONAL ) /*++ Routine Description: IIS Property Page Constructor Arguments: UINT nIDTemplate : Resource template CInetPropertySheet * pSheet : Associated property sheet UINT nIDCaption : Caption ID BOOL fEnableEnhancedFonts : Enable enhanced fonts Return Value: N/A --*/ : CPropertyPage(nIDTemplate, nIDCaption), m_nHelpContext(nIDTemplate + 0x20000), m_fEnableEnhancedFonts(fEnableEnhancedFonts), m_bChanged(FALSE), m_pSheet(pSheet) { //{{AFX_DATA_INIT(CInetPropertyPage) //}}AFX_DATA_INIT m_psp.dwFlags |= PSP_HASHELP; ASSERT(m_pSheet != NULL); m_pSheet->AttachPage(this); } CInetPropertyPage::~CInetPropertyPage() /*++ Routine Description: IIS Property Page Destructor Arguments: N/A Return Value: N/A --*/ { } void CInetPropertyPage::DoDataExchange( IN CDataExchange * pDX ) /*++ Routine Description: Initialise/Store control data Arguments: CDataExchange * pDX - DDX/DDV control structure Return Value: None --*/ { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CInetPropertyPage) //}}AFX_DATA_MAP } /* virtual */ void CInetPropertyPage::PostNcDestroy() /*++ Routine Description: handle destruction of the window by freeing the this pointer (as this modeless dialog must have been created on the heap) Arguments: None. Return Value: None --*/ { m_pSheet->Release(this); delete this; } // // Message Map // BEGIN_MESSAGE_MAP(CInetPropertyPage, CPropertyPage) //{{AFX_MSG_MAP(CInetPropertyPage) ON_COMMAND(ID_HELP, OnHelp) ON_WM_HELPINFO() //}}AFX_MSG_MAP END_MESSAGE_MAP() // // Message Handlers // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /* virtual */ BOOL CInetPropertyPage::OnInitDialog() /*++ Routine Description: WM_INITDIALOG handler. Initialize the dialog. Reset changed status (sometimes gets set by e.g. spinboxes when the dialog is constructed), so make sure the dialog is considered clean. Arguments: None Return Value: TRUE if no focus is to be set automatically, FALSE if the focus is already set. --*/ { m_bChanged = FALSE; // // Tell derived class to load its configuration parameters // CError err(LoadConfigurationParameters()); if (err.Succeeded()) { err = FetchLoadedValues(); } BOOL bResult = CPropertyPage::OnInitDialog(); err.MessageBoxOnFailure(); if (m_fEnableEnhancedFonts) { CFont * pFont = &m_fontBold; if (CreateSpecialDialogFont(this, pFont)) { ApplyFontToControls(this, pFont, IDC_ED_BOLD1, IDC_ED_BOLD5); } } // We should call AddRef here, not in page constructor, because PostNCDestroy() // is getting called only for pages that were activated, not for all created pages. // OnInitDialog is also called for activated pages only -- so we will get parity // and delete property sheet. // ASSERT(m_pSheet != NULL); m_pSheet->AddRef(); return bResult; } void CInetPropertyPage::OnHelp() /*++ Routine Description: 'Help' button handler Arguments: None Return Value: None --*/ { ASSERT_PTR(m_pSheet); #ifdef _DEBUG TCHAR szBuffer[20]; _stprintf(szBuffer,_T("WinHelp:0x%x\n"),m_nHelpContext);OutputDebugString(szBuffer); #endif m_pSheet->WinHelp(m_nHelpContext); } BOOL CInetPropertyPage::OnHelpInfo( IN HELPINFO * pHelpInfo ) /*++ Routine Description: Eat "help info" command Arguments: None Return Value: None --*/ { OnHelp(); return TRUE; } BOOL CInetPropertyPage::OnApply() /*++ Routine Description: Handle "OK" or "APPLY". Call the derived class to save its stuff, and set the dirty state depending on whether saving succeeded or failed. Arguments: None Return Value: None --*/ { BOOL bSuccess = TRUE; if (IsDirty()) { CError err(SaveInfo()); if (err.MessageBoxOnFailure()) { // // Failed, sheet will not be dismissed. // // CODEWORK: This page should be activated. // bSuccess = FALSE; } SetModified(!bSuccess); if (bSuccess && GetSheet()->RestartRequired()) { // ask user about immediate restart if (IDYES == ::AfxMessageBox(IDS_ASK_TO_RESTART, MB_YESNO | MB_ICONQUESTION)) { // restart IIS CIISMachine * pMachine = new CIISMachine(QueryAuthInfo()); if (pMachine != NULL) { CIISShutdownDlg dlg(pMachine, this); dlg.PerformCommand(ISC_RESTART); bSuccess = dlg.ServicesWereRestarted(); delete pMachine; } } // mark restart required false to suppress it on other pages GetSheet()->SetRestartRequired(FALSE); } } return bSuccess; } void CInetPropertyPage::SetModified( IN BOOL bChanged ) /*++ Routine Description: Keep private check on dirty state of the property page. Arguments: BOOL bChanged : Dirty flag Return Value: None --*/ { CPropertyPage::SetModified(bChanged); m_bChanged = bChanged; }