946 lines
23 KiB
C
946 lines
23 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996-1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
cluster.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Server side support for Cluster APIs dealing with the whole
|
|||
|
cluster.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 9-Feb-1996
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "apip.h"
|
|||
|
#include "clusverp.h"
|
|||
|
#include "clusudef.h"
|
|||
|
|
|||
|
|
|||
|
HCLUSTER_RPC
|
|||
|
s_ApiOpenCluster(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
OUT error_status_t *Status
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Opens a handle to the cluster. This context handle is
|
|||
|
currently used only to handle cluster notify additions
|
|||
|
and deletions correctly.
|
|||
|
|
|||
|
Added call to ApipConnectCallback which checks that connecting
|
|||
|
users have rights to open cluster.
|
|||
|
|
|||
|
Rod Sharper 03/27/97
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
Status - Returns any error that may occur.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A context handle to a cluster object if successful
|
|||
|
|
|||
|
NULL otherwise.
|
|||
|
|
|||
|
History:
|
|||
|
RodSh 27-Mar-1997 Modified to support secured user connections.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAPI_HANDLE Handle;
|
|||
|
|
|||
|
if ( CsUseAuthenticatedRPC ) {
|
|||
|
|
|||
|
// if user was not granted access don't return handle
|
|||
|
*Status = ApipConnectCallback( NULL, IDL_handle );
|
|||
|
if( *Status != RPC_S_OK ){
|
|||
|
SetLastError( *Status );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
|
|||
|
if (Handle == NULL) {
|
|||
|
CL_UNEXPECTED_ERROR( ERROR_NOT_ENOUGH_MEMORY );
|
|||
|
*Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
*Status = ERROR_SUCCESS;
|
|||
|
Handle->Type = API_CLUSTER_HANDLE;
|
|||
|
Handle->Flags = 0;
|
|||
|
Handle->Cluster = NULL;
|
|||
|
InitializeListHead(&Handle->NotifyList);
|
|||
|
|
|||
|
return(Handle);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiCloseCluster(
|
|||
|
IN OUT HCLUSTER_RPC *phCluster
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Closes an open cluster context handle.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
phCluster - Supplies a pointer to the HCLUSTER_RPC to be closed.
|
|||
|
Returns NULL
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAPI_HANDLE Handle;
|
|||
|
|
|||
|
Handle = (PAPI_HANDLE)*phCluster;
|
|||
|
if (Handle->Type != API_CLUSTER_HANDLE) {
|
|||
|
return(ERROR_INVALID_HANDLE);
|
|||
|
}
|
|||
|
ApipRundownNotify(Handle);
|
|||
|
|
|||
|
LocalFree(*phCluster);
|
|||
|
*phCluster = NULL;
|
|||
|
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HCLUSTER_RPC_rundown(
|
|||
|
IN HCLUSTER_RPC Cluster
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
RPC rundown procedure for a HCLUSTER_RPC. Just closes the handle.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Cluster - Supplies the HCLUSTER_RPC that is to be rundown.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
s_ApiCloseCluster(&Cluster);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiSetClusterName(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
IN LPCWSTR NewClusterName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Changes the current cluster's name.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used
|
|||
|
|
|||
|
NewClusterName - Supplies the new name of the cluster.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status = ERROR_SUCCESS;
|
|||
|
DWORD dwSize;
|
|||
|
LPWSTR pszClusterName = NULL;
|
|||
|
|
|||
|
API_CHECK_INIT();
|
|||
|
|
|||
|
//
|
|||
|
// Get the cluster name, which is kept in the root of the
|
|||
|
// cluster registry under the "ClusterName" value, call the
|
|||
|
// FM only if the new name is different
|
|||
|
//
|
|||
|
|
|||
|
dwSize = (MAX_COMPUTERNAME_LENGTH+1)*sizeof(WCHAR);
|
|||
|
retry:
|
|||
|
pszClusterName = (LPWSTR)LocalAlloc(LMEM_FIXED, dwSize);
|
|||
|
if (pszClusterName == NULL) {
|
|||
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
Status = DmQueryValue(DmClusterParametersKey,
|
|||
|
CLUSREG_NAME_CLUS_NAME,
|
|||
|
NULL,
|
|||
|
(LPBYTE)pszClusterName,
|
|||
|
&dwSize);
|
|||
|
|
|||
|
if (Status == ERROR_MORE_DATA) {
|
|||
|
//
|
|||
|
// Try again with a bigger buffer.
|
|||
|
//
|
|||
|
LocalFree(pszClusterName);
|
|||
|
goto retry;
|
|||
|
}
|
|||
|
|
|||
|
if ( Status == ERROR_SUCCESS ) {
|
|||
|
LPWSTR pszNewNameUpperCase = NULL;
|
|||
|
|
|||
|
pszNewNameUpperCase = (LPWSTR) LocalAlloc(
|
|||
|
LMEM_FIXED,
|
|||
|
(lstrlenW(NewClusterName) + 1) *
|
|||
|
sizeof(*NewClusterName)
|
|||
|
);
|
|||
|
|
|||
|
if (pszNewNameUpperCase != NULL) {
|
|||
|
lstrcpyW( pszNewNameUpperCase, NewClusterName );
|
|||
|
_wcsupr( pszNewNameUpperCase );
|
|||
|
|
|||
|
Status = ApipValidateClusterName( pszNewNameUpperCase );
|
|||
|
|
|||
|
if ( Status == ERROR_SUCCESS ) {
|
|||
|
Status = FmChangeClusterName(pszNewNameUpperCase);
|
|||
|
}
|
|||
|
|
|||
|
LocalFree( pszNewNameUpperCase );
|
|||
|
}
|
|||
|
else {
|
|||
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
FnExit:
|
|||
|
if ( pszClusterName ) LocalFree( pszClusterName );
|
|||
|
return(Status);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiGetClusterName(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
OUT LPWSTR *ClusterName,
|
|||
|
OUT LPWSTR *NodeName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the current cluster name and the name of the
|
|||
|
node this RPC connection is to.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used
|
|||
|
|
|||
|
ClusterName - Returns a pointer to the cluster name.
|
|||
|
This memory must be freed by the client side.
|
|||
|
|
|||
|
NodeName - Returns a pointer to the node name.
|
|||
|
This memory must be freed by the client side.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Size;
|
|||
|
DWORD Status=ERROR_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Get the current node name
|
|||
|
//
|
|||
|
*ClusterName = NULL;
|
|||
|
Size = MAX_COMPUTERNAME_LENGTH+1;
|
|||
|
*NodeName = MIDL_user_allocate(Size*sizeof(WCHAR));
|
|||
|
if (*NodeName == NULL) {
|
|||
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
GetComputerNameW(*NodeName, &Size);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get the cluster name, which is kept in the root of the
|
|||
|
// cluster registry under the "ClusterName" value.
|
|||
|
//
|
|||
|
|
|||
|
Status = ERROR_SUCCESS;
|
|||
|
Size = (MAX_COMPUTERNAME_LENGTH+1)*sizeof(WCHAR);
|
|||
|
retry:
|
|||
|
*ClusterName = MIDL_user_allocate(Size);
|
|||
|
if (*ClusterName == NULL) {
|
|||
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
Status = DmQueryValue(DmClusterParametersKey,
|
|||
|
CLUSREG_NAME_CLUS_NAME,
|
|||
|
NULL,
|
|||
|
(LPBYTE)*ClusterName,
|
|||
|
&Size);
|
|||
|
if (Status == ERROR_MORE_DATA) {
|
|||
|
//
|
|||
|
// Try again with a bigger buffer.
|
|||
|
//
|
|||
|
MIDL_user_free(*ClusterName);
|
|||
|
goto retry;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
FnExit:
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
if (*NodeName) MIDL_user_free(*NodeName);
|
|||
|
if (*ClusterName) MIDL_user_free(*ClusterName);
|
|||
|
*NodeName = NULL;
|
|||
|
*ClusterName = NULL;
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiGetClusterVersion(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
OUT LPWORD lpwMajorVersion,
|
|||
|
OUT LPWORD lpwMinorVersion,
|
|||
|
OUT LPWORD lpwBuildNumber,
|
|||
|
OUT LPWSTR *lpszVendorId,
|
|||
|
OUT LPWSTR *lpszCSDVersion
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the current cluster version information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used
|
|||
|
|
|||
|
lpdwMajorVersion - Returns the major version number of the cluster software
|
|||
|
|
|||
|
lpdwMinorVersion - Returns the minor version number of the cluster software
|
|||
|
|
|||
|
lpszVendorId - Returns a pointer to the vendor name. This memory must be
|
|||
|
freed by the client side.
|
|||
|
|
|||
|
lpszCSDVersion - Returns a pointer to the current CSD description. This memory
|
|||
|
must be freed by the client side.
|
|||
|
N.B. The CSD Version of a cluster is currently the same as the CSD
|
|||
|
Version of the base operating system.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPWSTR VendorString;
|
|||
|
LPWSTR CsdString;
|
|||
|
DWORD Length;
|
|||
|
OSVERSIONINFO OsVersionInfo;
|
|||
|
|
|||
|
Length = lstrlenA(VER_CLUSTER_PRODUCTNAME_STR)+1;
|
|||
|
VendorString = MIDL_user_allocate(Length*sizeof(WCHAR));
|
|||
|
if (VendorString == NULL) {
|
|||
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
}
|
|||
|
mbstowcs(VendorString, VER_CLUSTER_PRODUCTNAME_STR, Length);
|
|||
|
|
|||
|
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|||
|
GetVersionExW(&OsVersionInfo);
|
|||
|
Length = lstrlenW(OsVersionInfo.szCSDVersion)+1;
|
|||
|
CsdString = MIDL_user_allocate(Length*sizeof(WCHAR));
|
|||
|
if (CsdString == NULL) {
|
|||
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
}
|
|||
|
lstrcpyW(CsdString, OsVersionInfo.szCSDVersion);
|
|||
|
|
|||
|
*lpszCSDVersion = CsdString;
|
|||
|
*lpszVendorId = VendorString;
|
|||
|
*lpwMajorVersion = VER_PRODUCTVERSION_W >> 8;
|
|||
|
*lpwMinorVersion = VER_PRODUCTVERSION_W & 0xff;
|
|||
|
*lpwBuildNumber = (WORD)(CLUSTER_GET_MINOR_VERSION(CsMyHighestVersion));
|
|||
|
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiGetClusterVersion2(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
OUT LPWORD lpwMajorVersion,
|
|||
|
OUT LPWORD lpwMinorVersion,
|
|||
|
OUT LPWORD lpwBuildNumber,
|
|||
|
OUT LPWSTR *lpszVendorId,
|
|||
|
OUT LPWSTR *lpszCSDVersion,
|
|||
|
OUT PCLUSTER_OPERATIONAL_VERSION_INFO *ppClusterOpVerInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the current cluster version information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used
|
|||
|
|
|||
|
lpdwMajorVersion - Returns the major version number of the cluster software
|
|||
|
|
|||
|
lpdwMinorVersion - Returns the minor version number of the cluster software
|
|||
|
|
|||
|
lpszVendorId - Returns a pointer to the vendor name. This memory must be
|
|||
|
freed by the client side.
|
|||
|
|
|||
|
lpszCSDVersion - Returns a pointer to the current CSD description. This memory
|
|||
|
must be freed by the client side.
|
|||
|
N.B. The CSD Version of a cluster is currently the same as the CSD
|
|||
|
Version of the base operating system.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPWSTR VendorString = NULL;
|
|||
|
LPWSTR CsdString = NULL;
|
|||
|
DWORD Length;
|
|||
|
OSVERSIONINFO OsVersionInfo;
|
|||
|
DWORD dwStatus;
|
|||
|
PCLUSTER_OPERATIONAL_VERSION_INFO pClusterOpVerInfo=NULL;
|
|||
|
|
|||
|
|
|||
|
*lpszVendorId = NULL;
|
|||
|
*lpszCSDVersion = NULL;
|
|||
|
*ppClusterOpVerInfo = NULL;
|
|||
|
|
|||
|
Length = lstrlenA(VER_CLUSTER_PRODUCTNAME_STR)+1;
|
|||
|
VendorString = MIDL_user_allocate(Length*sizeof(WCHAR));
|
|||
|
if (VendorString == NULL) {
|
|||
|
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
mbstowcs(VendorString, VER_CLUSTER_PRODUCTNAME_STR, Length);
|
|||
|
|
|||
|
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|||
|
GetVersionExW(&OsVersionInfo);
|
|||
|
Length = lstrlenW(OsVersionInfo.szCSDVersion)+1;
|
|||
|
CsdString = MIDL_user_allocate(Length*sizeof(WCHAR));
|
|||
|
if (CsdString == NULL) {
|
|||
|
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
lstrcpyW(CsdString, OsVersionInfo.szCSDVersion);
|
|||
|
|
|||
|
|
|||
|
pClusterOpVerInfo = MIDL_user_allocate(sizeof(CLUSTER_OPERATIONAL_VERSION_INFO));
|
|||
|
if (pClusterOpVerInfo == NULL) {
|
|||
|
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
pClusterOpVerInfo->dwSize = sizeof(CLUSTER_OPERATIONAL_VERSION_INFO);
|
|||
|
pClusterOpVerInfo->dwReserved = 0;
|
|||
|
|
|||
|
dwStatus = NmGetClusterOperationalVersion(&(pClusterOpVerInfo->dwClusterHighestVersion),
|
|||
|
&(pClusterOpVerInfo->dwClusterLowestVersion),
|
|||
|
&(pClusterOpVerInfo->dwFlags));
|
|||
|
|
|||
|
*lpszCSDVersion = CsdString;
|
|||
|
*lpszVendorId = VendorString;
|
|||
|
*ppClusterOpVerInfo = pClusterOpVerInfo;
|
|||
|
*lpwMajorVersion = VER_PRODUCTVERSION_W >> 8;
|
|||
|
*lpwMinorVersion = VER_PRODUCTVERSION_W & 0xff;
|
|||
|
*lpwBuildNumber = (WORD)CLUSTER_GET_MINOR_VERSION(CsMyHighestVersion);
|
|||
|
|
|||
|
FnExit:
|
|||
|
if (dwStatus != ERROR_SUCCESS)
|
|||
|
{
|
|||
|
// free the strings
|
|||
|
if (VendorString) MIDL_user_free(VendorString);
|
|||
|
if (CsdString) MIDL_user_free(CsdString);
|
|||
|
if (pClusterOpVerInfo) MIDL_user_free(pClusterOpVerInfo);
|
|||
|
}
|
|||
|
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiGetQuorumResource(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
OUT LPWSTR *ppszResourceName,
|
|||
|
OUT LPWSTR *ppszClusFileRootPath,
|
|||
|
OUT DWORD *pdwMaxQuorumLogSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Gets the current cluster quorum resource.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
*ppszResourceName - Returns a pointer to the current quorum resource name. This
|
|||
|
memory must be freed by the client side.
|
|||
|
|
|||
|
*ppszClusFileRootPath - Returns the root path where the permanent cluster files are
|
|||
|
stored.
|
|||
|
|
|||
|
*pdwMaxQuorumLogSize - Returns the size at which the quorum log path is set.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
LPWSTR quorumId = NULL;
|
|||
|
DWORD idMaxSize = 0;
|
|||
|
DWORD idSize = 0;
|
|||
|
PFM_RESOURCE pResource=NULL;
|
|||
|
LPWSTR pszResourceName=NULL;
|
|||
|
LPWSTR pszClusFileRootPath=NULL;
|
|||
|
LPWSTR pszLogPath=NULL;
|
|||
|
LPWSTR pszEndDeviceName;
|
|||
|
|
|||
|
API_CHECK_INIT();
|
|||
|
//
|
|||
|
// Get the quorum resource value.
|
|||
|
//
|
|||
|
Status = DmQuerySz( DmQuorumKey,
|
|||
|
CLUSREG_NAME_QUORUM_RESOURCE,
|
|||
|
(LPWSTR*)&quorumId,
|
|||
|
&idMaxSize,
|
|||
|
&idSize);
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[API] s_ApiGetQuorumResource Failed to get quorum resource, error %1!u!.\n",
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reference the specified resource ID.
|
|||
|
//
|
|||
|
pResource = OmReferenceObjectById( ObjectTypeResource, quorumId );
|
|||
|
if (pResource == NULL) {
|
|||
|
Status = ERROR_RESOURCE_NOT_FOUND;
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[API] s_ApiGetQuorumResource Failed to find quorum resource object, error %1!u!\n",
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate buffer for returning the resource name.
|
|||
|
//
|
|||
|
pszResourceName = MIDL_user_allocate((lstrlenW(OmObjectName(pResource))+1)*sizeof(WCHAR));
|
|||
|
if (pszResourceName == NULL) {
|
|||
|
|
|||
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
lstrcpyW(pszResourceName, OmObjectName(pResource));
|
|||
|
|
|||
|
//
|
|||
|
// Get the root path for cluster temporary files
|
|||
|
//
|
|||
|
idMaxSize = 0;
|
|||
|
idSize = 0;
|
|||
|
|
|||
|
Status = DmQuerySz( DmQuorumKey,
|
|||
|
cszPath,
|
|||
|
(LPWSTR*)&pszLogPath,
|
|||
|
&idMaxSize,
|
|||
|
&idSize);
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[API] s_ApiGetQuorumResource Failed to get the log path, error %1!u!.\n",
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Allocate buffer for returning the resource name.
|
|||
|
//
|
|||
|
pszClusFileRootPath = MIDL_user_allocate((lstrlenW(pszLogPath)+1)*sizeof(WCHAR));
|
|||
|
if (pszClusFileRootPath == NULL) {
|
|||
|
|
|||
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
lstrcpyW(pszClusFileRootPath, pszLogPath);
|
|||
|
|
|||
|
|
|||
|
*ppszResourceName = pszResourceName;
|
|||
|
*ppszClusFileRootPath = pszClusFileRootPath;
|
|||
|
|
|||
|
DmGetQuorumLogMaxSize(pdwMaxQuorumLogSize);
|
|||
|
|
|||
|
FnExit:
|
|||
|
if (pResource) OmDereferenceObject(pResource);
|
|||
|
if (pszLogPath) LocalFree(pszLogPath);
|
|||
|
if (quorumId) LocalFree(quorumId);
|
|||
|
if (Status != ERROR_SUCCESS)
|
|||
|
{
|
|||
|
if (pszResourceName) MIDL_user_free(pszResourceName);
|
|||
|
if (pszClusFileRootPath) MIDL_user_free(pszClusFileRootPath);
|
|||
|
}
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiSetQuorumResource(
|
|||
|
IN HRES_RPC hResource,
|
|||
|
IN LPCWSTR lpszClusFileRootPath,
|
|||
|
IN DWORD dwMaxQuorumLogSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the current cluster quorum resource.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hResource - Supplies a handle to the resource that should be the cluster
|
|||
|
quorum resource.
|
|||
|
|
|||
|
lpszClusFileRootPath - The root path for storing
|
|||
|
permananent cluster maintenace files.
|
|||
|
|
|||
|
dwMaxQuorumLogSize - The maximum size of the quorum logs before they are
|
|||
|
reset by checkpointing. If 0, the default is used.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
PFM_RESOURCE Resource;
|
|||
|
LPCWSTR lpszPathName = NULL;
|
|||
|
|
|||
|
API_CHECK_INIT();
|
|||
|
VALIDATE_RESOURCE_EXISTS(Resource, hResource);
|
|||
|
|
|||
|
//
|
|||
|
// Chittur Subbaraman (chitturs) - 1/6/99
|
|||
|
//
|
|||
|
// Check whether the user is passing in a pointer to a NULL character
|
|||
|
// as the second parameter. If not, pass the parameter passed by the
|
|||
|
// user
|
|||
|
//
|
|||
|
if ( ( ARGUMENT_PRESENT( lpszClusFileRootPath ) ) &&
|
|||
|
( *lpszClusFileRootPath != L'\0' ) )
|
|||
|
{
|
|||
|
lpszPathName = lpszClusFileRootPath;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Let FM decide if this operation can be completed.
|
|||
|
//
|
|||
|
Status = FmSetQuorumResource(Resource, lpszPathName, dwMaxQuorumLogSize );
|
|||
|
if ( Status != ERROR_SUCCESS ) {
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//Update the path
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiSetNetworkPriorityOrder(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
IN DWORD NetworkCount,
|
|||
|
IN LPWSTR *NetworkIdList
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the priority order for internal (intracluster) networks.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used
|
|||
|
|
|||
|
NetworkCount - The count of networks in the NetworkList
|
|||
|
|
|||
|
NetworkList - An array of pointers to network IDs.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
API_CHECK_INIT();
|
|||
|
|
|||
|
return(
|
|||
|
NmSetNetworkPriorityOrder(
|
|||
|
NetworkCount,
|
|||
|
NetworkIdList
|
|||
|
)
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiBackupClusterDatabase(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
IN LPCWSTR lpszPathName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Requests for backup of the quorum log file and the checkpoint file.
|
|||
|
|
|||
|
Argument:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used
|
|||
|
|
|||
|
lpszPathName - The directory path name where the files have to be
|
|||
|
backed up. This path must be visible to the node
|
|||
|
on which the quorum resource is online.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
API_CHECK_INIT();
|
|||
|
|
|||
|
//
|
|||
|
// Let FM decide if this operation can be completed.
|
|||
|
//
|
|||
|
return( FmBackupClusterDatabase( lpszPathName ) );
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
ApipValidateClusterName(
|
|||
|
IN LPCWSTR lpszNewName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Check whether the new cluster name is valid
|
|||
|
|
|||
|
Argument:
|
|||
|
|
|||
|
lpszNewName - New cluster name.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD dwSize = 0;
|
|||
|
PFM_RESOURCE pResource = NULL;
|
|||
|
DWORD dwStatus;
|
|||
|
DWORD dwBytesReturned;
|
|||
|
DWORD dwRequired;
|
|||
|
LPWSTR lpszClusterNameResource = NULL;
|
|||
|
CLUSPROP_BUFFER_HELPER ListEntry;
|
|||
|
PVOID pPropList = NULL;
|
|||
|
DWORD cbListSize = 0;
|
|||
|
DWORD dwBufferSize;
|
|||
|
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[API] ApipValidateClusterName: Validating new name %1!ws!...\n",
|
|||
|
lpszNewName);
|
|||
|
|
|||
|
dwStatus = DmQuerySz( DmClusterParametersKey,
|
|||
|
CLUSREG_NAME_CLUS_CLUSTER_NAME_RES,
|
|||
|
&lpszClusterNameResource,
|
|||
|
&dwSize,
|
|||
|
&dwSize );
|
|||
|
|
|||
|
if ( dwStatus != ERROR_SUCCESS )
|
|||
|
{
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[API] ApipValidateClusterName: Failed to get cluster name resource from registry, error %1!u!...\n",
|
|||
|
dwStatus);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reference the specified resource ID.
|
|||
|
//
|
|||
|
pResource = OmReferenceObjectById( ObjectTypeResource,
|
|||
|
lpszClusterNameResource );
|
|||
|
|
|||
|
if ( pResource == NULL )
|
|||
|
{
|
|||
|
dwStatus = ERROR_RESOURCE_NOT_FOUND;
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[API] ApipValidateClusterName: Failed to find cluster name resource, %1!u!...\n",
|
|||
|
dwStatus);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
dwBufferSize = sizeof( ListEntry.pList->nPropertyCount ) +
|
|||
|
sizeof( *ListEntry.pName ) +
|
|||
|
ALIGN_CLUSPROP( ( lstrlenW( CLUSREG_NAME_NET_NAME ) + 1 ) * sizeof( WCHAR ) ) +
|
|||
|
sizeof( *ListEntry.pStringValue ) +
|
|||
|
ALIGN_CLUSPROP( ( lstrlenW( lpszNewName ) + 1 ) * sizeof( WCHAR ) ) +
|
|||
|
sizeof( *ListEntry.pSyntax );
|
|||
|
|
|||
|
ListEntry.pb = (PBYTE) LocalAlloc( LPTR, dwBufferSize );
|
|||
|
|
|||
|
if ( ListEntry.pb == NULL )
|
|||
|
{
|
|||
|
dwStatus = GetLastError();
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[API] ApipValidateClusterName: Error %1!u! in allocating memory...\n",
|
|||
|
dwStatus);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
pPropList = ListEntry.pb;
|
|||
|
|
|||
|
ListEntry.pList->nPropertyCount = 1;
|
|||
|
cbListSize += sizeof( ListEntry.pList->nPropertyCount );
|
|||
|
ListEntry.pb += sizeof( ListEntry.pList->nPropertyCount );
|
|||
|
|
|||
|
ListEntry.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
|
|||
|
ListEntry.pName->cbLength = ( lstrlenW( CLUSREG_NAME_NET_NAME ) + 1 ) * sizeof( WCHAR );
|
|||
|
lstrcpyW( ListEntry.pName->sz, CLUSREG_NAME_NET_NAME );
|
|||
|
cbListSize += sizeof( *ListEntry.pName ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
|
|||
|
ListEntry.pb += sizeof( *ListEntry.pName ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
|
|||
|
|
|||
|
ListEntry.pStringValue->Syntax.dw = CLUSPROP_SYNTAX_LIST_VALUE_SZ;
|
|||
|
ListEntry.pStringValue->cbLength = ( lstrlenW( lpszNewName ) + 1 ) * sizeof( WCHAR );
|
|||
|
lstrcpyW( ListEntry.pStringValue->sz, lpszNewName );
|
|||
|
cbListSize += sizeof( *ListEntry.pStringValue ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
|
|||
|
ListEntry.pb += sizeof( *ListEntry.pStringValue ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
|
|||
|
|
|||
|
ListEntry.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
|||
|
cbListSize += sizeof( *ListEntry.pSyntax );
|
|||
|
ListEntry.pb += sizeof( *ListEntry.pSyntax );
|
|||
|
|
|||
|
dwStatus = FmResourceControl( pResource,
|
|||
|
NULL,
|
|||
|
CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES,
|
|||
|
(PUCHAR)pPropList,
|
|||
|
cbListSize,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&dwBytesReturned,
|
|||
|
&dwRequired );
|
|||
|
|
|||
|
FnExit:
|
|||
|
LocalFree( lpszClusterNameResource );
|
|||
|
|
|||
|
LocalFree( pPropList );
|
|||
|
|
|||
|
if ( pResource != NULL )
|
|||
|
{
|
|||
|
OmDereferenceObject( pResource );
|
|||
|
}
|
|||
|
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[API] ApipValidateClusterName returns %1!u!...\n",
|
|||
|
dwStatus);
|
|||
|
|
|||
|
return( dwStatus );
|
|||
|
}
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
The set service account password API was added to the cluster
|
|||
|
service after Windows XP shipped. In order to add client-side clusapi.dll
|
|||
|
support to XP SP1 without breaking the XP SP1 build, this dummy server-side
|
|||
|
routine must be added, even though this code does not ship in XP SP1.
|
|||
|
|
|||
|
--*/
|
|||
|
error_status_t
|
|||
|
s_ApiSetServiceAccountPassword(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
IN LPWSTR lpszNewPassword,
|
|||
|
IN DWORD dwFlags,
|
|||
|
OUT IDL_CLUSTER_SET_PASSWORD_STATUS *ReturnStatusBufferPtr,
|
|||
|
IN DWORD ReturnStatusBufferSize,
|
|||
|
OUT DWORD *SizeReturned,
|
|||
|
OUT DWORD *ExpectedBufferSize
|
|||
|
)
|
|||
|
{
|
|||
|
return( ERROR_CALL_NOT_IMPLEMENTED );
|
|||
|
} // s_ApiSetServiceAccountPassword
|