|
|
/*++
Copyright (c) 1996-2000 Microsoft Corporation
Module Name:
cnapi.c
Abstract:
Cluster Network configuration APIs
Author:
Mike Massa (mikemas) 18-Mar-1996
Environment:
User Mode - Win32
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <clusapi.h>
#include <clusdef.h>
#include <ntddcnet.h>
#include <cnettest.h>
#include <cnetapi.h>
#include <clusrtl.h>
#include <winsock2.h>
#include <tdi.h>
#include <align.h>
//
// Private Support Routines.
//
static NTSTATUS OpenDevice( HANDLE *Handle, LPWSTR DeviceName, ULONG ShareAccess ) /*++
Routine Description:
This function opens a specified IO device.
Arguments:
Handle - pointer to location where the opened device Handle is returned.
DriverName - name of the device to be opened.
Return Value:
Windows Error Code.
--*/ { OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; UNICODE_STRING nameString; NTSTATUS status;
*Handle = NULL;
//
// Open a Handle to the device.
//
RtlInitUnicodeString(&nameString, DeviceName);
InitializeObjectAttributes( &objectAttributes, &nameString, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL );
status = NtCreateFile( Handle, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, ShareAccess, FILE_OPEN_IF, 0, NULL, 0 );
return(status);
} // OpenDevice
NTSTATUS DoIoctl( IN HANDLE Handle, IN DWORD IoctlCode, IN PVOID Request, IN DWORD RequestSize, IN PVOID Response, IN OUT PDWORD ResponseSize, IN LPOVERLAPPED Overlapped ) /*++
Routine Description:
Packages and issues an ioctl.
Arguments:
Handle - An open file Handle on which to issue the request.
IoctlCode - The IOCTL opcode.
Request - A pointer to the input buffer.
RequestSize - Size of the input buffer.
Response - A pointer to the output buffer.
ResponseSize - On input, the size in bytes of the output buffer. On output, the number of bytes returned in the output buffer.
Return Value:
NT Status Code.
--*/ { NTSTATUS status;
if (ARGUMENT_PRESENT(Overlapped)) { Overlapped->Internal = (ULONG_PTR) STATUS_PENDING;
status = NtDeviceIoControlFile( Handle, Overlapped->hEvent, NULL, (((DWORD_PTR) Overlapped->hEvent) & 1) ? NULL : Overlapped, (PIO_STATUS_BLOCK) &(Overlapped->Internal), IoctlCode, Request, RequestSize, Response, *ResponseSize );
} else { IO_STATUS_BLOCK ioStatusBlock = {0, 0}; HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (event != NULL) {
//
// Prevent operation from completing to a completion port.
//
event = (HANDLE) (((ULONG_PTR) event) | 1);
status = NtDeviceIoControlFile( Handle, event, NULL, NULL, &ioStatusBlock, IoctlCode, Request, RequestSize, Response, *ResponseSize );
if (status == STATUS_PENDING) { status = NtWaitForSingleObject( event, TRUE, NULL ); }
if (status == STATUS_SUCCESS) { status = ioStatusBlock.Status;
// NOTENOTE: on 64 bit this truncates might want to add > code
*ResponseSize = (ULONG)ioStatusBlock.Information; } else { *ResponseSize = 0; }
CloseHandle(event); } else { status = GetLastError(); } }
return(status);
} // DoIoctl
#define FACILITY_CODE_MASK 0x0FFF0000
#define FACILITY_CODE_SHIFT 16
#define SHIFTED_FACILITY_CLUSTER (FACILITY_CLUSTER_ERROR_CODE << FACILITY_CODE_SHIFT)
DWORD NtStatusToClusnetError( NTSTATUS Status ) { DWORD dosStatus;
if ( !((Status & FACILITY_CODE_MASK) == SHIFTED_FACILITY_CLUSTER) ) { dosStatus = RtlNtStatusToDosError(Status); } else { //dosStatus = (DWORD) Status;
switch ( Status ) {
case STATUS_CLUSTER_INVALID_NODE: dosStatus = ERROR_CLUSTER_INVALID_NODE; break;
case STATUS_CLUSTER_NODE_EXISTS: dosStatus = ERROR_CLUSTER_NODE_EXISTS; break;
case STATUS_CLUSTER_JOIN_IN_PROGRESS: dosStatus = ERROR_CLUSTER_JOIN_IN_PROGRESS; break;
case STATUS_CLUSTER_NODE_NOT_FOUND: dosStatus = ERROR_CLUSTER_NODE_NOT_FOUND; break;
case STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND: dosStatus = ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND; break;
case STATUS_CLUSTER_NETWORK_EXISTS: dosStatus = ERROR_CLUSTER_NETWORK_EXISTS; break;
case STATUS_CLUSTER_NETWORK_NOT_FOUND: dosStatus = ERROR_CLUSTER_NETWORK_NOT_FOUND; break;
case STATUS_CLUSTER_NETINTERFACE_EXISTS: dosStatus = ERROR_CLUSTER_NETINTERFACE_EXISTS; break;
case STATUS_CLUSTER_NETINTERFACE_NOT_FOUND: dosStatus =ERROR_CLUSTER_NETINTERFACE_NOT_FOUND; break;
case STATUS_CLUSTER_INVALID_REQUEST: dosStatus = ERROR_CLUSTER_INVALID_REQUEST; break;
case STATUS_CLUSTER_INVALID_NETWORK_PROVIDER: dosStatus = ERROR_CLUSTER_INVALID_NETWORK_PROVIDER; break;
case STATUS_CLUSTER_NODE_DOWN: dosStatus = ERROR_CLUSTER_NODE_DOWN; break;
case STATUS_CLUSTER_NODE_UNREACHABLE: dosStatus = ERROR_CLUSTER_NODE_UNREACHABLE; break;
case STATUS_CLUSTER_NODE_NOT_MEMBER: dosStatus = ERROR_CLUSTER_NODE_NOT_MEMBER; break;
case STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS: dosStatus = ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS; break;
case STATUS_CLUSTER_INVALID_NETWORK: dosStatus = ERROR_CLUSTER_INVALID_NETWORK; break;
case STATUS_CLUSTER_NODE_UP: dosStatus = ERROR_CLUSTER_NODE_UP; break;
case STATUS_CLUSTER_NODE_NOT_PAUSED: dosStatus = ERROR_CLUSTER_NODE_NOT_PAUSED; break;
case STATUS_CLUSTER_NO_SECURITY_CONTEXT: dosStatus = ERROR_CLUSTER_NO_SECURITY_CONTEXT; break;
case STATUS_CLUSTER_NETWORK_NOT_INTERNAL: dosStatus = ERROR_CLUSTER_NETWORK_NOT_INTERNAL; break;
case STATUS_CLUSTER_NODE_ALREADY_UP: dosStatus = ERROR_CLUSTER_NODE_ALREADY_UP; break;
case STATUS_CLUSTER_NODE_ALREADY_DOWN: dosStatus = ERROR_CLUSTER_NODE_ALREADY_DOWN; break;
case STATUS_CLUSTER_NETWORK_ALREADY_ONLINE: dosStatus = ERROR_CLUSTER_NETWORK_ALREADY_ONLINE; break;
case STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE: dosStatus = ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE; break;
case STATUS_CLUSTER_NODE_ALREADY_MEMBER: dosStatus = ERROR_CLUSTER_NODE_ALREADY_MEMBER; break;
default: dosStatus = (DWORD)Status; break; } }
return(dosStatus); }
//
// Public Routines
//
HANDLE ClusnetOpenControlChannel( IN ULONG ShareAccess ) { HANDLE handle = NULL; DWORD status;
status = OpenDevice(&handle, L"\\Device\\ClusterNetwork", ShareAccess);
if (status != ERROR_SUCCESS) { SetLastError(NtStatusToClusnetError(status)); }
return(handle);
} // ClusnetOpenControlChannel
DWORD ClusnetEnableShutdownOnClose( IN HANDLE ControlChannel ) { NTSTATUS status; ULONG responseSize = 0; CLUSNET_SHUTDOWN_ON_CLOSE_REQUEST request; DWORD requestSize = sizeof(request);
request.ProcessId = GetCurrentProcessId();
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_ENABLE_SHUTDOWN_ON_CLOSE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetEnableShutdownOnClose
DWORD ClusnetDisableShutdownOnClose( IN HANDLE ControlChannel ) { NTSTATUS status; ULONG responseSize = 0;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_DISABLE_SHUTDOWN_ON_CLOSE, NULL, 0, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetEnableShutdownOnClose
DWORD ClusnetInitialize( IN HANDLE ControlChannel, IN CL_NODE_ID LocalNodeId, IN ULONG MaxNodes, IN CLUSNET_NODE_UP_ROUTINE NodeUpRoutine, IN CLUSNET_NODE_DOWN_ROUTINE NodeDownRoutine, IN CLUSNET_CHECK_QUORUM_ROUTINE CheckQuorumRoutine, IN CLUSNET_HOLD_IO_ROUTINE HoldIoRoutine, IN CLUSNET_RESUME_IO_ROUTINE ResumeIoRoutine, IN CLUSNET_HALT_ROUTINE HaltRoutine ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CLUSNET_INITIALIZE_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.LocalNodeId = LocalNodeId; request.MaxNodes = MaxNodes;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_INITIALIZE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetInitialize
DWORD ClusnetShutdown( IN HANDLE ControlChannel ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; DWORD requestSize = 0; DWORD responseSize = 0;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_SHUTDOWN, NULL, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetShutdown
DWORD ClusnetRegisterNode( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_NODE_REG_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_REGISTER_NODE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetRegisterNode
DWORD ClusnetDeregisterNode( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_NODE_DEREG_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_DEREGISTER_NODE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetDeregisterNode
DWORD ClusnetRegisterNetwork( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, IN ULONG Priority, IN BOOLEAN Restricted ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_NETWORK_REG_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NetworkId; request.Priority = Priority; request.Restricted = Restricted;
status = DoIoctl( ControlChannel, IOCTL_CX_REGISTER_NETWORK, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetRegisterNetwork
DWORD ClusnetDeregisterNetwork( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_NETWORK_DEREG_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_DEREGISTER_NETWORK, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetDeregisterNetwork
DWORD ClusnetRegisterInterface( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId, IN ULONG Priority, IN PWSTR AdapterId, IN ULONG AdapterIdLength, IN PVOID TdiAddress, IN ULONG TdiAddressLength, OUT PULONG MediaStatus ) /*++
Routine Description:
Registers a node's interface on a network.
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
NodeId - The ID of the node for which to register the interface.
NetworkId - The ID of the network for which to register the interface.
Priority - The priority value assigned to the interface. If a value of zero is specified, the interface will inherit its priority from the network.
AdapterId - ID of adapter associated with interface AdapterIdLength - Length of buffer holding adapter ID, not including terminating UNICODE_NULL character
TdiAddress - A pointer to a TDI TRANSPORT_ADDRESS structure containing the transport address of the interface.
TdiAddressLength - The length, in bytes, of the TdiAddress buffer. MediaStatus - returned current status of media (e.g. cable disconnected) Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_INTERFACE_REG_REQUEST request; DWORD requestSize; CX_INTERFACE_REG_RESPONSE response; DWORD responseSize = sizeof(CX_INTERFACE_REG_RESPONSE); DWORD adapterIdOffset;
// calculate the size of the request structure without the adapter
// id string.
requestSize = FIELD_OFFSET(CX_INTERFACE_REG_REQUEST, TdiAddress) + TdiAddressLength;
// round request to type alignment for adapter id string
requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR));
// add buffer for interface name. null-terminate to be safe.
if (AdapterId == NULL) { AdapterIdLength = 0; } adapterIdOffset = requestSize; requestSize += AdapterIdLength + sizeof(UNICODE_NULL);
if (requestSize < sizeof(CX_INTERFACE_REG_REQUEST)) { requestSize = sizeof(CX_INTERFACE_REG_REQUEST); }
request = LocalAlloc(LMEM_FIXED, requestSize);
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
ZeroMemory(request, requestSize);
request->NodeId = NodeId; request->NetworkId = NetworkId; request->Priority = Priority; request->TdiAddressLength = TdiAddressLength;
MoveMemory( &(request->TdiAddress[0]), TdiAddress, TdiAddressLength );
request->AdapterIdLength = AdapterIdLength; request->AdapterIdOffset = adapterIdOffset;
if (AdapterId != NULL) { CopyMemory( (PUWSTR)((PUCHAR)request + adapterIdOffset), AdapterId, AdapterIdLength ); }
status = DoIoctl( ControlChannel, IOCTL_CX_REGISTER_INTERFACE, request, requestSize, &response, &responseSize, NULL );
LocalFree(request);
if (MediaStatus != NULL) { *MediaStatus = response.MediaStatus; }
return(NtStatusToClusnetError(status));
} // ClusnetRegisterInterface
DWORD ClusnetDeregisterInterface( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_INTERFACE_DEREG_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.NodeId = NodeId; request.NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_DEREGISTER_INTERFACE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetDeregisterInterface
DWORD ClusnetOnlineNodeComm( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId ) /*++
Routine Description:
Enables communication to the specified node.
Arguments:
ControlChannel - An open control channel handle to the Cluster Network driver.
NodeId - The ID of the node to which to enable communication.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_ONLINE_NODE_COMM_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_ONLINE_NODE_COMM, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetOnlineNodeCommunication
DWORD ClusnetOfflineNodeComm( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId ) /*++
Routine Description:
Disable communication to the specified node.
Arguments:
ControlChannel - An open control channel handle to the Cluster Network driver.
NodeId - The ID of the node to which to disable communication.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_OFFLINE_NODE_COMM_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_OFFLINE_NODE_COMM, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetOfflineNodeCommunication
DWORD ClusnetOnlineNetwork( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, IN PWCHAR TdiProviderName, IN PVOID TdiBindAddress, IN ULONG TdiBindAddressLength, IN LPWSTR AdapterName, OUT PVOID TdiBindAddressInfo, IN PULONG TdiBindAddressInfoLength ) /*++
Routine Description:
Brings a cluster network online using the specified TDI transport provider and local TDI transport address.
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
NetworkId - The ID of the network to bring online.
TdiProviderName - The name of the transport provider device that this network should open (e.g. \Device\Udp).
TdiAddress - A pointer to a TDI TRANSPORT_ADDRESS structure containing the transport address of the local interface to which the network should be bound.
TdiAddressLength - The length, in bytes, of the TdiAddress buffer.
AdapterName - name of the adapter on which this network is associated
TdiBindAddressInfo - A pointer to a TDI_ADDRESS_INFO structure. On output, this structure contains the actual address that the provider opened.
TdiBindAddressInfoLength - On input, a pointer to the size, in bytes, of the TdiBindAddressInfo parameter. On output, the variable is updated to the amount of date returned in the TdiBindAddressInfo structure.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_ONLINE_NETWORK_REQUEST request; DWORD requestSize; PVOID response; ULONG tdiProviderNameLength; ULONG adapterNameLength;
tdiProviderNameLength = (wcslen(TdiProviderName) + 1) * sizeof(WCHAR); adapterNameLength = (wcslen(AdapterName) + 1) * sizeof(WCHAR);
//
// The request size is based on the size and required alignment
// of each field of data following the structure.
//
requestSize = sizeof(CX_ONLINE_NETWORK_REQUEST);
// Provider Name
requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR)) + tdiProviderNameLength;
// Bind Address
requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR)) + TdiBindAddressLength;
// Adapter Name
requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR)) + adapterNameLength;
request = LocalAlloc(LMEM_FIXED, requestSize);
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->Id = NetworkId; request->TdiProviderNameLength = tdiProviderNameLength; request->TdiProviderNameOffset = ROUND_UP_COUNT(sizeof(CX_ONLINE_NETWORK_REQUEST), TYPE_ALIGNMENT(PWSTR));
MoveMemory( (((PUCHAR) request) + request->TdiProviderNameOffset), TdiProviderName, tdiProviderNameLength );
request->TdiBindAddressLength = TdiBindAddressLength; request->TdiBindAddressOffset = ROUND_UP_COUNT((request->TdiProviderNameOffset + tdiProviderNameLength), TYPE_ALIGNMENT(TRANSPORT_ADDRESS));
MoveMemory( (((PUCHAR) request) + request->TdiBindAddressOffset), TdiBindAddress, TdiBindAddressLength );
request->AdapterNameLength = adapterNameLength; request->AdapterNameOffset = ROUND_UP_COUNT((request->TdiBindAddressOffset + TdiBindAddressLength), TYPE_ALIGNMENT(PWSTR));
MoveMemory( (((PUCHAR) request) + request->AdapterNameOffset), AdapterName, adapterNameLength );
status = DoIoctl( ControlChannel, IOCTL_CX_ONLINE_NETWORK, request, requestSize, TdiBindAddressInfo, TdiBindAddressInfoLength, NULL );
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetOnlineNetwork
DWORD ClusnetOfflineNetwork( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_OFFLINE_NETWORK_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_OFFLINE_NETWORK, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetOfflineNetwork
DWORD ClusnetSetNetworkRestriction( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, IN BOOLEAN Restricted, IN ULONG NewPriority ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SET_NETWORK_RESTRICTION_REQUEST request; DWORD responseSize = 0;
request.Id = NetworkId; request.Restricted = Restricted; request.NewPriority = NewPriority;
status = DoIoctl( ControlChannel, IOCTL_CX_SET_NETWORK_RESTRICTION, &request, sizeof(CX_SET_NETWORK_RESTRICTION_REQUEST), NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetSetNetworkRestriction
DWORD ClusnetGetNetworkPriority( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, OUT PULONG Priority ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_GET_NETWORK_PRIORITY_REQUEST request; PCX_GET_NETWORK_PRIORITY_RESPONSE response; DWORD requestSize; DWORD responseSize;
requestSize = sizeof(CX_GET_NETWORK_PRIORITY_REQUEST); responseSize = sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE);
if (requestSize > responseSize) { request = LocalAlloc(LMEM_FIXED, requestSize); response = (PCX_GET_NETWORK_PRIORITY_RESPONSE) request; } else { response = LocalAlloc(LMEM_FIXED, responseSize); request = (PCX_GET_NETWORK_PRIORITY_REQUEST) response; }
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->Id = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_NETWORK_PRIORITY, request, requestSize, response, &responseSize, NULL );
if (status == STATUS_SUCCESS) { if (responseSize != sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE)) { status = STATUS_UNSUCCESSFUL; } else { *Priority = response->Priority; } }
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetGetNetworkPriority
DWORD ClusnetSetNetworkPriority( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, IN ULONG Priority ) /*++
Routine Description:
ControlChannel - An open handle to the Cluster Network control device.
Arguments:
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SET_NETWORK_PRIORITY_REQUEST request; DWORD responseSize = 0;
request.Id = NetworkId; request.Priority = Priority;
status = DoIoctl( ControlChannel, IOCTL_CX_SET_NETWORK_PRIORITY, &request, sizeof(CX_SET_NETWORK_PRIORITY_REQUEST), NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetSetNetworkPriority
DWORD ClusnetGetInterfacePriority( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId, OUT PULONG InterfacePriority, OUT PULONG NetworkPriority
) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_GET_INTERFACE_PRIORITY_REQUEST request; PCX_GET_INTERFACE_PRIORITY_RESPONSE response; DWORD requestSize; DWORD responseSize;
requestSize = sizeof(CX_GET_INTERFACE_PRIORITY_REQUEST); responseSize = sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE);
if (requestSize > responseSize) { request = LocalAlloc(LMEM_FIXED, requestSize); response = (PCX_GET_INTERFACE_PRIORITY_RESPONSE) request; } else { response = LocalAlloc(LMEM_FIXED, responseSize); request = (PCX_GET_INTERFACE_PRIORITY_REQUEST) response; }
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->NodeId = NodeId; request->NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_INTERFACE_PRIORITY, request, requestSize, response, &responseSize, NULL );
if (status == STATUS_SUCCESS) { if (responseSize != sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE)) { status = STATUS_UNSUCCESSFUL; } else { *InterfacePriority = response->InterfacePriority; *NetworkPriority = response->NetworkPriority; } }
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetGetInterfacePriority
DWORD ClusnetSetInterfacePriority( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId, IN ULONG Priority ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SET_INTERFACE_PRIORITY_REQUEST request; DWORD responseSize = 0;
request.NodeId = NodeId; request.NetworkId = NetworkId; request.Priority = Priority;
status = DoIoctl( ControlChannel, IOCTL_CX_SET_INTERFACE_PRIORITY, &request, sizeof(CX_SET_INTERFACE_PRIORITY_REQUEST), NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetGetInterfacePriority
DWORD ClusnetGetNodeCommState( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, OUT PCLUSNET_NODE_COMM_STATE State ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_GET_NODE_STATE_REQUEST request; PCX_GET_NODE_STATE_RESPONSE response; DWORD requestSize; DWORD responseSize;
requestSize = sizeof(CX_GET_NODE_STATE_REQUEST); responseSize = sizeof(CX_GET_NODE_STATE_RESPONSE);
if (requestSize > responseSize) { request = LocalAlloc(LMEM_FIXED, requestSize); response = (PCX_GET_NODE_STATE_RESPONSE) request; } else { response = LocalAlloc(LMEM_FIXED, responseSize); request = (PCX_GET_NODE_STATE_REQUEST) response; }
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_NODE_STATE, request, requestSize, response, &responseSize, NULL );
if (status == STATUS_SUCCESS) { if (responseSize != sizeof(CX_GET_NODE_STATE_RESPONSE)) { status = STATUS_UNSUCCESSFUL; } else { *State = response->State; } }
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetGetNodeState
DWORD ClusnetGetNetworkState( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, OUT PCLUSNET_NETWORK_STATE State ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_GET_NETWORK_STATE_REQUEST request; PCX_GET_NETWORK_STATE_RESPONSE response; DWORD requestSize; DWORD responseSize;
requestSize = sizeof(CX_GET_NETWORK_STATE_REQUEST); responseSize = sizeof(CX_GET_NETWORK_STATE_RESPONSE);
if (requestSize > responseSize) { request = LocalAlloc(LMEM_FIXED, requestSize); response = (PCX_GET_NETWORK_STATE_RESPONSE) request; } else { response = LocalAlloc(LMEM_FIXED, responseSize); request = (PCX_GET_NETWORK_STATE_REQUEST) response; }
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->Id = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_NETWORK_STATE, request, requestSize, response, &responseSize, NULL );
if (status == STATUS_SUCCESS) { if (responseSize != sizeof(CX_GET_NETWORK_STATE_RESPONSE)) { status = STATUS_UNSUCCESSFUL; } else { *State = response->State; } }
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetGetNetworkState
DWORD ClusnetGetInterfaceState( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId, OUT PCLUSNET_INTERFACE_STATE State ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; PCX_GET_INTERFACE_STATE_REQUEST request; PCX_GET_INTERFACE_STATE_RESPONSE response; DWORD requestSize; DWORD responseSize;
requestSize = sizeof(CX_GET_INTERFACE_STATE_REQUEST); responseSize = sizeof(CX_GET_INTERFACE_STATE_RESPONSE);
if (requestSize > responseSize) { request = LocalAlloc(LMEM_FIXED, requestSize); response = (PCX_GET_INTERFACE_STATE_RESPONSE) request; } else { response = LocalAlloc(LMEM_FIXED, responseSize); request = (PCX_GET_INTERFACE_STATE_REQUEST) response; }
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->NodeId = NodeId; request->NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_INTERFACE_STATE, request, requestSize, response, &responseSize, NULL );
if (status == STATUS_SUCCESS) { if (responseSize != sizeof(CX_GET_INTERFACE_STATE_RESPONSE)) { status = STATUS_UNSUCCESSFUL; } else { *State = response->State; } }
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetGetInterfaceState
#ifdef MM_IN_CLUSNSET
DWORD ClusnetFormCluster( IN HANDLE ControlChannel, IN ULONG ClockPeriod, IN ULONG SendHBRate, IN ULONG RecvHBRate ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CMM_FORM_CLUSTER_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.ClockPeriod = ClockPeriod; request.SendHBRate = SendHBRate; request.RecvHBRate = RecvHBRate;
status = DoIoctl( ControlChannel, IOCTL_CMM_FORM_CLUSTER, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetFormCluster
DWORD ClusnetJoinCluster( IN HANDLE ControlChannel, IN CL_NODE_ID JoiningNodeId, IN CLUSNET_JOIN_PHASE Phase, IN ULONG JoinTimeout, IN OUT PVOID * MessageToSend, OUT PULONG MessageLength, OUT PULONG DestNodeMask ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CMM_JOIN_CLUSTER_REQUEST request; DWORD requestSize = sizeof(request); PCMM_JOIN_CLUSTER_RESPONSE response; ULONG IoctlCode; DWORD responseSize;
//
// Parse the input parameters
//
if ( Phase == ClusnetJoinPhase1 ) IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE1; else if ( Phase == ClusnetJoinPhase2 ) IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE2; else if ( Phase == ClusnetJoinPhase3 ) IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE3; else if ( Phase == ClusnetJoinPhase4 ) IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE4; else if ( Phase == ClusnetJoinPhaseAbort ) IoctlCode = IOCTL_CMM_JOIN_CLUSTER_ABORT; else return(ERROR_INVALID_PARAMETER);
request.JoiningNode = JoiningNodeId; request.JoinTimeout = JoinTimeout;
//
// allocate space for the response buffer and a message space at the back
// of the struct. Current RGP message requirements are 80 bytes
// (sizeof(rgp_msgbuf)).
//
responseSize = sizeof(*response) + 200;
if (*MessageToSend != NULL) { //
// recycle old message buffer
//
response = CONTAINING_RECORD( *MessageToSend, CMM_JOIN_CLUSTER_RESPONSE, SendData ); } else { response = LocalAlloc(LMEM_FIXED, responseSize); }
if ( response == NULL ) { return(ERROR_NOT_ENOUGH_MEMORY); }
status = DoIoctl( ControlChannel, IoctlCode, &request, requestSize, response, &responseSize, NULL );
if (NT_SUCCESS(status)) { *MessageToSend = &(response->SendData[0]); *MessageLength = response->SizeOfSendData; *DestNodeMask = response->SendNodeMask;
return(ERROR_SUCCESS); }
LocalFree( response ); *MessageToSend = NULL;
return(NtStatusToClusnetError(status));
} // ClusnetJoinCluster
VOID ClusnetEndJoinCluster( IN HANDLE ControlChannel, IN PVOID LastSentMessage ) { ULONG responseSize = 0; PCMM_JOIN_CLUSTER_RESPONSE response;
if (LastSentMessage != NULL) { response = CONTAINING_RECORD( LastSentMessage, CMM_JOIN_CLUSTER_RESPONSE, SendData );
LocalFree(response); }
(VOID) DoIoctl( ControlChannel, IOCTL_CMM_JOIN_CLUSTER_END, NULL, 0, NULL, &responseSize, NULL );
return;
} // ClusnetEndJoinCluster
DWORD ClusnetDeliverJoinMessage( IN HANDLE ControlChannel, IN PVOID Message, IN ULONG MessageLength ) { NTSTATUS status; DWORD responseSize = 0;
status = DoIoctl( ControlChannel, IOCTL_CMM_DELIVER_JOIN_MESSAGE, Message, MessageLength, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetDeliverJoinMessage
DWORD ClusnetLeaveCluster( IN HANDLE ControlChannel ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; DWORD responseSize = 0;
status = DoIoctl( ControlChannel, IOCTL_CMM_LEAVE_CLUSTER, NULL, 0, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetLeaveCluster
DWORD ClusnetEvictNode( IN HANDLE ControlChannel, IN ULONG NodeId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CMM_EJECT_CLUSTER_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Node = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CMM_EJECT_CLUSTER, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetEvictNode
#endif // MM_IN_CLUSNSET
DWORD ClusnetGetNodeMembershipState( IN HANDLE ControlChannel, IN ULONG NodeId, OUT CLUSNET_NODE_STATE * State ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_GET_NODE_MMSTATE_REQUEST request; DWORD requestSize = sizeof(request); CX_GET_NODE_MMSTATE_RESPONSE response; DWORD responseSize = sizeof(response);
request.Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_NODE_MMSTATE, &request, requestSize, &response, &responseSize, NULL );
if (status == STATUS_SUCCESS) {
*State = response.State; }
return(NtStatusToClusnetError(status));
} // ClusnetGetNodeMembershipState
DWORD ClusnetSetNodeMembershipState( IN HANDLE ControlChannel, IN ULONG NodeId, IN CLUSNET_NODE_STATE State ) /*++
Routine Description:
Set the internal node membership state to the indicated value
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SET_NODE_MMSTATE_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize;
request.NodeId = NodeId; request.State = State;
status = DoIoctl( ControlChannel, IOCTL_CX_SET_NODE_MMSTATE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetSetNodeMembershipState
DWORD ClusnetSetEventMask( IN HANDLE ControlChannel, IN CLUSNET_EVENT_TYPE EventMask )
/*++
Routine Description:
Based on the supplied callback pointers, set the mask of events generated in kernel mode in which this file handle is interested
Arguments:
ControlChannel - An open handle to the Cluster Network control device. EventMask - bit mask of interested events
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CLUSNET_SET_EVENT_MASK_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.EventMask = EventMask; request.KmodeEventCallback = NULL;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_SET_EVENT_MASK, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetSetEventMask
DWORD ClusnetGetNextEvent( IN HANDLE ControlChannel, OUT PCLUSNET_EVENT Event, IN LPOVERLAPPED Overlapped OPTIONAL )
/*++
Routine Description:
Wait for the next event to be completed.
Arguments:
ControlChannel - An open handle to the Cluster Network control device. Event - handle to event that is set when IO is complete Response - pointer to structure that is filled in when IRP completes
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; ULONG ResponseSize = sizeof( CLUSNET_EVENT );
//
// if no event passed in, then assume the caller wants to block.
// we still need an event to block on while waiting...
//
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_GET_NEXT_EVENT, NULL, 0, Event, &ResponseSize, Overlapped );
return(NtStatusToClusnetError(status));
} // ClusnetGetNextEvent
DWORD ClusnetHalt( IN HANDLE ControlChannel )
/*++
Routine Description:
Tell clusnet that we need to halt immediately
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; DWORD responseSize;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_HALT, NULL, 0, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetHalt
DWORD ClusnetSetMemLogging( IN HANDLE ControlChannel, IN ULONG NumberOfEntries )
/*++
Routine Description:
Turn in-memory logging in clusnet on or off.
Arguments:
ControlChannel - An open handle to the Cluster Network control device. NumberOfEntires - # of entries to allocate for the log. Zero turns off logging
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CLUSNET_SET_MEM_LOGGING_REQUEST request; DWORD requestSize = sizeof( request ); DWORD responseSize;
request.NumberOfEntries = NumberOfEntries;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_SET_MEMORY_LOGGING, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetSetMemLogging
DWORD ClusnetSendPoisonPacket( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId )
/*++
Routine Description:
Send a poison packet to the indicated node
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SEND_POISON_PKT_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Id = NodeId;
status = DoIoctl( ControlChannel, IOCTL_CX_SEND_POISON_PACKET, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetSetOuterscreen( IN HANDLE ControlChannel, IN ULONG Outerscreen )
/*++
Routine Description:
set the cluster member outerscreen
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SET_OUTERSCREEN_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.Outerscreen = Outerscreen;
status = DoIoctl( ControlChannel, IOCTL_CX_SET_OUTERSCREEN, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetRegroupFinished( IN HANDLE ControlChannel, IN ULONG EventEpoch, IN ULONG RegroupEpoch )
/*++
Routine Description:
inform clusnet that regroup has finished
Arguments:
ControlChannel - An open handle to the Cluster Network control device. NewEpoch - new event epoch used to detect stale events
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_REGROUP_FINISHED_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.EventEpoch = EventEpoch; request.RegroupEpoch = RegroupEpoch;
status = DoIoctl( ControlChannel, IOCTL_CX_REGROUP_FINISHED, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetImportSecurityContexts( IN HANDLE ControlChannel, IN CL_NODE_ID JoiningNodeId, IN PWCHAR PackageName, IN ULONG SignatureSize, IN PVOID ServerContext, IN PVOID ClientContext )
/*++
Routine Description:
inform clusnet that regroup has finished
Arguments:
ControlChannel - An open handle to the Cluster Network control device. NewEpoch - new event epoch used to detect stale events
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/
{ NTSTATUS status; CX_IMPORT_SECURITY_CONTEXT_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.JoiningNodeId = JoiningNodeId; request.PackageName = PackageName; request.PackageNameSize = sizeof(WCHAR) * ( wcslen( PackageName ) + 1 ); request.SignatureSize = SignatureSize; request.ServerContext = ServerContext; request.ClientContext = ClientContext;
status = DoIoctl( ControlChannel, IOCTL_CX_IMPORT_SECURITY_CONTEXTS, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetReserveEndpoint( IN HANDLE ControlChannel, IN PWSTR EndpointString ) /*++
Routine Description:
Tell clusnet to tell TCP/IP to reserve the port number in EndpointString. Arguments:
ControlChannel - An open handle to the Cluster Network control device.
EndpointString - string containing port number assigned to clusnet Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { USHORT port; DWORD err; DWORD responseSize = 0; NTSTATUS status;
err = ClRtlTcpipStringToEndpoint(EndpointString, &port);
if (err == ERROR_SUCCESS) {
// TCP/IP needs the port in host byte-order format.
// ClRtlTcpipStringToEndpoint returns it in network
// byte-order format.
port = ntohs(port);
status = DoIoctl( ControlChannel, IOCTL_CX_RESERVE_ENDPOINT, &port, sizeof(port), NULL, &responseSize, NULL ); err = NtStatusToClusnetError(status); }
return err; }
DWORD ClusnetConfigureMulticast( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, IN ULONG MulticastNetworkBrand, IN PVOID MulticastAddress, IN ULONG MulticastAddressLength, IN PVOID Key, IN ULONG KeyLength ) /*++
Routine Description:
Configures multicast parameters for the specified network. --*/ { NTSTATUS status; PCX_CONFIGURE_MULTICAST_REQUEST request; DWORD requestSize; DWORD requestDataOffset = 0; DWORD responseSize = 0;
//
// The request size is based on the size and required alignment
// of each field of data following the structure. If there is no
// data following the structure, only the structure is required.
//
requestSize = sizeof(CX_CONFIGURE_MULTICAST_REQUEST); requestDataOffset = requestSize;
if (MulticastAddressLength != 0) { requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(TRANSPORT_ADDRESS) ) + MulticastAddressLength; }
if (KeyLength != 0) { requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PVOID) ) + KeyLength; }
//
// Allocate the request buffer.
//
request = LocalAlloc(LMEM_FIXED, requestSize);
if (request == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
request->NetworkId = NetworkId; request->MulticastNetworkBrand = MulticastNetworkBrand;
if (MulticastAddress != NULL) { request->MulticastAddress = ROUND_UP_COUNT( requestDataOffset, TYPE_ALIGNMENT(TRANSPORT_ADDRESS) ); MoveMemory( (((PUCHAR) request) + request->MulticastAddress), MulticastAddress, MulticastAddressLength ); request->MulticastAddressLength = MulticastAddressLength; requestDataOffset = request->MulticastAddress + request->MulticastAddressLength; } else { request->MulticastAddress = 0; request->MulticastAddressLength = 0; }
if (Key != NULL) { request->Key = ROUND_UP_COUNT( requestDataOffset, TYPE_ALIGNMENT(PVOID) ); MoveMemory( (((PUCHAR) request) + request->Key), Key, KeyLength ); request->KeyLength = KeyLength; requestDataOffset = request->Key + request->KeyLength; } else { request->Key = 0; request->KeyLength = 0; }
status = DoIoctl( ControlChannel, IOCTL_CX_CONFIGURE_MULTICAST, request, requestSize, NULL, &responseSize, NULL );
LocalFree(request);
return(NtStatusToClusnetError(status));
} // ClusnetConfigureMulticast
DWORD ClusnetGetMulticastReachableSet( IN HANDLE ControlChannel, IN CL_NETWORK_ID NetworkId, OUT ULONG * NodeScreen ) /*++
Routine Description:
Queries the current set of nodes considered reachable by a multicast on the specified network. Arguments:
ControlChannel - open clusnet control channel NetworkId - multicast network NodeScreen - mask of nodes Return value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_GET_MULTICAST_REACHABLE_SET_REQUEST request; CX_GET_MULTICAST_REACHABLE_SET_RESPONSE response; DWORD responseSize = sizeof(response);
request.Id = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_GET_MULTICAST_REACHABLE_SET, &request, sizeof(request), &response, &responseSize, NULL );
if (status == STATUS_SUCCESS) {
*NodeScreen = response.NodeScreen; }
return(NtStatusToClusnetError(status));
} // ClusnetGetMulticastReachableSet
DWORD ClusnetSetIamaliveParam( IN HANDLE ControlChannel, IN ULONG Timeout, IN ClussvcHangAction Action ) /*++
Routine Description:
Sets the Timeout and Action to be taken by clusnet in case of clusnet hang.
Arguments:
ControlChannel - An open handle to the Cluster Network control device. Timeout - Timeout in Secs. Action - Action to be taken by Clusnet in case of clussvc hang.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; DWORD responseSize = 0; CLUSNET_SET_IAMALIVE_PARAM_REQUEST request;
request.Timeout = Timeout; request.Action = Action;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_SET_IAMALIVE_PARAM, &request, sizeof(CLUSNET_SET_IAMALIVE_PARAM_REQUEST), NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetSetIamaliveParam
DWORD ClusnetIamalive( IN HANDLE ControlChannel ) /*++
Routine Description:
Clussvc to Clusnet Heartbeat Ioctl
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; DWORD requestSize = 0; DWORD responseSize = 0;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_IAMALIVE, NULL, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status));
} // ClusnetIamalive
#if DBG
DWORD ClusnetSetDebugMask( IN HANDLE ControlChannel, IN ULONG Mask ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CLUSNET_SET_DEBUG_MASK_REQUEST request; DWORD responseSize = 0;
request.DebugMask = Mask;
status = DoIoctl( ControlChannel, IOCTL_CLUSNET_SET_DEBUG_MASK, &request, sizeof(CLUSNET_SET_DEBUG_MASK_REQUEST), NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetOnlinePendingInterface( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_ONLINE_PENDING_INTERFACE_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.NodeId = NodeId; request.NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_ONLINE_PENDING_INTERFACE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetOnlineInterface( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_ONLINE_INTERFACE_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.NodeId = NodeId; request.NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_ONLINE_INTERFACE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetOfflineInterface( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_OFFLINE_INTERFACE_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.NodeId = NodeId; request.NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_OFFLINE_INTERFACE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetFailInterface( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_FAIL_INTERFACE_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0;
request.NodeId = NodeId; request.NetworkId = NetworkId;
status = DoIoctl( ControlChannel, IOCTL_CX_FAIL_INTERFACE, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
DWORD ClusnetSendMmMsg( IN HANDLE ControlChannel, IN CL_NODE_ID NodeId, IN ULONG Pattern ) /*++
Routine Description:
Arguments:
ControlChannel - An open handle to the Cluster Network control device.
Return Value:
ERROR_SUCCESS if the operation was successful. A Windows error code otherwise.
--*/ { NTSTATUS status; CX_SEND_MM_MSG_REQUEST request; DWORD requestSize = sizeof(request); DWORD responseSize = 0; DWORD i;
request.DestNodeId = NodeId;
for (i=0; i < CX_MM_MSG_DATA_LEN; i++) { request.MessageData[i] = Pattern; }
status = DoIoctl( ControlChannel, IOCTL_CX_SEND_MM_MSG, &request, requestSize, NULL, &responseSize, NULL );
return(NtStatusToClusnetError(status)); }
#endif // DBG
|