2961 lines
67 KiB
C
2961 lines
67 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
|
|||
|
|