Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1597 lines
34 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2001 Microsoft Corporation
//
// Module Name:
// ClusterUtils.h
//
// Description:
// This file contains the implementations of the ClusterUtils
// functions.
//
//
// Documentation:
//
// Maintained By:
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include <clusrtl.h>
#include "CBaseInfo.h"
#include "CBasePropList.h"
#include "ClusterUtils.h"
#define STACK_ARRAY_SIZE 256
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrSeparateDomainAndName()
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrSeparateDomainAndName(
BSTR bstrNameIn,
BSTR * pbstrDomainOut,
BSTR * pbstrNameOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
WCHAR * psz = NULL;
if ( bstrNameIn == NULL )
{
hr = THR( E_INVALIDARG );
goto Exit;
} // if:
psz = wcschr( bstrNameIn, L'.' );
if ( psz == NULL )
{
hr = THR( E_INVALIDARG );
goto Exit;
} // if:
if ( pbstrDomainOut != NULL )
{
psz++; // skip the .
*pbstrDomainOut = TraceSysAllocString( psz );
if ( *pbstrDomainOut == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Exit;
} // if:
psz--; // reset back to .
} // if:
if ( pbstrNameOut != NULL )
{
*pbstrNameOut = TraceSysAllocStringLen( NULL, (UINT)( psz - bstrNameIn ) );
if ( *pbstrNameOut == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Exit;
} // if:
wcsncpy( *pbstrNameOut, bstrNameIn, ( psz - bstrNameIn) );
} // if:
Exit:
HRETURN ( hr );
} //*** HrSeparateDomainAndName()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrAppendDomainToName()
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
// S_OK = TRUE
// S_FALSE = FALSE
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrAppendDomainToName(
BSTR bstrNameIn,
BSTR bstrDomainIn,
BSTR * pbstrDomainNameOut
)
{
TraceFunc( "" );
Assert( bstrNameIn != NULL );
Assert( pbstrDomainNameOut != NULL );
HRESULT hr = S_OK;
size_t cchName = 0;
if ( pbstrDomainNameOut == NULL )
{
hr = THR( E_POINTER );
goto Exit;
} // if:
if ( bstrNameIn == NULL )
{
hr = THR( E_INVALIDARG );
goto Exit;
} // if:
// Create a fully qualified node name
if ( bstrDomainIn != NULL )
{
cchName = wcslen( bstrNameIn ) + wcslen( bstrDomainIn ) + 1;
Assert( cchName <= MAXDWORD );
*pbstrDomainNameOut = TraceSysAllocStringLen( NULL, (UINT) cchName );
if ( *pbstrDomainNameOut == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Exit;
} // if:
wcscpy( *pbstrDomainNameOut, bstrNameIn );
wcscat( *pbstrDomainNameOut, L"." );
wcscat( *pbstrDomainNameOut, bstrDomainIn );
hr = S_OK;
} // if:
else
{
*pbstrDomainNameOut = TraceSysAllocString( bstrNameIn );
if ( *pbstrDomainNameOut == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Exit;
} // if:
hr = S_FALSE;
} // else:
Exit:
HRETURN( hr );
} //*** HrAppendDomainToName()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrIsCoreResource()
//
// Description:
// Determines whether the resource is a core resource.
//
// Arguments:
//
//
// Return Value:
// S_OK = TRUE
// S_FALSE = FALSE
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrIsCoreResource( HRESOURCE hResIn )
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
DWORD sc;
DWORD dwFlags = 0;
DWORD cb;
sc = TW32( ClusterResourceControl( hResIn, NULL, CLUSCTL_RESOURCE_GET_FLAGS, NULL, 0, &dwFlags, sizeof( dwFlags ), &cb ) );
if ( sc != ERROR_SUCCESS )
{
hr = HRESULT_FROM_WIN32( sc );
goto Exit;
} // if:
if ( dwFlags & CLUS_FLAG_CORE )
{
hr = S_OK;
} // if:
Exit:
HRETURN( hr );
} //*** HrIsCoreResource()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrIsResourceOfType()
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
// S_OK = TRUE
// S_FALSE = FALSE
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrIsResourceOfType(
HRESOURCE hResIn,
const WCHAR * pszResourceTypeIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
WCHAR * psz = NULL;
DWORD cbpsz = 33;
DWORD cb;
int idx;
psz = new WCHAR [ cbpsz * sizeof( WCHAR ) ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
for ( idx = 0; ; idx++ )
{
Assert( idx < 2 );
sc = ClusterResourceControl( hResIn, NULL, CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, NULL, 0, psz, cbpsz, &cb );
if ( sc == ERROR_MORE_DATA )
{
delete [] psz;
psz = NULL;
cbpsz = cb + 1;
psz = new WCHAR [ cbpsz * sizeof( WCHAR ) ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
continue;
} // if:
if ( sc != ERROR_SUCCESS )
{
hr = HRESULT_FROM_WIN32( TW32( sc ) );
goto CleanUp;
} // if:
break;
} // for:
if ( wcscmp( psz, pszResourceTypeIn ) == 0 )
{
hr = S_OK;
} // if:
else
{
hr = S_FALSE;
} // else:
goto CleanUp;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
CleanUp:
delete [] psz;
HRETURN( hr );
} //*** HrIsResourceOfType()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrGetIPAddressInfo()
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
//
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetIPAddressInfo( HRESOURCE hResIn, ULONG * pulIPAddress, ULONG * pulSubnetMask, BSTR * pbstrNetworkName )
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
CBasePropList cpl;
CBaseClusterResourceInfo cbri;
CLUSPROP_BUFFER_HELPER cpbh;
cbri.m_hResource = hResIn;
sc = TW32( cpl.ScGetProperties( cbri, cbri.ToCode( CONTROL_GET_PRIVATE_PROPERTIES ) ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
sc = TW32( cpl.ScMoveToPropertyByName( L"Address" ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
cpbh = cpl.CbhCurrentValue();
Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
sc = ClRtlTcpipStringToAddress( cpbh.pStringValue->sz, pulIPAddress );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
sc = TW32( cpl.ScMoveToPropertyByName( L"SubnetMask" ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
cpbh = cpl.CbhCurrentValue();
Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
sc = ClRtlTcpipStringToAddress( cpbh.pStringValue->sz, pulSubnetMask );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
if( pbstrNetworkName )
{
sc = TW32( cpl.ScMoveToPropertyByName( L"Network" ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
cpbh = cpl.CbhCurrentValue();
Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
*pbstrNetworkName = TraceSysAllocString( cpbh.pStringValue->sz );
if( *pbstrNetworkName == NULL )
{
hr = E_OUTOFMEMORY;
goto CleanUp;
}
}
goto CleanUp;
MakeHr:
hr = HRESULT_FROM_WIN32( sc );
CleanUp:
cbri.m_hResource = NULL;
HRETURN( hr );
} //*** HrGetIPAddressInfo()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrLoadCredentials()
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
//
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrLoadCredentials( BSTR bstrMachine, IClusCfgSetCredentials * piCCSC )
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
SC_HANDLE schSCM = NULL;
SC_HANDLE schClusSvc = NULL;
DWORD sc;
DWORD cbpqsc = 128;
DWORD cbRequired;
QUERY_SERVICE_CONFIG * pqsc = NULL;
schSCM = OpenSCManager( bstrMachine, NULL, GENERIC_READ );
if ( schSCM == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( hr );
goto CleanUp;
} // if:
schClusSvc = OpenService( schSCM, L"ClusSvc", GENERIC_READ );
if ( schClusSvc == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( hr );
goto CleanUp;
} // if:
for ( ; ; )
{
pqsc = (QUERY_SERVICE_CONFIG *) TraceAlloc( 0, cbpqsc );
if ( pqsc == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto CleanUp;
} // if:
if ( !QueryServiceConfig( schClusSvc, pqsc, cbpqsc, &cbRequired ) )
{
sc = GetLastError();
if ( sc == ERROR_INSUFFICIENT_BUFFER )
{
TraceFree( pqsc );
pqsc = NULL;
cbpqsc = cbRequired;
continue;
} // if:
else
{
TW32( sc );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // else:
} // if:
else
{
break;
} // else:
} // for:
hr = THR( piCCSC->SetDomainCredentials( pqsc->lpServiceStartName ) );
CleanUp:
if ( schClusSvc != NULL )
{
CloseServiceHandle( schClusSvc );
} // if:
if ( schSCM != NULL )
{
CloseServiceHandle( schSCM );
} // if:
if ( pqsc != NULL )
{
TraceFree( pqsc );
} // if:
HRETURN( hr );
} //*** HrLoadCredentials()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HRESULT
// HrGetNodeNameHostingResource(
// HCLUSTER hCluster,
// HRESOURCE hRes,
// BSTR * pbstrNameOut
// )
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetNodeNameHostingResource(
HCLUSTER hClusterIn,
HRESOURCE hResIn,
BSTR * pbstrNameOut
)
{
TraceFunc( "" );
WCHAR pszNodeBuffer[STACK_ARRAY_SIZE];
WCHAR pszGroupBuffer[STACK_ARRAY_SIZE];
DWORD sc;
HRESULT hr = S_OK;
BSTR bstrGroupName = NULL;
BSTR bstrNodeName = NULL;
DWORD dwNodeNameLen;
DWORD dwGroupNameLen;
HGROUP hGroup = NULL;
Assert( hClusterIn != NULL );
// Get the name and the group of the cluster.
dwNodeNameLen = STACK_ARRAY_SIZE;
dwGroupNameLen = STACK_ARRAY_SIZE;
sc = GetClusterResourceState( hResIn, pszNodeBuffer, &dwNodeNameLen, pszGroupBuffer, &dwGroupNameLen );
// Check to see if they were available and fit into the memory we allocated.
if( dwNodeNameLen == 0 && dwGroupNameLen == 0)
{
hr = E_FAIL;
goto Cleanup;
}
if ( dwNodeNameLen != 0 && dwNodeNameLen < STACK_ARRAY_SIZE )
{
bstrNodeName = TraceSysAllocString( pszNodeBuffer );
if( bstrNodeName == NULL)
goto OutOfMemory;
goto Success;
}
if ( dwGroupNameLen != 0 && dwGroupNameLen < STACK_ARRAY_SIZE )
{
bstrGroupName = TraceSysAllocString( pszGroupBuffer );
if( bstrGroupName == NULL)
goto OutOfMemory;
}
// Allocate memory and try again.
if( bstrNodeName == NULL )
{
bstrNodeName = TraceSysAllocStringByteLen( NULL, sizeof(WCHAR) * ( dwNodeNameLen + 2 ) );
if( bstrNodeName == NULL)
goto OutOfMemory;
}
if( bstrGroupName == NULL )
{
bstrGroupName = TraceSysAllocStringByteLen( NULL, sizeof(WCHAR) * ( dwGroupNameLen + 2 ) );
if( bstrGroupName == NULL)
goto OutOfMemory;
}
//
// Retrieve a second time.
//
dwNodeNameLen = SysStringLen( bstrNodeName );
dwGroupNameLen = SysStringLen( bstrGroupName );
sc = GetClusterResourceState( hResIn, pszNodeBuffer, &dwNodeNameLen, pszGroupBuffer, &dwGroupNameLen );
if( dwNodeNameLen != 0 )
goto Success;
if( dwGroupNameLen == 0 )
goto Cleanup;
//
// If we don't have the name yet, we have to look up the
// group name and figure out where it lives.
//
hGroup = OpenClusterGroup( hClusterIn, bstrGroupName );
if( hGroup == NULL )
goto Win32Error;
dwNodeNameLen = STACK_ARRAY_SIZE;
sc = GetClusterGroupState( hGroup, pszNodeBuffer, &dwNodeNameLen );
if( dwNodeNameLen == 0 )
{
if( sc == ClusterGroupStateUnknown )
goto Win32Error;
hr = E_FAIL;
goto Cleanup;
}
else if( dwNodeNameLen < STACK_ARRAY_SIZE )
{
bstrNodeName = TraceSysAllocString( pszNodeBuffer );
if( bstrNodeName == NULL)
goto OutOfMemory;
}
else
{
bstrNodeName = TraceSysAllocStringByteLen( NULL, sizeof(WCHAR) * ( dwNodeNameLen + 2 ) );
dwNodeNameLen = SysStringLen( bstrNodeName );
if( bstrNodeName == NULL)
goto OutOfMemory;
sc = GetClusterGroupState( hGroup, bstrNodeName, &dwNodeNameLen );
if( dwNodeNameLen == 0 )
{
if( sc == ClusterGroupStateUnknown )
goto Win32Error;
hr = E_FAIL;
goto Cleanup;
}
}
Success:
hr = S_OK;
*pbstrNameOut = bstrNodeName;
bstrNodeName = NULL;
Cleanup:
if( hGroup != NULL )
{
CloseClusterGroup( hGroup );
}
if( bstrGroupName )
{
TraceSysFreeString( bstrGroupName );
}
if( bstrNodeName )
{
TraceSysFreeString( bstrNodeName );
}
HRETURN( hr );
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
Win32Error:
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Cleanup;
} //*** HrGetNodeNameHostingResource()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HRESULT
// HrGetDependentIPAddressInfo(
// HCLUSTER hClusterIn,
// ULONG * pulIPAddress,
// ULONG * pulSubnetMask
// )
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetDependentIPAddressInfo(
HCLUSTER hClusterIn,
HRESOURCE hResIn,
ULONG * pulIPAddress,
ULONG * pulSubnetMask,
BSTR * pbstrNetworkName
)
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
DWORD sc;
HRESENUM hEnum = NULL;
DWORD idx;
WCHAR * psz = NULL;
DWORD cchpsz = 33;
DWORD dwType;
HRESOURCE hRes = NULL;
hEnum = ClusterResourceOpenEnum( hResIn, CLUSTER_RESOURCE_ENUM_DEPENDS );
if ( hEnum == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // if:
psz = new WCHAR [ cchpsz ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
for ( idx = 0; ; )
{
sc = TW32( ClusterResourceEnum( hEnum, idx, &dwType, psz, &cchpsz ) );
if ( sc == ERROR_NO_MORE_ITEMS )
{
break;
} // if:
if ( sc == ERROR_MORE_DATA )
{
delete [] psz;
psz = NULL;
cchpsz++;
psz = new WCHAR [ cchpsz ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
continue;
} // if:
if ( sc == ERROR_SUCCESS )
{
hRes = OpenClusterResource( hClusterIn, psz );
if ( hRes == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // if:
hr = THR( HrIsResourceOfType( hRes, L"IP Address" ) );
if ( SUCCEEDED( hr ) )
{
hr = THR( HrGetIPAddressInfo( hRes, pulIPAddress, pulSubnetMask, pbstrNetworkName ) ); // not recursive!
goto CleanUp;
} // if:
CloseClusterResource( hRes );
hRes = NULL;
idx++;
continue;
} // if:
hr = THR( HRESULT_FROM_WIN32( sc ) ); // must be an error!
goto CleanUp;
} // for:
goto CleanUp;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
CleanUp:
delete [] psz;
if ( hRes != NULL )
{
CloseClusterResource( hRes );
} // if:
if ( hEnum != NULL )
{
ClusterResourceCloseEnum( hEnum );
} // if:
HRETURN( hr );
} //*** HrGetDependentIPAddressInfo()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HRESULT
// HrGetIPAddressOfCluster(
// HCLUSTER hClusterIn,
// ULONG * pulIPAddress,
// ULONG * pulSubnetMask
// )
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetIPAddressOfCluster( HCLUSTER hClusterIn, ULONG * pulIPAddress, ULONG * pulSubnetMask, BSTR * pbstrNetworkName )
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
HCLUSENUM hEnum = NULL;
DWORD idx;
DWORD dwType;
WCHAR * psz = NULL;
DWORD cchpsz = 33;
HRESOURCE hRes = NULL;
hEnum = ClusterOpenEnum( hClusterIn, CLUSTER_ENUM_RESOURCE );
if ( hEnum == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // if:
psz = new WCHAR [ cchpsz ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
for ( idx = 0; ; )
{
sc = ClusterEnum( hEnum, idx, &dwType, psz, &cchpsz );
if ( sc == ERROR_MORE_DATA )
{
delete [] psz;
psz = NULL;
cchpsz++;
psz = new WCHAR [ cchpsz ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
continue;
} // if:
if ( sc == ERROR_SUCCESS )
{
hRes = OpenClusterResource( hClusterIn, psz );
if ( hRes == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // if:
hr = STHR( HrIsResourceOfType( hRes, L"Network Name" ) );
if ( FAILED( hr ) )
{
break;
} // if:
if ( hr == S_OK )
{
hr = STHR( HrIsCoreResource( hRes ) );
if ( FAILED( hr ) )
{
break;
} // if:
if ( hr == S_OK )
{
hr = THR( HrGetDependentIPAddressInfo( hClusterIn, hRes, pulIPAddress, pulSubnetMask, pbstrNetworkName ) );
if ( FAILED( hr ) )
{
break;
} // if:
} // if:
} // if:
CloseClusterResource( hRes );
hRes = NULL;
idx++;
continue;
} // if:
if ( sc == ERROR_NO_MORE_ITEMS )
{
hr = S_OK;
break;
} // if:
TW32( sc );
hr = HRESULT_FROM_WIN32( sc );
break;
} // for:
goto CleanUp;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
CleanUp:
delete [] psz;
if ( hRes != NULL )
{
CloseClusterResource( hRes );
} // if:
if ( hEnum != NULL )
{
ClusterCloseEnum( hEnum );
} // if:
HRETURN( hr );
} //*** HrGetIPAddressOfCluster()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrGetNodeNameHostingCluster()
//
// Description:
// Get the name of the node hosting the cluster service...
//
// Arguments:
//
//
// Return Value:
//
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetNodeNameHostingCluster( HCLUSTER hClusterIn, BSTR * pbstrNodeName )
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
HCLUSENUM hEnum = NULL;
DWORD idx;
DWORD dwType;
WCHAR * psz = NULL;
DWORD cchpsz = 33;
HRESOURCE hRes = NULL;
hEnum = ClusterOpenEnum( hClusterIn, CLUSTER_ENUM_RESOURCE );
if ( hEnum == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // if:
psz = new WCHAR [ cchpsz ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
for ( idx = 0; ; )
{
sc = ClusterEnum( hEnum, idx, &dwType, psz, &cchpsz );
if ( sc == ERROR_MORE_DATA )
{
delete [] psz;
psz = NULL;
cchpsz++;
psz = new WCHAR [ cchpsz ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
continue;
} // if:
if ( sc == ERROR_SUCCESS )
{
hRes = OpenClusterResource( hClusterIn, psz );
if ( hRes == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto CleanUp;
} // if:
hr = STHR( HrIsResourceOfType( hRes, L"Network Name" ) );
if ( FAILED( hr ) )
{
break;
} // if:
if ( hr == S_OK )
{
hr = THR( HrIsCoreResource( hRes ) );
if ( FAILED( hr ) )
{
break;
} // if:
if ( hr == S_OK )
{
hr = THR( HrGetNodeNameHostingResource( hClusterIn, hRes, pbstrNodeName ) );
if ( FAILED( hr ) )
{
break;
} // if:
else if( hr == S_OK )
{
goto CleanUp;
}
} // if:
} // if:
CloseClusterResource( hRes );
hRes = NULL;
idx++;
continue;
} // if:
if ( sc == ERROR_NO_MORE_ITEMS )
{
hr = S_OK;
break;
} // if:
TW32( sc );
hr = HRESULT_FROM_WIN32( sc );
break;
} // for:
goto CleanUp;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
CleanUp:
delete [] psz;
if ( hRes != NULL )
{
CloseClusterResource( hRes );
} // if:
if ( hEnum != NULL )
{
ClusterCloseEnum( hEnum );
} // if:
HRETURN( hr );
} //*** HrGetNodeNameHostingCluster()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrGetSCSIInfo()
//
// Description:
// Get the name of the node hosting the cluster service...
//
// Arguments:
//
//
// Return Value:
//
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetSCSIInfo(
HRESOURCE hResIn,
CLUS_SCSI_ADDRESS * pCSAOut,
DWORD * pdwSignatureOut,
DWORD * pdwDiskNumberOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
CBasePropValueList cpvl;
CBaseClusterResourceInfo cbri;
CLUSPROP_BUFFER_HELPER cpbh;
cbri.m_hResource = hResIn;
sc = TW32( cpvl.ScGetValueList( cbri, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
// loop through all the properties.
sc = cpvl.ScMoveToFirstValue();
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
do
{
if( sc != ERROR_SUCCESS )
goto MakeHr;
cpbh = cpvl;
switch ( cpbh.pSyntax->dw )
{
case CLUSPROP_SYNTAX_PARTITION_INFO :
{
break;
} // case: CLUSPROP_SYNTAX_PARTITION_INFO
case CLUSPROP_SYNTAX_DISK_SIGNATURE :
{
*pdwSignatureOut = cpbh.pDiskSignatureValue->dw;
break;
} // case: CLUSPROP_SYNTAX_DISK_SIGNATURE
case CLUSPROP_SYNTAX_SCSI_ADDRESS :
{
pCSAOut->dw = cpbh.pScsiAddressValue->dw;
break;
} // case: CLUSPROP_SYNTAX_SCSI_ADDRESS
case CLUSPROP_SYNTAX_DISK_NUMBER :
{
*pdwDiskNumberOut = cpbh.pDiskNumberValue->dw;
break;
} // case:
} // switch:
// Move to the next item.
sc = cpvl.ScCheckIfAtLastValue();
if( sc == ERROR_NO_MORE_ITEMS )
break;
sc = cpvl.ScMoveToNextValue();
} while( sc == ERROR_SUCCESS );
hr = S_OK;
Cleanup:
cbri.m_hResource = NULL;
HRETURN( hr );
MakeHr:
sc = GetLastError();
hr = HRESULT_FROM_WIN32( sc );
goto Cleanup;
} //*** HrGetSCSIInfo()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HrGetClusterInformation()
//
// Description:
// Get the cluster information. This includes the name and the version
// info.
//
// Arguments:
//
//
// Return Value:
//
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetClusterInformation(
HCLUSTER hClusterIn,
BSTR * pbstrClusterNameOut,
CLUSTERVERSIONINFO * pcviOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
WCHAR * psz = NULL;
DWORD cch = 33;
CLUSTERVERSIONINFO cvi;
if ( pbstrClusterNameOut == NULL )
{
goto Pointer;
} // if:
cvi.dwVersionInfoSize = sizeof( cvi );
if ( pcviOut == NULL )
{
pcviOut = &cvi;
} // if:
psz = new WCHAR[ cch ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
sc = GetClusterInformation( hClusterIn, psz, &cch, pcviOut );
if ( sc == ERROR_MORE_DATA )
{
delete [] psz;
psz = NULL;
psz = new WCHAR[ ++cch ];
if ( psz == NULL )
{
goto OutOfMemory;
} // if:
sc = GetClusterInformation( hClusterIn, psz, &cch, pcviOut );
} // if:
if ( sc != ERROR_SUCCESS )
{
hr = THR( HRESULT_FROM_WIN32( sc ) );
LogMsg( __FUNCTION__ ": GetClusterInformation() failed (hr = 0x%08x).", hr );
goto Cleanup;
} // if:
*pbstrClusterNameOut = TraceSysAllocString( psz );
if ( *pbstrClusterNameOut == NULL )
{
goto OutOfMemory;
} // if:
goto Cleanup;
Pointer:
hr = THR( E_POINTER );
goto Cleanup;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
Cleanup:
delete [] psz;
HRETURN( hr );
} //*** HrGetClusterInformation()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrGetClusterResourceState
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetClusterResourceState(
HRESOURCE hResourceIn
, BSTR * pbstrNodeNameOut
, BSTR * pbstrGroupNameOut
, CLUSTER_RESOURCE_STATE * pcrsStateOut
)
{
TraceFunc( "" );
Assert( hResourceIn != NULL );
HRESULT hr = S_OK;
CLUSTER_RESOURCE_STATE crsState = ClusterResourceStateUnknown;
WCHAR * pszNodeName = NULL;
DWORD cchNodeName = 33;
WCHAR * pszGroupName = NULL;
DWORD cchGroupName = 33;
pszNodeName = new WCHAR[ cchNodeName ];
if ( pszNodeName == NULL )
{
goto OutOfMemory;
} // if:
pszGroupName = new WCHAR[ cchGroupName ];
if ( pszGroupName == NULL )
{
goto OutOfMemory;
} // if:
crsState = GetClusterResourceState( hResourceIn, pszNodeName, &cchNodeName, pszGroupName, &cchGroupName );
if ( GetLastError() == ERROR_MORE_DATA )
{
crsState = ClusterResourceStateUnknown; // reset to error condition
delete [] pszNodeName;
pszNodeName = NULL;
cchNodeName++;
delete [] pszGroupName;
pszGroupName = NULL;
cchGroupName++;
pszNodeName = new WCHAR[ cchNodeName ];
if ( pszNodeName == NULL )
{
goto OutOfMemory;
} // if:
pszGroupName = new WCHAR[ cchGroupName ];
if ( pszGroupName == NULL )
{
goto OutOfMemory;
} // if:
crsState = GetClusterResourceState( hResourceIn, pszNodeName, &cchNodeName, pszGroupName, &cchGroupName );
if ( crsState == ClusterResourceStateUnknown )
{
DWORD sc;
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto Cleanup;
} // if:
} // if: more data
if ( pbstrNodeNameOut != NULL )
{
*pbstrNodeNameOut = TraceSysAllocString( pszNodeName );
if ( *pbstrNodeNameOut == NULL )
{
goto OutOfMemory;
} // if:
} // if:
if ( pbstrGroupNameOut != NULL )
{
*pbstrGroupNameOut = TraceSysAllocString( pszGroupName );
if ( *pbstrGroupNameOut == NULL )
{
goto OutOfMemory;
} // if:
} // if:
if ( pcrsStateOut != NULL )
{
*pcrsStateOut = crsState;
} // if:
goto Cleanup;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
Cleanup:
delete [] pszNodeName;
delete [] pszGroupName;
HRETURN( hr );
} //*** HrGetClusterResourceState
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrGetClusterQuorumResource()
//
// Description:
// Get the information about the quorum resource.
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success.
//
// Other HRESULT error codes.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrGetClusterQuorumResource(
HCLUSTER hClusterIn
, BSTR * pbstrResourceNameOut
, BSTR * pbstrDeviceNameOut
, DWORD * pdwMaxQuorumLogSizeOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
LPWSTR pszResourceName = NULL;
DWORD cchResourceName = 128;
DWORD cchTempResourceName = cchResourceName;
LPWSTR pszDeviceName = NULL;
DWORD cchDeviceName = 128;
DWORD cchTempDeviceName = cchDeviceName;
DWORD dwMaxQuorumLogSize = 0;
if ( hClusterIn == NULL )
{
hr = THR( E_INVALIDARG );
goto Cleanup;
} // if:
// Allocate the resource name buffer
pszResourceName = new WCHAR[ cchResourceName ];
if ( pszResourceName == NULL )
{
goto OutOfMemory;
} // if:
// Allocate the device name buffer
pszDeviceName = new WCHAR[ cchDeviceName ];
if ( pszDeviceName == NULL )
{
goto OutOfMemory;
} // if:
sc = GetClusterQuorumResource(
hClusterIn
, pszResourceName
, &cchTempResourceName
, pszDeviceName
, &cchTempDeviceName
, &dwMaxQuorumLogSize
);
if ( sc == ERROR_MORE_DATA )
{
delete [] pszResourceName;
pszResourceName = NULL;
cchResourceName = ++cchTempResourceName;
// Allocate the resource name buffer
pszResourceName = new WCHAR[ cchResourceName ];
if ( pszResourceName == NULL )
{
goto OutOfMemory;
} // if:
delete [] pszDeviceName;
pszDeviceName = NULL;
cchDeviceName = ++cchTempDeviceName;
// Allocate the device name buffer
pszDeviceName = new WCHAR[ cchDeviceName ];
if ( pszDeviceName == NULL )
{
goto OutOfMemory;
} // if:
sc = GetClusterQuorumResource(
hClusterIn
, pszResourceName
, &cchTempResourceName
, pszDeviceName
, &cchTempDeviceName
, &dwMaxQuorumLogSize
);
} // if:
if ( sc != ERROR_SUCCESS )
{
TW32( sc );
hr = HRESULT_FROM_WIN32( sc );
goto Cleanup;
} // if:
if ( pbstrResourceNameOut != NULL )
{
*pbstrResourceNameOut = TraceSysAllocString( pszResourceName );
if ( *pbstrResourceNameOut == NULL )
{
goto OutOfMemory;
} // if:
} // if:
if ( pbstrDeviceNameOut != NULL )
{
*pbstrDeviceNameOut = TraceSysAllocString( pszDeviceName );
if ( *pbstrDeviceNameOut == NULL )
{
goto OutOfMemory;
} // if:
} // if:
if ( pdwMaxQuorumLogSizeOut != NULL )
{
*pdwMaxQuorumLogSizeOut = dwMaxQuorumLogSize;
} // if:
goto Cleanup;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
Cleanup:
delete [] pszResourceName;
delete [] pszDeviceName;
HRETURN( hr );
} //*** HrGetClusterQuorumResource()