/*++ Copyright (c) 1994-2000 Microsoft Corporation Module Name : iisservice.cpp Abstract: IISService Object Author: Ronald Meijer (ronaldm) Sergei Antonov (sergeia) Project: Internet Services Manager Revision History: 10/28/2000 sergeia Split from iisobj.cpp --*/ #include "stdafx.h" #include "common.h" #include "inetprop.h" #include "InetMgrApp.h" #include "supdlgs.h" #include "connects.h" #include "iisobj.h" #include "ftpsht.h" #include "fservic.h" #include "facc.h" #include "fmessage.h" #include "fvdir.h" #include "fsecure.h" #include "w3sht.h" #include "wservic.h" #include "wvdir.h" #include "wsecure.h" #include "fltdlg.h" #include "filters.h" #include "w3accts.h" #include "perform.h" #include "docum.h" #include "httppage.h" #include "defws.h" #include "deffs.h" #include "errors.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW // // CIISService Implementation // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /* static */ HRESULT __cdecl CIISService::ShowFTPSiteProperties( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, IN CWnd * pMainWnd, OPTIONAL IN LPARAM lParam, OPTIONAL IN LONG_PTR handle OPTIONAL ) /*++ Routine Description: Callback function to display FTP site properties. Arguments: LPPROPERTYSHEETCALLBACK lpProvider Property sheet provider CComAuthInfo * pAuthInfo COM Authentication info or NULL. LPCTSTR lpszMDPath Metabase path CWnd * pMainWnd Parent window LPARAM lParam LPARAM to pass to MMC LONG handle handle to pass to MMC Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT_PTR(lpProvider); CError err; CFtpSheet * pSheet = new CFtpSheet( pAuthInfo, lpszMDPath, pMainWnd, lParam, handle ); if (pSheet) { pSheet->SetModeless(); CIISMachine * pOwner = ((CIISMBNode *)lParam)->GetOwner(); ASSERT(pOwner != NULL); // // Add instance pages // if (!pOwner->Has10ConnectionsLimit() || !CMetabasePath::IsMasterInstance(lpszMDPath)) { err = AddMMCPage(lpProvider, new CFtpServicePage(pSheet)); } err = AddMMCPage(lpProvider, new CFtpAccountsPage(pSheet)); err = AddMMCPage(lpProvider, new CFtpMessagePage(pSheet)); // // Add directory pages // err = AddMMCPage(lpProvider, new CFtpDirectoryPage(pSheet, TRUE)); if (pOwner->QueryMajorVersion() >= 6) { err = AddMMCPage(lpProvider, new CFtpSecurityPage(pSheet)); } // // Add master site pages // if (CMetabasePath::IsMasterInstance(lpszMDPath) && pOwner->QueryMajorVersion() >= 6) { err = AddMMCPage(lpProvider, new CDefFtpSitePage(pSheet)); } } else { err = ERROR_NOT_ENOUGH_MEMORY; } return err; } /* static */ HRESULT __cdecl CIISService::ShowFTPDirProperties( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, IN CWnd * pMainWnd, OPTIONAL IN LPARAM lParam, OPTIONAL IN LONG_PTR handle OPTIONAL ) /*++ Routine Description: Callback function to display FTP dir properties. Arguments: LPPROPERTYSHEETCALLBACK lpProvider Property sheet provider CComAuthInfo * pAuthInfo COM Authentication info or NULL. LPCTSTR lpszMDPath Metabase path CWnd * pMainWnd Parent window LPARAM lParam LPARAM to pass to MMC LONG handle handle to pass to MMC Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT_PTR(lpProvider); CError err; CFtpSheet * pSheet = new CFtpSheet( pAuthInfo, lpszMDPath, pMainWnd, lParam, handle ); if (pSheet) { pSheet->SetModeless(); CIISMachine * pOwner = ((CIISMBNode *)lParam)->GetOwner(); ASSERT(pOwner != NULL); // // Add directory pages // err = AddMMCPage(lpProvider, new CFtpDirectoryPage(pSheet, FALSE)); if (pOwner->QueryMajorVersion() >= 6) { err = AddMMCPage(lpProvider, new CFtpSecurityPage(pSheet)); } } else { err = ERROR_NOT_ENOUGH_MEMORY; } return err; } /* static */ HRESULT __cdecl CIISService::ShowWebSiteProperties( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, IN CWnd * pMainWnd, OPTIONAL IN LPARAM lParam, OPTIONAL IN LONG_PTR handle OPTIONAL ) /*++ Routine Description: Callback function to display Web site properties. Arguments: LPPROPERTYSHEETCALLBACK lpProvider Property sheet provider CComAuthInfo * pAuthInfo COM Authentication info or NULL. LPCTSTR lpszMDPath Metabase path CWnd * pMainWnd Parent window LPARAM lParam LPARAM to pass to MMC LONG handle handle to pass to MMC Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT_PTR(lpProvider); CError err; CW3Sheet * pSheet = new CW3Sheet( pAuthInfo, lpszMDPath, 0, pMainWnd, lParam, handle ); if (pSheet) { pSheet->SetModeless(); pSheet->SetSheetType(pSheet->SHEET_TYPE_SITE); CIISMachine * pOwner = ((CIISMBNode *)lParam)->GetOwner(); ASSERT(pOwner != NULL); BOOL bMaster = CMetabasePath::IsMasterInstance(lpszMDPath); BOOL bClient = pOwner->Has10ConnectionsLimit(); BOOL bDownlevel = (pOwner->QueryMajorVersion() == 5 && pOwner->QueryMinorVersion() == 0); // // Add instance pages // if (!bClient || !bMaster) { err = AddMMCPage(lpProvider, new CW3ServicePage(pSheet)); } if (!bClient) { err = AddMMCPage(lpProvider, new CW3AccountsPage(pSheet)); if (bDownlevel) { if (!bMaster) { err = AddMMCPage(lpProvider, new CW3PerfPage(pSheet)); } } else { err = AddMMCPage(lpProvider, new CW3PerfPage(pSheet)); } } err = AddMMCPage(lpProvider, new CW3FiltersPage(pSheet)); // // Add directory pages // err = AddMMCPage(lpProvider, new CW3DirectoryPage(pSheet, TRUE)); err = AddMMCPage(lpProvider, new CW3DocumentsPage(pSheet)); err = AddMMCPage(lpProvider, new CW3SecurityPage(pSheet, TRUE, FILE_ATTRIBUTE_VIRTUAL_DIRECTORY)); err = AddMMCPage(lpProvider, new CW3HTTPPage(pSheet)); err = AddMMCPage(lpProvider, new CW3ErrorsPage(pSheet)); if (bMaster && pOwner->QueryMajorVersion() >= 6) { err = AddMMCPage(lpProvider, new CDefWebSitePage(pSheet)); } } else { err = ERROR_NOT_ENOUGH_MEMORY; } return S_OK; } /* static */ HRESULT __cdecl CIISService::ShowWebDirProperties( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, IN CWnd * pMainWnd, OPTIONAL IN LPARAM lParam, OPTIONAL IN LONG_PTR handle OPTIONAL ) /*++ Routine Description: Callback function to display Web dir properties. Arguments: LPPROPERTYSHEETCALLBACK lpProvider Property sheet provider CComAuthInfo * pAuthInfo COM Authentication info or NULL. LPCTSTR lpszMDPath Metabase path CWnd * pMainWnd Parent window LPARAM lParam LPARAM to pass to MMC LONG handle handle to pass to MMC Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT_PTR(lpProvider); CError err; CW3Sheet * pSheet = new CW3Sheet( pAuthInfo, lpszMDPath, 0, pMainWnd, lParam, handle ); if (pSheet) { pSheet->SetModeless(); // // Add directory pages // pSheet->SetSheetType(pSheet->SHEET_TYPE_VDIR); err = AddMMCPage(lpProvider, new CW3DirectoryPage(pSheet, FALSE)); err = AddMMCPage(lpProvider, new CW3DocumentsPage(pSheet)); err = AddMMCPage(lpProvider, new CW3SecurityPage(pSheet, FALSE, FILE_ATTRIBUTE_VIRTUAL_DIRECTORY)); err = AddMMCPage(lpProvider, new CW3HTTPPage(pSheet)); err = AddMMCPage(lpProvider, new CW3ErrorsPage(pSheet)); } else { err = ERROR_NOT_ENOUGH_MEMORY; } return err; } // // Administrable services // /* static */ CIISService::SERVICE_DEF CIISService::_rgServices[] = { { _T("MSFTPSVC"), _T("ftp://"), IDS_SVC_FTP, iFolder, // TODO: Need service bitmap iFTPSite, iFTPDir, iFolder, iFile, IIS_CLASS_FTP_SERVICE_W, IIS_CLASS_FTP_SERVER_W, IIS_CLASS_FTP_VDIR_W, &CIISService::ShowFTPSiteProperties, &CIISService::ShowFTPDirProperties, }, { _T("W3SVC"), _T("http://"), IDS_SVC_WEB, iFolder, // TODO: Need service bitmap iWWWSite, iWWWDir, iFolder, iFile, IIS_CLASS_WEB_SERVICE_W, IIS_CLASS_WEB_SERVER_W, IIS_CLASS_WEB_VDIR_W, &CIISService::ShowWebSiteProperties, &CIISService::ShowWebDirProperties, }, }; /* static */ int CIISService::ResolveServiceName( IN LPCTSTR szServiceName ) /*++ Routine Description: Look up the service name in the table. Return table index. Arguments: LPCTSTR szServiceName : Metabase node name Return Value: Table index or -1 if not found. --*/ { int iDef = -1; // // Sequential search because we expect just a few entries // for (int i = 0; i < ARRAY_SIZE(_rgServices); ++i) { if (!::lstrcmpi(szServiceName, _rgServices[i].szNodeName)) { iDef = i; break; } } return iDef; } CIISService::CIISService( IN CIISMachine * pOwner, IN LPCTSTR szServiceName ) /*++ Routine Description: Constructor. Determine if the given service is administrable, and resolve the details Arguments: CIISMachine * pOwner : Owner machine object LPCTSTR szServiceName : Service name Return Value: N/A --*/ : CIISMBNode(pOwner, szServiceName) { m_iServiceDef = ResolveServiceName(QueryNodeName()); m_fManagedService = (m_iServiceDef >= 0); m_fCanAddInstance = pOwner->CanAddInstance(); if (m_fManagedService) { ASSERT(m_iServiceDef < ARRAY_SIZE(_rgServices)); VERIFY(m_bstrDisplayName.LoadString( _rgServices[m_iServiceDef].nDescriptiveName )); } } /* virtual */ CIISService::~CIISService() /*++ Routine Description: Destructor Arguments: N/A Return Value: N/A --*/ { } /* virtual */ void CIISService::InitializeChildHeaders( IN LPHEADERCTRL lpHeader ) /*++ Routine Description: Build result view for immediate descendant type Arguments: LPHEADERCTRL lpHeader : Header control Return Value: None --*/ { CIISSite::InitializeHeaders(lpHeader); } /* virtual */ HRESULT CIISService::EnumerateScopePane(HSCOPEITEM hParent) /*++ Routine Description: Enumerate scope child items. Arguments: HSCOPEITEM hParent : Parent console handle Return Value: HRESULT --*/ { CError err; DWORD dwInstance; CString strInstance; CMetaEnumerator * pme = NULL; if (!IsAdministrator()) { return err; } err = CreateEnumerator(pme); while (err.Succeeded()) { CIISSite * pSite; err = pme->Next(dwInstance, strInstance); if (err.Succeeded()) { TRACEEOLID("Enumerating node: " << dwInstance); if (NULL == (pSite = new CIISSite(m_pOwner, this, strInstance))) { err = ERROR_NOT_ENOUGH_MEMORY; break; } err = pSite->AddToScopePane(hParent); } } SAFE_DELETE(pme); if (err.Win32Error() == ERROR_NO_MORE_ITEMS) { err.Reset(); } if (err.Failed()) { DisplayError(err); } // SetInterfaceError(err); return err; } /* virtual */ HRESULT CIISService::AddMenuItems( IN LPCONTEXTMENUCALLBACK lpContextMenuCallback, IN OUT long * pInsertionAllowed, IN DATA_OBJECT_TYPES type ) { ASSERT_READ_PTR(lpContextMenuCallback); // // Add base menu items // HRESULT hr = CIISObject::AddMenuItems( lpContextMenuCallback, pInsertionAllowed, type ); if (SUCCEEDED(hr) && m_fCanAddInstance) { ASSERT(pInsertionAllowed != NULL); if (IsAdministrator() && (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0) { AddMenuSeparator(lpContextMenuCallback); if (lstrcmpi(GetNodeName(), SZ_MBN_FTP) == 0) { AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_FTP_SITE); } else if (lstrcmpi(GetNodeName(), SZ_MBN_WEB) == 0) { AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_WEB_SITE); } } // // CODEWORK: Add new instance commands for each of the services // keeping in mind which ones are installed and all. // add that info to the table, remembering that this // is per service. // } return hr; } HRESULT CIISService::InsertNewInstance(DWORD inst) { CError err; // Now we should insert and select this new site TCHAR buf[16]; CIISSite * pSite = new CIISSite(m_pOwner, this, _itot(inst, buf, 10)); if (pSite != NULL) { // If service is not expanded we will get error and no effect if (!IsExpanded()) { SelectScopeItem(); IConsoleNameSpace2 * pConsole = (IConsoleNameSpace2 *)GetConsoleNameSpace(); pConsole->Expand(QueryScopeItem()); } // WAS needs some time to update status of new site as started Sleep(1000); err = pSite->AddToScopePaneSorted(QueryScopeItem(), FALSE); if (err.Succeeded()) { VERIFY(SUCCEEDED(pSite->SelectScopeItem())); } } else { err = ERROR_NOT_ENOUGH_MEMORY; } return err; } HRESULT CIISService::Command( IN long lCommandID, IN CSnapInObjectRootBase * pObj, IN DATA_OBJECT_TYPES type ) { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); HRESULT hr = S_OK; DWORD inst; switch (lCommandID) { case IDM_NEW_FTP_SITE: if (SUCCEEDED(hr = AddFTPSite(pObj, type, &inst))) { hr = InsertNewInstance(inst); } break; case IDM_NEW_WEB_SITE: if (SUCCEEDED(hr = AddWebSite(pObj, type, &inst))) { hr = InsertNewInstance(inst); } break; default: hr = CIISMBNode::Command(lCommandID, pObj, type); break; } return hr; } /* virtual */ HRESULT CIISService::BuildURL( OUT CComBSTR & bstrURL ) const /*++ Routine Description: Recursively build up the URL from the current node and its parents. Arguments: CComBSTR & bstrURL : Returns URL Return Value: HRESULT --*/ { // // This starts off the URL // ASSERT(m_iServiceDef < ARRAY_SIZE(_rgServices)); bstrURL = _rgServices[m_iServiceDef].szProtocol; return S_OK; } HRESULT CIISService::ShowSitePropertiesDlg( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, IN CWnd * pMainWnd, OPTIONAL IN LPARAM lParam, OPTIONAL IN LONG_PTR handle OPTIONAL ) /*++ Routine Description: Display site properties dialog Arguments: LPPROPERTYSHEETCALLBACK lpProvider Property sheet provider CComAuthInfo * pAuthInfo COM Authentication info or NULL. LPCTSTR lpszMDPath Metabase path CWnd * pMainWnd Parent window LPARAM lParam LPARAM to pass to MMC LONG handle handle to pass to MMC Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT(m_iServiceDef >= 0 && m_iServiceDef < ARRAY_SIZE(_rgServices)); return (*_rgServices[m_iServiceDef].pfnSitePropertiesDlg)( lpProvider, pAuthInfo, lpszMDPath, pMainWnd, lParam, handle ); } HRESULT CIISService::ShowDirPropertiesDlg( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, IN CWnd * pMainWnd, OPTIONAL IN LPARAM lParam, OPTIONAL IN LONG_PTR handle OPTIONAL ) /*++ Routine Description: Display directory properties dialog Arguments: LPPROPERTYSHEETCALLBACK lpProvider Property sheet provider CComAuthInfo * pAuthInfo COM Authentication info or NULL. LPCTSTR lpszMDPath Metabase path CWnd * pMainWnd Parent window LPARAM lParam LPARAM to pass to MMC LONG handle handle to pass to MMC Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT(m_iServiceDef >= 0 && m_iServiceDef < ARRAY_SIZE(_rgServices)); return (*_rgServices[m_iServiceDef].pfnDirPropertiesDlg)( lpProvider, pAuthInfo, lpszMDPath, pMainWnd, lParam, handle ); } /* virtual */ HRESULT CIISService::CreatePropertyPages( IN LPPROPERTYSHEETCALLBACK lpProvider, IN LONG_PTR handle, IN IUnknown * pUnk, IN DATA_OBJECT_TYPES type ) /*++ Routine Description: Create the property pages for the given object Arguments: LPPROPERTYSHEETCALLBACK lpProvider : Provider LONG_PTR handle : Handle. IUnknown * pUnk, DATA_OBJECT_TYPES type Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CComBSTR bstrPath; // // CODEWORK: What to do with m_err? This might be // a bad machine object in the first place. Aborting // when the machine object has an error code isn't // such a bad solution here. // /* if (m_err.Failed()) { m_err.MessageBox(); return m_err; } */ CError err(BuildMetaPath(bstrPath)); if (err.Succeeded()) { // // Show master properties // err = ShowSitePropertiesDlg( lpProvider, QueryAuthInfo(), bstrPath, GetMainWindow(), (LPARAM)this, handle ); } err.MessageBoxOnFailure(); return err; }