windows-nt/Source/XPSP1/NT/base/cluster/admin/common/cluswrap.cpp
2020-09-26 16:20:57 +08:00

2376 lines
67 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c)1997-2001 Microsoft Corporation
//
// Module Name:
// ClusWrap.cpp
//
// Description:
// Wrapper functions for Cluster APIs.
//
// Author:
// Galen Barbee (galenb) 15-Aug-1998
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <clusapi.h>
#include "cluswrap.h"
/////////////////////////////////////////////////////////////////////////////
// Type Definitions
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterInformation
//
// Description:
// Wraps the GetClusterInformation function.
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapGetClusterInformation(
IN HCLUSTER hCluster,
OUT LPWSTR * ppszClusterName,
OUT OPTIONAL LPCLUSTERVERSIONINFO pClusterInfo
)
{
DWORD dwStatus;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameter.
if ( ppszClusterName != NULL )
{
*ppszClusterName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = GetClusterInformation( hCluster, pwszName, &cchTempName, pClusterInfo );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = GetClusterInformation( hCluster, pwszName, &cchTempName, pClusterInfo );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppszClusterName != NULL ) )
{
*ppszClusterName = pwszName;
}
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppszClusterName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapGetClusterInformation()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterQuorumResource
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapGetClusterQuorumResource(
IN HCLUSTER hCluster,
OUT LPWSTR * ppwszResourceName,
OUT LPWSTR * ppwszDeviceName,
OUT LPDWORD pdwMaxQuorumLogSize
)
{
DWORD dwStatus;
LPWSTR pwszResourceName = NULL;
DWORD cchResourceName = 128;
DWORD cchTempResourceName = cchResourceName;
LPWSTR pwszDeviceName = NULL;
DWORD cchDeviceName = 128;
DWORD cchTempDeviceName = cchDeviceName;
DWORD dwMaxQuorumLogSize = 0;
// Zero the out parameters
if ( ppwszResourceName != NULL )
{
*ppwszResourceName = NULL;
}
if ( ppwszDeviceName != NULL )
{
*ppwszDeviceName = NULL;
}
if ( pdwMaxQuorumLogSize != NULL )
{
*pdwMaxQuorumLogSize = 0;
}
// Allocate the resource name buffer
pwszResourceName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchResourceName * sizeof( *pwszResourceName ) );
if ( pwszResourceName != NULL )
{
// Allocate the device name buffer
pwszDeviceName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchDeviceName * sizeof( *pwszDeviceName ) );
if ( pwszDeviceName != NULL )
{
dwStatus = GetClusterQuorumResource( hCluster,
pwszResourceName,
&cchTempResourceName,
pwszDeviceName,
&cchTempDeviceName,
&dwMaxQuorumLogSize );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszResourceName );
pwszResourceName = NULL;
cchResourceName = ++cchTempResourceName;
// Allocate the resource name buffer
pwszResourceName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchResourceName * sizeof( *pwszResourceName ) );
if ( pwszResourceName != NULL )
{
LocalFree( pwszDeviceName );
pwszDeviceName = NULL;
cchDeviceName = ++cchTempDeviceName;
// Allocate the device name buffer
pwszDeviceName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchDeviceName * sizeof( *pwszDeviceName ) );
if ( pwszDeviceName != NULL )
{
dwStatus = GetClusterQuorumResource( hCluster,
pwszResourceName,
&cchTempResourceName,
pwszDeviceName,
&cchTempDeviceName,
&dwMaxQuorumLogSize );
}
else
{
dwStatus = GetLastError();
}
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
}
else
{
dwStatus = GetLastError();
}
//
// if we succeeded and if the argument is not NULL then return it.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszResourceName != NULL ) )
{
*ppwszResourceName = pwszResourceName;
}
//
// if we succeeded and if the argument is not NULL then return it.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszDeviceName != NULL ) )
{
*ppwszDeviceName = pwszDeviceName;
}
//
// if we succeeded and if the argument is not NULL then return it.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwMaxQuorumLogSize != NULL ) )
{
*pdwMaxQuorumLogSize = dwMaxQuorumLogSize;
}
//
// if we didn't succeeded or if the string argument is NULL then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszResourceName == NULL ) )
{
LocalFree( pwszResourceName );
}
//
// if we didn't succeeded or if the string argument is NULL then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszDeviceName == NULL ) )
{
LocalFree( pwszDeviceName );
}
return dwStatus;
} //*** WrapGetClusterQuorumResource()
/////////////////////////////////////////////////////////////////////////////
//++
//
// Function: WrapClusterEnum
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapClusterEnum(
IN HCLUSENUM hEnum,
IN DWORD dwIndex,
OUT LPDWORD pdwType,
OUT LPWSTR * ppwszName
)
{
DWORD dwStatus;
DWORD dwType = 0;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameters
if ( pdwType != NULL )
{
*pdwType = 0;
}
if ( ppwszName != NULL )
{
*ppwszName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterEnum( hEnum, dwIndex, &dwType, pwszName, &cchTempName );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterEnum( hEnum, dwIndex, &dwType, pwszName, &cchTempName );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if we succeeded and if the argument is not NULL then return it.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwType != NULL ) )
{
*pdwType = dwType;
}
//
// if we succeeded and if the string argument is not NULL then return the string.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszName != NULL ) )
{
*ppwszName = pwszName;
}
//
// if we didn't succeeded or if the string argument is NULL then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapClusterEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterNodeId
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapGetClusterNodeId(
IN HNODE hNode,
OUT LPWSTR * ppwszNodeId
)
{
DWORD dwStatus;
LPWSTR pwszNodeId = NULL;
DWORD cchNodeId = 128;
DWORD cchTempNodeId = cchNodeId;
// Zero the out parameters
if ( ppwszNodeId != NULL )
{
*ppwszNodeId = NULL;
}
pwszNodeId = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchNodeId * sizeof( *pwszNodeId ) );
if ( pwszNodeId != NULL)
{
dwStatus = GetClusterNodeId( hNode, pwszNodeId, &cchTempNodeId );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszNodeId );
pwszNodeId = NULL;
cchNodeId = ++cchTempNodeId;
pwszNodeId = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchNodeId * sizeof( *pwszNodeId ) );
if ( pwszNodeId != NULL)
{
dwStatus = GetClusterNodeId( hNode, pwszNodeId, &cchTempNodeId );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if we succeeded and if the argument is not NULL then return it.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszNodeId != NULL ) )
{
*ppwszNodeId = pwszNodeId;
}
//
// if we didn't succeeded or if the string argument is NULL then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszNodeId == NULL ) )
{
LocalFree( pwszNodeId );
}
return dwStatus;
} //*** WrapGetClusterNodeId()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterGroupState
//
// Description:
// Wrapper function for GetClusterGroupState.
//
// Arguments:
// hGroup [IN] - The group handle.
// ppwszNodeName [OUT] - Catches the name of the node that the group
// is online, if not NULL.
//
// Return Value:
// A cluster group state enum.
//
//--
/////////////////////////////////////////////////////////////////////////////
CLUSTER_GROUP_STATE WINAPI WrapGetClusterGroupState(
IN HGROUP hGroup,
OUT OPTIONAL LPWSTR * ppwszNodeName // = NULL
)
{
CLUSTER_GROUP_STATE cState = ClusterGroupStateUnknown;
if ( ppwszNodeName == NULL )
{
// The caller is not interested in the node name.
// So, just call the actual function.
cState = GetClusterGroupState( hGroup, NULL, 0 );
} // if: the pointer to the node name pointer is not provided.
else
{
LPWSTR pwszNodeName = NULL;
DWORD cchNodeName = 128;
DWORD cchTempNodeName = cchNodeName;
// Zero the out parameters
*ppwszNodeName = NULL;
pwszNodeName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchNodeName * sizeof( *pwszNodeName ) );
if ( pwszNodeName != NULL )
{
cState = GetClusterGroupState( hGroup, pwszNodeName, &cchTempNodeName );
if ( GetLastError() == ERROR_MORE_DATA )
{
cState = ClusterGroupStateUnknown; // reset to error condition
LocalFree( pwszNodeName );
cchNodeName = ++cchTempNodeName;
pwszNodeName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchNodeName * sizeof( *pwszNodeName ) );
if ( pwszNodeName != NULL )
{
cState = GetClusterGroupState( hGroup, pwszNodeName, &cchTempNodeName );
}
}
}
//
// if there was not an error, then return the string.
//
if ( cState != ClusterGroupStateUnknown )
{
*ppwszNodeName = pwszNodeName;
}
else
{
LocalFree( pwszNodeName );
}
} // else: the pointer to the node name pointer is not NULL.
return cState;
} //*** WrapGetClusterGroupState()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapClusterGroupEnum
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapClusterGroupEnum(
IN HGROUPENUM hGroupEnum,
IN DWORD dwIndex,
OUT LPDWORD pdwType,
OUT LPWSTR * ppwszName
)
{
DWORD dwStatus;
DWORD dwType = 0;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameters
if ( pdwType != NULL )
{
*pdwType = NULL;
}
if ( ppwszName != NULL )
{
*ppwszName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterGroupEnum( hGroupEnum, dwIndex, &dwType, pwszName, &cchTempName );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterGroupEnum( hGroupEnum, dwIndex, &dwType, pwszName, &cchTempName );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if there was not an error and the argument was not NULL, then return the value.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwType != NULL ) )
{
*pdwType = dwType;
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszName != NULL ) )
{
*ppwszName = pwszName;
}
//
// if there was an error and the argument was NULL, then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapClusterGroupEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapClusterNetworkEnum
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapClusterNetworkEnum(
IN HNETWORKENUM hEnum,
IN DWORD dwIndex,
OUT LPDWORD pdwType,
OUT LPWSTR * ppwszName
)
{
DWORD dwStatus;
DWORD dwType = 0;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameters
if ( pdwType != NULL )
{
*pdwType = 0;
}
if ( ppwszName != NULL )
{
*ppwszName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterNetworkEnum( hEnum, dwIndex, &dwType, pwszName, &cchTempName );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterNetworkEnum( hEnum, dwIndex, &dwType, pwszName, &cchTempName );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if there was not an error and the argument was not NULL, then return the value.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwType != NULL ) )
{
*pdwType = dwType;
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszName != NULL ) )
{
*ppwszName = pwszName;
}
//
// if there was an error and the argument was NULL, then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapClusterNetworkEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapClusterNodeEnum
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapClusterNodeEnum(
IN HNODEENUM hEnum,
IN DWORD dwIndex,
OUT LPDWORD pdwType,
OUT LPWSTR * ppwszName
)
{
DWORD dwStatus;
DWORD dwType = 0;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameters
if ( pdwType != NULL )
{
*pdwType = 0;
}
if ( ppwszName != NULL )
{
*ppwszName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterNodeEnum( hEnum, dwIndex, &dwType, pwszName, &cchTempName );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterNodeEnum( hEnum, dwIndex, &dwType, pwszName, &cchTempName );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if there was not an error and the argument was not NULL, then return the value.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwType != NULL ) )
{
*pdwType = dwType;
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszName != NULL ) )
{
*ppwszName = pwszName;
}
//
// if there was an error and the argument was NULL, then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapClusterNodeEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterResourceState
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
CLUSTER_RESOURCE_STATE WINAPI WrapGetClusterResourceState(
IN HRESOURCE hResource,
OUT OPTIONAL LPWSTR * ppwszNodeName,
OUT OPTIONAL LPWSTR * ppwszGroupName
)
{
CLUSTER_RESOURCE_STATE cState = ClusterResourceStateUnknown;
LPWSTR pwszNodeName = NULL;
DWORD cchNodeName = 128;
LPWSTR pwszGroupName = NULL;
DWORD cchGroupName = 128;
DWORD cchTempNodeName = cchNodeName;
DWORD cchTempGroupName = cchGroupName;
// Zero the out parameters
if ( ppwszNodeName != NULL )
{
*ppwszNodeName = NULL;
}
if ( ppwszGroupName != NULL )
{
*ppwszGroupName = NULL;
}
pwszNodeName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchNodeName * sizeof( *pwszNodeName ) );
if ( pwszNodeName != NULL )
{
pwszGroupName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchGroupName * sizeof( *pwszGroupName ) );
if ( pwszGroupName != NULL )
{
cState = GetClusterResourceState( hResource, pwszNodeName, &cchTempNodeName, pwszGroupName, &cchTempGroupName );
if ( GetLastError() == ERROR_MORE_DATA )
{
cState = ClusterResourceStateUnknown; // reset to error condition
LocalFree( pwszNodeName );
pwszNodeName = NULL;
cchNodeName = ++cchTempNodeName;
LocalFree( pwszGroupName );
pwszGroupName = NULL;
cchGroupName = ++cchTempGroupName;
pwszNodeName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchNodeName * sizeof( *pwszNodeName ) );
if ( pwszNodeName != NULL )
{
pwszGroupName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchGroupName * sizeof( *pwszGroupName ) );
if ( pwszGroupName != NULL )
{
cState = GetClusterResourceState( hResource,
pwszNodeName,
&cchNodeName,
pwszGroupName,
&cchGroupName );
}
}
}
}
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( cState != ClusterResourceStateUnknown ) && ( ppwszNodeName != NULL ) )
{
*ppwszNodeName = pwszNodeName;
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( cState != ClusterResourceStateUnknown ) && ( ppwszGroupName != NULL ) )
{
*ppwszGroupName = pwszGroupName;
}
//
// if there was an error or the argument was NULL, then free the string.
//
if ( ( cState == ClusterResourceStateUnknown ) || ( ppwszNodeName == NULL ) )
{
LocalFree( pwszNodeName );
}
//
// if there was an error or the argument was NULL, then free the string.
//
if ( ( cState == ClusterResourceStateUnknown ) || ( ppwszGroupName == NULL ) )
{
LocalFree( pwszGroupName );
}
return cState;
} //*** WrapGetClusterResourceState()
/*
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterNetInterfaceState
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
CLUSTER_NETINTERFACE_STATE WINAPI WrapGetClusterNetInterfaceState(
IN HNETINTERFACE hNetInterface
)
{
return GetClusterNetInterfaceState( hNetInterface );
} //*** WrapGetClusterNetInterfaceState()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapGetClusterNetworkState
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
CLUSTER_NETWORK_STATE WINAPI WrapGetClusterNetworkState(
IN HNETWORK hNetwork
)
{
return GetClusterNetworkState( hNetwork );
} //*** WrapGetClusterNetworkState()
*/
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapClusterResourceEnum
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapClusterResourceEnum(
IN HRESENUM hResEnum,
IN DWORD dwIndex,
OUT LPDWORD pdwType,
OUT LPWSTR * ppwszName
)
{
DWORD dwStatus;
DWORD dwType = 0;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameters
if ( pdwType != NULL )
{
*pdwType = 0;
}
if ( ppwszName != NULL )
{
*ppwszName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pwszName, &cchTempName );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pwszName, &cchTempName );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if there was not an error and the argument was not NULL, then return the value.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwType != NULL ) )
{
*pdwType = dwType;
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszName != NULL ) )
{
*ppwszName = pwszName;
}
//
// if there was an error and the argument was NULL, then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapClusterResourceEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WrapClusterResourceTypeEnum
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WrapClusterResourceTypeEnum(
IN HRESTYPEENUM hResEnum,
IN DWORD dwIndex,
OUT LPDWORD pdwType,
OUT LPWSTR * ppwszName
)
{
DWORD dwStatus;
DWORD dwType = 0;
LPWSTR pwszName = NULL;
DWORD cchName = 128;
DWORD cchTempName = cchName;
// Zero the out parameters
if ( pdwType != NULL )
{
*pdwType = 0;
}
if ( ppwszName != NULL )
{
*ppwszName = NULL;
}
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterResourceTypeEnum( hResEnum, dwIndex, &dwType, pwszName, &cchTempName );
if ( dwStatus == ERROR_MORE_DATA )
{
LocalFree( pwszName );
pwszName = NULL;
cchName = ++cchTempName;
pwszName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, cchName * sizeof( *pwszName ) );
if ( pwszName != NULL )
{
dwStatus = ClusterResourceTypeEnum( hResEnum, dwIndex, &dwType, pwszName, &cchTempName );
}
else
{
dwStatus = GetLastError();
}
}
}
else
{
dwStatus = GetLastError();
}
//
// if there was not an error and the argument was not NULL, then return the value.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( pdwType != NULL ) )
{
*pdwType = dwType;
}
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( dwStatus == ERROR_SUCCESS ) && ( ppwszName != NULL ) )
{
*ppwszName = pwszName;
}
//
// if there was an error and the argument was NULL, then free the string.
//
if ( ( dwStatus != ERROR_SUCCESS ) || ( ppwszName == NULL ) )
{
LocalFree( pwszName );
}
return dwStatus;
} //*** WrapClusterResourceTypeEnum()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// Misc helper functions, etc.
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CClusterNotifyPort
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusterNotifyPort::CClusterNotifyPort
//
// Description: This class is a wrapper for the cluster notify port
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusterNotifyPort::CClusterNotifyPort( void )
{
m_dwNotifyKey = 0;
m_dwFilterType = 0;
m_szName = NULL;
m_cchName = 0;
m_hChange = NULL;
} //*** CClusterNotifyPort::CClusterNotifyPort()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusterNotifyPort::~CClusterNotifyPort
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusterNotifyPort::~CClusterNotifyPort( void )
{
if( NULL != m_szName )
{
delete [] m_szName;
}
Close();
} //*** CClusterNotifyPort::~CClusterNotifyPort()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusterNotifyPort::Create
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CClusterNotifyPort::Create(
HCHANGE hChange,
HCLUSTER hCluster,
DWORD dwFilter,
DWORD_PTR dwNotifyKey
)
{
DWORD sc = ERROR_SUCCESS;
m_hChange = CreateClusterNotifyPort( hChange, hCluster, dwFilter, dwNotifyKey );
if ( m_hChange == NULL )
{
sc = GetLastError();
}
return sc;
} //*** CClusterNotifyPort::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusterNotifyPort::Close
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CClusterNotifyPort::Close( void )
{
DWORD sc = ERROR_SUCCESS;
if ( m_hChange != NULL )
{
sc = CloseClusterNotifyPort( m_hChange );
}
return sc;
} //*** CClusterNotifyPort::Close()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusterNotifyPort::Register
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CClusterNotifyPort::Register(
DWORD dwFilterType,
HANDLE hObject,
DWORD_PTR dwNotifyKey
)
{
return RegisterClusterNotify( m_hChange, dwFilterType, hObject, dwNotifyKey );
} //*** CClusterNotifyPort::Register()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusterNotifyPort::GetNotify
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CClusterNotifyPort::GetNotify( void )
{
DWORD sc = ERROR_SUCCESS;
DWORD cchName;
cchName = m_cchName;
//
// Wait until state changes or 1 second elapses
//
sc = GetClusterNotify( m_hChange, &m_dwNotifyKey, &m_dwFilterType, m_szName, &cchName, 1000 );
//
// If we got an error_more_data or we passed in a NULL buffer pointer and got error_success
// then we have to resize our buffer. Member m_szName is initialized to NULL.
//
if ( sc == ERROR_MORE_DATA ||
( m_szName == NULL && sc == ERROR_SUCCESS ) )
{
//
// resize the buffer
//
delete [] m_szName;
cchName++; // add one for NULL
m_cchName = cchName;
m_szName = new WCHAR[ m_cchName ];
if ( m_szName == NULL )
{
sc = ERROR_NOT_ENOUGH_MEMORY;
} // if:
else
{
cchName = m_cchName;
sc = GetClusterNotify( m_hChange, &m_dwNotifyKey, &m_dwFilterType, m_szName, &cchName, 0 );
} // else:
} // if:
return sc;
} //*** CClusterNotifyPort::GetNotify()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WaitForResourceStateChange
//
// Description:
// Wait for the resource state to change to a non pending state.
//
// Arguments:
// hCluster [IN] - handle to the cluster
// pwszName [IN] - name of the resource to wait on
// pPort [IN] - notification port to use
// pnWait [IN OUT] - ~ number of seconds to wait
//
// Return Value:
// ERROR_SUCCESS or other Win32 error
//
//--
/////////////////////////////////////////////////////////////////////////////
static DWORD WaitForResourceStateChange(
IN HCLUSTER hCluster,
IN LPWSTR pwszName,
IN CClusterNotifyPort * pPort,
IN OUT DWORD * pnWait
)
{
CLUSTER_RESOURCE_STATE crs = ClusterResourceStateUnknown;
HRESOURCE hResource = NULL;
DWORD _sc = ERROR_SUCCESS;
if ( pnWait != NULL )
{
hResource = OpenClusterResource( hCluster, pwszName );
if ( hResource != NULL )
{
while ( *pnWait > 0 )
{
crs = WrapGetClusterResourceState( hResource, NULL, NULL );
if ( crs != ClusterResourceStateUnknown )
{
//
// if the state is greater than ClusterResourcePending then it's
// in a pending state and we want to wait for the next notification.
//
if ( crs > ClusterResourcePending )
{
pPort->GetNotify(); // this will only wait for up to 1 second.
--(*pnWait);
} // if: resource is in pending state
else
{
break;
} // else if: resource is no longer in a pending state
} // if: WrapClusterResourceState
else
{
_sc = GetLastError();
break;
} // else: WrapClusterResourceState failed
} // while: *pnWait > 0
CloseClusterResource( hResource );
} // if: OpenClusterResource ok
else
{
_sc = GetLastError();
} // else: OpenClusterResource failed
} // if: pnWait not NULL, this is for safety only
return _sc;
} //*** WaitForResourceStateChange()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWaitForResourceStateChange
//
// Description:
// Wrapper for WaitForResourceStateChange.
//
// Arguments:
// hCluster [IN] - handle to the cluster
// pwszName [IN] - name of the resource to wait on
// pPort [IN] - notification port to use
// pnWait [IN OUT] - ~ number of seconds to wait
//
// Return Value:
// S_OK or other Win32 HRESULT error
//
//--
/////////////////////////////////////////////////////////////////////////////
static HRESULT HrWaitForResourceStateChange(
IN HCLUSTER hCluster,
IN LPWSTR pwszName,
IN CClusterNotifyPort * pPort,
IN OUT DWORD * pnWait
)
{
DWORD _sc = WaitForResourceStateChange( hCluster, pwszName, pPort, pnWait );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWaitForResourceStateChange()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WaitForResourceGroupStateChange
//
// Description:
// Wait for the resource group state to change to a non pending state.
//
// Arguments:
// hCluster [IN] - handle to the cluster
// hGroup [IN] - handle to the group to wait on
// pnWait [IN OUT] - ~ number of seconds to wait
//
// Return Value:
// ERROR_SUCCESS or other Win32 error
//
//--
/////////////////////////////////////////////////////////////////////////////
static DWORD WaitForResourceGroupStateChange(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN OUT DWORD * pnWait
)
{
CLUSTER_GROUP_STATE _cgs = ClusterGroupStateUnknown;
DWORD _sc = ERROR_SUCCESS;
if ( pnWait != NULL )
{
CClusterNotifyPort _port; // Wait for a group state change event
_sc = _port.Create( (HCHANGE) INVALID_HANDLE_VALUE, hCluster );
if ( _sc == ERROR_SUCCESS )
{
_sc = _port.Register( CLUSTER_CHANGE_GROUP_STATE, hGroup );
if ( _sc == ERROR_SUCCESS )
{
while ( *pnWait > 0 )
{
_cgs = WrapGetClusterGroupState( hGroup, NULL );
if ( _cgs != ClusterGroupStateUnknown )
{
//
// if the state is ClusterGroupPending then it's
// in a pending state and we want to wait for the next notification.
//
if ( _cgs == ClusterGroupPending )
{
_port.GetNotify(); // this will only wait for up to 1 second.
--(*pnWait);
} // if: resource is in pending state
else
{
break;
} // else if: resource is no longer in a pending state
} // if: WrapClusterResourceState
else
{
_sc = GetLastError();
break;
} // else: WrapClusterResourceState failed
} // while: *pnWait > 0
} // if: port created
else
{
_sc = GetLastError();
} // else: port registration failed
} // if: create notification port
} // if: pnWait not NULL, this is for safety only
return _sc;
} //*** WaitForResourceGroupStateChange()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWaitForResourceGroupStateChange
//
// Description:
// Wrapper for WaitForResourceGroupStateChange
//
// Arguments:
// hCluster [IN] - handle to the cluster
// hGroup [IN] - handle to the group to wait on
// pnWait [IN OUT] - ~ number of seconds to wait
//
// Return Value:
// S_OK or other Win32 HRESULT error
//
//--
/////////////////////////////////////////////////////////////////////////////
static HRESULT HrWaitForResourceGroupStateChange(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN OUT DWORD * pnWait
)
{
DWORD _sc = WaitForResourceGroupStateChange( hCluster, hGroup, pnWait );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWaitForResourceGroupStateChange()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WaitForGroupToQuiesce
//
// Description:
// Wait for each of the resources in the group to leave a pending state.
//
// Arguments:
// hCluster [IN] - handle to the cluster
// hGroup [IN] - handle to the group
// pnWait [IN OUT] - ~ seconds to wait
//
// Return Value:
// ERROR_SUCCESS or error code
//
//--
/////////////////////////////////////////////////////////////////////////////
static DWORD WaitForGroupToQuiesce(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN OUT DWORD * pnWait
)
{
HGROUPENUM hEnum = NULL;
DWORD _sc = ERROR_SUCCESS;
if ( ( pnWait != NULL ) && ( *pnWait > 0 ) )
{
hEnum = ClusterGroupOpenEnum( hGroup, CLUSTER_GROUP_ENUM_CONTAINS );
if ( hEnum != NULL)
{
CClusterNotifyPort port; // Wait for a group state change event
_sc = port.Create( (HCHANGE) INVALID_HANDLE_VALUE, hCluster );
if ( _sc == ERROR_SUCCESS )
{
LPWSTR pwszName = NULL;
DWORD dwIndex = 0;
DWORD dwType = 0;
_sc = port.Register( CLUSTER_CHANGE_GROUP_STATE, hGroup );
if ( _sc == ERROR_SUCCESS )
{
for ( dwIndex = 0; _sc == ERROR_SUCCESS; dwIndex++ )
{
_sc = WrapClusterGroupEnum( hEnum, dwIndex, &dwType, &pwszName );
if ( _sc == ERROR_NO_MORE_ITEMS )
{
_sc = ERROR_SUCCESS;
break;
} // if: WrapClusterGroupEnum out of items -- leave! we are done...
else if ( _sc == ERROR_SUCCESS )
{
_sc = WaitForResourceStateChange( hCluster, pwszName, &port, pnWait );
::LocalFree( pwszName );
pwszName = NULL;
} // if: WrapClusterGroupEnum succeeded
else
{
_sc = GetLastError();
} // else: WrapClusterGroupEnum failed!
} // for: enum the resources in the group
} // if: notification port registered
else
{
_sc = GetLastError();
} // else: port registration failed
} // if: create notification port
ClusterGroupCloseEnum( hEnum );
} // if: ClusterGroupOpenEnum succeeds
else
{
_sc = GetLastError();
} // else: ClusterGroupOpenEnum failed
} // if: no wait time....
return _sc;
} //*** WaitForGroupToQuiesce()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWaitForGroupToQuiesce
//
// Description:
// Wrapper for WaitForGroupToQuiesce
//
// Arguments:
// hCluster [IN] - handle to the cluster
// hGroup [IN] - handle to the group
// pnWait [IN OUT] - ~ seconds to wait
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
static HRESULT HrWaitForGroupToQuiesce(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN OUT DWORD * pnWait
)
{
DWORD _sc = WaitForGroupToQuiesce( hCluster, hGroup, pnWait );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWaitForGroupToQuiesce()
/////////////////////////////////////////////////////////////////////////////
//++
//
// WaitForResourceToQuiesce
//
// Description:
// Wrapper function that is called after OnlineClusterResouce and
// OfflineClusterResource that waits for the resource to finish its
// state change. Returns the pending state of the resource after the
// wait period has expired and the state has not changed.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hResource [IN] - the resource handle to take on or offline
// pnWait [IN, OUT] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// ERROR_SUCCESS or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
static DWORD WaitForResourceToQuiesce(
IN HCLUSTER hCluster,
IN HRESOURCE hResource,
IN OUT DWORD * pnWait,
OUT long * pbPending
)
{
CLUSTER_RESOURCE_STATE crs = ClusterResourceStateUnknown;
DWORD _sc = ERROR_SUCCESS;
if ( ( pnWait != NULL ) && ( *pnWait > 0 ) )
{
CClusterNotifyPort port; // if wait is specified open a notify port.
_sc = port.Create( (HCHANGE) INVALID_HANDLE_VALUE, hCluster );
if ( _sc == ERROR_SUCCESS )
{
_sc = port.Register( CLUSTER_CHANGE_RESOURCE_STATE, hResource );
if ( _sc == ERROR_SUCCESS )
{
//
// Check the state before we check the notification port.
//
crs = WrapGetClusterResourceState( hResource, NULL, NULL );
if ( crs != ClusterResourceStateUnknown )
{
while ( ( *pnWait > 0 ) && ( crs > ClusterResourcePending ) )
{
port.GetNotify(); // waits for ~ 1 second
crs = WrapGetClusterResourceState( hResource, NULL, NULL );
--(*pnWait);
} // while:
} // if: get resource state
else
{
_sc = GetLastError();
} // else: get resource state failed
} // if: port was registered ok
} // if: port was created ok
} // if: *pnWait > 0
else
{
crs = ClusterResourceOnlinePending;
} // else: no time to wait and the resource is/was ERROR_IO_PENDING
//
// return the pending state if the caller has asked for it
//
if ( pbPending != NULL )
{
if ( crs > ClusterResourcePending )
{
*pbPending = TRUE;
} // if: is the resource still in a pending state
} // if: does the argument exist?
return _sc;
} //*** WaitForResourceToQuiesce()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWaitForResourceToQuiesce
//
// Description:
// Wrapper function for WaitForResourceToQuiesce
//
// Arguments:
// hCluster [IN] - the cluster handle
// hResource [IN] - the resource handle to take on or offline
// pnWait [IN, OUT] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
static HRESULT HrWaitForResourceToQuiesce(
IN HCLUSTER hCluster,
IN HRESOURCE hResource,
IN OUT DWORD * pnWait,
OUT long * pbPending
)
{
DWORD _sc = WaitForResourceToQuiesce( hCluster, hResource, pnWait, pbPending );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWaitForResourceToQuiesce()
/////////////////////////////////////////////////////////////////////////////
//++
//
// ScWrapOnlineClusterResource
//
// Description:
// Wrapper function for OnlineClusterResouce that returns the pending
// state of the resource after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hResource [IN] - the resource handle to take on or offline
// nWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// ERROR_SUCCESS or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD ScWrapOnlineClusterResource(
IN HCLUSTER hCluster,
IN HRESOURCE hResource,
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ERROR_SUCCESS;
_sc = OnlineClusterResource( hResource );
if ( _sc == ERROR_IO_PENDING )
{
_sc = WaitForResourceToQuiesce( hCluster, hResource, &nWait, pbPending );
} // if: ERROR_IO_PENDING
else if ( _sc == ERROR_SUCCESS )
{
if ( pbPending != NULL )
{
*pbPending = FALSE;
}
} // else if: ERROR_SUCCESS, resource must be online!
return _sc;
} //*** ScWrapOnlineClusterResource()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWrapOnlineClusterResource
//
// Description:
// Wrapper function for WrapOnlineClusterResouce
//
// Arguments:
// hCluster [IN] - the cluster handle
// hResource [IN] - the resource handle to take on or offline
// nWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT HrWrapOnlineClusterResource(
IN HCLUSTER hCluster,
IN HRESOURCE hResource,
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ScWrapOnlineClusterResource( hCluster, hResource, nWait, pbPending );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWrapOnlineClusterResource()
/////////////////////////////////////////////////////////////////////////////
//++
//
// ScWrapOfflineClusterResource
//
// Description:
// Wrapper function for OfflineClusterResouce that returns the pending
// state of the resource after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hResource [IN] - the resource handle to take on or offline
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// ERROR_SUCCESS or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD ScWrapOfflineClusterResource(
IN HCLUSTER hCluster,
IN HRESOURCE hResource,
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ERROR_SUCCESS;
_sc = OfflineClusterResource( hResource );
if ( _sc == ERROR_IO_PENDING )
{
_sc = WaitForResourceToQuiesce( hCluster, hResource, &nWait, pbPending );
} // if: ERROR_IO_PENDING
else if ( _sc == ERROR_SUCCESS )
{
if ( pbPending != NULL )
{
*pbPending = FALSE;
}
} // else if: ERROR_SUCCESS, resource must be online!
return _sc;
} //*** ScWrapOfflineClusterResource()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWrapOfflineClusterResource
//
// Description:
// Wrapper function for ScWrapOfflineClusterResource
//
// Arguments:
// hCluster [IN] - the cluster handle
// hResource [IN] - the resource handle to take on or offline
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT HrWrapOfflineClusterResource(
IN HCLUSTER hCluster,
IN HRESOURCE hResource,
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ScWrapOfflineClusterResource( hCluster, hResource, nWait, pbPending );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWrapOfflineClusterResource()
/////////////////////////////////////////////////////////////////////////////
//++
//
// ScWrapOnlineClusterGroup
//
// Description:
// Wrapper function for OnlineClusterGroup that returns the pending state
// of the group after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hGroup [IN] - the group handle to online
// hNode [IN] - the node the group should be brought online
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// ERROR_SUCCESS or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD ScWrapOnlineClusterGroup(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN HNODE hNode, //=NULL
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
CLUSTER_GROUP_STATE cgs = ClusterGroupStateUnknown;
DWORD _sc = ERROR_SUCCESS;
BOOL bPending = FALSE;
_sc = OnlineClusterGroup( hGroup, hNode );
if ( _sc == ERROR_IO_PENDING )
{
//
// is a wait time provided?
//
if ( nWait > 0 )
{
//
// Check the group state before we check the state of the resources. When reporting the
// group state the cluster API pulls the resource states online and offline pending up
// to online or offline respectivly. It also pulls the failed state up to offline. This
// means that a group state of online or offline is misleading because one or more
// resources could be in a pending state. The only absolute state is PartialOnline, at
// least one resource is offline (or failed).
//
cgs = WrapGetClusterGroupState( hGroup, NULL );
if ( cgs == ClusterGroupPending )
{
_sc = WaitForResourceGroupStateChange( hCluster, hGroup, &nWait );
} // if: group state is pending
else if ( ( cgs == ClusterGroupOnline ) || ( cgs == ClusterGroupPartialOnline ) )
{
_sc = WaitForGroupToQuiesce( hCluster, hGroup, &nWait );
if ( _sc == ERROR_SUCCESS )
{
bPending = ( nWait == 0 ); // if we ran out of time then something isn't online
} // if: HrWaitForGroupToQuiesce ok
} // else if: group is online -- we have to check all of the resources, on downlevel clusters...
else if ( cgs == ClusterGroupStateUnknown )
{
_sc = GetLastError();
} // else if: get group state failed
} // if: pnWait > 0
else
{
bPending = TRUE;
} // if: no wait was specified
} // if: OnlineClusterGroup returned ERROR_IO_PENDING
//
// return the pending state if the caller has asked for it
//
if ( pbPending != NULL )
{
*pbPending = bPending;
} // if: does the argument exist?
return _sc;
} //*** ScWrapOnlineClusterGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWrapOnlineClusterGroup
//
// Description:
// Wrapper function for ScWrapOnlineClusterGroup
//
// Arguments:
// hCluster [IN] - the cluster handle
// hGroup [IN] - the group handle to online
// hNode [IN] - the node the group should be brought online
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT HrWrapOnlineClusterGroup(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN HNODE hNode, //=NULL
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ScWrapOnlineClusterGroup( hCluster, hGroup, hNode, nWait, pbPending );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWrapOnlineClusterGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// ScWrapOfflineClusterGroup
//
// Description:
// Wrapper function for OfflineClusterGroup that returns the pending
// state of the group after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hGroup [IN] - the group handle to online
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// ERROR_SUCCESS or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD ScWrapOfflineClusterGroup(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
CLUSTER_GROUP_STATE cgs = ClusterGroupStateUnknown;
DWORD _sc = ERROR_SUCCESS;
BOOL bPending = FALSE;
_sc = OfflineClusterGroup( hGroup );
if ( _sc == ERROR_IO_PENDING )
{
//
// is a wait time provided?
//
if ( nWait > 0 )
{
//
// Check the group state before we check the state of the resources. When reporting the
// group state the cluster API pulls the resource states online and offline pending up
// to online or offline respectivly. It also pulls the failed state up to offline. This
// means that a group state of online or offline is misleading because one or more
// resources could be in a pending state.
//
cgs = WrapGetClusterGroupState( hGroup, NULL );
if ( cgs == ClusterGroupPending )
{
_sc = WaitForResourceGroupStateChange( hCluster, hGroup, &nWait );
} // if: group state is pending
else if ( cgs == ClusterGroupStateUnknown )
{
_sc = GetLastError();
} // else if: get group state failed
else if ( ( cgs == ClusterGroupOffline ) || ( cgs == ClusterGroupPartialOnline ) )
{
_sc = WaitForGroupToQuiesce( hCluster, hGroup, &nWait );
if ( _sc == ERROR_SUCCESS )
{
bPending = ( nWait == 0 ); // if we ran out of time then something isn't online
} // if: HrWaitForGroupToQuiesce ok
} // else if: group is offline -- we have to check all of the resources...
} // if: pnWait > 0
else
{
bPending = TRUE;
} // if: no wait was specified
} // if: OfflineClusterGroup returned ERROR_IO_PENDING
//
// return the pending state if the caller has asked for it
//
if ( pbPending != NULL )
{
*pbPending = bPending;
} // if: does the argument exist?
return _sc;
} //*** ScWrapOfflineClusterGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWrapOfflineClusterGroup
//
// Description:
// Wrapper function for OfflineClusterGroup that returns the pending
// state of the group after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hGroup [IN] - the group handle to online
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT HrWrapOfflineClusterGroup(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ScWrapOfflineClusterGroup( hCluster, hGroup, nWait, pbPending );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWrapOfflineClusterGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// ScWrapMoveClusterGroup
//
// Description:
// Wrapper function for MoveClusterGroup that returns the pending state
// of the group after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hGroup [IN] - the group handle to online
// hNode [IN] - the node the group should be brought online
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// ERROR_SUCCESS or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD ScWrapMoveClusterGroup(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN HNODE hNode, //=NULL
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
LPWSTR pszOriginNodeName = NULL;
BOOL bPending = FALSE;
DWORD _sc;
do // dummy do-while look to avoid gotos.
{
CLUSTER_GROUP_STATE cgsInitialState = ClusterGroupStateUnknown;
CLUSTER_GROUP_STATE cgsCurrentState = ClusterGroupStateUnknown;
LPWSTR pszCurrentNodeName = NULL;
// Get the initial group state.
cgsInitialState = WrapGetClusterGroupState( hGroup, &pszOriginNodeName );
if ( cgsInitialState == ClusterGroupStateUnknown )
{
// Error getting the group state
_sc = GetLastError();
break;
}
// Move the cluster group.
_sc = MoveClusterGroup( hGroup, hNode );
//
// When MoveClusterGroup returns ERROR_SUCCESS, it just means that the group
// has changed ownership successfully, but it does not mean that the group is
// back to the state it was in before the move. Therefore, we still need to
// wait, if a wait time is provided. If not, we are done.
//
if ( nWait <= 0 )
{
break;
}
//
// MoveClusterGroup is not done yet
//
if ( _sc == ERROR_IO_PENDING )
{
_sc = ERROR_SUCCESS;
do // while (nWait > 0)
{
//
// Get the name of the node which currently owns this group.
//
cgsCurrentState = WrapGetClusterGroupState( hGroup, &pszCurrentNodeName );
if ( cgsCurrentState == ClusterGroupStateUnknown )
{
// Error getting the group state
_sc = GetLastError();
break;
}
if ( lstrcmpiW( pszOriginNodeName, pszCurrentNodeName ) != 0 )
{
//
// If the current owner node is not the original owner, then the call to
// move group has succeeded. So quit this loop (we still have to see
// if the group is stable though)
//
break;
} // if: current owner node is not the same as the original owner node
else
{
//
// Current owner is the same as the original owner.
// Wait for one second and check again.
//
LocalFree( pszCurrentNodeName );
pszCurrentNodeName = NULL; // Required to prevent freeing memory twice
--nWait;
Sleep( 1000 );
} // if: current owner node is the same as the original owner node
}
while ( nWait > 0 );
LocalFree( pszCurrentNodeName );
//
// If we ran out of time waiting for MoveClusterGroup to complete, then
// set the pending flag and quit.
//
if ( nWait <= 0 )
{
bPending = TRUE;
break;
}
} // if: MoveClusterGroup returned ERROR_IO_PENDING
else
{
cgsCurrentState = WrapGetClusterGroupState( hGroup, NULL );
if ( cgsCurrentState == ClusterGroupStateUnknown )
{
// Error getting the group state
_sc = GetLastError();
}
} // else: MoveClusterGroup returned ERROR_SUCCESS
//
// if something went wrong with MoveClusterGroup, while waiting
// for it to comeplete or with WrapGetClusterGroupState, then quit.
//
if ( _sc != ERROR_SUCCESS )
{
break;
}
//
// If the state of the group on the destination node is ClusterGroupFailed
// then there is nothing much we can do.
//
if ( cgsCurrentState == ClusterGroupFailed )
{
break;
}
//
// Check the group state before we check the state of the resources. When reporting the
// group state the cluster API of a NT4 node pulls the resource states online and offline
// pending up to online or offline respectivly. It also pulls the failed state up to offline.
// This means that a group state of online or offline is misleading because one or more
// resources could be in a pending state. The only absolute state is PartialOnline, at
// least one resource is offline (or failed).
//
if ( cgsCurrentState == ClusterGroupPending )
{
// The current state is pending. So wait for a state change.
_sc = WaitForResourceGroupStateChange( hCluster, hGroup, &nWait );
} // if: the group state is pending.
else
{
_sc = WaitForGroupToQuiesce( hCluster, hGroup, &nWait );
} // else: group state is online, offline or partial online
if ( _sc == ERROR_SUCCESS )
{
bPending = ( nWait == 0 );
} // if: everything ok so far
}
while ( FALSE ); // dummy do-while look to avoid gotos
LocalFree( pszOriginNodeName );
//
// return the pending state if the caller has asked for it
//
if ( pbPending != NULL )
{
*pbPending = bPending;
} // if: does the argument exist?
return _sc;
} //*** ScWrapMoveClusterGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrWrapMoveClusterGroup
//
// Description:
// Wrapper function for ScWrapMoveClusterGroup that returns the pending state
// of the group after the wait period has expired.
//
// Arguments:
// hCluster [IN] - the cluster handle
// hGroup [IN] - the group handle to online
// hNode [IN] - the node the group should be brought online
// pnWait [IN] - ~ how many seconds to wait
// pbPending [OUT] - true if the resource is in a pending state
//
// Return Value:
// S_OK or Win32 error code
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT HrWrapMoveClusterGroup(
IN HCLUSTER hCluster,
IN HGROUP hGroup,
IN HNODE hNode, //=NULL
IN DWORD nWait, //=0
OUT long * pbPending //=NULL
)
{
DWORD _sc = ScWrapMoveClusterGroup ( hCluster, hGroup, hNode, nWait, pbPending );
return HRESULT_FROM_WIN32( _sc );
} //*** HrWrapMoveClusterGroup()