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.
 
 
 
 
 
 

1667 lines
41 KiB

/*++
Copyright (c) 1994-2000 Microsoft Corporation
Module Name :
app_pools.cpp
Abstract:
IIS Application Pools nodes
Author:
Sergei Antonov (sergeia)
Project:
Internet Services Manager
Revision History:
11/03/2000 sergeia Initial creation
--*/
#include "stdafx.h"
#include "common.h"
#include "inetprop.h"
#include "InetMgrApp.h"
#include "iisobj.h"
#include "shts.h"
#include "app_sheet.h"
#include "app_pool_sheet.h"
#include "tracker.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
extern CPropertySheetTracker g_OpenPropertySheetTracker;
CAppPoolsContainer::CAppPoolsContainer(
CIISMachine * pOwner,
CIISService * pService
)
: CIISMBNode(pOwner, SZ_MBN_APP_POOLS),
m_pWebService(pService)
{
VERIFY(m_bstrDisplayName.LoadString(IDS_APP_POOLS));
}
CAppPoolsContainer::~CAppPoolsContainer()
{
}
/*virtual*/
HRESULT
CAppPoolsContainer::RefreshData()
{
CError err;
CComBSTR bstrPath;
err = BuildMetaPath(bstrPath);
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,bstrPath);
if (!IsLostInterface(err))
{
// reset error if an other error other than No interface
err.Reset();
}
if (err.Succeeded())
{
return CIISMBNode::RefreshData();
}
DisplayError(err);
return err;
}
HRESULT
CAppPoolsContainer::RefreshDataChildren(CString AppPoolToRefresh,BOOL bVerifyChildren)
{
IConsoleNameSpace2 * pConsoleNameSpace = (IConsoleNameSpace2 *)GetConsoleNameSpace();
HSCOPEITEM hChildItem = NULL;
LONG_PTR cookie;
BOOL bMyVerifyChildren = FALSE;
HRESULT hr = pConsoleNameSpace->GetChildItem(m_hScopeItem, &hChildItem, &cookie);
if (AppPoolToRefresh.IsEmpty())
{
// don't verify children when they ask for *.*
bMyVerifyChildren = FALSE;
}
else
{
bMyVerifyChildren = TRUE;
}
if (bVerifyChildren)
{
bMyVerifyChildren = TRUE;
}
while(SUCCEEDED(hr) && hChildItem)
{
CAppPoolNode * pItem = (CAppPoolNode *)cookie;
if (pItem)
{
if (pItem->IsExpanded())
{
if (AppPoolToRefresh.IsEmpty())
{
pItem->RefreshData(TRUE,bMyVerifyChildren);
pItem->RefreshDisplay(FALSE);
}
else
{
if (0 == AppPoolToRefresh.CompareNoCase(pItem->QueryDisplayName()))
{
pItem->RefreshData(TRUE,bMyVerifyChildren);
pItem->RefreshDisplay(FALSE);
}
}
}
}
hr = pConsoleNameSpace->GetNextItem(hChildItem, &hChildItem, &cookie);
}
return hr;
}
/* virtual */
HRESULT
CAppPoolsContainer::EnumerateScopePane(HSCOPEITEM hParent)
{
CPoolList list;
CError err = EnumerateAppPools(&list);
if (err.Succeeded())
{
POSITION pos = list.GetHeadPosition();
while (pos)
{
CAppPoolNode * pool = list.GetNext(pos);
pool->AddRef();
err = pool->AddToScopePane(hParent);
if (err.Failed())
{
pool->Release();
break;
}
}
}
list.RemoveAll();
DisplayError(err);
return err;
}
/* virtual */
LPOLESTR
CAppPoolsContainer::GetResultPaneColInfo(int nCol)
{
if (nCol == 0)
{
return QueryDisplayName();
}
return OLESTR("");
}
HRESULT
CAppPoolsContainer::EnumerateAppPools(CPoolList * pList)
{
ASSERT(pList != NULL);
CString strPool;
CComBSTR bstrPath;
CError err;
DWORD dwState;
do
{
err = BuildMetaPath(bstrPath);
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,bstrPath);
BREAK_ON_ERR_FAILURE(err)
CMetaKey mk(QueryInterface(), bstrPath, METADATA_PERMISSION_READ);
err = mk.QueryResult();
BREAK_ON_ERR_FAILURE(err)
CStringListEx list;
err = mk.GetChildPaths(list);
BREAK_ON_ERR_FAILURE(err)
CString key_type;
POSITION pos = list.GetHeadPosition();
while (err.Succeeded() && pos != NULL)
{
strPool = list.GetNext(pos);
err = mk.QueryValue(MD_KEY_TYPE, key_type, NULL, strPool);
if (err == (HRESULT)MD_ERROR_DATA_NOT_FOUND)
{
err.Reset();
}
err = mk.QueryValue(MD_APPPOOL_STATE, dwState, NULL, strPool);
if (err == (HRESULT)MD_ERROR_DATA_NOT_FOUND)
{
// if not found then it's state is off..
dwState = MD_APPPOOL_STATE_STOPPED;
err.Reset();
}
// Get the app pool state
if (err.Succeeded() && (key_type.CompareNoCase(_T("IIsApplicationPool")) == 0))
{
CAppPoolNode * pool;
if (NULL == (pool = new CAppPoolNode(m_pOwner, this, strPool, dwState)))
{
err = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pList->AddTail(pool);
}
}
} while (FALSE);
return err;
}
/* virtual */
void
CAppPoolsContainer::InitializeChildHeaders(LPHEADERCTRL lpHeader)
/*++
Routine Description:
Build result view for immediate descendant type
Arguments:
LPHEADERCTRL lpHeader : Header control
--*/
{
CAppPoolNode::InitializeHeaders(lpHeader);
}
/* virtual */
HRESULT
CAppPoolsContainer::CreatePropertyPages(
LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
IUnknown * pUnk,
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());
CError err;
if (S_FALSE == (HRESULT)(err = CIISMBNode::CreatePropertyPages(lpProvider, handle, pUnk, type)))
{
return S_OK;
}
if (ERROR_ALREADY_EXISTS == err.Win32Error())
{
return S_FALSE;
}
if (err.Succeeded())
{
CComBSTR path;
err = BuildMetaPath(path);
if (err.Succeeded())
{
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,path);
if (err.Succeeded())
{
CAppPoolSheet * pSheet = new CAppPoolSheet(
QueryAuthInfo(), path, GetMainWindow(GetConsole()), (LPARAM)this,
(LPARAM)GetOwner()
);
if (pSheet != NULL)
{
// cache handle for user in MMCPropertyChangeNotify
m_ppHandle = handle;
pSheet->SetModeless();
err = AddMMCPage(lpProvider, new CAppPoolRecycle(pSheet));
err = AddMMCPage(lpProvider, new CAppPoolPerf(pSheet));
err = AddMMCPage(lpProvider, new CAppPoolHealth(pSheet));
// err = AddMMCPage(lpProvider, new CAppPoolDebug(pSheet));
err = AddMMCPage(lpProvider, new CAppPoolIdent(pSheet));
// err = AddMMCPage(lpProvider, new CAppPoolCache(pSheet));
// err = AddMMCPage(lpProvider, new CPoolProcessOpt(pSheet));
}
}
}
}
err.MessageBoxOnFailure();
return err;
}
/* virtual */
HRESULT
CAppPoolsContainer::BuildMetaPath(
OUT CComBSTR & bstrPath
) const
/*++
Routine Description:
Recursively build up the metabase path from the current node
and its parents. We cannot use CIISMBNode method because AppPools
is located under w3svc, but rendered after machine.
Arguments:
CComBSTR & bstrPath : Returns metabase path
Return Value:
HRESULT
--*/
{
HRESULT hr = S_OK;
ASSERT(m_pWebService != NULL);
hr = m_pWebService->BuildMetaPath(bstrPath);
if (SUCCEEDED(hr))
{
bstrPath.Append(_cszSeparator);
bstrPath.Append(QueryNodeName());
return hr;
}
//
// No service node
//
ASSERT_MSG("No WebService pointer");
return E_UNEXPECTED;
}
HRESULT
CAppPoolsContainer::QueryDefaultPoolId(CString& id)
//
// Returns pool id which is set on master node for web service
//
{
CError err;
CComBSTR path;
CString service;
BuildMetaPath(path);
CMetabasePath::GetServicePath(path, service);
CMetaKey mk(QueryAuthInfo(), service, METADATA_PERMISSION_READ);
err = mk.QueryResult();
if (err.Succeeded())
{
err = mk.QueryValue(MD_APP_APPPOOL_ID, id);
}
return err;
}
/* virtual */
HRESULT
CAppPoolsContainer::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))
{
ASSERT(pInsertionAllowed != NULL);
if (IsAdministrator())
{
if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
{
AddMenuSeparator(lpContextMenuCallback);
AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_APP_POOL);
if (IsConfigImportExportable())
{
AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_APP_POOL_FROM_FILE);
}
}
if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) != 0)
{
if (IsConfigImportExportable())
{
AddMenuSeparator(lpContextMenuCallback);
AddMenuItemByCommand(lpContextMenuCallback, IDM_TASK_EXPORT_CONFIG_WIZARD);
}
}
}
}
return hr;
}
HRESULT
CAppPoolsContainer::Command(
long lCommandID,
CSnapInObjectRootBase * pObj,
DATA_OBJECT_TYPES type
)
{
HRESULT hr = S_OK;
CString name;
switch (lCommandID)
{
case IDM_NEW_APP_POOL:
{
CError err;
CComBSTR bstrMetaPath;
VERIFY(SUCCEEDED(BuildMetaPath(bstrMetaPath)));
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,bstrMetaPath);
if (!IsLostInterface(err))
{
// reset error if an other error other than No interface
err.Reset();
}
if (err.Succeeded())
{
if ( SUCCEEDED(hr = AddAppPool(pObj, type, this, name))
&& !name.IsEmpty()
)
{
hr = InsertNewPool(name);
}
}
}
break;
//
// Pass on to base class
//
default:
hr = CIISMBNode::Command(lCommandID, pObj, type);
}
return hr;
}
HRESULT
CAppPoolsContainer::InsertNewPool(CString& id)
{
CError err;
if (!IsExpanded())
{
SelectScopeItem();
IConsoleNameSpace2 * pConsoleNameSpace
= (IConsoleNameSpace2 *)GetConsoleNameSpace();
pConsoleNameSpace->Expand(QueryScopeItem());
HSCOPEITEM hChildItem = NULL;
LONG_PTR cookie;
HRESULT hr = pConsoleNameSpace->GetChildItem(m_hScopeItem, &hChildItem, &cookie);
while(SUCCEEDED(hr) && hChildItem)
{
CAppPoolNode * pItem = (CAppPoolNode *)cookie;
ASSERT_PTR(pItem);
if (0 == id.Compare(pItem->QueryDisplayName()))
{
pItem->SelectScopeItem();
// set status to running when creating a new apppool
pItem->ChangeState(MD_APPPOOL_COMMAND_START);
break;
}
hr = pConsoleNameSpace->GetNextItem(hChildItem, &hChildItem, &cookie);
}
}
else
{
// Now we should insert and select this new site
CAppPoolNode * pPool = new CAppPoolNode(m_pOwner, this, id, 0);
if (pPool != NULL)
{
err = pPool->RefreshData();
if (err.Succeeded())
{
pPool->AddRef();
err = pPool->AddToScopePaneSorted(QueryScopeItem(), FALSE);
if (err.Succeeded())
{
VERIFY(SUCCEEDED(pPool->SelectScopeItem()));
// set status to running when creating a new apppool
pPool->ChangeState(MD_APPPOOL_COMMAND_START);
}
else
{
pPool->Release();
}
}
}
else
{
err = ERROR_NOT_ENOUGH_MEMORY;
}
}
return err;
}
////////////////////////////////////////////////////////////////////////////////
// CAppPoolNode implementation
//
// App Pool Result View definition
//
/* static */ int
CAppPoolNode::_rgnLabels[COL_TOTAL] =
{
IDS_RESULT_SERVICE_DESCRIPTION,
IDS_RESULT_SERVICE_STATE,
IDS_RESULT_STATUS
};
/* static */ int
CAppPoolNode::_rgnWidths[COL_TOTAL] =
{
180,
70,
200
};
/* static */ CComBSTR CAppPoolNode::_bstrStarted;
/* static */ CComBSTR CAppPoolNode::_bstrStopped;
/* static */ CComBSTR CAppPoolNode::_bstrUnknown;
/* static */ CComBSTR CAppPoolNode::_bstrPending;
/* static */ BOOL CAppPoolNode::_fStaticsLoaded = FALSE;
CAppPoolNode::CAppPoolNode(
CIISMachine * pOwner,
CAppPoolsContainer * pContainer,
LPCTSTR name,
DWORD dwState
)
: CIISMBNode(pOwner, name),
m_pContainer(pContainer),
m_dwWin32Error(0),
m_dwState(dwState)
{
}
CAppPoolNode::~CAppPoolNode()
{
}
#if 0
// This is too expensive
BOOL
CAppPoolNode::IsDeletable() const
{
// We could delete node if it is empty and it is not default app pool
BOOL bRes = TRUE;
CComBSTR path;
CStringListEx strListOfApps;
BuildMetaPath(path);
CIISMBNode * that = (CIISMBNode *)this;
CIISAppPool pool(that->QueryAuthInfo(), (LPCTSTR)path);
HRESULT hr = pool.EnumerateApplications(strListOfApps);
bRes = (SUCCEEDED(hr) && strListOfApps.GetCount() == 0);
if (bRes)
{
CString buf;
hr = m_pContainer->QueryDefaultPoolId(buf);
bRes = buf.CompareNoCase(QueryNodeName()) != 0;
}
return bRes;
}
#endif
HRESULT
CAppPoolNode::DeleteNode(IResultData * pResult)
{
CError err;
// check if they have the property sheet open on it.
if (IsMyPropertySheetOpen())
{
::AfxMessageBox(IDS_CLOSE_PROPERTY_SHEET);
return S_OK;
}
// this could be an orphaned property sheet
// check if an orphaned property sheet is open on this item.
CIISObject * pAlreadyOpenProp = NULL;
if (TRUE == g_OpenPropertySheetTracker.FindAlreadyOpenPropertySheet(this,&pAlreadyOpenProp))
{
// Bring it to the foreground, and bail
HWND hHwnd = 0;
if (pAlreadyOpenProp)
{
if (hHwnd = pAlreadyOpenProp->IsMyPropertySheetOpen())
{
if (hHwnd && (hHwnd != (HWND) 1))
{
// Perhapse we should cancel the already
// opened property sheet...just a thought
if (!SetForegroundWindow(hHwnd))
{
// wasn't able to bring this property sheet to
// the foreground, the propertysheet must not
// exist anymore. let's just clean the hwnd
// so that the user will be able to open propertysheet
pAlreadyOpenProp->SetMyPropertySheetOpen(0);
}
else
{
::AfxMessageBox(IDS_CLOSE_PROPERTY_SHEET);
return S_OK;
}
}
}
}
}
CComBSTR path;
BuildMetaPath(path);
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,path);
if (!IsLostInterface(err))
{
// reset error if an other error other than No interface
err.Reset();
}
if (err.Succeeded())
{
if (!NoYesMessageBox(IDS_CONFIRM_DELETE))
return err;
CIISAppPool pool(QueryAuthInfo(), (LPCTSTR)path);
err = pool.Delete(QueryNodeName());
if (err.Succeeded())
{
err = RemoveScopeItem();
}
if (err.Win32Error() == ERROR_NOT_EMPTY)
{
CString msg;
msg.LoadString(IDS_ERR_NONEMPTY_APPPOOL);
AfxMessageBox(msg);
}
else
{
err.MessageBoxOnFailure();
}
}
else
{
err.MessageBoxOnFailure();
}
return err;
}
/* virtual */
HRESULT
CAppPoolNode::BuildMetaPath(CComBSTR & bstrPath) const
{
HRESULT hr = S_OK;
ASSERT(m_pContainer != NULL);
hr = m_pContainer->BuildMetaPath(bstrPath);
if (SUCCEEDED(hr))
{
bstrPath.Append(_cszSeparator);
bstrPath.Append(QueryNodeName());
return hr;
}
//
// No service node
//
ASSERT_MSG("No pointer to container");
return E_UNEXPECTED;
}
/* virtual */
LPOLESTR
CAppPoolNode::GetResultPaneColInfo(
IN int nCol
)
/*++
Routine Description:
Return result pane string for the given column number
Arguments:
int nCol : Column number
Return Value:
String
--*/
{
switch(nCol)
{
case COL_DESCRIPTION:
return QueryDisplayName();
case COL_STATE:
switch(m_dwState)
{
case MD_APPPOOL_STATE_STARTED:
return _bstrStarted;
case MD_APPPOOL_STATE_STOPPED:
return _bstrStopped;
case MD_APPPOOL_STATE_STARTING:
case MD_APPPOOL_STATE_STOPPING:
return _bstrPending;
default:
return OLESTR("");
}
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
CAppPoolNode::QueryImage() const
{
if (m_dwWin32Error != 0)
{
return iAppPoolErr;
}
else
{
if (m_dwState == MD_APPPOOL_STATE_STOPPED)
{
return iAppPoolStop;
}
else
{
return iAppPool;
}
}
}
/* virtual */
LPOLESTR
CAppPoolNode::QueryDisplayName()
{
if (m_strDisplayName.IsEmpty())
{
RefreshData();
m_strDisplayName = QueryNodeName();
}
return (LPTSTR)(LPCTSTR)m_strDisplayName;
}
/* virtual */
HRESULT
CAppPoolNode::RefreshData()
{
CError err;
CComBSTR bstrPath1;
CMetaKey * pKey = NULL;
do
{
err = BuildMetaPath(bstrPath1);
if (err.Failed())
{
break;
}
BOOL fContinue = TRUE;
while (fContinue)
{
fContinue = FALSE;
if (NULL == (pKey = new CMetaKey(QueryInterface(), bstrPath1)))
{
TRACEEOLID("RefreshData: Out Of Memory");
err = ERROR_NOT_ENOUGH_MEMORY;
break;
}
err = pKey->QueryResult();
if (IsLostInterface(err))
{
SAFE_DELETE(pKey);
fContinue = OnLostInterface(err);
}
}
if (err.Failed())
{
break;
}
CAppPoolProps pool(pKey, _T(""));
err = pool.LoadData();
if (err.Failed())
{
break;
}
// Assign the data
m_dwState = pool.m_dwState;
m_strDisplayName = QueryNodeName();
m_dwWin32Error = pool.m_dwWin32Error;
}
while(FALSE);
SAFE_DELETE(pKey);
return err;
}
HRESULT
CAppPoolNode::RefreshData(BOOL bRefreshChildren,BOOL bMyVerifyChildren)
{
CError err;
// call regular refreshdata on this node...
err = RefreshData();
// -------------------------------------
// Loop thru all of our children to make
// sure they are all still jiving..
// -------------------------------------
if (bRefreshChildren)
{
CComBSTR bstrPath1;
POSITION pos1 = NULL;
CApplicationList MyMMCList;
CApplicationNode * pItemFromMMC = NULL;
// create a list of what is in mmc...
MyMMCList.RemoveAll();
HSCOPEITEM hChild = NULL, hCurrent;
LONG_PTR cookie = 0;
IConsoleNameSpace2 * pConsoleNameSpace = (IConsoleNameSpace2 *)GetConsoleNameSpace();
err = pConsoleNameSpace->GetChildItem(QueryScopeItem(), &hChild, &cookie);
while (err.Succeeded() && hChild != NULL)
{
CIISMBNode * pNode = (CIISMBNode *)cookie;
if (pNode)
{
if (IsEqualGUID(* (GUID *)pNode->GetNodeType(),cApplicationNode))
{
CApplicationNode * pNode2 = (CApplicationNode *) pNode;
if (pNode2)
{
// clean the displayname, it could have changed..
// and this could be the real reason for the refresh...
pNode2->QueryDisplayName(TRUE);
MyMMCList.AddTail(pNode2);
}
}
}
hCurrent = hChild;
err = pConsoleNameSpace->GetNextItem(hCurrent, &hChild, &cookie);
}
// Loop thru and see if we need to add anything
CStringListEx strListOfApps;
BuildMetaPath(bstrPath1);
CIISAppPool pool(QueryAuthInfo(), (LPCTSTR)bstrPath1);
err = pool.EnumerateApplications(strListOfApps);
if (err.Succeeded() && strListOfApps.GetCount() > 0)
{
POSITION pos2 = NULL;
DWORD iNumApp = 0;
CString strAppInMetabase;
CString strAppInMetabaseName;
pos1 = strListOfApps.GetHeadPosition();
while ( pos1 != NULL)
{
BOOL bExistsInUI = FALSE;
strAppInMetabase = strListOfApps.GetNext(pos1);
iNumApp = CMetabasePath::GetInstanceNumber(strAppInMetabase);
if (iNumApp > 0)
{
CMetabasePath::CleanMetaPath(strAppInMetabase);
CMetabasePath::GetLastNodeName(strAppInMetabase, strAppInMetabaseName);
// Check if this item is in the list...
// Loop through our list
// and see if we need to add anything
pos2 = MyMMCList.GetHeadPosition();
while (pos2)
{
pItemFromMMC = MyMMCList.GetNext(pos2);
if (pItemFromMMC)
{
CComBSTR bstrPath2;
err = pItemFromMMC->BuildMetaPath(bstrPath2);
CString csAppID = bstrPath2;
CMetabasePath::CleanMetaPath(csAppID);
if (0 == csAppID.CompareNoCase(strAppInMetabase))
{
bExistsInUI = TRUE;
break;
}
}
}
if (!bExistsInUI)
{
TRACEEOL(strAppInMetabase << ", not exist but should, adding to UI...");
CApplicationNode * app_node = new CApplicationNode(GetOwner(), strAppInMetabase, strAppInMetabaseName);
if (app_node != NULL)
{
app_node->AddRef();
app_node->AddToScopePane(m_hScopeItem, TRUE, TRUE, FALSE);
}
}
}
}
}
// Loop through our list and find stuff we want to delete
BuildMetaPath(bstrPath1);
pos1 = MyMMCList.GetHeadPosition();
BOOL bMarkedForDelete = FALSE;
while (pos1)
{
pItemFromMMC = MyMMCList.GetNext(pos1);
bMarkedForDelete = FALSE;
// see if it exists in the metabase,
// if it doesn't then add it to the delete list...
if (pItemFromMMC)
{
CComBSTR bstrPath3;
pItemFromMMC->BuildMetaPath(bstrPath3);
// check if path exists...
CMetaKey mk(QueryInterface(), bstrPath3);
if (!mk.Succeeded())
{
// delete it
bMarkedForDelete = TRUE;
}
else
{
// doesn't need to be removed...
// put perhase it does..
// check if this Application is actually being used
// by the site!
if (bMyVerifyChildren)
{
// Lookup that website
// and get it's App that it's using
// see if it's the same as this AppID (BuildMetaPath(bstrPath1);)
err = mk.QueryResult();
if (err.Succeeded())
{
CString csAppID = bstrPath1;
CString csAppIDName;
CMetabasePath::CleanMetaPath(csAppID);
CMetabasePath::GetLastNodeName(csAppID, csAppIDName);
CString id;
err = mk.QueryValue(MD_APP_APPPOOL_ID, id);
err = mk.QueryResult();
if (err.Succeeded())
{
if (0 != csAppIDName.CompareNoCase(id))
{
// the web site, isn't actually using it..
// delete it
bMarkedForDelete = TRUE;
}
}
}
}
}
if (bMarkedForDelete)
{
// delete it list...
TRACEEOL(bstrPath3 << ", not exist, removing from UI...");
// remove it from the UI
pItemFromMMC->RemoveScopeItem();
// delete the object
pItemFromMMC->Release();
}
}
}
}
return err;
}
/* virtual */
int
CAppPoolNode::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 CAppPoolNode objects
//
CAppPoolNode * pPool = (CAppPoolNode *)pObject;
switch(nCol)
{
case COL_DESCRIPTION:
case COL_STATE:
default:
//
// Lexical sort
//
return ::lstrcmpi(
GetResultPaneColInfo(nCol),
pObject->GetResultPaneColInfo(nCol)
);
}
}
/* virtual */
void
CAppPoolNode::InitializeChildHeaders(LPHEADERCTRL lpHeader)
/*++
Routine Description:
Build result view for immediate descendant type
Arguments:
LPHEADERCTRL lpHeader : Header control
--*/
{
CApplicationNode::InitializeHeaders(lpHeader);
}
/* static */
void
CAppPoolNode::InitializeHeaders(LPHEADERCTRL lpHeader)
/*++
Routine Description:
Initialize the result headers
Arguments:
LPHEADERCTRL lpHeader : Header control
--*/
{
CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
if (!_fStaticsLoaded)
{
_fStaticsLoaded =
_bstrStarted.LoadString(IDS_STARTED) &&
_bstrStopped.LoadString(IDS_STOPPED) &&
_bstrUnknown.LoadString(IDS_UNKNOWN) &&
_bstrPending.LoadString(IDS_PENDING);
}
}
/* virtual */
HRESULT
CAppPoolNode::EnumerateScopePane(
IN HSCOPEITEM hParent
)
/*++
Routine Description:
Enumerate scope child items.
Arguments:
HSCOPEITEM hParent : Parent console handle
Return Value:
HRESULT
--*/
{
CError err;
do
{
CComBSTR path;
BuildMetaPath(path);
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,path);
BREAK_ON_ERR_FAILURE(err)
CIISAppPool pool(QueryAuthInfo(), path);
if (pool.Succeeded())
{
CStringListEx strListOfApps;
err = pool.EnumerateApplications(strListOfApps);
if (err.Succeeded() && strListOfApps.GetCount() > 0)
{
POSITION pos = strListOfApps.GetHeadPosition();
while ( pos != NULL)
{
CString app = strListOfApps.GetNext(pos);
DWORD i = CMetabasePath::GetInstanceNumber(app);
if (i > 0)
{
CString name;
CMetabasePath::CleanMetaPath(app);
CMetabasePath::GetLastNodeName(app, name);
CApplicationNode * app_node = new CApplicationNode(
GetOwner(), app, name);
if (app_node != NULL)
{
app_node->AddRef();
app_node->AddToScopePane(m_hScopeItem, TRUE, TRUE, FALSE);
}
else
{
err = ERROR_NOT_ENOUGH_MEMORY;
}
}
}
}
}
} while (FALSE);
return err;
}
/* virtual */
HRESULT
CAppPoolNode::CreatePropertyPages(
LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
IUnknown * pUnk,
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());
CError err;
if (S_FALSE == (HRESULT)(err = CIISMBNode::CreatePropertyPages(lpProvider, handle, pUnk, type)))
{
return S_OK;
}
if (ERROR_ALREADY_EXISTS == err.Win32Error())
{
return S_FALSE;
}
if (err.Succeeded())
{
CComBSTR path;
err = BuildMetaPath(path);
if (err.Succeeded())
{
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,path);
if (err.Succeeded())
{
CAppPoolSheet * pSheet = new CAppPoolSheet(
QueryAuthInfo(), path, GetMainWindow(GetConsole()), (LPARAM)this,
(LPARAM) m_pContainer
);
if (pSheet != NULL)
{
// cache handle for user in MMCPropertyChangeNotify
m_ppHandle = handle;
pSheet->SetModeless();
err = AddMMCPage(lpProvider, new CAppPoolRecycle(pSheet));
err = AddMMCPage(lpProvider, new CAppPoolPerf(pSheet));
err = AddMMCPage(lpProvider, new CAppPoolHealth(pSheet));
// err = AddMMCPage(lpProvider, new CAppPoolDebug(pSheet));
err = AddMMCPage(lpProvider, new CAppPoolIdent(pSheet));
// err = AddMMCPage(lpProvider, new CAppPoolCache(pSheet));
// err = AddMMCPage(lpProvider, new CPoolProcessOpt(pSheet));
}
}
}
}
err.MessageBoxOnFailure();
return err;
}
/* virtual */
HRESULT
CAppPoolNode::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
);
ASSERT(pInsertionAllowed != NULL);
if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) != 0)
{
AddMenuSeparator(lpContextMenuCallback);
AddMenuItemByCommand(lpContextMenuCallback, IDM_START, IsStartable() ? 0 : MF_GRAYED);
AddMenuItemByCommand(lpContextMenuCallback, IDM_STOP, IsStoppable() ? 0 : MF_GRAYED);
AddMenuItemByCommand(lpContextMenuCallback, IDM_RECYCLE, IsRunning() ? 0 : MF_GRAYED);
}
if (SUCCEEDED(hr))
{
ASSERT(pInsertionAllowed != NULL);
if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
{
AddMenuSeparator(lpContextMenuCallback);
AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_APP_POOL);
if (IsConfigImportExportable())
{
AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_APP_POOL_FROM_FILE);
}
}
if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) != 0)
{
if (IsConfigImportExportable())
{
AddMenuSeparator(lpContextMenuCallback);
AddMenuItemByCommand(lpContextMenuCallback, IDM_TASK_EXPORT_CONFIG_WIZARD);
}
}
}
return hr;
}
/* virtual */
HRESULT
CAppPoolNode::Command(
IN long lCommandID,
IN CSnapInObjectRootBase * pObj,
IN 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
--*/
{
HRESULT hr = S_OK;
CString name;
DWORD command = 0;
CError err;
CComBSTR bstrMetaPath;
BOOL bNeedMetabase = FALSE;
BOOL bHaveMetabase = FALSE;
switch (lCommandID)
{
case IDM_NEW_APP_POOL:
case IDM_START:
case IDM_STOP:
case IDM_RECYCLE:
bNeedMetabase = TRUE;
break;
default:
bNeedMetabase = FALSE;
}
if (bNeedMetabase)
{
// WARNING:bstrMetaPath will be used by switch statement below
VERIFY(SUCCEEDED(BuildMetaPath(bstrMetaPath)));
err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,bstrMetaPath);
if (!IsLostInterface(err))
{
// reset error if an other error other than No interface
err.Reset();
}
if (err.Succeeded())
{
bHaveMetabase = TRUE;
}
}
switch (lCommandID)
{
case IDM_NEW_APP_POOL:
if (bHaveMetabase)
{
if (SUCCEEDED(hr = AddAppPool(pObj, type, m_pContainer, name)) && !name.IsEmpty())
{
hr = m_pContainer->InsertNewPool(name);
}
}
break;
case IDM_START:
if (bHaveMetabase)
{
command = MD_APPPOOL_COMMAND_START;
}
break;
case IDM_STOP:
if (bHaveMetabase)
{
command = MD_APPPOOL_COMMAND_STOP;
}
break;
case IDM_RECYCLE:
{
if (bHaveMetabase)
{
CIISAppPool pool(QueryAuthInfo(), (LPCTSTR)bstrMetaPath);
err = pool.Recycle(QueryNodeName());
hr = err;
}
break;
}
//
// Pass on to base class
//
default:
hr = CIISMBNode::Command(lCommandID, pObj, type);
}
if (command != 0)
{
hr = ChangeState(command);
}
return hr;
}
HRESULT
CAppPoolNode::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);
CAppPoolProps prop(QueryAuthInfo(), bstrPath);
err = prop.LoadData();
BREAK_ON_ERR_FAILURE(err)
err = prop.ChangeState(dwCommand);
BREAK_ON_ERR_FAILURE(err)
err = RefreshData();
if (err.Succeeded())
{
err = RefreshDisplay();
}
}
while(FALSE);
err.MessageBoxOnFailure();
return err;
}
////////////////////////////////////////////////////////////////////////
/* static */ int
CApplicationNode::_rgnLabels[COL_TOTAL] =
{
IDS_RESULT_SERVICE_DESCRIPTION,
IDS_RESULT_PATH,
};
/* static */ int
CApplicationNode::_rgnWidths[COL_TOTAL] =
{
180,
200,
};
/* static */
void
CApplicationNode::InitializeHeaders(LPHEADERCTRL lpHeader)
/*++
Routine Description:
Initialize the result headers
Arguments:
LPHEADERCTRL lpHeader : Header control
--*/
{
CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
}
LPOLESTR
CApplicationNode::QueryDisplayName()
/*++
Routine Description:
Return primary display name of this site.
Arguments:
None
Return Value:
The display name
--*/
{
return QueryDisplayName(FALSE);
}
LPOLESTR
CApplicationNode::QueryDisplayName(BOOL bForceQuery)
{
if (m_strDisplayName.IsEmpty() || bForceQuery)
{
CMetaKey mk(QueryInterface(), m_meta_path, METADATA_PERMISSION_READ);
if (mk.Succeeded())
{
mk.QueryValue(MD_APP_FRIENDLY_NAME, m_strDisplayName);
if (m_strDisplayName.IsEmpty())
{
m_strDisplayName = QueryNodeName();
}
}
}
return (LPTSTR)(LPCTSTR)m_strDisplayName;
}
HRESULT
CApplicationNode::BuildMetaPath(CComBSTR& path) const
{
path = m_meta_path;
return S_OK;
}
LPOLESTR
CApplicationNode::GetResultPaneColInfo(
IN int nCol
)
/*++
Routine Description:
Return result pane string for the given column number
Arguments:
int nCol : Column number
Return Value:
String
--*/
{
switch(nCol)
{
case COL_ALIAS:
return QueryDisplayName();
case COL_PATH:
{
CString buf;
return (LPTSTR)(LPCTSTR)FriendlyAppRoot(m_meta_path, buf);
}
}
ASSERT_MSG("Bad column number");
return OLESTR("");
}
LPCTSTR
CApplicationNode::FriendlyAppRoot(
LPCTSTR lpAppRoot,
CString & strFriendly
)
/*++
Routine Description:
Convert the metabase app root path to a friendly display name
format.
Arguments:
LPCTSTR lpAppRoot : App root
CString & strFriendly : Output friendly app root format
Return Value:
Reference to the output string
Notes:
App root must have been cleaned from WAM format prior
to calling this function (see first ASSERT below)
--*/
{
if (lpAppRoot != NULL && *lpAppRoot != 0)
{
//
// Make sure we cleaned up WAM format
//
ASSERT(*lpAppRoot != _T('/'));
strFriendly.Empty();
CInstanceProps prop(QueryAuthInfo(), lpAppRoot);
HRESULT hr = prop.LoadData();
if (SUCCEEDED(hr))
{
CString root, tail;
strFriendly.Format(_T("<%s>"), prop.GetDisplayText(root));
CMetabasePath::GetRootPath(lpAppRoot, root, &tail);
if (!tail.IsEmpty())
{
//
// Add rest of dir path
//
strFriendly += _T("/");
strFriendly += tail;
}
//
// Now change forward slashes in the path to backward slashes
//
// CvtPathToDosStyle(strFriendly);
return strFriendly;
}
}
//
// Bogus
//
VERIFY(strFriendly.LoadString(IDS_APPROOT_UNKNOWN));
return strFriendly;
}
//////////////////////////////////////////////////////////////////////////