Leaked source code of windows server 2003
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

/*++
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;
}