Example #1
0
/////////////////////////////////////////////////////////////////////////////
//++
//
//	CBasePropertyPage::BuildPropList
//
//	Routine Description:
//		Build the property list.
//
//	Arguments:
//		rcpl		[IN OUT] Cluster property list.
//
//	Return Value:
//		None.
//
//	Exceptions Thrown:
//		Any exceptions thrown by CClusPropList::AddProp().
//
//--
/////////////////////////////////////////////////////////////////////////////
void CBasePropertyPage::BuildPropList(
	IN OUT CClusPropList & rcpl
	)
{
	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:
				rcpl.AddProp(
						pprop->m_pwszName,
						*pprop->m_value.pstr,
						*pprop->m_valuePrev.pstr
						);
				break;
			case CLUSPROP_FORMAT_DWORD:
				rcpl.AddProp(
						pprop->m_pwszName,
						*pprop->m_value.pdw,
						*pprop->m_valuePrev.pdw
						);
				break;
			case CLUSPROP_FORMAT_BINARY:
			case CLUSPROP_FORMAT_MULTI_SZ:
				rcpl.AddProp(
						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;
		}  // switch:  property format
	}  // for:  each property

}  //*** CBasePropertyPage::BuildPropList()
Example #2
0
/////////////////////////////////////////////////////////////////////////////
//++
//
//	CBasePropertyPage::BSetPrivateProps
//
//	Routine Description:
//		Set the private properties for this object.
//
//	Arguments:
//		bValidateOnly	[IN] TRUE = only validate the data.
//
//	Return Value:
//		ERROR_SUCCESS	The operation was completed successfully.
//		!0				Failure.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CBasePropertyPage::BSetPrivateProps(IN BOOL bValidateOnly)
{
	BOOL			bSuccess	= TRUE;
	CClusPropList	cpl(BWizard() /*bAlwaysAddProp*/);
	CWaitCursor	wc;

	ASSERT(Peo() != NULL);

	// Build the property list.
	try
	{
		BuildPropList(cpl);
	}  // try
	catch (CException * pe)
	{
		pe->ReportError();
		pe->Delete();
		bSuccess = FALSE;
	}  // catch:  CException

	// Set the data.
	if (bSuccess)
	{
		if ((cpl.PbProplist() != NULL) && (cpl.CbProplist() > 0))
		{
			DWORD		dwStatus;
			DWORD		dwControlCode;
			DWORD		cbProps;

			switch (Cot())
			{
				case CLUADMEX_OT_NODE:
					ASSERT(Peo()->PndNodeData() != NULL);
					ASSERT(Peo()->PndNodeData()->m_hnode != NULL);

					// Determine which control code to use.
					if (bValidateOnly)
						dwControlCode = CLUSCTL_NODE_VALIDATE_PRIVATE_PROPERTIES;
					else
						dwControlCode = CLUSCTL_NODE_SET_PRIVATE_PROPERTIES;

					// Set private properties.
					dwStatus = ClusterNodeControl(
									Peo()->PndNodeData()->m_hnode,
									NULL,	// hNode
									dwControlCode,
									cpl.PbProplist(),
									cpl.CbProplist(),
									NULL,	// lpOutBuffer
									0,		// nOutBufferSize
									&cbProps
									);
					break;
				case CLUADMEX_OT_GROUP:
					ASSERT(Peo()->PgdGroupData() != NULL);
					ASSERT(Peo()->PgdGroupData()->m_hgroup != NULL);

					// Determine which control code to use.
					if (bValidateOnly)
						dwControlCode = CLUSCTL_GROUP_VALIDATE_PRIVATE_PROPERTIES;
					else
						dwControlCode = CLUSCTL_GROUP_SET_PRIVATE_PROPERTIES;

					// Set private properties.
					dwStatus = ClusterGroupControl(
									Peo()->PgdGroupData()->m_hgroup,
									NULL,	// hNode
									dwControlCode,
									cpl.PbProplist(),
									cpl.CbProplist(),
									NULL,	// lpOutBuffer
									0,		// nOutBufferSize
									&cbProps
									);
					break;
				case CLUADMEX_OT_RESOURCE:
					ASSERT(Peo()->PrdResData() != NULL);
					ASSERT(Peo()->PrdResData()->m_hresource != NULL);

					// Determine which control code to use.
					if (bValidateOnly)
						dwControlCode = CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES;
					else
						dwControlCode = CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES;

					// Set private properties.
					dwStatus = ClusterResourceControl(
									Peo()->PrdResData()->m_hresource,
									NULL,	// hNode
									dwControlCode,
									cpl.PbProplist(),
									cpl.CbProplist(),
									NULL,	// lpOutBuffer
									0,		// nOutBufferSize
									&cbProps
									);
					break;
				case CLUADMEX_OT_RESOURCETYPE:
					ASSERT(Peo()->PodObjData() != NULL);
					ASSERT(Peo()->PodObjData()->m_strName.GetLength() > 0);

					// Determine which control code to use.
					if (bValidateOnly)
						dwControlCode = CLUSCTL_RESOURCE_TYPE_VALIDATE_PRIVATE_PROPERTIES;
					else
						dwControlCode = CLUSCTL_RESOURCE_TYPE_SET_PRIVATE_PROPERTIES;

					// Set private properties.
					dwStatus = ClusterResourceTypeControl(
									Hcluster(),
									Peo()->PodObjData()->m_strName,
									NULL,	// hNode
									dwControlCode,
									cpl.PbProplist(),
									cpl.CbProplist(),
									NULL,	// lpOutBuffer
									0,		// nOutBufferSize
									&cbProps
									);
					break;
				case CLUADMEX_OT_NETWORK:
					ASSERT(Peo()->PndNetworkData() != NULL);
					ASSERT(Peo()->PndNetworkData()->m_hnetwork != NULL);

					// Determine which control code to use.
					if (bValidateOnly)
						dwControlCode = CLUSCTL_NETWORK_VALIDATE_PRIVATE_PROPERTIES;
					else
						dwControlCode = CLUSCTL_NETWORK_SET_PRIVATE_PROPERTIES;

					// Set private properties.
					dwStatus = ClusterNetworkControl(
									Peo()->PndNetworkData()->m_hnetwork,
									NULL,	// hNode
									dwControlCode,
									cpl.PbProplist(),
									cpl.CbProplist(),
									NULL,	// lpOutBuffer
									0,		// nOutBufferSize
									&cbProps
									);
					break;
				case CLUADMEX_OT_NETINTERFACE:
					ASSERT(Peo()->PndNetInterfaceData() != NULL);
					ASSERT(Peo()->PndNetInterfaceData()->m_hnetinterface != NULL);

					// Determine which control code to use.
					if (bValidateOnly)
						dwControlCode = CLUSCTL_NETINTERFACE_VALIDATE_PRIVATE_PROPERTIES;
					else
						dwControlCode = CLUSCTL_NETINTERFACE_SET_PRIVATE_PROPERTIES;

					// Set private properties.
					dwStatus = ClusterNetInterfaceControl(
									Peo()->PndNetInterfaceData()->m_hnetinterface,
									NULL,	// hNode
									dwControlCode,
									cpl.PbProplist(),
									cpl.CbProplist(),
									NULL,	// lpOutBuffer
									0,		// nOutBufferSize
									&cbProps
									);
					break;
				default:
					ASSERT(0);
			}  // switch:  object type

			// Handle errors.
			if (dwStatus != ERROR_SUCCESS)
			{
				CString strMsg;
				FormatError(strMsg, dwStatus);
				AfxMessageBox(strMsg);
				if (bValidateOnly
						|| (dwStatus != ERROR_RESOURCE_PROPERTIES_STORED))
					bSuccess = FALSE;
			}  // if:  error setting/validating data
		}  // if:  there is data to set
	}  // if:  no errors building the property list

	// Save data locally.
	if (!bValidateOnly && bSuccess)
	{
		// 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:
						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();
			bSuccess = FALSE;
		}  // catch:  CException
	}  // if:  not just validating and successful so far

	return bSuccess;

}  //*** CBasePropertyPage::BSetPrivateProps()
Example #3
0
/////////////////////////////////////////////////////////////////////////////
//++
//
//	CBasePropertyPage::DwParseProperties
//
//	Routine Description:
//		Parse the properties of the resource.  This is in a separate function
//		from BInit so that the optimizer can do a better job.
//
//	Arguments:
//		rcpl			[IN] Cluster property list to parse.
//
//	Return Value:
//		ERROR_SUCCESS	Properties were parsed successfully.
//
//	Exceptions Thrown:
//		Any exceptions from CString::operator=().
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CBasePropertyPage::DwParseProperties(IN const CClusPropList & rcpl)
{
	DWORD							cProps;
	DWORD							cprop;
	DWORD							cbProps;
	const CObjectProperty *			pprop;
	CLUSPROP_BUFFER_HELPER			props;
	CLUSPROP_PROPERTY_NAME const *	pName;

	ASSERT(rcpl.PbProplist() != NULL);

	props.pb = rcpl.PbProplist();
	cbProps = rcpl.CbProplist();

	// Loop through each property.
	for (cProps = *(props.pdw++) ; cProps > 0 ; cProps--)
	{
		pName = props.pName;
		ASSERT(pName->Syntax.dw == CLUSPROP_SYNTAX_NAME);
		props.pb += sizeof(*pName) + ALIGN_CLUSPROP(pName->cbLength);

		// Decrement the counter by the size of the name.
		ASSERT(cbProps > sizeof(*pName) + ALIGN_CLUSPROP(pName->cbLength));
		cbProps -= sizeof(*pName) + ALIGN_CLUSPROP(pName->cbLength);

		ASSERT(cbProps > sizeof(*props.pValue) + ALIGN_CLUSPROP(props.pValue->cbLength));

		// Parse known properties.
		for (pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop--)
		{
			if (lstrcmpiW(pName->sz, pprop->m_pwszName) == 0)
			{
				ASSERT(props.pSyntax->wFormat == pprop->m_propFormat);
				switch (pprop->m_propFormat)
				{
					case CLUSPROP_FORMAT_SZ:
					case CLUSPROP_FORMAT_EXPAND_SZ:
						ASSERT((props.pValue->cbLength == (lstrlenW(props.pStringValue->sz) + 1) * sizeof(WCHAR))
								|| ((props.pValue->cbLength == 0) && (props.pStringValue->sz[0] == L'\0')));
						*pprop->m_value.pstr = props.pStringValue->sz;
						*pprop->m_valuePrev.pstr = props.pStringValue->sz;
						break;
					case CLUSPROP_FORMAT_DWORD:
						ASSERT(props.pValue->cbLength == sizeof(DWORD));
						*pprop->m_value.pdw = props.pDwordValue->dw;
						*pprop->m_valuePrev.pdw = props.pDwordValue->dw;
						break;
					case CLUSPROP_FORMAT_BINARY:
					case CLUSPROP_FORMAT_MULTI_SZ:
						*pprop->m_value.ppb = props.pBinaryValue->rgb;
						*pprop->m_value.pcb = props.pBinaryValue->cbLength;
						*pprop->m_valuePrev.ppb = props.pBinaryValue->rgb;
						*pprop->m_valuePrev.pcb = props.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 match
		}  // for:  each property

		// If the property wasn't known, ask the derived class to parse it.
		if (cprop == 0)
		{
			DWORD		dwStatus;

			dwStatus = DwParseUnknownProperty(pName->sz, props, cbProps);
			if (dwStatus != ERROR_SUCCESS)
				return dwStatus;
		}  // if:  property not parsed

		// Advance the buffer pointer past the value in the value list.
		while ((props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
				&& (cbProps > 0))
		{
			ASSERT(cbProps > sizeof(*props.pValue) + ALIGN_CLUSPROP(props.pValue->cbLength));
			cbProps -= sizeof(*props.pValue) + ALIGN_CLUSPROP(props.pValue->cbLength);
			props.pb += sizeof(*props.pValue) + ALIGN_CLUSPROP(props.pValue->cbLength);
		}  // while:  more values in the list

		// Advance the buffer pointer past the value list endmark.
		ASSERT(cbProps >= sizeof(*props.pSyntax));
		cbProps -= sizeof(*props.pSyntax);
		props.pb += sizeof(*props.pSyntax); // endmark
	}  // for:  each property

	return ERROR_SUCCESS;

}  //*** CBasePropertyPage::DwParseProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
//  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::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::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