1215 lines
24 KiB
C++
1215 lines
24 KiB
C++
/*++
|
|
|
|
Copyright (c) 1994-2001 Microsoft Corporation
|
|
|
|
Module Name :
|
|
iissite.cpp
|
|
|
|
Abstract:
|
|
IIS Site 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 "iisobj.h"
|
|
#include "machsht.h"
|
|
#include "errors.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
//
|
|
// CIISSite implementation
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
//
|
|
// Site Result View definition
|
|
//
|
|
/* static */ int
|
|
CIISSite::_rgnLabels[COL_TOTAL] =
|
|
{
|
|
IDS_RESULT_SERVICE_DESCRIPTION,
|
|
IDS_RESULT_SERVICE_STATE,
|
|
IDS_RESULT_SERVICE_DOMAIN_NAME,
|
|
IDS_RESULT_SERVICE_IP_ADDRESS,
|
|
IDS_RESULT_SERVICE_TCP_PORT,
|
|
IDS_RESULT_STATUS,
|
|
};
|
|
|
|
|
|
/* static */ int
|
|
CIISSite::_rgnWidths[COL_TOTAL] =
|
|
{
|
|
180,
|
|
70,
|
|
120,
|
|
105,
|
|
40,
|
|
200,
|
|
};
|
|
|
|
|
|
|
|
/* static */ CComBSTR CIISSite::_bstrStarted;
|
|
/* static */ CComBSTR CIISSite::_bstrStopped;
|
|
/* static */ CComBSTR CIISSite::_bstrPaused;
|
|
/* static */ CComBSTR CIISSite::_bstrUnknown;
|
|
/* static */ CComBSTR CIISSite::_bstrPending;
|
|
/* static */ CComBSTR CIISSite::_bstrAllUnassigned;
|
|
/* static */ BOOL CIISSite::_fStaticsLoaded = FALSE;
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISSite::InitializeHeaders(LPHEADERCTRL lpHeader)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL lpHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
|
|
// CIISDirectory::InitializeHeaders(lpHeader);
|
|
if (!_fStaticsLoaded)
|
|
{
|
|
_fStaticsLoaded =
|
|
_bstrStarted.LoadString(IDS_STARTED) &&
|
|
_bstrStopped.LoadString(IDS_STOPPED) &&
|
|
_bstrPaused.LoadString(IDS_PAUSED) &&
|
|
_bstrUnknown.LoadString(IDS_UNKNOWN) &&
|
|
_bstrPending.LoadString(IDS_PENDING) &&
|
|
_bstrAllUnassigned.LoadString(IDS_IP_ALL_UNASSIGNED);
|
|
}
|
|
}
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CIISSite::InitializeChildHeaders(
|
|
IN LPHEADERCTRL lpHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build result view for immediate descendant type
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL lpHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISDirectory::InitializeHeaders(lpHeader);
|
|
}
|
|
|
|
|
|
CIISSite::CIISSite(
|
|
IN CIISMachine * pOwner,
|
|
IN CIISService * pService,
|
|
IN LPCTSTR szNodeName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor. Determine if the given service is administrable,
|
|
and resolve the details
|
|
|
|
Arguments:
|
|
|
|
CIISMachine * pOwner : Owner machine object
|
|
CIISService * pService : Service type
|
|
LPCTSTR szNodeName : Node name (numeric)
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
Notes:
|
|
|
|
This constructor does not immediately resolve the display name of the
|
|
site. It will only resolve its display information when asked
|
|
|
|
--*/
|
|
: CIISMBNode(pOwner, szNodeName),
|
|
m_pService(pService),
|
|
m_fResolved(FALSE),
|
|
m_strDisplayName(),
|
|
//
|
|
// Data members -- plonk in some defaults
|
|
//
|
|
m_dwState(MD_SERVER_STATE_INVALID),
|
|
m_fDeletable(FALSE),
|
|
m_fWolfPackEnabled(FALSE),
|
|
m_fFrontPageWeb(FALSE),
|
|
m_sPort(80),
|
|
m_dwID(::_ttol(szNodeName)),
|
|
m_dwIPAddress(0L),
|
|
m_dwWin32Error(ERROR_SUCCESS),
|
|
m_bstrHostHeaderName(),
|
|
m_bstrComment()
|
|
{
|
|
ASSERT_PTR(m_pService);
|
|
}
|
|
|
|
|
|
|
|
CIISSite::CIISSite(
|
|
IN CIISMachine * pOwner,
|
|
IN CIISService * pService,
|
|
IN LPCTSTR szNodeName,
|
|
IN DWORD dwState,
|
|
IN BOOL fDeletable,
|
|
IN BOOL fClusterEnabled,
|
|
IN USHORT sPort,
|
|
IN DWORD dwID,
|
|
IN DWORD dwIPAddress,
|
|
IN DWORD dwWin32Error,
|
|
IN LPOLESTR szHostHeaderName,
|
|
IN LPOLESTR szComment
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Construct with full information
|
|
|
|
Arguments:
|
|
|
|
CIISMachine * pOwner : Owner machine object
|
|
CIISService * pService : Service type
|
|
LPCTSTR szNodeName : Node name (numeric)
|
|
|
|
plus datamembers
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CIISMBNode(pOwner, szNodeName),
|
|
m_pService(pService),
|
|
m_fResolved(TRUE),
|
|
m_strDisplayName(),
|
|
//
|
|
// Data Members
|
|
//
|
|
m_dwState(dwState),
|
|
m_fDeletable(fDeletable),
|
|
m_fWolfPackEnabled(fClusterEnabled),
|
|
m_sPort(sPort),
|
|
m_dwID(dwID),
|
|
m_dwIPAddress(dwIPAddress),
|
|
m_dwWin32Error(dwWin32Error),
|
|
m_bstrHostHeaderName(szHostHeaderName),
|
|
m_bstrComment(szComment)
|
|
{
|
|
ASSERT_PTR(m_pService);
|
|
}
|
|
|
|
|
|
|
|
CIISSite::~CIISSite()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor
|
|
|
|
Arguments:
|
|
|
|
N/A
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISSite::RefreshData()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Refresh relevant configuration data required for display.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CError err;
|
|
CWaitCursor wait;
|
|
CComBSTR bstrPath;
|
|
CMetaKey * pKey = NULL;
|
|
|
|
do
|
|
{
|
|
ASSERT_PTR(_lpConsoleNameSpace);
|
|
err = BuildMetaPath(bstrPath);
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
// We need instance key here
|
|
CString path_inst;
|
|
CMetabasePath::GetInstancePath(bstrPath, path_inst);
|
|
|
|
BOOL fContinue = TRUE;
|
|
while (fContinue)
|
|
{
|
|
fContinue = FALSE;
|
|
if (NULL == (pKey = new CMetaKey(QueryInterface(), path_inst)))
|
|
{
|
|
TRACEEOLID("RefreshData: OOM");
|
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
err = pKey->QueryResult();
|
|
if (IsLostInterface(err))
|
|
{
|
|
SAFE_DELETE(pKey);
|
|
fContinue = OnLostInterface(err);
|
|
}
|
|
}
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
|
|
CInstanceProps inst(pKey, _T(""), m_dwID);
|
|
err = inst.LoadData();
|
|
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
|
|
m_dwState = inst.m_dwState;
|
|
m_fDeletable = !inst.m_fNotDeletable;
|
|
|
|
//
|
|
// Don't be confused -- cluster enabled refers
|
|
// to wolfpack and has nothing to do with app server
|
|
//
|
|
m_fWolfPackEnabled = inst.IsClusterEnabled();
|
|
m_sPort = (SHORT)inst.m_nTCPPort;
|
|
m_dwID = inst.QueryInstance();
|
|
m_dwIPAddress = inst.m_iaIpAddress;
|
|
m_dwWin32Error = inst.m_dwWin32Error;
|
|
m_bstrHostHeaderName = inst.m_strDomainName;
|
|
m_bstrComment = inst.m_strComment;
|
|
m_strDisplayName.Empty();
|
|
// Check if it is Frontpage controlled site
|
|
pKey->QueryValue(MD_FRONTPAGE_WEB, m_fFrontPageWeb);
|
|
|
|
CChildNodeProps child(pKey, SZ_MBN_ROOT);
|
|
err = child.LoadData();
|
|
BREAK_ON_ERR_FAILURE(err);
|
|
|
|
m_strRedirectPath = child.GetRedirectedPath();
|
|
}
|
|
while(FALSE);
|
|
|
|
SAFE_DELETE(pKey);
|
|
|
|
if (m_dwWin32Error == ERROR_SUCCESS)
|
|
{
|
|
m_dwWin32Error = err.Win32Error();
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISSite::QueryImage() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return bitmap index for the site
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Bitmap index
|
|
|
|
--*/
|
|
{
|
|
ASSERT_PTR(m_pService);
|
|
if (!m_fResolved)
|
|
{
|
|
TRACEEOLID("Resolving name for site #" << QueryNodeName());
|
|
|
|
if (m_hScopeItem == NULL)
|
|
{
|
|
//
|
|
// BUGBUG:
|
|
//
|
|
// This is probably related to MMC bug #324519
|
|
// where we're asked for the display info immediately
|
|
// after adding the item to the console view. This
|
|
// appears to fail only on refresh because the scope
|
|
// item handle is missing, and we can't build a metabase
|
|
// path yet.
|
|
//
|
|
TRACEEOLID("BUGBUG: Prematurely asked for display information");
|
|
//ASSERT(FALSE);
|
|
return iError;
|
|
}
|
|
CIISSite * that = (CIISSite *)this;
|
|
CError err = that->RefreshData();
|
|
that->m_fResolved = err.Succeeded();
|
|
}
|
|
return !m_dwWin32Error && m_pService ? m_pService->QuerySiteImage() : iError;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPOLESTR
|
|
CIISSite::QueryDisplayName()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return primary display name of this site.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
The display name
|
|
|
|
--*/
|
|
{
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
if (!m_fResolved)
|
|
{
|
|
TRACEEOLID("Resolving name for site #" << QueryNodeName());
|
|
|
|
if (m_hScopeItem == NULL)
|
|
{
|
|
//
|
|
// BUGBUG:
|
|
//
|
|
// This is probably related to MMC bug #324519
|
|
// where we're asked for the display info immediately
|
|
// after adding the item to the console view. This
|
|
// appears to fail only on refresh because the scope
|
|
// item handle is missing, and we can't build a metabase
|
|
// path yet.
|
|
//
|
|
TRACEEOLID("BUGBUG: Prematurely asked for display information");
|
|
//ASSERT(FALSE);
|
|
return OLESTR("");
|
|
}
|
|
|
|
CError err = RefreshData();
|
|
m_fResolved = err.Succeeded();
|
|
}
|
|
|
|
if (m_strDisplayName.IsEmpty())
|
|
{
|
|
CIPAddress ia(m_dwIPAddress);
|
|
CInstanceProps::GetDisplayText(
|
|
m_strDisplayName,
|
|
m_bstrComment,
|
|
m_bstrHostHeaderName,
|
|
ia,
|
|
m_sPort,
|
|
m_dwID
|
|
);
|
|
}
|
|
CString buf = m_strDisplayName;
|
|
if (m_dwState == MD_SERVER_STATE_STOPPED)
|
|
{
|
|
buf.Format(IDS_STOPPED_SITE_FMT, m_strDisplayName);
|
|
}
|
|
else if (m_dwState == MD_SERVER_STATE_PAUSED)
|
|
{
|
|
buf.Format(IDS_PAUSED_SITE_FMT, m_strDisplayName);
|
|
}
|
|
m_bstrDisplayNameStatus = buf;
|
|
// return (LPTSTR)(LPCTSTR)m_strDisplayName;
|
|
return m_bstrDisplayNameStatus;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPOLESTR
|
|
CIISSite::GetResultPaneColInfo(int nCol)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return result pane string for the given column number
|
|
|
|
Arguments:
|
|
|
|
int nCol : Column number
|
|
|
|
Return Value:
|
|
|
|
String
|
|
|
|
--*/
|
|
{
|
|
ASSERT(_fStaticsLoaded);
|
|
|
|
TCHAR sz[255];
|
|
|
|
switch(nCol)
|
|
{
|
|
case COL_DESCRIPTION:
|
|
return QueryDisplayName();
|
|
|
|
case COL_STATE:
|
|
switch(m_dwState)
|
|
{
|
|
case MD_SERVER_STATE_STARTED:
|
|
return _bstrStarted;
|
|
|
|
case MD_SERVER_STATE_PAUSED:
|
|
return _bstrPaused;
|
|
|
|
case MD_SERVER_STATE_STOPPED:
|
|
return _bstrStopped;
|
|
|
|
case MD_SERVER_STATE_STARTING:
|
|
case MD_SERVER_STATE_PAUSING:
|
|
case MD_SERVER_STATE_CONTINUING:
|
|
case MD_SERVER_STATE_STOPPING:
|
|
return _bstrPending;
|
|
}
|
|
|
|
return OLESTR("");
|
|
|
|
case COL_DOMAIN_NAME:
|
|
return m_bstrHostHeaderName;
|
|
|
|
case COL_IP_ADDRESS:
|
|
{
|
|
CIPAddress ia(m_dwIPAddress);
|
|
|
|
if (ia.IsZeroValue())
|
|
{
|
|
_bstrResult = _bstrAllUnassigned;
|
|
}
|
|
else
|
|
{
|
|
_bstrResult = ia;
|
|
}
|
|
}
|
|
return _bstrResult;
|
|
|
|
case COL_TCP_PORT:
|
|
_bstrResult = ::_itot(m_sPort, sz, 10);
|
|
return _bstrResult;
|
|
|
|
case COL_STATUS:
|
|
{
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
|
|
CError err(m_dwWin32Error);
|
|
if (err.Succeeded())
|
|
{
|
|
return OLESTR("");
|
|
}
|
|
|
|
_bstrResult = err;
|
|
}
|
|
return _bstrResult;
|
|
}
|
|
|
|
ASSERT_MSG("Bad column number");
|
|
|
|
return OLESTR("");
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISSite::CompareResultPaneItem(CIISObject * pObject, int nCol)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare two CIISObjects on sort item criteria
|
|
|
|
Arguments:
|
|
|
|
CIISObject * pObject : Object to compare against
|
|
int nCol : Column number to sort on
|
|
|
|
Return Value:
|
|
|
|
0 if the two objects are identical
|
|
<0 if this object is less than pObject
|
|
>0 if this object is greater than pObject
|
|
|
|
--*/
|
|
{
|
|
ASSERT_READ_PTR(pObject);
|
|
|
|
if (nCol == 0)
|
|
{
|
|
return CompareScopeItem(pObject);
|
|
}
|
|
|
|
//
|
|
// First criteria is object type
|
|
//
|
|
int n1 = QuerySortWeight();
|
|
int n2 = pObject->QuerySortWeight();
|
|
|
|
if (n1 != n2)
|
|
{
|
|
return n1 - n2;
|
|
}
|
|
|
|
//
|
|
// Both are CIISSite objects
|
|
//
|
|
CIISSite * pSite = (CIISSite *)pObject;
|
|
|
|
switch(nCol)
|
|
{
|
|
//
|
|
// Special case columns
|
|
//
|
|
case COL_IP_ADDRESS:
|
|
{
|
|
CIPAddress ia1(m_dwIPAddress);
|
|
CIPAddress ia2(pSite->QueryIPAddress());
|
|
|
|
return ia1.CompareItem(ia2);
|
|
}
|
|
|
|
case COL_TCP_PORT:
|
|
n1 = QueryPort();
|
|
n2 = pSite->QueryPort();
|
|
return n1 - n2;
|
|
|
|
case COL_STATUS:
|
|
{
|
|
DWORD dw1 = QueryWin32Error();
|
|
DWORD dw2 = pSite->QueryWin32Error();
|
|
|
|
return dw1 - dw2;
|
|
}
|
|
|
|
case COL_DESCRIPTION:
|
|
case COL_STATE:
|
|
case COL_DOMAIN_NAME:
|
|
default:
|
|
//
|
|
// Lexical sort
|
|
//
|
|
return ::lstrcmpi(
|
|
GetResultPaneColInfo(nCol),
|
|
pObject->GetResultPaneColInfo(nCol)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISSite::BuildURL(CComBSTR & bstrURL) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Recursively build up the URL from the current node
|
|
and its parents. For a site node, add the machine name.
|
|
|
|
Arguments:
|
|
|
|
CComBSTR & bstrURL : Returns URL
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Prepend parent portion (protocol in this case)
|
|
//
|
|
CIISMBNode * pNode = GetParentNode();
|
|
|
|
if (pNode)
|
|
{
|
|
hr = pNode->BuildURL(bstrURL);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CString strOwner;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Try to build an URL. Use in order of priority:
|
|
//
|
|
// Domain name:port/root
|
|
// ip address:port/root
|
|
// computer name:port/root
|
|
//
|
|
if (m_bstrHostHeaderName.Length())
|
|
{
|
|
strOwner = m_bstrHostHeaderName;
|
|
}
|
|
else if (m_dwIPAddress != 0L)
|
|
{
|
|
CIPAddress ia(m_dwIPAddress);
|
|
ia.QueryIPAddress(strOwner);
|
|
}
|
|
else
|
|
{
|
|
if (IsLocal())
|
|
{
|
|
//
|
|
// Security reasons restrict this to "localhost" oftentimes
|
|
//
|
|
strOwner = _bstrLocalHost;
|
|
}
|
|
else
|
|
{
|
|
LPOLESTR lpOwner = QueryMachineName();
|
|
strOwner = PURE_COMPUTER_NAME(lpOwner);
|
|
}
|
|
}
|
|
|
|
TCHAR szPort[6]; // 65536 max.
|
|
_itot(m_sPort, szPort, 10);
|
|
|
|
strOwner += _T(":");
|
|
strOwner += szPort;
|
|
|
|
bstrURL.Append(strOwner);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*virtual*/
|
|
HRESULT
|
|
CIISSite::AddMenuItems(
|
|
LPCONTEXTMENUCALLBACK piCallback,
|
|
long * pInsertionAllowed,
|
|
DATA_OBJECT_TYPES type
|
|
)
|
|
{
|
|
ASSERT_READ_PTR(piCallback);
|
|
//
|
|
// Add base menu items
|
|
//
|
|
HRESULT hr = CIISObject::AddMenuItems(
|
|
piCallback,
|
|
pInsertionAllowed,
|
|
type
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pInsertionAllowed != NULL);
|
|
if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
|
|
{
|
|
AddMenuSeparator(piCallback);
|
|
if (IsFtpSite())
|
|
{
|
|
if (GetOwner()->CanAddInstance() && !GetOwner()->Has10ConnectionsLimit())
|
|
{
|
|
AddMenuItemByCommand(piCallback, IDM_NEW_FTP_SITE);
|
|
}
|
|
AddMenuItemByCommand(piCallback, IDM_NEW_FTP_VDIR);
|
|
}
|
|
else if (IsWebSite())
|
|
{
|
|
if (GetOwner()->CanAddInstance() && !GetOwner()->Has10ConnectionsLimit())
|
|
{
|
|
AddMenuItemByCommand(piCallback, IDM_NEW_WEB_SITE);
|
|
}
|
|
AddMenuItemByCommand(piCallback, IDM_NEW_WEB_VDIR);
|
|
}
|
|
}
|
|
if (!m_fFrontPageWeb && (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) != 0)
|
|
{
|
|
AddMenuSeparator(piCallback);
|
|
AddMenuItemByCommand(piCallback, IDM_TASK_SECURITY_WIZARD);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CIISSite::InsertNewInstance(DWORD inst)
|
|
{
|
|
return m_pService->InsertNewInstance(inst);
|
|
}
|
|
|
|
HRESULT
|
|
CIISSite::InsertNewAlias(CString alias)
|
|
{
|
|
CError err;
|
|
// Now we should insert and select this new site
|
|
CIISDirectory * pAlias = new CIISDirectory(m_pOwner, m_pService, alias);
|
|
if (pAlias != NULL)
|
|
{
|
|
// If item is not expanded we will get error and no effect
|
|
if (!IsExpanded())
|
|
{
|
|
SelectScopeItem();
|
|
IConsoleNameSpace2 * pConsole
|
|
= (IConsoleNameSpace2 *)GetConsoleNameSpace();
|
|
pConsole->Expand(QueryScopeItem());
|
|
}
|
|
err = pAlias->AddToScopePaneSorted(QueryScopeItem(), FALSE);
|
|
if (err.Succeeded())
|
|
{
|
|
VERIFY(SUCCEEDED(pAlias->SelectScopeItem()));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISSite::Command(
|
|
long lCommandID,
|
|
CSnapInObjectRootBase * pObj,
|
|
DATA_OBJECT_TYPES type
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle command from context menu.
|
|
|
|
Arguments:
|
|
|
|
long lCommandID : Command ID
|
|
CSnapInObjectRootBase * pObj : Base object
|
|
DATA_OBJECT_TYPES type : Data object type
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwCommand = 0;
|
|
DWORD inst;
|
|
CString alias;
|
|
|
|
switch (lCommandID)
|
|
{
|
|
case IDM_STOP:
|
|
dwCommand = MD_SERVER_COMMAND_STOP;
|
|
break;
|
|
|
|
case IDM_START:
|
|
dwCommand = m_dwState == MD_SERVER_STATE_PAUSED ?
|
|
MD_SERVER_COMMAND_CONTINUE : MD_SERVER_COMMAND_START;
|
|
break;
|
|
|
|
case IDM_PAUSE:
|
|
dwCommand = m_dwState == MD_SERVER_STATE_PAUSED ?
|
|
MD_SERVER_COMMAND_CONTINUE : MD_SERVER_COMMAND_PAUSE;
|
|
break;
|
|
|
|
case IDM_NEW_FTP_SITE:
|
|
if (SUCCEEDED(hr = AddFTPSite(pObj, type, &inst)))
|
|
{
|
|
hr = InsertNewInstance(inst);
|
|
}
|
|
break;
|
|
|
|
case IDM_NEW_FTP_VDIR:
|
|
if (SUCCEEDED(hr = CIISMBNode::AddFTPVDir(pObj, type, alias)))
|
|
{
|
|
hr = InsertNewAlias(alias);
|
|
}
|
|
break;
|
|
|
|
case IDM_NEW_WEB_SITE:
|
|
if (SUCCEEDED(hr = CIISMBNode::AddWebSite(pObj, type, &inst)))
|
|
{
|
|
hr = InsertNewInstance(inst);
|
|
}
|
|
break;
|
|
|
|
case IDM_NEW_WEB_VDIR:
|
|
if (SUCCEEDED(hr = CIISMBNode::AddWebVDir(pObj, type, alias)))
|
|
{
|
|
hr = InsertNewAlias(alias);
|
|
}
|
|
break;
|
|
//
|
|
// Pass on to base class
|
|
//
|
|
default:
|
|
hr = CIISMBNode::Command(lCommandID, pObj, type);
|
|
}
|
|
|
|
if (dwCommand)
|
|
{
|
|
hr = ChangeState(dwCommand);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISSite::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())
|
|
{
|
|
err = ShowPropertiesDlg(
|
|
lpProvider,
|
|
QueryAuthInfo(),
|
|
bstrPath,
|
|
GetMainWindow(),
|
|
(LPARAM)this,
|
|
handle
|
|
);
|
|
}
|
|
|
|
err.MessageBoxOnFailure();
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISSite::ChangeState(DWORD dwCommand)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Change the state of this instance (started/stopped/paused)
|
|
|
|
Arguments:
|
|
|
|
DWORD dwCommand : MD_SERVER_COMMAND_START, etc.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CError err;
|
|
CComBSTR bstrPath;
|
|
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
|
|
do
|
|
{
|
|
CWaitCursor wait;
|
|
|
|
err = BuildMetaPath(bstrPath);
|
|
// We need instance key here
|
|
CString path_inst;
|
|
CMetabasePath::GetInstancePath(bstrPath, path_inst);
|
|
BREAK_ON_ERR_FAILURE(err)
|
|
|
|
CInstanceProps ip(QueryAuthInfo(), path_inst);
|
|
|
|
err = ip.LoadData();
|
|
BREAK_ON_ERR_FAILURE(err)
|
|
|
|
err = ip.ChangeState(dwCommand);
|
|
BREAK_ON_ERR_FAILURE(err)
|
|
|
|
err = RefreshData();
|
|
if (err.Succeeded())
|
|
{
|
|
err = RefreshDisplay();
|
|
}
|
|
}
|
|
while(FALSE);
|
|
|
|
err.MessageBoxOnFailure();
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISSite::EnumerateScopePane(HSCOPEITEM hParent)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate scope child items.
|
|
|
|
Arguments:
|
|
|
|
HSCOPEITEM hParent : Parent console handle
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CError err = EnumerateVDirs(hParent, m_pService);
|
|
if (err.Succeeded() && !IsFtpSite() && m_strRedirectPath.IsEmpty())
|
|
{
|
|
if (m_dwWin32Error == ERROR_SUCCESS)
|
|
{
|
|
err = EnumerateWebDirs(hParent, m_pService);
|
|
}
|
|
}
|
|
if (err.Failed())
|
|
{
|
|
m_dwWin32Error = err.Win32Error();
|
|
RefreshDisplay();
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/*virtual*/
|
|
HRESULT
|
|
CIISSite::EnumerateResultPane(BOOL fExp, IHeaderCtrl * pHdr, IResultData * pResData)
|
|
{
|
|
CError err = CIISObject::EnumerateResultPane(fExp, pHdr, pResData);
|
|
if ( err.Succeeded()
|
|
&& QueryWin32Error() == ERROR_SUCCESS
|
|
&& !IsFtpSite()
|
|
&& m_strRedirectPath.IsEmpty()
|
|
)
|
|
{
|
|
err = CIISMBNode::EnumerateResultPane_(fExp, pHdr, pResData, m_pService);
|
|
if (err.Failed())
|
|
{
|
|
m_dwWin32Error = err.Win32Error();
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISSite::BuildMetaPath(CComBSTR & bstrPath) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Recursively build up the metabase path from the current node
|
|
and its parents
|
|
|
|
Arguments:
|
|
|
|
CComBSTR & bstrPath : Returns metabase path
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
Notes:
|
|
|
|
This will return the home directory path, e.g. "lm/w3svc/2/root",
|
|
not the path of the instance.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Build instance path
|
|
//
|
|
HRESULT hr = CIISMBNode::BuildMetaPath(bstrPath);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Add root directory path
|
|
//
|
|
bstrPath.Append(_cszSeparator);
|
|
bstrPath.Append(g_cszRoot);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// CODEWORK: make it work from CIISMBNode::DeleteNode
|
|
HRESULT
|
|
CIISSite::DeleteNode(IResultData * pResult)
|
|
{
|
|
CError err;
|
|
|
|
if (!NoYesMessageBox(IDS_CONFIRM_DELETE))
|
|
return err;
|
|
|
|
do
|
|
{
|
|
CComBSTR path;
|
|
CMetaInterface * pInterface = QueryInterface();
|
|
ASSERT(pInterface != NULL);
|
|
err = CIISMBNode::BuildMetaPath(path);
|
|
if (err.Failed())
|
|
break;
|
|
CMetaKey mk(pInterface, METADATA_MASTER_ROOT_HANDLE, METADATA_PERMISSION_WRITE);
|
|
if (!mk.Succeeded())
|
|
break;
|
|
err = mk.DeleteKey(path);
|
|
if (err.Failed())
|
|
break;
|
|
|
|
err = RemoveScopeItem();
|
|
|
|
} while (FALSE);
|
|
|
|
if (err.Failed())
|
|
{
|
|
DisplayError(err);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
//
|
|
// We are not supporting empty comments on sites. Even if it is OK for
|
|
// metabase, it will bring more problems in UI. Empty name will be displayed
|
|
// as [Site #N] in UI, and when user will try to rename it again, it could be
|
|
// stored in metabase in this format.
|
|
//
|
|
HRESULT
|
|
CIISSite::RenameItem(LPOLESTR new_name)
|
|
{
|
|
CComBSTR path;
|
|
CError err;
|
|
if (new_name != NULL && lstrlen(new_name) > 0)
|
|
{
|
|
err = BuildMetaPath(path);
|
|
if (err.Succeeded())
|
|
{
|
|
// We need instance key here
|
|
CString path_inst;
|
|
CMetabasePath::GetInstancePath(path, path_inst);
|
|
|
|
CMetaKey mk(QueryInterface(), path_inst, METADATA_PERMISSION_WRITE);
|
|
|
|
err = mk.QueryResult();
|
|
if (err.Succeeded())
|
|
{
|
|
err = mk.SetValue(MD_SERVER_COMMENT, CString(new_name));
|
|
if (err.Succeeded())
|
|
{
|
|
m_strDisplayName = new_name;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return err;
|
|
}
|