mirror of https://github.com/tongzx/nt5src
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.
617 lines
18 KiB
617 lines
18 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-2000 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// RootNode.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the CRootNodeData and CRootNodeDataPage classes.
|
|
//
|
|
// Author:
|
|
// David Potter (davidp) November 10, 1997
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Notes:
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "RootNode.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// class CRootNodeData
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// static variables
|
|
|
|
static const GUID g_CClusterAdminGUID_NODETYPE =
|
|
{ 0x12e7ed20, 0x5540, 0x11d1, { 0x9a, 0xa4, 0x0, 0xc0, 0x4f, 0xb9, 0x3a, 0x80 } };
|
|
|
|
const GUID * CRootNodeData::s_pguidNODETYPE = &g_CClusterAdminGUID_NODETYPE;
|
|
LPCWSTR CRootNodeData::s_pszNODETYPEGUID = _T("12E7ED20-5540-11D1-9AA4-00C04FB93A80");
|
|
WCHAR CRootNodeData::s_szDISPLAY_NAME[256] = { 0 };
|
|
const CLSID * CRootNodeData::s_pclsidSNAPIN_CLASSID = &CLSID_ClusterAdmin;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::CRootNodeData
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// pComponentData Pointer to component data object.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CRootNodeData::CRootNodeData( CClusterComponentData * pcd )
|
|
: CBaseNodeObjImpl< CRootNodeData >( pcd )
|
|
{
|
|
//
|
|
// Initialize the scope data item.
|
|
//
|
|
memset( &m_scopeDataItem, 0, sizeof(SCOPEDATAITEM) );
|
|
m_scopeDataItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM;
|
|
m_scopeDataItem.displayname = MMC_CALLBACK;
|
|
m_scopeDataItem.nImage = IMGLI_CLUSTER;
|
|
m_scopeDataItem.nOpenImage = IMGLI_CLUSTER;
|
|
m_scopeDataItem.lParam = (LPARAM) this;
|
|
|
|
//
|
|
// Initialize the result data item.
|
|
//
|
|
memset( &m_resultDataItem, 0, sizeof(RESULTDATAITEM) );
|
|
m_resultDataItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
|
|
m_resultDataItem.str = MMC_CALLBACK;
|
|
m_resultDataItem.nImage = IMGLI_CLUSTER;
|
|
m_resultDataItem.lParam = (LPARAM) this;
|
|
|
|
} //*** CRootNodeData::CRootNodeData()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::~CRootNodeData
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CRootNodeData::~CRootNodeData( void )
|
|
{
|
|
} //*** CRootNodeData::CRootNodeData()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::CreatePropertyPages [IExtendPropertySheet]
|
|
//
|
|
// Routine Description:
|
|
// Called to create property pages for the MMC node and add them to
|
|
// the sheet.
|
|
//
|
|
// Arguments:
|
|
// lpProvider [IN] Pointer to the IPropertySheetCallback interface.
|
|
// handle [IN] Specifies the handle used to route the
|
|
// MMCN_PROPERTY_CHANGE notification message to the
|
|
// appropriate IComponent or IComponentData.
|
|
// pUnk [IN] Pointer to the IDataObject interface on the object
|
|
// that contains context information about the node.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CRootNodeData::CreatePropertyPages(
|
|
LPPROPERTYSHEETCALLBACK lpProvider,
|
|
long handle,
|
|
IUnknown * pUnk
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CRootNodeDataPage * pPage = new CRootNodeDataPage( _T("ClusterAdmin") );
|
|
if ( pPage == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
} // if: error allocating memory
|
|
else
|
|
{
|
|
lpProvider->AddPage( pPage->Create() );
|
|
} // else: memory allocated successfully
|
|
|
|
return hr;
|
|
|
|
} //*** CRootNodeData::CreatePropertyPages()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::GetDisplayName [CSnapInDataInterface]
|
|
//
|
|
// Routine Description:
|
|
// Returns the display name of this node.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// Pointer to Unicode string containing the display name.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void * CRootNodeData::GetDisplayName( void )
|
|
{
|
|
// If the display name hasn't been read from the
|
|
if ( s_szDISPLAY_NAME[0] == L'\0' )
|
|
{
|
|
CString strDisplayName;
|
|
strDisplayName.LoadString( IDS_NODETYPE_STATIC_NODE );
|
|
lstrcpyW(s_szDISPLAY_NAME, strDisplayName);
|
|
} // if: display name hasn't been loaded yet
|
|
|
|
return (void *) s_szDISPLAY_NAME;
|
|
|
|
} //*** CRootNodeData::GetDisplayName()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::Notify [ISnapInDataInterface]
|
|
//
|
|
// Routine Description:
|
|
// Notifies the snap-in of actions taken by the user. Handles
|
|
// notifications sent through both IComponent and IComponentData.
|
|
//
|
|
// Arguments:
|
|
// event [IN] Identifies the action taken by the user.
|
|
// arg Depends on the notification type.
|
|
// param Depends on the notification type.
|
|
// pComponentData Pointer to the IComponentData interface if this
|
|
// was invoked through that interface.
|
|
// pComponent Pointer to the IComponent interface if this was
|
|
// invoked through that interface.
|
|
// type Type of object.
|
|
//
|
|
// Return Value:
|
|
// HRESULT
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//#if 0
|
|
STDMETHODIMP CRootNodeData::Notify(
|
|
MMC_NOTIFY_TYPE event,
|
|
LPARAM arg,
|
|
LPARAM param,
|
|
IComponentData * pComponentData,
|
|
IComponent * pComponent,
|
|
DATA_OBJECT_TYPES type
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( pComponentData != NULL )
|
|
ATLTRACE( _T("IComponentData::Notify(%d, %d, %d, %d)"), event, arg, param, type );
|
|
else
|
|
ATLTRACE( _T("IComponent::Notify(%d, %d, %d, %d)"), event, arg, param, type );
|
|
|
|
switch ( event )
|
|
{
|
|
case MMCN_ACTIVATE:
|
|
ATLTRACE( _T(" - MMCN_ACTIVATE\n") );
|
|
break;
|
|
case MMCN_ADD_IMAGES:
|
|
ATLTRACE( _T(" - MMCN_ADD_IMAGES\n") );
|
|
hr = OnAddImages( (IImageList *) arg, (HSCOPEITEM) param, pComponentData, pComponent, type );
|
|
break;
|
|
case MMCN_BTN_CLICK:
|
|
ATLTRACE( _T(" - MMCN_BTN_CLICK\n") );
|
|
break;
|
|
case MMCN_CLICK:
|
|
ATLTRACE( _T(" - MMCN_CLICK\n") );
|
|
break;
|
|
case MMCN_CONTEXTHELP:
|
|
hr = HrDisplayContextHelp();
|
|
break;
|
|
case MMCN_DBLCLICK:
|
|
ATLTRACE( _T(" - MMCN_DBLCLICK\n") );
|
|
break;
|
|
case MMCN_DELETE:
|
|
ATLTRACE( _T(" - MMCN_DELETE\n") );
|
|
break;
|
|
case MMCN_EXPAND:
|
|
ATLTRACE( _T(" - MMCN_EXPAND\n") );
|
|
hr = OnExpand( (BOOL) arg, (HSCOPEITEM) param, pComponentData, pComponent, type );
|
|
break;
|
|
case MMCN_MINIMIZED:
|
|
ATLTRACE( _T(" - MMCN_MINIMIZED\n") );
|
|
break;
|
|
case MMCN_PROPERTY_CHANGE:
|
|
ATLTRACE( _T(" - MMCN_PROPERTY_CHANGE\n") );
|
|
break;
|
|
case MMCN_REMOVE_CHILDREN:
|
|
ATLTRACE( _T(" - MMCN_REMOVE_CHILDREN\n") );
|
|
break;
|
|
case MMCN_RENAME:
|
|
ATLTRACE( _T(" - MMCN_RENAME\n") );
|
|
break;
|
|
case MMCN_SELECT:
|
|
ATLTRACE( _T(" - MMCN_SELECT\n") );
|
|
break;
|
|
case MMCN_SHOW:
|
|
ATLTRACE( _T(" - MMCN_SHOW\n") );
|
|
break;
|
|
case MMCN_VIEW_CHANGE:
|
|
ATLTRACE( _T(" - MMCN_VIEW_CHANGE\n") );
|
|
break;
|
|
default:
|
|
ATLTRACE( _T(" - *** UNKNOWN event ***\n") );
|
|
break;
|
|
} // switch: event
|
|
|
|
return hr;
|
|
|
|
} //*** CRootNodeData::Notify()
|
|
//#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::OnAddImages
|
|
//
|
|
// Routine Description:
|
|
// Adds images to the result pane image list.
|
|
//
|
|
// Arguments:
|
|
// pImageList Pointer to the result pane's image list (IImageList).
|
|
// hsi Specifies the HSCOPEITEM of the item that was
|
|
// selected or deselected.
|
|
//
|
|
// Return Value:
|
|
// HRESULT
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CRootNodeData::OnAddImages(
|
|
IImageList * pImageList,
|
|
HSCOPEITEM hsi,
|
|
IComponentData * pComponentData,
|
|
IComponent * pComponent,
|
|
DATA_OBJECT_TYPES type
|
|
)
|
|
{
|
|
_ASSERTE( pImageList != NULL );
|
|
|
|
CBitmap bm16;
|
|
CBitmap bm32;
|
|
COLORREF crMaskColor = RGB( 255, 0, 255 );
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Add an image for the cluster object.
|
|
//
|
|
|
|
bm16.LoadBitmap( IDB_CLUSTER_16 );
|
|
if ( bm16.m_hBitmap != NULL )
|
|
{
|
|
bm32.LoadBitmap( IDB_CLUSTER_32 );
|
|
if ( bm32.m_hBitmap != NULL )
|
|
{
|
|
hr = pImageList->ImageListSetStrip(
|
|
(LONG_PTR *) bm16.m_hBitmap,
|
|
(LONG_PTR *) bm32.m_hBitmap,
|
|
IMGLI_CLUSTER,
|
|
crMaskColor
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
ATLTRACE( _T("CRootNodeData::OnAddImages() - IImageList::ImageListSetStrip failed with %08.8x\n"), hr );
|
|
} // if: error setting bitmaps into image list
|
|
} // if: 32x32 bitmap loaded successfully
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
} // else: error loading 32x32 bitmap
|
|
} // if: 16x16 bitmap loaded successfully
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
} // else: error loading 32x32 bitmap
|
|
|
|
return hr;
|
|
|
|
} //*** CRootNodeData::OnAddImages()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::OnExpand
|
|
//
|
|
// Routine Description:
|
|
// Node is expanding or contracting.
|
|
//
|
|
// Arguments:
|
|
// pImageList Pointer to the result pane's image list (IImageList).
|
|
// hsi Specifies the HSCOPEITEM of the item that was
|
|
// selected or deselected.
|
|
//
|
|
// Return Value:
|
|
// HRESULT
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CRootNodeData::OnExpand(
|
|
BOOL bExpanding,
|
|
HSCOPEITEM hsi,
|
|
IComponentData * pComponentData,
|
|
IComponent * pComponent,
|
|
DATA_OBJECT_TYPES type
|
|
)
|
|
{
|
|
m_scopeDataItem.ID = hsi;
|
|
return S_OK;
|
|
|
|
} //*** CRootNodeData::OnExpand()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::OnManageCluster
|
|
//
|
|
// Routine Description:
|
|
// Manage the cluster on this node.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// HRESULT
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CRootNodeData::OnManageCluster(
|
|
bool & bHandled,
|
|
CSnapInObjectRoot * pObj
|
|
)
|
|
{
|
|
BOOL bSuccessful;
|
|
DWORD dwStatus;
|
|
HRESULT hr = S_OK;
|
|
CString strCommandLine;
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
LPCWSTR pszMachineName = Pcd()->PwszMachineName();
|
|
|
|
ZeroMemory( &si, sizeof(si) );
|
|
si.cb = sizeof(si);
|
|
|
|
//
|
|
// Find the Cluster Administrator executable.
|
|
//
|
|
dwStatus = ScFindCluAdmin( strCommandLine );
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( dwStatus );
|
|
CNTException nte( dwStatus, IDS_ERROR_FINDING_CLUADMIN );
|
|
nte.ReportError( MB_OK | MB_ICONEXCLAMATION );
|
|
return hr;
|
|
} // if: failed to find the executable
|
|
|
|
//
|
|
// Construct the command line. If the machine name is blank, we are
|
|
// on the local machine. Specify a dot (.) in its place.
|
|
//
|
|
if ( *pszMachineName == L'\0' )
|
|
{
|
|
strCommandLine += _T(" .");
|
|
} // if: running on the cluster node
|
|
else
|
|
{
|
|
strCommandLine += _T(" ");
|
|
strCommandLine += pszMachineName;
|
|
} // else: not running on the cluster node
|
|
|
|
//
|
|
// Create a process for Cluster Administrator.
|
|
//
|
|
bSuccessful = CreateProcess(
|
|
NULL, // lpApplicationName
|
|
(LPTSTR)(LPCTSTR) strCommandLine, // lpCommandLine
|
|
NULL, // lpProcessAttributes
|
|
NULL, // lpThreadAttributes
|
|
FALSE, // bInheritHandles
|
|
CREATE_DEFAULT_ERROR_MODE // dwCreationFlags
|
|
| CREATE_UNICODE_ENVIRONMENT,
|
|
GetEnvironmentStrings(), // lpEnvironment
|
|
NULL, // lpCurrentDirectory
|
|
&si, // lpStartupInfo
|
|
&pi // lpProcessInfo
|
|
);
|
|
if ( !bSuccessful )
|
|
{
|
|
dwStatus = GetLastError();
|
|
hr = HRESULT_FROM_WIN32( dwStatus );
|
|
CNTException nte( dwStatus, IDS_ERROR_LAUNCHING_CLUADMIN, strCommandLine );
|
|
nte.ReportError( MB_OK | MB_ICONEXCLAMATION );
|
|
} // if: error invoking Cluster Administrator
|
|
else
|
|
{
|
|
CloseHandle( pi.hProcess );
|
|
} // else: no error invoking Cluster Administrator
|
|
|
|
return hr;
|
|
|
|
} //*** CRootNodeData::OnManageCluster()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::ScFindCluAdmin
|
|
//
|
|
// Routine Description:
|
|
// Find the Cluster Administrator image.
|
|
//
|
|
// Arguments:
|
|
// rstrImage [OUT] String in which to return the path.
|
|
//
|
|
// Return Value:
|
|
// HRESULT
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
DWORD CRootNodeData::ScFindCluAdmin( CString & rstrImage )
|
|
{
|
|
DWORD dwStatus;
|
|
CRegKey rk;
|
|
TCHAR szImage[MAX_PATH];
|
|
DWORD cbImage = sizeof(szImage);
|
|
|
|
// Loop to avoid using goto's
|
|
do
|
|
{
|
|
//
|
|
// Open the App Paths registry key for CluAdmin.
|
|
//
|
|
dwStatus = rk.Open(
|
|
HKEY_LOCAL_MACHINE,
|
|
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\CluAdmin.exe"),
|
|
KEY_READ
|
|
);
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
} // if: error opening the registry key
|
|
|
|
//
|
|
// Read the value.
|
|
//
|
|
dwStatus = rk.QueryValue( szImage, _T(""), &cbImage );
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
} // if: error reading the value
|
|
|
|
//
|
|
// Expand any environment string that may be embedded in the value.
|
|
//
|
|
|
|
TCHAR tszExpandedRegValue[_MAX_PATH];
|
|
|
|
|
|
dwStatus = ExpandEnvironmentStrings( szImage,
|
|
tszExpandedRegValue,
|
|
(DWORD) _MAX_PATH );
|
|
|
|
_ASSERTE( dwStatus != 0 );
|
|
|
|
if ( dwStatus != 0L )
|
|
{
|
|
rstrImage = tszExpandedRegValue;
|
|
|
|
dwStatus = 0L;
|
|
}
|
|
else
|
|
{
|
|
// Could not expand the environment string.
|
|
|
|
rstrImage = szImage;
|
|
|
|
dwStatus = GetLastError();
|
|
} // if: testing value returned by ExpandEnvironmentStrings
|
|
|
|
|
|
} while ( 0 );
|
|
|
|
return dwStatus;
|
|
|
|
} //*** CRootNodeData::ScFindCluAdmin()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CRootNodeData::HrDisplayContextHelp
|
|
//
|
|
// Routine Description:
|
|
// Display context-sensitive help.
|
|
//
|
|
// Arguments:
|
|
// pszHelpTopic [OUT] Pointer to the address of the NULL-terminated
|
|
// UNICODE string that contains the full path of
|
|
// compiled help file (.chm) for the snap-in.
|
|
//
|
|
// Return Value:
|
|
// HRESULT
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CRootNodeData::HrDisplayContextHelp( void )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDisplayHelp * pi = NULL;
|
|
LPOLESTR postr = NULL;
|
|
|
|
// Loop to avoid goto's.
|
|
do
|
|
{
|
|
//
|
|
// Get the IDisplayHelp interface pointer.
|
|
//
|
|
hr = Pcd()->m_spConsole->QueryInterface(
|
|
IID_IDisplayHelp,
|
|
reinterpret_cast< void ** >( &pi )
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
break;
|
|
} // if: error getting interface pointer
|
|
|
|
//
|
|
// Construct the help topic path.
|
|
//
|
|
postr = reinterpret_cast< LPOLESTR >( CoTaskMemAlloc( sizeof( FULL_HELP_TOPIC ) ) );
|
|
if ( postr == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
} // if: error allocating memory
|
|
wcscpy( postr, FULL_HELP_TOPIC );
|
|
|
|
//
|
|
// Show the topic.
|
|
//
|
|
hr = pi->ShowTopic( postr );
|
|
if ( ! FAILED( hr ) )
|
|
{
|
|
postr = NULL;
|
|
} // if: topic shown successfully
|
|
} while ( 0 );
|
|
|
|
//
|
|
// Cleanup before returning.
|
|
//
|
|
if ( postr != NULL )
|
|
{
|
|
CoTaskMemFree( postr );
|
|
} // if: topic string not passed to MMC successfully
|
|
if ( pi != NULL )
|
|
{
|
|
pi->Release();
|
|
} // if: valid interface pointer
|
|
|
|
return hr;
|
|
|
|
} //*** CRootNodeData::HrDisplayContextHelp()
|