windows-nt/Source/XPSP1/NT/base/cluster/resdll/clnetres/clnetresex/extobj.cpp
2020-09-26 16:20:57 +08:00

912 lines
25 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999 Microsoft Corporation
//
// Module Name:
// ExtObj.cpp
//
// Description:
// Implementation of the CExtObject class, which implements the
// extension interfaces required by a Microsoft Windows NT Cluster
// Administrator Extension DLL.
//
// Author:
// David Potter (DavidP) March 24, 1999
//
// Revision History:
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ClNetResEx.h"
#include "ExtObj.h"
#include "Dhcp.h"
#include "Wins.h"
/////////////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////////////
const WCHAR g_wszResourceTypeNames[] =
L"DHCP Service\0"
L"WINS Service\0"
;
const DWORD g_cchResourceTypeNames = sizeof( g_wszResourceTypeNames ) / sizeof( WCHAR );
static CRuntimeClass * g_rgprtcDhcpResPSPages[] = {
RUNTIME_CLASS( CDhcpParamsPage ),
NULL
};
static CRuntimeClass * g_rgprtcWinsResPSPages[] = {
RUNTIME_CLASS( CWinsParamsPage ),
NULL
};
static CRuntimeClass ** g_rgpprtcResPSPages[] = {
g_rgprtcDhcpResPSPages,
g_rgprtcWinsResPSPages,
};
static CRuntimeClass ** g_rgpprtcResWizPages[] = {
g_rgprtcDhcpResPSPages,
g_rgprtcWinsResPSPages,
};
/////////////////////////////////////////////////////////////////////////////
// CExtObject
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::CExtObject
//
// Description:
// Default constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CExtObject::CExtObject( void )
{
m_piData = NULL;
m_piWizardCallback = NULL;
m_bWizard = FALSE;
m_istrResTypeName = 0;
m_lcid = NULL;
m_hfont = NULL;
m_hicon = NULL;
m_hcluster = NULL;
m_cobj = 0;
m_podObjData = NULL;
} //*** CExtObject::CExtObject()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::~CExtObject
//
// Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CExtObject::~CExtObject( void )
{
// Release the data interface.
if ( PiData() != NULL )
{
PiData()->Release();
m_piData = NULL;
} // if: we have a data interface pointer
// Release the wizard callback interface.
if ( PiWizardCallback() != NULL )
{
PiWizardCallback()->Release();
m_piWizardCallback = NULL;
} // if: we have a wizard callback interface pointer
// Delete the pages.
{
POSITION pos;
pos = Lpg().GetHeadPosition();
while ( pos != NULL )
{
delete Lpg().GetNext(pos);
} // while: more pages in the list
} // Delete the pages
delete m_podObjData;
} //*** CExtObject::~CExtObject()
/////////////////////////////////////////////////////////////////////////////
// ISupportErrorInfo Implementation
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::InterfaceSupportsErrorInfo (ISupportErrorInfo)
//
// Routine Description:
// Indicates whether an interface suportes the IErrorInfo interface.
// This interface is provided by ATL.
//
// Arguments:
// riid Interface ID.
//
// Return Value:
// S_OK Interface supports IErrorInfo.
// S_FALSE Interface does not support IErrorInfo.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtObject::InterfaceSupportsErrorInfo( REFIID riid )
{
static const IID * _rgiid[] =
{
&IID_IWEExtendPropertySheet,
&IID_IWEExtendWizard,
};
int _iiid;
for ( _iiid = 0 ; _iiid < sizeof( _rgiid ) / sizeof( _rgiid[ 0 ] ) ; _iiid++ )
{
if ( InlineIsEqualGUID( *_rgiid[ _iiid ], riid ) )
{
return S_OK;
} // if: found a matching IID
}
return S_FALSE;
} //*** CExtObject::InterfaceSupportsErrorInfo()
/////////////////////////////////////////////////////////////////////////////
// IWEExtendPropertySheet Implementation
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::CreatePropertySheetPages (IWEExtendPropertySheet)
//
// Description:
// Create property sheet pages and add them to the sheet.
//
// Arguments:
// piData [IN]
// IUnkown pointer from which to obtain interfaces for obtaining data
// describing the object for which the sheet is being displayed.
//
// piCallback [IN]
// Pointer to an IWCPropertySheetCallback interface for adding pages
// to the sheet.
//
// Return Value:
// NOERROR Pages added successfully.
// E_INVALIDARG Invalid arguments to the function.
// E_OUTOFMEMORY Error allocating memory.
// E_FAIL Error creating a page.
// E_NOTIMPL Not implemented for this type of data.
// _hr Any error codes from HrGetUIInfo() or HrSaveData().
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtObject::CreatePropertySheetPages(
IN IUnknown * piData,
IN IWCPropertySheetCallback * piCallback
)
{
HRESULT _hr = NOERROR;
CException _exc( FALSE /*bAutoDelete*/ );
CRuntimeClass ** _pprtc = NULL;
int _irtc;
CBasePropertyPage * _ppage;
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
// Validate the parameters.
if ( (piData == NULL) || (piCallback == NULL) )
{
return E_INVALIDARG;
} // if: all interfaces not specified
try
{
// Get info about displaying UI.
_hr = HrGetUIInfo( piData );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error getting UI info
// Save the data.
_hr = HrSaveData( piData );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error saving data from host
// Delete any previous pages.
{
POSITION pos;
pos = Lpg().GetHeadPosition();
while ( pos != NULL )
{
delete Lpg().GetNext( pos );
} // while: more pages in the list
Lpg().RemoveAll();
} // Delete any previous pages
// Create property pages.
ASSERT( PodObjData() != NULL );
switch ( PodObjData()->m_cot )
{
case CLUADMEX_OT_RESOURCE:
_pprtc = g_rgpprtcResPSPages[ IstrResTypeName() ];
break;
default:
_hr = E_NOTIMPL;
throw &_exc;
break;
} // switch: object type
// Create each page.
for ( _irtc = 0 ; _pprtc[ _irtc ] != NULL ; _irtc++ )
{
// Create the page.
_ppage = static_cast< CBasePropertyPage * >( _pprtc[ _irtc ]->CreateObject() );
ASSERT( _ppage->IsKindOf( _pprtc[ _irtc ] ) );
// Add it to the list.
Lpg().AddTail( _ppage );
// Initialize the property page.
_hr = _ppage->HrInit( this );
if ( FAILED( _hr ) )
{
throw &_exc;
} // if: error initializing the page
// Create the page.
_hr = _ppage->HrCreatePage();
if ( FAILED( _hr ) )
{
throw &_exc;
} // if: error creating the page
// Add it to the property sheet.
_hr = piCallback->AddPropertySheetPage( reinterpret_cast< LONG * >( _ppage->Hpage() ) );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error adding the page to the sheet
} // for: each page in the list
} // try
catch ( CMemoryException * _pme )
{
TRACE( _T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n") );
_pme->Delete();
_hr = E_OUTOFMEMORY;
} // catch: anything
catch ( CException * _pe )
{
TRACE( _T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n") );
_pe->Delete();
if ( _hr == NOERROR )
{
_hr = E_FAIL;
} // if: _hr hasn't beeen set yet
} // catch: anything
if ( _hr != NOERROR )
{
piData->Release();
m_piData = NULL;
} // if: error occurred
piCallback->Release();
return _hr;
} //*** CExtObject::CreatePropertySheetPages()
/////////////////////////////////////////////////////////////////////////////
// IWEExtendWizard Implementation
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::CreateWizardPages (IWEExtendWizard)
//
// Description:
// Create property sheet pages and add them to the wizard.
//
// Arguments:
// piData [IN]
// IUnkown pointer from which to obtain interfaces for obtaining data
// describing the object for which the wizard is being displayed.
//
// piCallback [IN]
// Pointer to an IWCPropertySheetCallback interface for adding pages
// to the sheet.
//
// Return Value:
// NOERROR Pages added successfully.
// E_INVALIDARG Invalid arguments to the function.
// E_OUTOFMEMORY Error allocating memory.
// E_FAIL Error creating a page.
// E_NOTIMPL Not implemented for this type of data.
// _hr Any error codes from HrGetUIInfo() or HrSaveData().
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtObject::CreateWizardPages(
IN IUnknown * piData,
IN IWCWizardCallback * piCallback
)
{
HRESULT _hr = NOERROR;
CException _exc( FALSE /*bAutoDelete*/ );
CRuntimeClass ** _pprtc = NULL;
int _irtc;
CBasePropertyPage * _ppage;
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
// Validate the parameters.
if ( (piData == NULL) || (piCallback == NULL) )
{
return E_INVALIDARG;
} // if: all interfaces not specified
try
{
// Get info about displaying UI.
_hr = HrGetUIInfo( piData );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error getting UI info
// Save the data.
_hr = HrSaveData( piData );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error saving data from host
// Delete any previous pages.
{
POSITION pos;
pos = Lpg().GetHeadPosition();
while ( pos != NULL )
{
delete Lpg().GetNext( pos );
} // while: more pages in the list
Lpg().RemoveAll();
} // Delete any previous pages
m_piWizardCallback = piCallback;
m_bWizard = TRUE;
// Create property pages.
ASSERT( PodObjData() != NULL );
switch ( PodObjData()->m_cot )
{
case CLUADMEX_OT_RESOURCE:
_pprtc = g_rgpprtcResWizPages[ IstrResTypeName() ];
break;
default:
_hr = E_NOTIMPL;
throw &_exc;
break;
} // switch: object type
// Create each page.
for ( _irtc = 0 ; _pprtc[ _irtc ] != NULL ; _irtc++ )
{
// Create the page.
_ppage = static_cast< CBasePropertyPage * >( _pprtc[ _irtc ]->CreateObject() );
ASSERT( _ppage->IsKindOf( _pprtc[ _irtc ] ) );
// Add it to the list.
Lpg().AddTail( _ppage );
// Initialize the property page.
_hr = _ppage->HrInit( this );
if ( FAILED( _hr ) )
{
throw &_exc;
} // if: error initializing the page
// Create the page.
_hr = _ppage->HrCreatePage();
if ( FAILED( _hr ) )
{
throw &_exc;
} // if: error creating the page
// Add it to the property sheet.
_hr = piCallback->AddWizardPage( reinterpret_cast< LONG * >( _ppage->Hpage() ) );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error adding the page to the sheet
} // for: each page in the list
} // try
catch ( CMemoryException * _pme )
{
TRACE( _T("CExtObject::CreateWizardPages() - Failed to add wizard page\n") );
_pme->Delete();
_hr = E_OUTOFMEMORY;
} // catch: anything
catch ( CException * _pe )
{
TRACE( _T("CExtObject::CreateWizardPages() - Failed to add wizard page\n") );
_pe->Delete();
if ( _hr == NOERROR )
{
_hr = E_FAIL;
} // if: _hr hasn't beeen set yet
} // catch: anything
if ( _hr != NOERROR )
{
piCallback->Release();
if ( m_piWizardCallback == piCallback )
{
m_piWizardCallback = NULL;
} // if: already saved interface pointer
piData->Release();
m_piData = NULL;
} // if: error occurred
return _hr;
} //*** CExtObject::CreateWizardPages()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::HrGetUIInfo
//
// Description:
// Get info about displaying UI.
//
// Arguments:
// piData [IN]
// IUnkown pointer from which to obtain interfaces for obtaining data
// describing the object.
//
// Return Value:
// NOERROR
// Data saved successfully.
//
// E_NOTIMPL
// Not implemented for this type of data.
//
// _hr
// Any error codes from IUnknown::QueryInterface(),
// HrGetObjectName(), or HrGetResourceName().
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CExtObject::HrGetUIInfo( IN IUnknown * piData )
{
HRESULT _hr = NOERROR;
ASSERT( piData != NULL );
// Save info about all types of objects.
{
IGetClusterUIInfo * _pi;
_hr = piData->QueryInterface( IID_IGetClusterUIInfo, reinterpret_cast< LPVOID * >( &_pi ) );
if ( _hr != NOERROR )
{
return _hr;
} // if: error querying for interface
m_lcid = _pi->GetLocale();
m_hfont = _pi->GetFont();
m_hicon = _pi->GetIcon();
_pi->Release();
} // Save info about all types of objects
return _hr;
} //*** CExtObject::HrGetUIInfo()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::HrSaveData
//
// Routine Description:
// Save data from the object so that it can be used for the life
// of the object.
//
// Arguments:
// piData [IN]
// IUnkown pointer from which to obtain interfaces for obtaining data
// describing the object.
//
// Return Value:
// NOERROR
// Data saved successfully.
//
// E_NOTIMPL
// Not implemented for this type of data.
//
// _hr
// Any error codes from IUnknown::QueryInterface(),
// HrGetObjectName(), or HrGetResourceName().
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CExtObject::HrSaveData( IN IUnknown * piData )
{
HRESULT _hr = NOERROR;
ASSERT( piData != NULL );
if ( piData != m_piData )
{
if ( m_piData != NULL )
{
m_piData->Release();
} // if: interface queried for previously
m_piData = piData;
} // if: different data interface pointer
// Save info about all types of objects.
{
IGetClusterDataInfo * _pi;
_hr = piData->QueryInterface( IID_IGetClusterDataInfo, reinterpret_cast< LPVOID * >( &_pi ) );
if ( _hr != NOERROR )
{
return _hr;
} // if: error querying for interface
m_hcluster = _pi->GetClusterHandle();
m_cobj = _pi->GetObjectCount();
if ( Cobj() != 1 ) // Only have support for one selected object.
{
_hr = E_NOTIMPL;
} // if: too many objects for us to handle
_pi->Release();
if ( _hr != NOERROR )
{
return _hr;
} // if: error occurred before here
} // Save info about all types of objects
// Save info about this object.
_hr = HrGetObjectInfo();
return _hr;
} //*** CExtObject::HrSaveData()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::HrGetObjectInfo
//
// Description:
// Get information about the object.
//
// Arguments:
// None.
//
// Return Value:
// NOERROR
// Data saved successfully.
//
// E_OUTOFMEMORY
/// Error allocating memory.
//
// E_NOTIMPL
// Not implemented for this type of data.
//
// _hr
// Any error codes from IUnknown::QueryInterface(),
// HrGetObjectName(), or HrGetResourceTypeName().
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CExtObject::HrGetObjectInfo( void )
{
HRESULT _hr = NOERROR;
IGetClusterObjectInfo * _piGcoi;
CLUADMEX_OBJECT_TYPE _cot = CLUADMEX_OT_NONE;
CException _exc( FALSE /*bAutoDelete*/ );
const CString * _pstrResTypeName = NULL;
ASSERT( PiData() != NULL );
// Get object info.
{
// Get an IGetClusterObjectInfo interface pointer.
_hr = PiData()->QueryInterface( IID_IGetClusterObjectInfo, reinterpret_cast< LPVOID * >( &_piGcoi ) );
if ( _hr != NOERROR )
{
return _hr;
} // if: error querying for interface
// Read the object data.
try
{
// Delete the previous object data.
delete m_podObjData;
m_podObjData = NULL;
// Get the type of the object.
_cot = _piGcoi->GetObjectType( 0 );
switch ( _cot )
{
case CLUADMEX_OT_RESOURCE:
{
IGetClusterResourceInfo * _pi;
m_podObjData = new CResData;
if ( m_podObjData == NULL )
{
_hr = E_OUTOFMEMORY;
throw &_exc;
} // if: error allocating memory
// Get an IGetClusterResourceInfo interface pointer.
_hr = PiData()->QueryInterface( IID_IGetClusterResourceInfo, reinterpret_cast< LPVOID * >( &_pi ) );
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error querying for interface
PrdResDataRW()->m_hresource = _pi->GetResourceHandle( 0 );
ASSERT( PrdResDataRW()->m_hresource != NULL );
if ( PrdResDataRW()->m_hresource == NULL )
{
_hr = E_INVALIDARG;
} // if invalid resource handle
else
{
_hr = HrGetResourceTypeName( _pi );
} // else: resource handle is valid
_pi->Release();
if ( _hr != NOERROR )
{
throw &_exc;
} // if: error occurred above
_pstrResTypeName = &PrdResDataRW()->m_strResTypeName;
} // if: object is a resource
break;
case CLUADMEX_OT_RESOURCETYPE:
m_podObjData = new CObjData;
if ( m_podObjData == NULL )
{
_hr = E_OUTOFMEMORY;
throw &_exc;
}
_pstrResTypeName = &PodObjDataRW()->m_strName;
break;
default:
_hr = E_NOTIMPL;
throw &_exc;
} // switch: object type
PodObjDataRW()->m_cot = _cot;
_hr = HrGetObjectName( _piGcoi );
} // try
catch ( CException * _pe )
{
if ( !FAILED (_hr) )
{
_hr = E_FAIL;
}
_pe->Delete();
} // catch: CException
_piGcoi->Release();
// If we failed to initialize _pstrResTypeName, then bail.
// We are doing this because of PREFIX, which assumes that the
// new operator for OT_RESOURCETYPE above can fail -
// but it should never happen that the new should perform a throw.
if ( _pstrResTypeName == NULL )
{
_hr = E_OUTOFMEMORY;
}
if ( _hr != NOERROR )
{
return _hr;
} // if: error occurred above
} // Get object info
// If this is a resource or resource type, see if we know about this type.
if ( ( (_cot == CLUADMEX_OT_RESOURCE)
|| (_cot == CLUADMEX_OT_RESOURCETYPE) )
&& (_hr == NOERROR) )
{
LPCWSTR _pwszResTypeName;
// Find the resource type name in our list.
// Save the index for use in other arrays.
for ( m_istrResTypeName = 0, _pwszResTypeName = g_wszResourceTypeNames
; *_pwszResTypeName != L'\0'
; m_istrResTypeName++, _pwszResTypeName += lstrlenW( _pwszResTypeName ) + 1
)
{
if ( _pstrResTypeName->CompareNoCase( _pwszResTypeName ) == 0 )
{
break;
} // if: found resource type name
} // for: each resource type in the list
if ( *_pwszResTypeName == L'\0' )
{
_hr = E_NOTIMPL;
} // if: resource type name not found
} // See if we know about this resource type
return _hr;
} //*** CExtObject::HrGetObjectInfo()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::HrGetObjectName
//
// Description:
// Get the name of the object.
//
// Arguments:
// piData [IN]
// IGetClusterObjectInfo interface pointer for getting the object
// name.
//
// Return Value:
// NOERROR
// Data saved successfully.
//
// E_OUTOFMEMORY
// Error allocating memory.
//
// E_NOTIMPL
// Not implemented for this type of data.
//
// _hr
// Any error codes from IGetClusterObjectInfo::GetObjectInfo().
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CExtObject::HrGetObjectName( IN IGetClusterObjectInfo * pi )
{
HRESULT _hr = NOERROR;
WCHAR * _pwszName = NULL;
LONG _cchName;
ASSERT( pi != NULL );
_hr = pi->GetObjectName( 0, NULL, &_cchName );
if ( _hr != NOERROR )
{
return _hr;
} // if: error getting object name
try
{
_pwszName = new WCHAR[ _cchName ];
_hr = pi->GetObjectName( 0, _pwszName, &_cchName );
if ( _hr != NOERROR )
{
delete [] _pwszName;
_pwszName = NULL;
} // if: error getting object name
PodObjDataRW()->m_strName = _pwszName;
} // try
catch ( CMemoryException * _pme )
{
_pme->Delete();
_hr = E_OUTOFMEMORY;
} // catch: CMemoryException
delete [] _pwszName;
return _hr;
} //*** CExtObject::HrGetObjectName()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExtObject::HrGetResourceTypeName
//
// Routine Description:
// Get the name of the resource's type.
//
// Arguments:
// piData [IN]
// IGetClusterResourceInfo interface pointer for getting the resource
// type name.
//
// Return Value:
// NOERROR
// Data saved successfully.
//
// E_OUTOFMEMORY
// Error allocating memory.
//
// E_NOTIMPL
// Not implemented for this type of data.
//
// _hr
// Any error codes from IGetClusterResourceInfo
// ::GetResourceTypeName().
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CExtObject::HrGetResourceTypeName( IN IGetClusterResourceInfo * pi )
{
HRESULT _hr = NOERROR;
WCHAR * _pwszName = NULL;
LONG _cchName;
ASSERT( pi != NULL );
_hr = pi->GetResourceTypeName( 0, NULL, &_cchName );
if ( _hr != NOERROR )
{
return _hr;
} // if: error getting resource type name
try
{
_pwszName = new WCHAR[ _cchName ];
_hr = pi->GetResourceTypeName( 0, _pwszName, &_cchName );
if ( _hr != NOERROR )
{
delete [] _pwszName;
_pwszName = NULL;
} // if: error getting resource type name
PrdResDataRW()->m_strResTypeName = _pwszName;
} // try
catch ( CMemoryException * _pme )
{
_pme->Delete();
_hr = E_OUTOFMEMORY;
} // catch: CMemoryException
delete [] _pwszName;
return _hr;
} //*** CExtObject::HrGetResourceTypeName()