You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
550 lines
16 KiB
550 lines
16 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// CClusDiskJoin.cpp
|
|
//
|
|
// Description:
|
|
// Contains the definition of the CClusDiskJoin class.
|
|
//
|
|
// Maintained By:
|
|
// David Potter (DavidP) 14-JUN-2001
|
|
// Vij Vasu (Vvasu) 08-MAR-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Include Files
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The precompiled header.
|
|
#include "Pch.h"
|
|
|
|
// The header for this file
|
|
#include "CClusDiskJoin.h"
|
|
|
|
// For the CBaseClusterJoin class.
|
|
#include "CBaseClusterJoin.h"
|
|
|
|
// For the CImpersonateUser class.
|
|
#include "CImpersonateUser.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Macro definitions
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name of the private property of a physical disk resouce that has its signature.
|
|
#define PHYSICAL_DISK_SIGNATURE_PRIVPROP_NAME L"Signature"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDiskJoin::CClusDiskJoin
|
|
//
|
|
// Description:
|
|
// Constructor of the CClusDiskJoin class
|
|
//
|
|
// Arguments:
|
|
// pbcjParentActionIn
|
|
// Pointer to the base cluster action of which this action is a part.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusDiskJoin::CClusDiskJoin(
|
|
CBaseClusterJoin * pbcjParentActionIn
|
|
)
|
|
: BaseClass( pbcjParentActionIn )
|
|
, m_nSignatureArraySize( 0 )
|
|
, m_nSignatureCount( 0 )
|
|
{
|
|
|
|
TraceFunc( "" );
|
|
|
|
SetRollbackPossible( true );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDiskJoin::CClusDiskJoin
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDiskJoin::~CClusDiskJoin
|
|
//
|
|
// Description:
|
|
// Destructor of the CClusDiskJoin class.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusDiskJoin::~CClusDiskJoin( void )
|
|
{
|
|
TraceFunc( "" );
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDiskJoin::~CClusDiskJoin
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDiskJoin::Commit
|
|
//
|
|
// Description:
|
|
// Configure and start the service.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any that are thrown by the contained actions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDiskJoin::Commit( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
// Call the base class commit method.
|
|
BaseClass::Commit();
|
|
|
|
try
|
|
{
|
|
// Create and start the service.
|
|
ConfigureService();
|
|
|
|
// Try and attach to all the disks that the sponsor knows about.
|
|
AttachToClusteredDisks();
|
|
|
|
} // try:
|
|
catch( ... )
|
|
{
|
|
// If we are here, then something went wrong with the create.
|
|
|
|
LogMsg( "[BC] Caught exception during commit." );
|
|
|
|
//
|
|
// Cleanup anything that the failed create might have done.
|
|
// Catch any exceptions thrown during Cleanup to make sure that there
|
|
// is no collided unwind.
|
|
//
|
|
try
|
|
{
|
|
CleanupService();
|
|
}
|
|
catch( ... )
|
|
{
|
|
//
|
|
// The rollback of the committed action has failed.
|
|
// There is nothing that we can do.
|
|
// We certainly cannot rethrow this exception, since
|
|
// the exception that caused the rollback is more important.
|
|
//
|
|
|
|
TW32( ERROR_CLUSCFG_ROLLBACK_FAILED );
|
|
|
|
LogMsg( "[BC] THIS COMPUTER MAY BE IN AN INVALID STATE. Caught an exception during cleanup." );
|
|
|
|
} // catch: all
|
|
|
|
// Rethrow the exception thrown by commit.
|
|
throw;
|
|
|
|
} // catch: all
|
|
|
|
// If we are here, then everything went well.
|
|
SetCommitCompleted( true );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDiskJoin::Commit
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDiskJoin::Rollback
|
|
//
|
|
// Description:
|
|
// Cleanup the service.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDiskJoin::Rollback( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
// Call the base class rollback method.
|
|
BaseClass::Rollback();
|
|
|
|
// Cleanup the service.
|
|
CleanupService();
|
|
|
|
SetCommitCompleted( false );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDiskJoin::Rollback
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDiskJoin::AttachToClusteredDisks
|
|
//
|
|
// Description:
|
|
// Get the signatures of all disks that have been clustered from the sponsor.
|
|
// Attach to all these disks.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDiskJoin::AttachToClusteredDisks( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
DWORD sc = ERROR_SUCCESS;
|
|
|
|
// Get the parent action pointer.
|
|
CBaseClusterJoin * pcjClusterJoin = dynamic_cast< CBaseClusterJoin *>( PbcaGetParent() );
|
|
|
|
// If the parent action of this action is not CBaseClusterJoin
|
|
if ( pcjClusterJoin == NULL )
|
|
{
|
|
THROW_ASSERT( E_POINTER, "The parent action of this action is not CBaseClusterJoin." );
|
|
} // an invalid pointer was passed in.
|
|
|
|
|
|
//
|
|
// Connect to the sponsor cluster and get the signatures of all clustered disks.
|
|
//
|
|
|
|
// Smart handle to sponsor cluster
|
|
SmartClusterHandle schSponsorCluster;
|
|
|
|
LogMsg( "[BC] Attempting to impersonate the cluster service account." );
|
|
|
|
// Impersonate the cluster service account, so that we can contact the sponsor cluster.
|
|
// The impersonation is automatically ended when this object is destroyed.
|
|
CImpersonateUser ciuImpersonateClusterServiceAccount( pcjClusterJoin->HGetClusterServiceAccountToken() );
|
|
|
|
{
|
|
LogMsg( "[BC] Opening a cluster handle to the sponsor cluster with the '%ws' binding string.", pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
|
|
// Open a handle to the sponsor cluster.
|
|
HCLUSTER hSponsorCluster = OpenCluster( pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
|
|
// Assign it to a smart handle for safe release.
|
|
schSponsorCluster.Assign( hSponsorCluster );
|
|
}
|
|
|
|
// Did we succeed in opening a handle to the sponsor cluster?
|
|
if ( schSponsorCluster.FIsInvalid() )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
LogMsg( "[BC] Error %#08x occurred trying to open a cluster handle to the sponsor cluster with the '%ws' binding string.", sc, pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
goto Cleanup;
|
|
} // if: OpenCluster() failed
|
|
|
|
LogMsg( "[BC] Enumerating all '%s' resources in the cluster.", CLUS_RESTYPE_NAME_PHYS_DISK );
|
|
|
|
// Enumerate all the physical disk resouces in the cluster and get their signatures.
|
|
sc = TW32( ResUtilEnumResourcesEx(
|
|
schSponsorCluster.HHandle()
|
|
, NULL
|
|
, CLUS_RESTYPE_NAME_PHYS_DISK
|
|
, S_ScResourceEnumCallback
|
|
, this
|
|
) );
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
// Free the signature array.
|
|
m_rgdwSignatureArray.PRelease();
|
|
m_nSignatureArraySize = 0;
|
|
m_nSignatureCount = 0;
|
|
|
|
LogMsg( "[BC] An error occurred trying enumerate resources in the sponsor cluster." );
|
|
goto Cleanup;
|
|
} // if: ResUtilEnumResourcesEx() failed
|
|
|
|
Cleanup:
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying to attach to the disks in the sponsor cluster. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDISK_CONFIGURE );
|
|
} // if: something has gone wrong
|
|
else
|
|
{
|
|
LogMsg( "[BC] Attaching to the %d disks in the sponsor cluster.", m_nSignatureCount );
|
|
|
|
AttachToDisks(
|
|
m_rgdwSignatureArray.PMem()
|
|
, m_nSignatureCount
|
|
);
|
|
} // else: everything has gone well so far
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDiskJoin::AttachToClusteredDisks
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDiskJoin::ScAddSignature
|
|
//
|
|
// Description:
|
|
// Add a signature to the array of signatures of disks that ClusDisk should
|
|
// attach to. If the array is already full, grow the array.
|
|
//
|
|
// Arguments:
|
|
// dwSignatureIn
|
|
// Signature to be added to the array.
|
|
//
|
|
// Return Value:
|
|
// ERROR_SUCCESS
|
|
// If everything was ok.
|
|
//
|
|
// Other Win32 error codes on failure.
|
|
//
|
|
// Exceptions Thrown:
|
|
// None. This function is called from a callback routine and therefore
|
|
// cannot throw any exceptions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
DWORD
|
|
CClusDiskJoin::ScAddSignature( DWORD dwSignatureIn ) throw()
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
DWORD sc = ERROR_SUCCESS;
|
|
|
|
// Is the capacity of the array reached?
|
|
if ( m_nSignatureCount == m_nSignatureArraySize )
|
|
{
|
|
// Increase the array size by a random amount.
|
|
const int nGrowSize = 256;
|
|
|
|
TraceFlow2( "Signature count has reached array size ( %d ). Growing array by %d.", m_nSignatureArraySize, nGrowSize );
|
|
|
|
m_nSignatureArraySize += nGrowSize;
|
|
|
|
// Grow the array.
|
|
DWORD * pdwNewArray = new DWORD[ m_nSignatureArraySize ];
|
|
|
|
if ( pdwNewArray == NULL )
|
|
{
|
|
LogMsg( "[BC] Memory allocation failed trying to allocate %d DWORDs for signatures.", m_nSignatureArraySize );
|
|
sc = TW32( ERROR_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
} // if: memory allocation failed
|
|
|
|
// Copy the old array into the new one.
|
|
CopyMemory( pdwNewArray, m_rgdwSignatureArray.PMem(), m_nSignatureCount * sizeof( DWORD ) );
|
|
|
|
// Free the old array and store the new one.
|
|
m_rgdwSignatureArray.Assign( pdwNewArray );
|
|
|
|
} // if: the array capacity has been reached
|
|
|
|
// Store the new signature in next array location
|
|
( m_rgdwSignatureArray.PMem() )[ m_nSignatureCount ] = dwSignatureIn;
|
|
|
|
++m_nSignatureCount;
|
|
|
|
TraceFlow2( "Signature %#08X added to array. There are now %d signature in the array.", dwSignatureIn, m_nSignatureCount );
|
|
|
|
Cleanup:
|
|
|
|
W32RETURN( sc );
|
|
|
|
} //*** CClusDiskJoin::ScAddSignature
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// static
|
|
// CClusDiskJoin::S_ScResourceEnumCallback
|
|
//
|
|
// Description:
|
|
// This function is called back for every physical disk resouce by
|
|
// ResUtilEnumResourcesEx() as a part of enumerating resources.
|
|
// This function gets the signature of the current physical disk
|
|
// resource and stores it in the object that initiated the enumeration
|
|
// ( the pointer to the object is in parameter 4 ).
|
|
//
|
|
// Arguments:
|
|
// hClusterIn
|
|
// Handle to the cluster whose resources are being enumerated.
|
|
//
|
|
// hSelfIn
|
|
// hSelfIn passed to ResUtilEnumResourcesEx(), if any.
|
|
//
|
|
// hCurrentResourceIn
|
|
// Handle to the current resource.
|
|
//
|
|
// pvParamIn
|
|
// Pointer to the object of this class that initiated this enumeration.
|
|
//
|
|
// Return Value:
|
|
// ERROR_SUCCESS
|
|
// If everything was ok.
|
|
//
|
|
// Other Win32 error codes on failure.
|
|
// Returning an error code will terminate the enumeration.
|
|
//
|
|
// Exceptions Thrown:
|
|
// None. This function is called from a callback routine and therefore
|
|
// cannot throw any exceptions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
DWORD
|
|
CClusDiskJoin::S_ScResourceEnumCallback(
|
|
HCLUSTER hClusterIn
|
|
, HRESOURCE hSelfIn
|
|
, HRESOURCE hCurrentResourceIn
|
|
, PVOID pvParamIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
DWORD sc = ERROR_SUCCESS;
|
|
CClusDiskJoin * pcdjThisObject = reinterpret_cast< CClusDiskJoin * >( pvParamIn );
|
|
|
|
//
|
|
// Get the 'Signature' private property of this physical disk.
|
|
//
|
|
|
|
SmartByteArray sbaPropertyBuffer;
|
|
DWORD dwBytesReturned = 0;
|
|
DWORD dwBufferSize;
|
|
DWORD dwSignature = 0;
|
|
|
|
LogMsg( "[BC] Trying to get the signature of the disk resource whose handle is %p.", hCurrentResourceIn );
|
|
|
|
// Get the size of the buffer required to hold all the private properties of this resource.
|
|
sc = ClusterResourceControl(
|
|
hCurrentResourceIn
|
|
, NULL
|
|
, CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES
|
|
, NULL
|
|
, 0
|
|
, NULL
|
|
, 0
|
|
, &dwBytesReturned
|
|
);
|
|
|
|
if ( ( sc != ERROR_MORE_DATA ) && ( sc != ERROR_SUCCESS ) )
|
|
{
|
|
// Something went wrong.
|
|
TW32( sc );
|
|
LogMsg( "[BC] Error %#08x getting size of required buffer for private properties.", sc );
|
|
goto Cleanup;
|
|
} // if: the return value of ClusterResourceControl() was not ERROR_MORE_DATA
|
|
|
|
dwBufferSize = dwBytesReturned;
|
|
|
|
// Allocate the memory required for the property buffer.
|
|
sbaPropertyBuffer.Assign( new BYTE[ dwBufferSize ] );
|
|
if ( sbaPropertyBuffer.FIsEmpty() )
|
|
{
|
|
LogMsg( "[BC] Memory allocation failed trying to allocate %d bytes.", dwBufferSize );
|
|
sc = TW32( ERROR_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
} // if: memory allocation failed
|
|
|
|
|
|
// Get the all the private properties of this resource.
|
|
sc = TW32( ClusterResourceControl(
|
|
hCurrentResourceIn
|
|
, NULL
|
|
, CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES
|
|
, NULL
|
|
, 0
|
|
, sbaPropertyBuffer.PMem()
|
|
, dwBufferSize
|
|
, &dwBytesReturned
|
|
) );
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x getting private properties.", sc );
|
|
goto Cleanup;
|
|
} // if: an error occurring trying to get the private properties.
|
|
|
|
// Get the signature of this disk resource.
|
|
sc = TW32( ResUtilFindDwordProperty(
|
|
sbaPropertyBuffer.PMem()
|
|
, dwBufferSize
|
|
, PHYSICAL_DISK_SIGNATURE_PRIVPROP_NAME
|
|
, &dwSignature
|
|
) );
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying to get the value of the '%ws' property from the private property list.", sc, PHYSICAL_DISK_SIGNATURE_PRIVPROP_NAME );
|
|
goto Cleanup;
|
|
} // if: we could not get the signature
|
|
|
|
sc = TW32( pcdjThisObject->ScAddSignature( dwSignature ) );
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC] Error %#08x occurred trying to add the signature to the signature array." );
|
|
goto Cleanup;
|
|
} // if: we could not store the signature
|
|
|
|
Cleanup:
|
|
|
|
W32RETURN( sc );
|
|
|
|
} //*** CClusDiskJoin::S_ScResourceEnumCallback
|