|
|
/////////////////////////////////////////////////////////////////////////////
//
// 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()
|