You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
13 KiB
411 lines
13 KiB
/*++
|
|
|
|
Copyright (C) 2001 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
NCclusfunc.cxx
|
|
|
|
Abstract:
|
|
|
|
This module provides several utility functions for cluster related operations.
|
|
|
|
Author:
|
|
|
|
Felix Maxa (AMaxa) 16 May 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <clusapi.h>
|
|
#include "ncnamecache.hxx"
|
|
#include "ncclusapi.hxx"
|
|
|
|
using namespace NCoreLibrary;
|
|
|
|
LPCWSTR g_pszIPAddressResource = L"IP Address";
|
|
LPCWSTR g_pszIPAddressProperty = L"Address";
|
|
|
|
/*++
|
|
|
|
Name:
|
|
|
|
ClusResControl
|
|
|
|
Description:
|
|
|
|
Helper function. Encapsulates a call to ClusterResourceControl. The function
|
|
allocates a buffer. Upon success, the caller nedds to free the buffer using
|
|
delete [].
|
|
|
|
Arguments:
|
|
|
|
ClusterAPI - reference to object exposing cluster APIs
|
|
hResource - handle to cluster resource
|
|
ControlCode - control code for ClusterResourceControl
|
|
ppBuffer - pointer to address where to store byte array
|
|
pcBytesReturned - number of bytes returned by ClusterResourceControl (not
|
|
necessarily the number of byes allocated for *ppBuffer)
|
|
|
|
Return Value:
|
|
|
|
S_OK - success. ppBuffer can be used and must be freed using delete []
|
|
any other HRESULT - failure
|
|
|
|
--*/
|
|
HRESULT
|
|
ClusResControl(
|
|
IN TClusterAPI& ClusterAPI,
|
|
IN HRESOURCE hResource,
|
|
IN DWORD ControlCode,
|
|
OUT BYTE **ppBuffer,
|
|
IN DWORD *pcBytesReturned OPTIONAL
|
|
)
|
|
{
|
|
TStatusH hRetval;
|
|
|
|
hRetval DBGCHK = ppBuffer ? S_OK : E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
DWORD Error;
|
|
DWORD cbBuffer = kBufferAllocHint;
|
|
DWORD cbNeeded = 0;
|
|
|
|
*ppBuffer = new BYTE[cbBuffer];
|
|
|
|
Error = *ppBuffer ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
if (Error == ERROR_SUCCESS)
|
|
{
|
|
Error = ClusterAPI.pfnClusterResourceControl(hResource,
|
|
NULL,
|
|
ControlCode,
|
|
NULL,
|
|
0,
|
|
*ppBuffer,
|
|
cbBuffer,
|
|
&cbNeeded);
|
|
|
|
if (Error == ERROR_MORE_DATA)
|
|
{
|
|
cbBuffer = cbNeeded;
|
|
|
|
delete [] *ppBuffer;
|
|
|
|
*ppBuffer = new BYTE[cbBuffer];
|
|
|
|
Error = *ppBuffer ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
if (Error == ERROR_SUCCESS)
|
|
{
|
|
Error = ClusterAPI.pfnClusterResourceControl(hResource,
|
|
NULL,
|
|
ControlCode,
|
|
NULL,
|
|
0,
|
|
*ppBuffer,
|
|
cbBuffer,
|
|
&cbNeeded);
|
|
}
|
|
}
|
|
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
delete [] *ppBuffer;
|
|
|
|
*ppBuffer = NULL;
|
|
|
|
cbNeeded = 0;
|
|
}
|
|
|
|
if (pcBytesReturned)
|
|
{
|
|
*pcBytesReturned = cbNeeded;
|
|
}
|
|
}
|
|
|
|
hRetval DBGCHK = HRESULT_FROM_WIN32(Error);
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
/*++
|
|
|
|
Name:
|
|
|
|
GetResourceIPAddress
|
|
|
|
Description:
|
|
|
|
Helper function used in GetClusterIPAddresses. Checks if a cluster resource is an IP address
|
|
reosurce, in which case it retrieve the IP associated.
|
|
|
|
Arguments:
|
|
|
|
ClusterAPI - reference to object exposing cluster APIs
|
|
hCluster - handle retrieved via OpenCluster
|
|
pszResource - resource name
|
|
ppszAddress - pointer to where to receive string representing IP address
|
|
|
|
Return Value:
|
|
|
|
S_OK - success. ppszAddress may still be NULL on success. success means
|
|
either the reosurce is not IP resource or it is IP resource and
|
|
the ppszAddress is then not NULL. ppszAddress must be freed by caller
|
|
using LocalFree.
|
|
any other HRESULT - failure
|
|
|
|
--*/
|
|
HRESULT
|
|
GetResourceIPAddress(
|
|
IN TClusterAPI& ClusterAPI,
|
|
IN HCLUSTER hCluster,
|
|
IN LPCWSTR pszResource,
|
|
OUT LPWSTR *ppszAddress
|
|
)
|
|
{
|
|
HRESOURCE hResource;
|
|
TStatusH hRetval;
|
|
|
|
hRetval DBGCHK = hCluster && pszResource && ppszAddress ? S_OK : E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
*ppszAddress = NULL;
|
|
|
|
hResource = ClusterAPI.pfnOpenClusterResource(hCluster, pszResource);
|
|
|
|
hRetval DBGCHK = hResource ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
BYTE *pResType = NULL;
|
|
|
|
hRetval DBGCHK = ClusResControl(ClusterAPI,
|
|
hResource,
|
|
CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
|
|
&pResType,
|
|
NULL);
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
//
|
|
// Check resource type. We are interested only in IP Address resources.
|
|
//
|
|
if (!_wcsicmp(reinterpret_cast<LPWSTR>(pResType), g_pszIPAddressResource))
|
|
{
|
|
LPWSTR pszIPAddress = NULL;
|
|
BYTE *pResProp = NULL;
|
|
DWORD cbResProp = 0;
|
|
|
|
//
|
|
// Get all the private properties of the IP Address resource.
|
|
//
|
|
hRetval DBGCHK = ClusResControl(ClusterAPI,
|
|
hResource,
|
|
CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,
|
|
&pResProp,
|
|
&cbResProp);
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
//
|
|
// Scan for the property indicating the IP address of the resource
|
|
//
|
|
DWORD Error = ClusterAPI.pfnResUtilFindSzProperty(pResProp,
|
|
cbResProp,
|
|
g_pszIPAddressProperty,
|
|
ppszAddress);
|
|
|
|
hRetval DBGCHK = HRESULT_FROM_WIN32(Error);
|
|
}
|
|
|
|
delete [] pResProp;
|
|
}
|
|
}
|
|
|
|
delete [] pResType;
|
|
|
|
ClusterAPI.pfnCloseClusterResource(hResource);
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
/*++
|
|
|
|
Name:
|
|
|
|
GetClusterIPAddresses
|
|
|
|
Description:
|
|
|
|
Fill in a list with the IP addresses used by the cluster service running on the local machine.
|
|
The function returns S_OK if the cluster service is not running. In that case the list will be
|
|
empty.
|
|
|
|
Arguments:
|
|
|
|
pClusterIPsList - pointer to list of TStringNodes.
|
|
|
|
Return Value:
|
|
|
|
S_OK - success. pClusterIPsList will have 0 or more elements represeting each
|
|
an IP address used by cluster resources
|
|
any other HRESULT - failure
|
|
|
|
--*/
|
|
HRESULT
|
|
GetClusterIPAddresses(
|
|
IN TList<TStringNode> *pClusterIPsList
|
|
)
|
|
{
|
|
TStatusH hRetval;
|
|
HCLUSTER hCluster;
|
|
TClusterAPI ClusterAPI;
|
|
|
|
hRetval DBGCHK = pClusterIPsList ? ClusterAPI.Valid() : E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hCluster = ClusterAPI.pfnOpenCluster(NULL);
|
|
|
|
//
|
|
// If we cannot open the cluster then we return success to our caller.
|
|
//
|
|
if (hCluster)
|
|
{
|
|
HCLUSENUM hClusEnum;
|
|
|
|
hClusEnum = ClusterAPI.pfnClusterOpenEnum(hCluster, CLUSTER_ENUM_RESOURCE);
|
|
|
|
hRetval DBGCHK = hClusEnum ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
BOOL bDone = FALSE;
|
|
DWORD Index = 0;
|
|
LPWSTR pszName = NULL;
|
|
DWORD cchName = 0;
|
|
DWORD cchNeeded;
|
|
DWORD ResourceType;
|
|
|
|
cchName = cchNeeded = kBufferAllocHint;
|
|
|
|
//
|
|
// We need to initialize pszName to a valid non NULL memory block, otherwise
|
|
// CluserEnum AV's.
|
|
//
|
|
pszName = new WCHAR[cchName];
|
|
|
|
hRetval DBGCHK = pszName ? S_OK : E_OUTOFMEMORY;
|
|
|
|
for (Index = 0; !bDone && SUCCEEDED(hRetval);)
|
|
{
|
|
DWORD Error;
|
|
|
|
cchNeeded = cchName;
|
|
|
|
Error = ClusterAPI.pfnClusterEnum(hClusEnum,
|
|
Index,
|
|
&ResourceType,
|
|
pszName,
|
|
&cchNeeded);
|
|
|
|
switch (Error)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
{
|
|
LPWSTR pszAddress = NULL;
|
|
|
|
hRetval DBGCHK = GetResourceIPAddress(ClusterAPI, hCluster, pszName, &pszAddress);
|
|
|
|
if (pszAddress)
|
|
{
|
|
TStringNode *pNode = new TStringNode(pszAddress);
|
|
|
|
hRetval DBGCHK = pNode ? S_OK : E_OUTOFMEMORY;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = pNode->Valid();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = pClusterIPsList->AddAtHead(pNode);
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
//
|
|
// List took ownership of pNode.
|
|
//
|
|
pNode = NULL;
|
|
}
|
|
}
|
|
|
|
delete pNode;
|
|
|
|
LocalFree(pszAddress);
|
|
}
|
|
|
|
Index++;
|
|
|
|
break;
|
|
}
|
|
|
|
case ERROR_MORE_DATA:
|
|
{
|
|
delete [] pszName;
|
|
|
|
//
|
|
// cchNeeded returns the number of characters needed, excluding the terminating NULL
|
|
//
|
|
cchName = cchNeeded + 1;
|
|
|
|
pszName = new WCHAR[cchName];
|
|
|
|
if (!pszName)
|
|
{
|
|
hRetval DBGCHK = E_OUTOFMEMORY;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ERROR_NO_MORE_ITEMS:
|
|
{
|
|
delete [] pszName;
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
delete [] pszName;
|
|
hRetval DBGCHK = HRESULT_FROM_WIN32(Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
ClusterAPI.pfnClusterCloseEnum(hClusEnum);
|
|
}
|
|
|
|
ClusterAPI.pfnCloseCluster(hCluster);
|
|
}
|
|
else
|
|
{
|
|
DWORD Error = GetLastError();
|
|
|
|
DBGMSG(DBG_WARN, ("\n\nGetClusterIPAddresses OpenCluster failed with Win32 error %u !!!\n\n", Error));
|
|
}
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|