windows-nt/Source/XPSP1/NT/base/cluster/clusnet/api/cnetapi.c
2020-09-26 16:20:57 +08:00

2961 lines
67 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 NewEpoch
)
/*++
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.NewEpoch = NewEpoch;
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,
IN PVOID Salt,
IN ULONG SaltLength
)
/*++
Routine Description:
Configures multicast parameters for the specified network.
--*/
{
NTSTATUS status;
PCX_CONFIGURE_MULTICAST_REQUEST request;
DWORD requestSize;
DWORD responseSize;
//
// 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);
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;
}
if (SaltLength != 0) {
requestSize = ROUND_UP_COUNT(requestSize,
TYPE_ALIGNMENT(PVOID)
) +
SaltLength;
}
//
// 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(sizeof(CX_CONFIGURE_MULTICAST_REQUEST),
TYPE_ALIGNMENT(TRANSPORT_ADDRESS));
MoveMemory(
(((PUCHAR) request) + request->MulticastAddress),
MulticastAddress,
MulticastAddressLength
);
request->MulticastAddressLength = MulticastAddressLength;
} else {
request->MulticastAddress = 0;
request->MulticastAddressLength = 0;
}
if (Key != NULL) {
request->Key =
ROUND_UP_COUNT((request->MulticastAddress
+ request->MulticastAddressLength),
TYPE_ALIGNMENT(PVOID));
MoveMemory(
(((PUCHAR) request) + request->Key),
Key,
KeyLength
);
request->KeyLength = KeyLength;
} else {
request->Key = 0;
request->KeyLength = 0;
}
if (Salt != NULL) {
request->Salt =
ROUND_UP_COUNT((request->Key + request->KeyLength),
TYPE_ALIGNMENT(PVOID));
MoveMemory(
(((PUCHAR) request) + request->Salt),
Salt,
SaltLength
);
request->SaltLength = SaltLength;
} else {
request->Salt = 0;
request->SaltLength = 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
#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