1598 lines
34 KiB
C++
1598 lines
34 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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()
|