2025-11-28 00:35:46 +09:00

1608 lines
46 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 <company name>
//
// Module Name:
// BasePage.cpp
//
// Description:
// Implementation of the CBasePropertyPage class.
//
// Author:
// <name> (<e-mail name>) Mmmm DD, 2003
//
// Revision History:
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ClipBook ServerEx.h"
#include "ExtObj.h"
#include "BasePage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBasePropertyPage property page
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE( CBasePropertyPage, CPropertyPage )
/////////////////////////////////////////////////////////////////////////////
// Message Maps
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP( CBasePropertyPage, CPropertyPage )
//{{AFX_MSG_MAP(CBasePropertyPage)
ON_WM_CREATE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::CBasePropertyPage
//
// Description:
// Default constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CBasePropertyPage::CBasePropertyPage( void )
{
CommonConstruct();
} //*** CBasePropertyPage::CBasePropertyPage
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::CBasePropertyPage
//
// Description:
// Default constructor.
//
// Arguments:
// nIDTemplateIn
// Dialog template resource ID.
//
// nIDCaptionIn
// Caption string resource ID.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CBasePropertyPage::CBasePropertyPage(
UINT nIDTemplateIn
, UINT nIDCaptionIn
)
: CPropertyPage( nIDTemplateIn, nIDCaptionIn )
{
CommonConstruct();
} //*** CBasePropertyPage::CBasePropertyPage
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::CommonConstruct
//
// Description:
// Common construction.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void
CBasePropertyPage::CommonConstruct( void )
{
//{{AFX_DATA_INIT(CBasePropertyPage)
//}}AFX_DATA_INIT
m_peo = NULL;
m_hpage = NULL;
m_bBackPressed = FALSE;
m_bSaved = FALSE;
m_iddPropertyPage = NULL;
m_iddWizardPage = NULL;
m_idsCaption = NULL;
m_bDoDetach = FALSE;
} //*** CBasePropertyPage::CommonConstruct
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::HrInit
//
// Description:
// Initialize the page.
//
// Arguments:
// peoInout
// Pointer to the extension object.
//
// Return Value:
// S_OK
// Page initialized successfully.
//
// Other HRESULTs
// Page failed to initialize.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT
CBasePropertyPage::HrInit(
CExtObject * peoInout
)
{
ASSERT( peoInout != NULL );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
HRESULT hr = S_OK;
CWaitCursor wc;
DWORD sc = ERROR_SUCCESS;
CClusPropList cpl;
m_peo = peoInout;
//
// Don't display a help button.
//
m_psp.dwFlags &= ~PSP_HASHELP;
//
// Construct the property page.
//
if ( Peo()->BWizard() )
{
ASSERT( IddWizardPage() != NULL);
Construct( IddWizardPage(), IdsCaption() );
} // if: adding page to wizard
else
{
ASSERT( IddPropertyPage() != NULL );
Construct( IddPropertyPage(), IdsCaption() );
} // else: adding page to property sheet
//
// Read the properties private to this resource and parse them.
//
ASSERT( Peo() != NULL );
ASSERT( Peo()->PodObjData() );
//
// Read the properties.
//
switch ( Cot() )
{
case CLUADMEX_OT_CLUSTER:
{
CClusterData * pccd = reinterpret_cast< CClusterData * >( Peo()->PodObjData() );
ASSERT( pccd && (pccd->GetHCluster() != NULL) );
sc = cpl.ScGetClusterProperties(
pccd->GetHCluster()
, CLUSCTL_CLUSTER_GET_PRIVATE_PROPERTIES
);
break;
}
case CLUADMEX_OT_NODE:
{
CNodeData * pcnd = reinterpret_cast< CNodeData * >( Peo()->PodObjData() );
ASSERT( pcnd && (pcnd->GetHNode() != NULL) );
sc = cpl.ScGetNodeProperties(
pcnd->GetHNode()
, CLUSCTL_NODE_GET_PRIVATE_PROPERTIES
);
break;
}
case CLUADMEX_OT_GROUP:
{
CGroupData * pcgd = reinterpret_cast< CGroupData * >( Peo()->PodObjData() );
ASSERT( pcgd && (pcgd->GetHGroup() != NULL) );
sc = cpl.ScGetGroupProperties(
pcgd->GetHGroup()
, CLUSCTL_GROUP_GET_PRIVATE_PROPERTIES
);
break;
}
case CLUADMEX_OT_RESOURCE:
{
CResData * pcrd = reinterpret_cast< CResData * >( Peo()->PodObjData() );
ASSERT( pcrd && (pcrd->GetHResource() != NULL) );
sc = cpl.ScGetResourceProperties(
pcrd->GetHResource()
, CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES
);
break;
}
case CLUADMEX_OT_RESOURCETYPE:
{
CResTypeData * pcrd = reinterpret_cast< CResTypeData * >( Peo()->PodObjData() );
ASSERT( pcrd && (pcrd->StrName().GetLength() > 0) );
sc = cpl.ScGetResourceTypeProperties(
Hcluster()
, pcrd->StrName()
, CLUSCTL_RESOURCE_TYPE_GET_PRIVATE_PROPERTIES
);
break;
}
case CLUADMEX_OT_NETWORK:
{
CNetworkData * pcnd = reinterpret_cast< CNetworkData * >( Peo()->PodObjData() );
ASSERT( pcnd && (pcnd->GetHNetwork() != NULL) );
sc = cpl.ScGetNetworkProperties(
pcnd->GetHNetwork()
, CLUSCTL_NETWORK_GET_PRIVATE_PROPERTIES
);
break;
}
case CLUADMEX_OT_NETINTERFACE:
{
CNetInterfaceData * pcnd = reinterpret_cast< CNetInterfaceData * >( Peo()->PodObjData() );
ASSERT( pcnd && (pcnd->GetHNetInterface() != NULL) );
sc = cpl.ScGetNetInterfaceProperties(
pcnd->GetHNetInterface()
, CLUSCTL_NETINTERFACE_GET_PRIVATE_PROPERTIES
);
break;
}
default:
ASSERT( 0 );
} // switch: object type
//
// Parse the properties.
//
if ( sc == ERROR_SUCCESS )
{
// Parse the properties.
try
{
sc = ScParseProperties( cpl );
} // try
catch ( CMemoryException * pme )
{
hr = E_OUTOFMEMORY;
pme->Delete();
} // catch: CMemoryException
} // if: properties read successfully
if ( sc != ERROR_SUCCESS )
{
hr = HRESULT_FROM_WIN32( sc );
goto Cleanup;
} // if: error parsing getting or parsing properties
Cleanup:
return hr;
} //*** CBasePropertyPage::HrInit
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::HrCreatePage
//
// Description:
// Create the page.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Page created successfully.
//
// Other HRESULTs
// Error creating the page.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT
CBasePropertyPage::HrCreatePage( void )
{
ASSERT( m_hpage == NULL );
HRESULT hr = S_OK;
m_hpage = CreatePropertySheetPage( reinterpret_cast< LPPROPSHEETPAGEW >( &m_psp ) );
if ( m_hpage == NULL )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
} // if: error creating the page
return hr;
} //*** CBasePropertyPage::HrCreatePage
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::ScParseProperties
//
// Description:
// Parse the properties of the resource. This is in a separate function
// from HrInit so that the optimizer can do a better job.
//
// Arguments:
// rcplIn
// Cluster property list to parse.
//
// Return Values:
// ERROR_SUCCESS
// Properties were parsed successfully.
//
// Other HRESULTs
// Error parsing the properties. (Includes any error returned from
// ScParseUnknownProperty().)
//
// Exceptions Thrown:
// Any exceptions from CString::operator=().
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD
CBasePropertyPage::ScParseProperties(
CClusPropList & rcplIn
)
{
DWORD sc = ERROR_SUCCESS;
DWORD cprop;
const CObjectProperty * pprop;
ASSERT( rcplIn.PbPropList() != NULL );
sc = rcplIn.ScMoveToFirstProperty();
while ( sc == ERROR_SUCCESS )
{
//
// Parse known properties.
//
for ( pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop-- )
{
if ( NIStringCompareW(
rcplIn.PszCurrentPropertyName()
, pprop->m_pwszName
, rcplIn.CbhCurrentPropertyName().pName->cbLength / sizeof( WCHAR )
) == 0
)
{
if ( rcplIn.CpfCurrentValueFormat() == pprop->m_propFormat )
{
switch ( pprop->m_propFormat )
{
case CLUSPROP_FORMAT_SZ:
case CLUSPROP_FORMAT_EXPAND_SZ:
ASSERT( (rcplIn.CbCurrentValueLength() == (lstrlenW( rcplIn.CbhCurrentValue().pStringValue->sz ) + 1) * sizeof( WCHAR ))
|| ( (rcplIn.CbCurrentValueLength() == 0)
&& (rcplIn.CbhCurrentValue().pStringValue->sz[ 0 ] == L'\0') ) );
*pprop->m_value.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
*pprop->m_valuePrev.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
//
// See if we need to find an expanded version
//
if ( pprop->m_valueEx.pstr != NULL )
{
// Copy the non-expanded one just in case there isn't an expanded version
*pprop->m_valueEx.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
// See if they included an expanded version
rcplIn.ScMoveToNextPropertyValue( );
if ( rcplIn.CpfCurrentValueFormat( ) == CLUSPROP_FORMAT_EXPANDED_SZ )
{
*pprop->m_valueEx.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
} // if: found expanded version
} // if: *pprop->m_valueEx.pstr is present
break;
case CLUSPROP_FORMAT_EXPANDED_SZ:
ASSERT( (rcplIn.CbCurrentValueLength() == (lstrlenW( rcplIn.CbhCurrentValue().pStringValue->sz ) + 1) * sizeof( WCHAR ))
|| ( (rcplIn.CbCurrentValueLength() == 0)
&& (rcplIn.CbhCurrentValue().pStringValue->sz[ 0 ] == L'\0') ) );
*pprop->m_value.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
*pprop->m_valuePrev.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
//
// See if we need to find an expanded version
//
if ( *pprop->m_valueEx.pstr ) // can not use != NULL because overloading tries to do a string compare!
{
// Copy the expanded version
*pprop->m_valueEx.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
// See if they included a non-expanded version
rcplIn.ScMoveToNextPropertyValue( );
if ( rcplIn.CpfCurrentValueFormat( ) == CLUSPROP_FORMAT_SZ )
{
*pprop->m_value.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
*pprop->m_valuePrev.pstr = rcplIn.CbhCurrentValue().pStringValue->sz;
} // if: found non-expanded version
} // if: *pprop->m_valueEx.pstr is present
break;
case CLUSPROP_FORMAT_DWORD:
case CLUSPROP_FORMAT_LONG:
ASSERT( rcplIn.CbCurrentValueLength() == sizeof( DWORD ) );
*pprop->m_value.pdw = rcplIn.CbhCurrentValue().pDwordValue->dw;
*pprop->m_valuePrev.pdw = rcplIn.CbhCurrentValue().pDwordValue->dw;
break;
case CLUSPROP_FORMAT_BINARY:
case CLUSPROP_FORMAT_MULTI_SZ:
*pprop->m_value.ppb = rcplIn.CbhCurrentValue().pBinaryValue->rgb;
*pprop->m_value.pcb = rcplIn.CbhCurrentValue().pBinaryValue->cbLength;
*pprop->m_valuePrev.ppb = rcplIn.CbhCurrentValue().pBinaryValue->rgb;
*pprop->m_valuePrev.pcb = rcplIn.CbhCurrentValue().pBinaryValue->cbLength;
break;
default:
ASSERT(0); // don't know how to deal with this type
} // switch: property format
//
// Exit the loop since we found the parameter.
//
break;
}// if: found a type match
} // if: found a string match
} // for: each property that we know about
//
// If the property wasn't known, ask the derived class to parse it.
//
if ( cprop == 0 )
{
sc = ScParseUnknownProperty(
rcplIn.CbhCurrentPropertyName().pName->sz
, rcplIn.CbhCurrentValue()
, rcplIn.RPvlPropertyValue().CbDataLeft()
);
if ( sc != ERROR_SUCCESS )
{
return sc;
} // if: error parsing the unknown property
} // if: property not parsed
//
// Advance the buffer pointer past the value in the value list.
//
sc = rcplIn.ScMoveToNextProperty();
} // while: more properties to parse
//
// If we reached the end of the properties, fix the return code.
//
if ( sc == ERROR_NO_MORE_ITEMS )
{
sc = ERROR_SUCCESS;
} // if: ended loop after parsing all properties
return sc;
} //*** CBasePropertyPage::ScParseProperties
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnCreate
//
// Description:
// Handler for the WM_CREATE message.
//
// Arguments:
// lpCreateStructIn
// Window create structure.
//
// Return Value:
// -1
// Error.
//
// 0
// Success.
//
//--
/////////////////////////////////////////////////////////////////////////////
int
CBasePropertyPage::OnCreate(
LPCREATESTRUCT lpCreateStructIn
)
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//
// Attach the window to the property page structure.
// This has been done once already in the main application, since the
// main application owns the property sheet. It needs to be done here
// so that the window handle can be found in the DLL's handle map.
//
if ( FromHandlePermanent( m_hWnd ) == NULL ) // is the window handle already in the handle map
{
HWND hWnd = m_hWnd;
m_hWnd = NULL;
Attach( hWnd );
m_bDoDetach = TRUE;
} // if: is the window handle in the handle map
return CPropertyPage::OnCreate( lpCreateStructIn );
} //*** CBasePropertyPage::OnCreate
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnDestroy
//
// Description:
// Handler for the WM_DESTROY message.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void
CBasePropertyPage::OnDestroy( void )
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//
// Detach the window from the property page structure.
// This will be done again by the main application, since it owns the
// property sheet. It needs to be done here so that the window handle
// can be removed from the DLL's handle map.
//
if ( m_bDoDetach )
{
if ( m_hWnd != NULL )
{
HWND hWnd = m_hWnd;
Detach();
m_hWnd = hWnd;
} // if: do we have a window handle?
} // if: do we need to balance the attach we did with a detach?
CPropertyPage::OnDestroy();
} //*** CBasePropertyPage::OnDestroy
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::DoDataExchange
//
// Description:
// Do data exchange between the dialog and the class.
//
// Arguments:
// pDXIn
// Data exchange object
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void
CBasePropertyPage::DoDataExchange(
CDataExchange * pDXIn
)
{
if ( ! pDXIn->m_bSaveAndValidate || ! BSaved() )
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//{{AFX_DATA_MAP(CBasePropertyPage)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
DDX_Control( pDXIn, IDC_PP_ICON, m_staticIcon );
DDX_Control( pDXIn, IDC_PP_TITLE, m_staticTitle );
if ( pDXIn->m_bSaveAndValidate )
{
if ( ! BBackPressed() )
{
CWaitCursor wc;
//
// Validate the data.
//
if ( ! BSetPrivateProps( TRUE /*fValidateOnlyIn*/ ) )
{
pDXIn->Fail();
} // if: error setting private properties
} // if: Back button not pressed
} // if: saving data from dialog
else
{
//
// Set the title.
//
DDX_Text( pDXIn, IDC_PP_TITLE, m_strTitle );
} // if: not saving data
} // if: not saving or haven't saved yet
//
// Call the base class method.
//
CPropertyPage::DoDataExchange( pDXIn );
} //*** CBasePropertyPage::DoDataExchange
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnInitDialog
//
// Description:
// Handler for the WM_INITDIALOG message.
//
// Arguments:
// None.
//
// Return Value:
// TRUE
// We need the focus to be set for us.
//
// FALSE
// We already set the focus to the proper control.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::OnInitDialog( void )
{
ASSERT( Peo() != NULL );
ASSERT( Peo()->PodObjData() != NULL );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//
// Set the title string.
//
m_strTitle = Peo()->PodObjData()->StrName();
//
// Call the base class method.
//
CPropertyPage::OnInitDialog();
//
// Display an icon for the object.
//
if ( Peo()->Hicon() != NULL )
{
m_staticIcon.SetIcon( Peo()->Hicon() );
} // if: an icon was specified
//
// Return TRUE unless you set the focus to a control.
//
// EXCEPTION: OCX Property Pages should return FALSE.
//
return TRUE;
} //*** CBasePropertyPage::OnInitDialog
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnSetActive
//
// Description:
// Handler for the PSN_SETACTIVE message.
//
// Arguments:
// None.
//
// Return Value:
// TRUE
// Page successfully initialized.
//
// FALSE
// Page not initialized.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::OnSetActive( void )
{
HRESULT hr = S_OK;
ASSERT( Peo() != NULL);
ASSERT( Peo()->PodObjData() != NULL );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//
// Reread the data.
//
hr = Peo()->HrGetObjectInfo();
if ( FAILED( hr ) )
{
return FALSE;
} // if: error getting object info
//
// Set the title string.
//
m_strTitle = Peo()->PodObjData()->StrName();
m_bBackPressed = FALSE;
m_bSaved = FALSE;
return CPropertyPage::OnSetActive();
} //*** CBasePropertyPage::OnSetActive
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnApply
//
// Description:
// Handler for the PSM_APPLY message.
//
// Arguments:
// None.
//
// Return Value:
// TRUE
// Page successfully applied.
//
// FALSE
// Error applying page.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::OnApply( void )
{
ASSERT( ! BWizard() );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
CWaitCursor wc;
if ( BApplyChanges() == FALSE )
{
return FALSE;
} // if: error applying changes
return CPropertyPage::OnApply();
} //*** CBasePropertyPage::OnApply
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnWizardBack
//
// Description:
// Handler for the PSN_WIZBACK message.
//
// Arguments:
// None.
//
// Return Value:
// -1
// Don't change the page.
//
// 0
// Change the page.
//
//--
/////////////////////////////////////////////////////////////////////////////
LRESULT
CBasePropertyPage::OnWizardBack( void )
{
LRESULT lResult = 0L;
ASSERT( BWizard() );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
lResult = CPropertyPage::OnWizardBack();
if ( lResult != -1 )
{
m_bBackPressed = TRUE;
} // if: no error occurred
return lResult;
} //*** CBasePropertyPage::OnWizardBack
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnWizardNext
//
// Description:
// Handler for the PSN_WIZNEXT message.
//
// Arguments:
// None.
//
// Return Value:
// -1
// Don't change the page.
//
// 0
// Change the page.
//
//--
/////////////////////////////////////////////////////////////////////////////
LRESULT
CBasePropertyPage::OnWizardNext( void )
{
ASSERT( BWizard() );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
CWaitCursor wc;
//
// Update the data in the class from the page.
// This necessary because, while OnKillActive() will call UpdateData(),
// it is called after this method is called, and we need to be sure that
// data has been saved before we apply them.
//
if ( ! UpdateData( TRUE /*bSaveAndValidate*/ ) )
{
return -1;
} // if: error updating data
//
// Save the data in the sheet.
//
if ( BApplyChanges() == FALSE )
{
return -1;
} // if: error applying changes
//
// Create the object.
//
return CPropertyPage::OnWizardNext();
} //*** CBasePropertyPage::OnWizardNext
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnWizardFinish
//
// Description:
// Handler for the PSN_WIZFINISH message.
//
// Arguments:
// None.
//
// Return Value:
// FALSE
// Don't change the page.
//
// TRUE
// Change the page.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::OnWizardFinish( void )
{
ASSERT( BWizard() );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
CWaitCursor wc;
//
// BUG! There should be no need to call UpdateData in this function.
// See BUG: Finish Button Fails Data Transfer from Page to Variables
// KB Article ID: Q150349
//
//
// Update the data in the class from the page.
//
if ( UpdateData( TRUE /*bSaveAndValidate*/ ) == FALSE )
{
return FALSE;
} // if: error updating data
// Save the data in the sheet.
if ( BApplyChanges() == FALSE )
{
return FALSE;
} // if: error applying changes
return CPropertyPage::OnWizardFinish();
} //*** CBasePropertyPage::OnWizardFinish
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::OnChangeCtrl
//
// Description:
// Handler for the messages sent when a control is changed. This
// method can be specified in a message map if all that needs to be
// done is enable the Apply button.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void
CBasePropertyPage::OnChangeCtrl( void )
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
SetModified( TRUE );
} //*** CBasePropertyPage::OnChangeCtrl
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::EnableNext
//
// Description:
// Enables or disables the NEXT or FINISH button.
//
// Arguments:
// fEnableIn
// TRUE = enable the button, FALSE = disable the button.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void
CBasePropertyPage::EnableNext(
BOOL fEnableIn // = TRUE
)
{
ASSERT( BWizard() );
ASSERT( PiWizardCallback() );
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
PiWizardCallback()->EnableNext( reinterpret_cast< LONG * >( Hpage() ), fEnableIn );
} //*** CBasePropertyPage::EnableNext
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::BApplyChanges
//
// Description:
// Apply changes made on the page.
//
// Arguments:
// None.
//
// Return Value:
// TRUE
// Page successfully applied.
//
// FALSE
// Error applying page.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::BApplyChanges( void )
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
CWaitCursor wc;
//
// Save data.
//
return BSetPrivateProps();
} //*** CBasePropertyPage::BApplyChanges
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::BBuildPropList
//
// Description:
// Build the property list.
//
// Arguments:
// rcplIn
// Cluster property list.
//
// fNoNewPropsIn
// TRUE = exclude properties marked with opfNew.
//
// Return Value:
// TRUE
// Property list built successfully.
//
// FALSE
// Error building property list.
//
// Exceptions Thrown:
// Any exceptions thrown by CClusPropList::AddProp().
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::BBuildPropList(
CClusPropList & rcplIn
, BOOL fNoNewPropsIn // = FALSE
)
{
BOOL fNewPropsFound = FALSE;
DWORD cprop;
const CObjectProperty * pprop;
for ( pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop-- )
{
if ( fNoNewPropsIn && (pprop->m_dwFlags & CObjectProperty::opfNew) )
{
fNewPropsFound = TRUE;
continue;
} // if: no new props allowed and this is a new property
switch ( pprop->m_propFormat )
{
case CLUSPROP_FORMAT_SZ:
rcplIn.ScAddProp(
pprop->m_pwszName
, *pprop->m_value.pstr
, *pprop->m_valuePrev.pstr
);
break;
case CLUSPROP_FORMAT_EXPAND_SZ:
rcplIn.ScAddExpandSzProp(
pprop->m_pwszName
, *pprop->m_value.pstr
, *pprop->m_valuePrev.pstr
);
break;
case CLUSPROP_FORMAT_DWORD:
rcplIn.ScAddProp(
pprop->m_pwszName
, *pprop->m_value.pdw
, *pprop->m_valuePrev.pdw
);
break;
case CLUSPROP_FORMAT_LONG:
rcplIn.ScAddProp(
pprop->m_pwszName
, *pprop->m_value.pl
, *pprop->m_valuePrev.pl
);
break;
case CLUSPROP_FORMAT_BINARY:
case CLUSPROP_FORMAT_MULTI_SZ:
rcplIn.ScAddProp(
pprop->m_pwszName
, *pprop->m_value.ppb
, *pprop->m_value.pcb
, *pprop->m_valuePrev.ppb
, *pprop->m_valuePrev.pcb
);
break;
default:
ASSERT( 0 ); // don't know how to deal with this type
return FALSE;
} // switch: property format
} // for: each property
return ( !( fNoNewPropsIn || fNewPropsFound ) );
} //*** CBasePropertyPage::BBuildPropList
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::BSetPrivateProps
//
// Description:
// Set the private properties for this object.
//
// Arguments:
// fValidateOnlyIn
// TRUE = only validate the data.
//
// fNoNewPropsIn
// TRUE = exclude properties marked with opfNew.
//
// Return Value:
// ERROR_SUCCESS
// The operation was completed successfully.
//
// Other Win32 values.
// Failure.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL
CBasePropertyPage::BSetPrivateProps(
BOOL fValidateOnlyIn // = FALSE
, BOOL fNoNewPropsIn // = FALSE
)
{
BOOL fSuccess = TRUE;
CClusPropList cpl( BWizard() /*bAlwaysAddProp*/ );
ASSERT( Peo() != NULL );
ASSERT( Peo()->PodObjData() );
//
// Build the property list.
//
try
{
fSuccess = BBuildPropList( cpl, fNoNewPropsIn );
} // try
catch ( CException * pe )
{
pe->ReportError();
pe->Delete();
fSuccess = FALSE;
} // catch: CException
//
// Set the data.
//
if ( fSuccess )
{
if ( (cpl.PbPropList() != NULL) && (cpl.CbPropList() > 0) )
{
DWORD sc = ERROR_SUCCESS;
DWORD dwControlCode;
DWORD cbProps;
switch ( Cot() )
{
case CLUADMEX_OT_NODE:
{
CNodeData * pcnd = reinterpret_cast< CNodeData * >( Peo()->PodObjData() );
ASSERT( pcnd && (pcnd->GetHNode() != NULL) );
//
// Determine which control code to use.
//
if ( fValidateOnlyIn )
{
dwControlCode = CLUSCTL_NODE_VALIDATE_PRIVATE_PROPERTIES;
} // if: only validating data
else
{
dwControlCode = CLUSCTL_NODE_SET_PRIVATE_PROPERTIES;
} // else: setting data
//
// Set private properties.
//
sc = ClusterNodeControl(
pcnd->GetHNode()
, NULL // hNode
, dwControlCode
, cpl.PbPropList()
, static_cast< DWORD >( cpl.CbPropList() )
, NULL // lpOutBuffer
, 0 // nOutBufferSize
, &cbProps
);
break;
} // case:
case CLUADMEX_OT_GROUP:
{
CGroupData * pcgd = reinterpret_cast< CGroupData * >( Peo()->PodObjData() );
ASSERT( pcgd && (pcgd->GetHGroup() != NULL) );
//
// Determine which control code to use.
//
if ( fValidateOnlyIn )
{
dwControlCode = CLUSCTL_GROUP_VALIDATE_PRIVATE_PROPERTIES;
} // if: only validating data
else
{
dwControlCode = CLUSCTL_GROUP_SET_PRIVATE_PROPERTIES;
} // else: setting data
//
// Set private properties.
//
sc = ClusterGroupControl(
pcgd->GetHGroup()
, NULL // hNode
, dwControlCode
, cpl.PbPropList()
, static_cast< DWORD >( cpl.CbPropList() )
, NULL // lpOutBuffer
, 0 // nOutBufferSize
, &cbProps
);
break;
} // case:
case CLUADMEX_OT_RESOURCE:
{
CResData * pcrd = reinterpret_cast< CResData * >( Peo()->PodObjData() );
ASSERT( pcrd && (pcrd->GetHResource() != NULL) );
//
// Determine which control code to use.
//
if ( fValidateOnlyIn )
{
dwControlCode = CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES;
} // if: only validating data
else
{
dwControlCode = CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES;
} // else: setting data
//
// Set private properties.
//
sc = ClusterResourceControl(
pcrd->GetHResource()
, NULL // hNode
, dwControlCode
, cpl.PbPropList()
, static_cast< DWORD >( cpl.CbPropList() )
, NULL // lpOutBuffer
, 0 // nOutBufferSize
, &cbProps
);
break;
} // case:
case CLUADMEX_OT_RESOURCETYPE:
{
CResTypeData * pcrd = reinterpret_cast< CResTypeData * >( Peo()->PodObjData() );
ASSERT( pcrd && (pcrd->StrName().GetLength() > 0) );
//
// Determine which control code to use.
//
if ( fValidateOnlyIn )
{
dwControlCode = CLUSCTL_RESOURCE_TYPE_VALIDATE_PRIVATE_PROPERTIES;
} // if: only validating data
else
{
dwControlCode = CLUSCTL_RESOURCE_TYPE_SET_PRIVATE_PROPERTIES;
} // else: setting data
//
// Set private properties.
//
sc = ClusterResourceTypeControl(
Hcluster()
, pcrd->StrName()
, NULL // hNode
, dwControlCode
, cpl.PbPropList()
, static_cast< DWORD >( cpl.CbPropList() )
, NULL // lpOutBuffer
, 0 // nOutBufferSize
, &cbProps
);
break;
} // case:
case CLUADMEX_OT_NETWORK:
{
CNetworkData * pcnd = reinterpret_cast< CNetworkData * >( Peo()->PodObjData() );
ASSERT( pcnd && (pcnd->GetHNetwork() != NULL) );
//
// Determine which control code to use.
//
if ( fValidateOnlyIn )
{
dwControlCode = CLUSCTL_NETWORK_VALIDATE_PRIVATE_PROPERTIES;
} // if: only validating data
else
{
dwControlCode = CLUSCTL_NETWORK_SET_PRIVATE_PROPERTIES;
} // else: setting data
//
// Set private properties.
//
sc = ClusterNetworkControl(
pcnd->GetHNetwork()
, NULL // hNode
, dwControlCode
, cpl.PbPropList()
, static_cast< DWORD >( cpl.CbPropList() )
, NULL // lpOutBuffer
, 0 // nOutBufferSize
, &cbProps
);
break;
} // case:
case CLUADMEX_OT_NETINTERFACE:
{
CNetInterfaceData * pcnd = reinterpret_cast< CNetInterfaceData * >( Peo()->PodObjData() );
ASSERT( pcnd && (pcnd->GetHNetInterface() != NULL) );
//
// Determine which control code to use.
//
if ( fValidateOnlyIn )
{
dwControlCode = CLUSCTL_NETINTERFACE_VALIDATE_PRIVATE_PROPERTIES;
} // if: only validating data
else
{
dwControlCode = CLUSCTL_NETINTERFACE_SET_PRIVATE_PROPERTIES;
} // else: setting data
//
// Set private properties.
//
sc = ClusterNetInterfaceControl(
pcnd->GetHNetInterface()
, NULL // hNode
, dwControlCode
, cpl.PbPropList()
, static_cast< DWORD >( cpl.CbPropList() )
, NULL // lpOutBuffer
, 0 // nOutBufferSize
, &cbProps
);
break;
} // case:
default:
ASSERT( 0 );
} // switch: object type
//
// Handle errors.
//
if ( sc != ERROR_SUCCESS )
{
if ( sc == ERROR_INVALID_PARAMETER )
{
if ( ! fNoNewPropsIn )
{
fSuccess = BSetPrivateProps( fValidateOnlyIn, TRUE /*fNoNewPropsIn*/ );
} // if: new props are allowed
else
fSuccess = FALSE;
} // if: invalid parameter error occurred
else
{
fSuccess = FALSE;
} // else: some other error occurred
//
// If an error occurred, display an error message.
//
if ( ! fSuccess )
{
DisplaySetPropsError( sc, fValidateOnlyIn ? IDS_ERROR_VALIDATING_PROPERTIES : IDS_ERROR_SETTING_PROPERTIES );
if ( sc == ERROR_RESOURCE_PROPERTIES_STORED )
{
fSuccess = TRUE;
} // if: properties only stored
} // if: error occurred
} // if: error setting/validating data
} // if: there is data to set
} // if: no errors building the property list
//
// Save data locally.
//
if ( ! fValidateOnlyIn && fSuccess )
{
//
// Save new values as previous values.
//
try
{
DWORD cprop;
const CObjectProperty * pprop;
for ( pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop-- )
{
switch ( pprop->m_propFormat )
{
case CLUSPROP_FORMAT_SZ:
case CLUSPROP_FORMAT_EXPAND_SZ:
ASSERT(pprop->m_value.pstr != NULL);
ASSERT(pprop->m_valuePrev.pstr != NULL);
*pprop->m_valuePrev.pstr = *pprop->m_value.pstr;
break;
case CLUSPROP_FORMAT_DWORD:
case CLUSPROP_FORMAT_LONG:
ASSERT( pprop->m_value.pdw != NULL );
ASSERT( pprop->m_valuePrev.pdw != NULL );
*pprop->m_valuePrev.pdw = *pprop->m_value.pdw;
break;
case CLUSPROP_FORMAT_BINARY:
case CLUSPROP_FORMAT_MULTI_SZ:
ASSERT( pprop->m_value.ppb != NULL );
ASSERT( *pprop->m_value.ppb != NULL );
ASSERT( pprop->m_value.pcb != NULL );
ASSERT( pprop->m_valuePrev.ppb != NULL );
ASSERT( *pprop->m_valuePrev.ppb != NULL );
ASSERT( pprop->m_valuePrev.pcb != NULL );
delete [] *pprop->m_valuePrev.ppb;
*pprop->m_valuePrev.ppb = new BYTE[ *pprop->m_value.pcb ];
CopyMemory( *pprop->m_valuePrev.ppb, *pprop->m_value.ppb, *pprop->m_value.pcb );
*pprop->m_valuePrev.pcb = *pprop->m_value.pcb;
break;
default:
ASSERT( 0 ); // don't know how to deal with this type
} // switch: property format
} // for: each property
} // try
catch ( CException * pe )
{
pe->ReportError();
pe->Delete();
fSuccess = FALSE;
} // catch: CException
} // if: not just validating and successful so far
//
// Indicate we successfully saved the properties.
//
if ( ! fValidateOnlyIn && fSuccess )
{
m_bSaved = TRUE;
} // if: successfully saved data
return fSuccess;
} //*** CBasePropertyPage::BSetPrivateProps
/////////////////////////////////////////////////////////////////////////////
//++
//
// CBasePropertyPage::DisplaySetPropsError
//
// Routine Description:
// Display an error caused by setting or validating properties.
//
// Arguments:
// scIn
// Status to display error on.
//
// idsOperIn
// Operation message.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void
CBasePropertyPage::DisplaySetPropsError(
DWORD scIn
, UINT idsOperIn
) const
{
CString strErrorMsg;
CString strOperMsg;
CString strMsgIdFmt;
CString strMsgId;
CString strMsg;
UNREFERENCED_PARAMETER( idsOperIn );
strOperMsg.LoadString( IDS_ERROR_SETTING_PROPERTIES );
FormatError( strErrorMsg, scIn );
strMsgIdFmt.LoadString( IDS_ERROR_MSG_ID );
strMsgId.Format( strMsgIdFmt, scIn, scIn );
strMsg.Format( _T("%s\n\n%s%s"), strOperMsg, strErrorMsg, strMsgId );
AfxMessageBox( strMsg );
} //*** CBasePropertyPage::DisplaySetPropsError