|
|
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999-2002 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; } // if: object is a resource type
break;
default: _hr = E_NOTIMPL; throw &_exc; break; } // 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; BSTR _bstr = NULL;
ASSERT( pi != NULL );
_hr = pi->GetObjectName( 0, NULL, &_cchName ); if ( _hr != NOERROR ) { goto Cleanup; } // if: error getting object name
_bstr = SysAllocStringLen( NULL, _cchName ); if ( _bstr != NULL ) { try { _hr = pi->GetObjectName( 0, _bstr, &_cchName ); if ( _hr == NOERROR ) { _pwszName = new WCHAR[_cchName]; _hr = StringCchCopyW( _pwszName, _cchName, _bstr ); if ( FAILED( _hr ) ) { goto Cleanup; } _pwszName[ _cchName - 1 ] = L'\0'; }
PodObjDataRW()->m_strName = _pwszName; } // try
catch ( CMemoryException * _pme ) { _pme->Delete(); _hr = E_OUTOFMEMORY; } // catch: CMemoryException
SysFreeString( _bstr ); } // if: ( _bstr != NULL )
else { _hr = E_OUTOFMEMORY; }
Cleanup:
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; BSTR _bstr = NULL;
ASSERT( pi != NULL );
_hr = pi->GetResourceTypeName( 0, NULL, &_cchName ); if ( _hr != NOERROR ) { goto Cleanup; } // if: error getting resource type name
_bstr = SysAllocStringLen( NULL, _cchName ); if ( _bstr != NULL ) { try { _hr = pi->GetResourceTypeName( 0, _bstr, &_cchName ); if ( _hr == NOERROR ) { _pwszName = new WCHAR[_cchName]; _hr = StringCchCopyW( _pwszName, _cchName, _bstr ); if ( FAILED( _hr ) ) { goto Cleanup; } _pwszName[ _cchName - 1 ] = L'\0'; }
PrdResDataRW()->m_strResTypeName = _pwszName; } // try
catch ( CMemoryException * _pme ) { _pme->Delete(); _hr = E_OUTOFMEMORY; } // catch: CMemoryException
SysFreeString( _bstr ); } // if: ( _bstr != NULL )
else { _hr = E_OUTOFMEMORY; }
Cleanup:
delete [] _pwszName; return _hr;
} //*** CExtObject::HrGetResourceTypeName()
|