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.
 
 
 
 
 
 

1591 lines
42 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
ioctl.c
Abstract:
Node control functions.
Author:
John Vert (jvert) 2-Mar-1997
Revision History:
--*/
#include "nmp.h"
#define SECURITY_WIN32
#include <Security.h>
//
// Node Common properties.
//
//
// Read-Write Common Properties.
//
RESUTIL_PROPERTY_ITEM
NmpNodeCommonProperties[] = {
{ CLUSREG_NAME_NODE_DESC, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, 0 },
{ CLUSREG_NAME_CLUS_EVTLOG_PROPAGATION, NULL, CLUSPROP_FORMAT_DWORD, 1, 0, 1, 0},
{ NULL, NULL, 0, 0, 0, 0, 0 } };
//
// Read-Only Common Properties.
//
RESUTIL_PROPERTY_ITEM
NmpNodeROCommonProperties[] = {
{ CLUSREG_NAME_NODE_NAME, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY },
{ CLUSREG_NAME_NODE_HIGHEST_VERSION, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY },
{ CLUSREG_NAME_NODE_LOWEST_VERSION, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY },
{ CLUSREG_NAME_NODE_MAJOR_VERSION, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY},
{ CLUSREG_NAME_NODE_MINOR_VERSION, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY},
{ CLUSREG_NAME_NODE_BUILD_NUMBER, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY},
{ CLUSREG_NAME_NODE_CSDVERSION, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY},
{ NULL, NULL, 0, 0, 0, 0, 0 } };
//
// Cluster registry API function pointers.
//
CLUSTER_REG_APIS
NmpClusterRegApis = {
(PFNCLRTLCREATEKEY) DmRtlCreateKey,
(PFNCLRTLOPENKEY) DmRtlOpenKey,
(PFNCLRTLCLOSEKEY) DmCloseKey,
(PFNCLRTLSETVALUE) DmSetValue,
(PFNCLRTLQUERYVALUE) DmQueryValue,
(PFNCLRTLENUMVALUE) DmEnumValue,
(PFNCLRTLDELETEVALUE) DmDeleteValue,
NULL,
NULL,
NULL
};
//
// Local Function Prototypes
//
DWORD
NmpNodeControl(
IN PNM_NODE Node,
IN DWORD ControlCode,
IN PUCHAR InBuffer,
IN DWORD InBufferSize,
OUT PUCHAR OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required,
IN BOOLEAN AllowForwarding
);
DWORD
NmpNodeEnumCommonProperties(
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
);
DWORD
NmpNodeGetCommonProperties(
IN PNM_NODE Node,
IN BOOL ReadOnly,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
);
DWORD
NmpNodeValidateCommonProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
);
DWORD
NmpNodeSetCommonProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
);
DWORD
NmpNodeEnumPrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
);
DWORD
NmpNodeGetPrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
);
DWORD
NmpNodeValidatePrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
);
DWORD
NmpNodeSetPrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
);
DWORD
NmpNodeGetFlags(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
);
DWORD
NmpNodeGetClusterServiceAccountName(
IN PNM_NODE Node,
IN PUCHAR InBuffer,
IN DWORD InBufferSize,
OUT PUCHAR OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required,
IN BOOLEAN AllowForwarding
);
/////////////////////////////////////////////////////////////////////////////
//
// Remote procedures called by other nodes
//
/////////////////////////////////////////////////////////////////////////////
error_status_t
s_NmRpcNodeControl(
IN handle_t IDL_handle,
IN LPCWSTR NodeId,
IN DWORD ControlCode,
IN UCHAR *InBuffer,
IN DWORD InBufferSize,
OUT UCHAR *OutBuffer,
IN DWORD OutBufferSize,
OUT DWORD *BytesReturned,
OUT DWORD *Required
)
/*++
Routine Description:
Server-side routine for handling forwarded node control requests.
Arguments:
IDL_handle - RPC binding handle. Not used.
NodeId - Supplies the ID of the node to be controlled.
ControlCode- Supplies the control code that defines the
structure and action of the node control.
Values of ControlCode between 0 and 0x10000000 are reserved
for future definition and use by Microsoft. All other values
are available for use by ISVs
InBuffer- Supplies a pointer to the input buffer to be passed
to the node.
InBufferSize- Supplies the size, in bytes, of the data pointed
to by lpInBuffer.
OutBuffer- Supplies a pointer to the output buffer to be
filled in by the node.
OutBufferSize- Supplies the size, in bytes, of the available
space pointed to by OutBuffer.
BytesReturned - Returns the number of bytes of lpOutBuffer
actually filled in by the node.
Required - Returns the number of bytes if the OutBuffer is not big
enough.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
PNM_NODE node;
DWORD status;
if (!NmpEnterApi(NmStateOnline)) {
ClRtlLogPrint(LOG_NOISE,
"[NM] Not in valid state to process forwarded NodeControl "
"request.\n"
);
return ERROR_NODE_NOT_AVAILABLE;
}
node = OmReferenceObjectById(ObjectTypeNode, NodeId);
if (node != NULL) {
status = NmpNodeControl(
node,
ControlCode,
InBuffer,
InBufferSize,
OutBuffer,
OutBufferSize,
BytesReturned,
Required,
FALSE // Prohibit forwarding to another node
);
OmDereferenceObject(node);
}
else {
status = ERROR_CLUSTER_NODE_NOT_FOUND;
ClRtlLogPrint(LOG_UNUSUAL,
"[NM] s_NmRpcNodeControl: Node %1!ws! does not exist.\n",
NodeId
);
}
NmpLeaveApi();
return status;
}// s_NmRpcNodeControl()
/////////////////////////////////////////////////////////////////////////////
//
// Routines called by other cluster service components
//
/////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
NmNodeControl(
IN PNM_NODE Node,
IN PNM_NODE HostNode OPTIONAL,
IN DWORD ControlCode,
IN PUCHAR InBuffer,
IN DWORD InBufferSize,
OUT PUCHAR OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
Provides for arbitrary communication and control between an application
and a specific instance of a node.
Arguments:
Node - Supplies the node to be controlled.
HostNode - Supplies the host node on which the resource control should
be delivered. If this is NULL, the local node is used. Not honored!
ControlCode- Supplies the control code that defines the
structure and action of the resource control.
Values of ControlCode between 0 and 0x10000000 are reserved
for future definition and use by Microsoft. All other values
are available for use by ISVs
InBuffer- Supplies a pointer to the input buffer to be passed
to the resource.
InBufferSize- Supplies the size, in bytes, of the data pointed
to by lpInBuffer..
OutBuffer- Supplies a pointer to the output buffer to be
filled in by the resource..
OutBufferSize- Supplies the size, in bytes, of the available
space pointed to by lpOutBuffer.
BytesReturned - Returns the number of bytes of lpOutBuffer
actually filled in by the resource..
Required - Returns the number of bytes if the OutBuffer is not big
enough.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
Notes:
This routine assumes that a reference has been placed on the object
specified by the Node argument.
--*/
{
DWORD status;
if (NmpEnterApi(NmStateOnline)) {
status = NmpNodeControl(
Node,
ControlCode,
InBuffer,
InBufferSize,
OutBuffer,
OutBufferSize,
BytesReturned,
Required,
TRUE // Permit forwarding to another node
);
NmpLeaveApi();
}
else {
status = ERROR_NODE_NOT_AVAILABLE;
ClRtlLogPrint(LOG_NOISE,
"[NM] Not in valid state to process NodeControl request.\n"
);
}
return(status);
} // NmNodeControl
/////////////////////////////////////////////////////////////////////////////
//
// Local routines
//
/////////////////////////////////////////////////////////////////////////////
DWORD
NmpRpcNodeControlWrapper(
IN PNM_NODE TargetNode,
IN DWORD ControlCode,
IN PUCHAR InBuffer,
IN DWORD InBufferSize,
OUT PUCHAR OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
This routine is a wrapper of routine NmRpcNodeControl.
Verifies that the state of TargetNode is UP or PAUSED.
Call NmRpcNodeControl.
Translate return status code of NmRpcNodeControl based on
whether TargetNode is up or down.
Arguments:
TargetNode - A pointer to the object for the node that was the
target of the remote call.
InBuffer- Supplies a pointer to the input buffer to be passed
to the node.
InBufferSize- Supplies the size, in bytes, of the data pointed
to by lpInBuffer.
OutBuffer- Supplies a pointer to the output buffer to be
filled in by the node.
OutBufferSize- Supplies the size, in bytes, of the available
space pointed to by OutBuffer.
BytesReturned - Returns the number of bytes of lpOutBuffer
actually filled in by the node.
Required - Returns the number of bytes if the OutBuffer is not big
enough.
Return Value:
The translated status code of NmRpcNodeControl.
--*/
{
DWORD returnStatus;
ClRtlLogPrint(
LOG_NOISE,
"[NM] Forwarding request for node control code (%1!u!) "
"to node %2!u!.\n",
ControlCode,
TargetNode->NodeId
);
NmpAcquireLock();
if (NM_NODE_UP(TargetNode)) {
NmpReleaseLock();
CL_ASSERT(Session[TargetNode->NodeId] != NULL);
returnStatus = NmRpcNodeControl(
Session[TargetNode->NodeId],
OmObjectId(TargetNode),
ControlCode,
InBuffer,
InBufferSize,
OutBuffer,
OutBufferSize,
BytesReturned,
Required
);
if (returnStatus != RPC_S_OK) {
//
// Translate the status for return to the
// cluster API client.
//
NmpAcquireLock();
if (!NM_NODE_UP(TargetNode)) {
//
// The node is down.
//
switch ( returnStatus ) {
//
// These constants are copied from ReconnectCluster() in file
// clusapi\reconect.c
//
case RPC_S_CALL_FAILED:
case RPC_S_INVALID_BINDING:
case RPC_S_SERVER_UNAVAILABLE:
case RPC_S_SERVER_TOO_BUSY:
case RPC_S_UNKNOWN_IF:
case RPC_S_CALL_FAILED_DNE:
case RPC_X_SS_IN_NULL_CONTEXT:
case RPC_S_UNKNOWN_AUTHN_SERVICE:
returnStatus = ERROR_HOST_NODE_NOT_AVAILABLE;
break;
default:
//
// Don't translate
//
break;
} // switch
}
else {
//
// The node is up. Return the status as is. If the status is
// RPC_S_CALL_FAILED, RPC_S_INVALID_BINDING, or
// RPC_S_UNKNOWN_AUTHN_SERVICE, then the cluster API client will
// go through the reconnect procedure when it receives the status.
// For now, that seems to be the right thing to do, even though the
// client is talking to the local node, which is up. It is not clear
// what alternate status codes we would map these to otherwise.
//
}
NmpReleaseLock();
} // if (returnStatus != RPC_S_OK)
} // if (NM_NODE_UP(Node))
else
{
NmpReleaseLock();
ClRtlLogPrint(
LOG_NOISE,
"[NM] Node %1!u! is not up. Cannot forward request "
"for node control code (%2!u!) to that node.\n",
TargetNode->NodeId,
ControlCode
);
returnStatus = ERROR_HOST_NODE_NOT_AVAILABLE;
}
return(returnStatus);
} // NmpRpcNodeControlWrapper
DWORD
NmpNodeControl(
IN PNM_NODE Node,
IN DWORD ControlCode,
IN PUCHAR InBuffer,
IN DWORD InBufferSize,
OUT PUCHAR OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required,
IN BOOLEAN AllowForwarding
)
/*++
Routine Description:
Provides for arbitrary communication and control between an application
and a specific instance of a node.
Arguments:
Node - Supplies the node to be controlled.
ControlCode- Supplies the control code that defines the
structure and action of the node control.
Values of ControlCode between 0 and 0x10000000 are reserved
for future definition and use by Microsoft. All other values
are available for use by ISVs
InBuffer- Supplies a pointer to the input buffer to be passed
to the node.
InBufferSize- Supplies the size, in bytes, of the data pointed
to by lpInBuffer.
OutBuffer- Supplies a pointer to the output buffer to be
filled in by the node.
OutBufferSize- Supplies the size, in bytes, of the available
space pointed to by OutBuffer.
BytesReturned - Returns the number of bytes of lpOutBuffer
actually filled in by the node.
Required - Returns the number of bytes if the OutBuffer is not big
enough.
AllowForwarding - Indicates whether the request may be forwarded to
another node for execution. This is a safety check to
prevent the accidental introduction of cycles.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
Notes:
This routine assumes that a reference has been placed on the object
specified by the Node argument.
--*/
{
DWORD status;
HDMKEY nodeKey;
CLUSPROP_BUFFER_HELPER props;
DWORD bufSize;
BOOLEAN success;
//
// Cluster service ioctls were designed to have access modes, e.g.
// read-only, read-write, etc. These access modes are not implemented.
// If eventually they are implemented, an access mode check should be
// placed here.
//
if ( CLUSCTL_GET_CONTROL_OBJECT( ControlCode ) != CLUS_OBJECT_NODE ) {
return(ERROR_INVALID_FUNCTION);
}
nodeKey = DmOpenKey( DmNodesKey,
OmObjectId( Node ),
MAXIMUM_ALLOWED
);
if ( nodeKey == NULL ) {
return(GetLastError());
}
switch ( ControlCode ) {
case CLUSCTL_NODE_UNKNOWN:
*BytesReturned = 0;
status = ERROR_SUCCESS;
break;
case CLUSCTL_NODE_GET_NAME:
if ( OmObjectName( Node ) == NULL ) {
return(ERROR_NOT_READY);
}
props.pb = OutBuffer;
bufSize = (lstrlenW( OmObjectName( Node ) ) + 1) * sizeof(WCHAR);
if ( bufSize > OutBufferSize ) {
*Required = bufSize;
*BytesReturned = 0;
status = ERROR_MORE_DATA;
} else {
lstrcpyW( props.psz, OmObjectName( Node ) );
*BytesReturned = bufSize;
*Required = 0;
status = ERROR_SUCCESS;
}
break;
case CLUSCTL_NODE_GET_CLUSTER_SERVICE_ACCOUNT_NAME:
status = NmpNodeGetClusterServiceAccountName(
Node,
InBuffer,
InBufferSize,
OutBuffer,
OutBufferSize,
BytesReturned,
Required,
AllowForwarding
);
break;
case CLUSCTL_NODE_GET_ID:
if ( OmObjectId( Node ) == NULL ) {
return(ERROR_NOT_READY);
}
props.pb = OutBuffer;
bufSize = (lstrlenW( OmObjectId( Node ) ) + 1) * sizeof(WCHAR);
if ( bufSize > OutBufferSize ) {
*Required = bufSize;
*BytesReturned = 0;
status = ERROR_MORE_DATA;
} else {
lstrcpyW( props.psz, OmObjectId( Node ) );
*BytesReturned = bufSize;
*Required = 0;
status = ERROR_SUCCESS;
}
break;
case CLUSCTL_NODE_ENUM_COMMON_PROPERTIES:
status = NmpNodeEnumCommonProperties( OutBuffer,
OutBufferSize,
BytesReturned,
Required );
break;
case CLUSCTL_NODE_GET_RO_COMMON_PROPERTIES:
status = NmpNodeGetCommonProperties( Node,
TRUE, // ReadOnly
nodeKey,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
break;
case CLUSCTL_NODE_GET_COMMON_PROPERTIES:
status = NmpNodeGetCommonProperties( Node,
FALSE, // ReadOnly
nodeKey,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
break;
case CLUSCTL_NODE_VALIDATE_COMMON_PROPERTIES:
status = NmpNodeValidateCommonProperties( Node,
nodeKey,
InBuffer,
InBufferSize );
break;
case CLUSCTL_NODE_SET_COMMON_PROPERTIES:
status = NmpNodeSetCommonProperties( Node,
nodeKey,
InBuffer,
InBufferSize );
break;
case CLUSCTL_NODE_ENUM_PRIVATE_PROPERTIES:
status = NmpNodeEnumPrivateProperties( Node,
nodeKey,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
break;
case CLUSCTL_NODE_GET_RO_PRIVATE_PROPERTIES:
if ( OutBufferSize < sizeof(DWORD) ) {
*BytesReturned = 0;
*Required = sizeof(DWORD);
if ( OutBuffer == NULL ) {
status = ERROR_SUCCESS;
} else {
status = ERROR_MORE_DATA;
}
} else {
LPDWORD ptrDword = (LPDWORD) OutBuffer;
*ptrDword = 0;
*BytesReturned = sizeof(DWORD);
status = ERROR_SUCCESS;
}
break;
case CLUSCTL_NODE_GET_PRIVATE_PROPERTIES:
status = NmpNodeGetPrivateProperties( Node,
nodeKey,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
break;
case CLUSCTL_NODE_VALIDATE_PRIVATE_PROPERTIES:
status = NmpNodeValidatePrivateProperties( Node,
nodeKey,
InBuffer,
InBufferSize );
break;
case CLUSCTL_NODE_SET_PRIVATE_PROPERTIES:
status = NmpNodeSetPrivateProperties( Node,
nodeKey,
InBuffer,
InBufferSize );
break;
case CLUSCTL_NODE_GET_CHARACTERISTICS:
if ( OutBufferSize < sizeof(DWORD) ) {
*BytesReturned = 0;
*Required = sizeof(DWORD);
if ( OutBuffer == NULL ) {
status = ERROR_SUCCESS;
} else {
status = ERROR_MORE_DATA;
}
} else {
*BytesReturned = sizeof(DWORD);
*(LPDWORD)OutBuffer = 0;
status = ERROR_SUCCESS;
}
break;
case CLUSCTL_NODE_GET_FLAGS:
status = NmpNodeGetFlags( Node,
nodeKey,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
break;
default:
status = ERROR_INVALID_FUNCTION;
break;
}
DmCloseKey( nodeKey );
return(status);
} // NmpNodeControl
DWORD
NmpNodeEnumCommonProperties(
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
Enumerates the common property names for a given node.
Arguments:
OutBuffer - Supplies the output buffer.
OutBufferSize - Supplies the size of the output buffer.
BytesReturned - The number of bytes returned in OutBuffer.
Required - The required number of bytes if OutBuffer is too small.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
//
// Get the common properties.
//
status = ClRtlEnumProperties( NmpNodeCommonProperties,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
return(status);
} // NmpNodeEnumCommonProperties
DWORD
NmpNodeGetCommonProperties(
IN PNM_NODE Node,
IN BOOL ReadOnly,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
Gets the common properties for a given node.
Arguments:
Node - Supplies the node.
ReadOnly - TRUE if the read-only properties should be read. FALSE otherwise.
RegistryKey - Supplies the registry key for this node.
OutBuffer - Supplies the output buffer.
OutBufferSize - Supplies the size of the output buffer.
BytesReturned - The number of bytes returned in OutBuffer.
Required - The required number of bytes if OutBuffer is too small.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
PRESUTIL_PROPERTY_ITEM propertyTable;
if ( ReadOnly ) {
propertyTable = NmpNodeROCommonProperties;
} else {
propertyTable = NmpNodeCommonProperties;
}
//
// Get the common properties.
//
status = ClRtlGetProperties( RegistryKey,
&NmpClusterRegApis,
propertyTable,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
return(status);
} // NmpNodeGetCommonProperties
DWORD
NmpNodeValidateCommonProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
)
/*++
Routine Description:
Validates the common properties for a given node.
Arguments:
Node - Supplies the node object.
InBuffer - Supplies the input buffer.
InBufferSize - Supplies the size of the input buffer.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
//
// Validate the property list.
//
status = ClRtlVerifyPropertyTable( NmpNodeCommonProperties,
NULL, // Reserved
FALSE, // Don't allow unknowns
InBuffer,
InBufferSize,
NULL );
if ( status != ERROR_SUCCESS ) {
ClRtlLogPrint( LOG_CRITICAL,
"[NM] ValidateCommonProperties, error in verify routine.\n");
}
return(status);
} // NmpNodeValidateCommonProperties
DWORD
NmpNodeSetCommonProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
)
/*++
Routine Description:
Sets the common properties for a given node.
Arguments:
Node - Supplies the node object.
InBuffer - Supplies the input buffer.
InBufferSize - Supplies the size of the input buffer.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
//
// Validate the property list.
//
status = ClRtlVerifyPropertyTable( NmpNodeCommonProperties,
NULL, // Reserved
FALSE, // Don't allow unknowns
InBuffer,
InBufferSize,
NULL );
if ( status == ERROR_SUCCESS ) {
status = ClRtlSetPropertyTable( NULL,
RegistryKey,
&NmpClusterRegApis,
NmpNodeCommonProperties,
NULL, // Reserved
FALSE, // Don't allow unknowns
InBuffer,
InBufferSize,
FALSE, // bForceWrite
NULL );
if ( status != ERROR_SUCCESS ) {
ClRtlLogPrint( LOG_CRITICAL,
"[NM] SetCommonProperties, error in set routine.\n");
}
} else {
ClRtlLogPrint( LOG_CRITICAL,
"[NM] SetCommonProperties, error in verify routine.\n");
}
return(status);
} // NmpNodeSetCommonProperties
DWORD
NmpNodeEnumPrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
Enumerates the private property names for a given node.
Arguments:
Node - Supplies the node object.
RegistryKey - Registry key for the node.
OutBuffer - Supplies the output buffer.
OutBufferSize - Supplies the size of the output buffer.
BytesReturned - The number of bytes returned in OutBuffer.
Required - The required number of bytes if OutBuffer is too small.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
HDMKEY parametersKey;
DWORD totalBufferSize = 0;
*BytesReturned = 0;
*Required = 0;
//
// Clear the output buffer
//
ZeroMemory( OutBuffer, OutBufferSize );
//
// Open the cluster node parameters key.
//
parametersKey = DmOpenKey( RegistryKey,
CLUSREG_KEYNAME_PARAMETERS,
MAXIMUM_ALLOWED );
if ( parametersKey == NULL ) {
status = GetLastError();
if ( status == ERROR_FILE_NOT_FOUND ) {
status = ERROR_SUCCESS;
}
return(status);
}
//
// Enum the private properties for the node.
//
status = ClRtlEnumPrivateProperties( parametersKey,
&NmpClusterRegApis,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
DmCloseKey( parametersKey );
return(status);
} // NmpNodeEnumPrivateProperties
DWORD
NmpNodeGetPrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
Gets the private properties for a given node.
Arguments:
Node - Supplies the node object.
OutBuffer - Supplies the output buffer.
OutBufferSize - Supplies the size of the output buffer.
BytesReturned - The number of bytes returned in OutBuffer.
Required - The required number of bytes if OutBuffer is too small.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
HDMKEY parametersKey;
DWORD totalBufferSize = 0;
*BytesReturned = 0;
*Required = 0;
//
// Clear the output buffer
//
ZeroMemory( OutBuffer, OutBufferSize );
//
// Open the cluster node parameters key.
//
parametersKey = DmOpenKey( RegistryKey,
CLUSREG_KEYNAME_PARAMETERS,
MAXIMUM_ALLOWED );
if ( parametersKey == NULL ) {
status = GetLastError();
if ( status == ERROR_FILE_NOT_FOUND ) {
//
// If we don't have a parameters key, then return an
// item count of 0 and an endmark.
//
totalBufferSize = sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
if ( OutBufferSize < totalBufferSize ) {
*Required = totalBufferSize;
status = ERROR_MORE_DATA;
} else {
// This is somewhat redundant since we zero the
// buffer above, but it's here for clarity.
CLUSPROP_BUFFER_HELPER buf;
buf.pb = OutBuffer;
buf.pList->nPropertyCount = 0;
buf.pdw++;
buf.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
*BytesReturned = totalBufferSize;
status = ERROR_SUCCESS;
}
}
return(status);
}
//
// Get private properties for the node.
//
status = ClRtlGetPrivateProperties( parametersKey,
&NmpClusterRegApis,
OutBuffer,
OutBufferSize,
BytesReturned,
Required );
DmCloseKey( parametersKey );
return(status);
} // NmpNodeGetPrivateProperties
DWORD
NmpNodeValidatePrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
)
/*++
Routine Description:
Validates the private properties for a given node.
Arguments:
Node - Supplies the node object.
RegistryKey - Registry key for the node.
InBuffer - Supplies the input buffer.
InBufferSize - Supplies the size of the input buffer.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
//
// Validate the property list.
//
status = ClRtlVerifyPrivatePropertyList( InBuffer,
InBufferSize );
return(status);
} // NmpNodeValidatePrivateProperties
DWORD
NmpNodeSetPrivateProperties(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
IN PVOID InBuffer,
IN DWORD InBufferSize
)
/*++
Routine Description:
Sets the private properties for a given node.
Arguments:
Node - Supplies the node object.
RegistryKey - Registry key for the node.
InBuffer - Supplies the input buffer.
InBufferSize - Supplies the size of the input buffer.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
HDMKEY parametersKey;
DWORD disposition;
//
// Validate the property list.
//
status = ClRtlVerifyPrivatePropertyList( InBuffer,
InBufferSize );
if ( status == ERROR_SUCCESS ) {
//
// Open the cluster node\xx\parameters key
//
parametersKey = DmOpenKey( RegistryKey,
CLUSREG_KEYNAME_PARAMETERS,
MAXIMUM_ALLOWED );
if ( parametersKey == NULL ) {
status = GetLastError();
if ( status == ERROR_FILE_NOT_FOUND ) {
//
// Try to create the parameters key.
//
parametersKey = DmCreateKey( RegistryKey,
CLUSREG_KEYNAME_PARAMETERS,
0,
KEY_READ | KEY_WRITE,
NULL,
&disposition );
if ( parametersKey == NULL ) {
status = GetLastError();
return(status);
}
}
}
status = ClRtlSetPrivatePropertyList( NULL, // IN HANDLE hXsaction
parametersKey,
&NmpClusterRegApis,
InBuffer,
InBufferSize );
DmCloseKey( parametersKey );
}
return(status);
} // NmpNodeSetPrivateProperties
DWORD
NmpNodeGetFlags(
IN PNM_NODE Node,
IN HDMKEY RegistryKey,
OUT PVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required
)
/*++
Routine Description:
Gets the flags for a given node.
Arguments:
Node - Supplies the node.
RegistryKey - Registry key for the node.
OutBuffer - Supplies the output buffer.
OutBufferSize - Supplies the size of the output buffer.
BytesReturned - The number of bytes returned in OutBuffer.
Required - The required number of bytes if OutBuffer is too small.
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
*BytesReturned = 0;
if ( OutBufferSize < sizeof(DWORD) ) {
*Required = sizeof(DWORD);
if ( OutBuffer == NULL ) {
status = ERROR_SUCCESS;
} else {
status = ERROR_MORE_DATA;
}
} else {
DWORD valueType;
//
// Read the Flags value for the node.
//
*BytesReturned = OutBufferSize;
status = DmQueryValue( RegistryKey,
CLUSREG_NAME_FLAGS,
&valueType,
OutBuffer,
BytesReturned );
if ( status == ERROR_FILE_NOT_FOUND ) {
*BytesReturned = sizeof(DWORD);
*(LPDWORD)OutBuffer = 0;
status = ERROR_SUCCESS;
}
}
return(status);
} // NmpNodeGetFlags
DWORD
NmpNodeGetClusterServiceAccountName(
IN PNM_NODE Node,
IN PUCHAR InBuffer,
IN DWORD InBufferSize,
OUT PUCHAR OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesReturned,
OUT LPDWORD Required,
IN BOOLEAN AllowForwarding
)
/*++
Routine Description:
Processes a node control request to obtain the name of the user account
under which the cluster service is running on the specified node.
Arguments:
Node - Supplies the node to be controlled.
InBuffer- Supplies a pointer to the input buffer to be passed
to the node.
InBufferSize- Supplies the size, in bytes, of the data pointed
to by lpInBuffer.
OutBuffer- Supplies a pointer to the output buffer to be
filled in by the node.
OutBufferSize- Supplies the size, in bytes, of the available
space pointed to by OutBuffer.
BytesReturned - Returns the number of bytes of lpOutBuffer
actually filled in by the node.
Required - Returns the number of bytes if the OutBuffer is not big
enough.
AllowForwarding - Indicates whether the request may be forwarded to
another node for execution. This is a safety check to
prevent the accidental introduction of cycles.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
Notes:
This routine assumes that a reference has been placed on the object
specified by the Node argument.
--*/
{
DWORD status;
if ( Node->NodeId != NmLocalNodeId )
{
//
// Need to forward to the subject node for execution.
//
if (AllowForwarding)
{
status = NmpRpcNodeControlWrapper( Node,
CLUSCTL_NODE_GET_CLUSTER_SERVICE_ACCOUNT_NAME,
InBuffer,
InBufferSize,
OutBuffer,
OutBufferSize,
BytesReturned,
Required
);
}
else
{
ClRtlLogPrint(LOG_UNUSUAL,
"[NM] Not allowed to forward request for the cluster service "
"account name to node %1!u! - possible cycle.\n",
Node->NodeId
);
status = ERROR_INVALID_FUNCTION;
//
// Currently, this path should never be taken.
// If it is taken, then a cycle was probably introduced.
//
CL_ASSERT(AllowForwarding != FALSE);
}
}
else {
//
// The local node is the subject of the query, so
// we can execute this request locally.
//
BOOLEAN success;
ClRtlLogPrint(
LOG_NOISE,
"[NM] Processing request for the cluster service account name.\n"
);
*BytesReturned = OutBufferSize/sizeof(WCHAR);
success = GetUserNameExW(
NameUserPrincipal,
(LPWSTR)OutBuffer,
BytesReturned
);
*BytesReturned = *BytesReturned * sizeof(WCHAR);
if ( success ) {
status = ERROR_SUCCESS;
} else {
*Required = *BytesReturned;
*BytesReturned = 0;
status = GetLastError();
}
}
return status;
} // NmpNodeGetClusterServiceAccountName