|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
cxdisp.c
Abstract:
Dispatch routines for the Cluster Transport.
Author:
Mike Massa (mikemas) July 29, 1996
Revision History:
Who When What -------- -------- ---------------------------------------------- mikemas 07-29-96 created
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
#include "cxdisp.tmh"
#include <align.h>
//
// Local Prototypes
//
NTSTATUS CxDispatchRegisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchDeregisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchRegisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchDeregisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchRegisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchDeregisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchOnlineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchOfflineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchOnlineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchOfflineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSetNetworkRestriction( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetNetworkState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetInterfaceState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchIgnoreNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSendPoisonPacket( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSetOuterscreen( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchRegroupFinished( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchImportSecurityContext( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchReserveClusnetEndpoint( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchConfigureMulticast( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchGetMulticastReachableSet( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
#if DBG
NTSTATUS CxDispatchOnlinePendingInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchOnlineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchOfflineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchFailInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS CxDispatchSendMmMsg( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
#endif // DBG
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CxDispatchDeviceControl)
#pragma alloc_text(PAGE, CxDispatchRegisterNode)
#pragma alloc_text(PAGE, CxDispatchDeregisterNode)
#pragma alloc_text(PAGE, CxDispatchRegisterNetwork)
#pragma alloc_text(PAGE, CxDispatchDeregisterNetwork)
#pragma alloc_text(PAGE, CxDispatchRegisterInterface)
#pragma alloc_text(PAGE, CxDispatchDeregisterInterface)
#pragma alloc_text(PAGE, CxDispatchOnlineNodeComm)
#pragma alloc_text(PAGE, CxDispatchOfflineNodeComm)
#pragma alloc_text(PAGE, CxDispatchOnlineNetwork)
#pragma alloc_text(PAGE, CxDispatchOfflineNetwork)
#pragma alloc_text(PAGE, CxDispatchSetNetworkRestriction)
#pragma alloc_text(PAGE, CxDispatchGetNetworkPriority)
#pragma alloc_text(PAGE, CxDispatchSetNetworkPriority)
#pragma alloc_text(PAGE, CxDispatchGetInterfacePriority)
#pragma alloc_text(PAGE, CxDispatchSetInterfacePriority)
#pragma alloc_text(PAGE, CxDispatchGetNodeState)
#pragma alloc_text(PAGE, CxDispatchGetNetworkState)
#pragma alloc_text(PAGE, CxDispatchGetInterfaceState)
#pragma alloc_text(PAGE, CxDispatchGetNodeMembershipState)
#pragma alloc_text(PAGE, CxDispatchSetNodeMembershipState)
#pragma alloc_text(PAGE, CxDispatchSendPoisonPacket)
#pragma alloc_text(PAGE, CxDispatchSetOuterscreen)
#pragma alloc_text(PAGE, CxDispatchRegroupFinished)
#pragma alloc_text(PAGE, CxDispatchImportSecurityContext)
#pragma alloc_text(PAGE, CxDispatchReserveClusnetEndpoint)
#pragma alloc_text(PAGE, CxDispatchConfigureMulticast)
#pragma alloc_text(PAGE, CxDispatchGetMulticastReachableSet)
#if DBG
#pragma alloc_text(PAGE, CxDispatchOnlinePendingInterface)
#pragma alloc_text(PAGE, CxDispatchOnlineInterface)
#pragma alloc_text(PAGE, CxDispatchOfflineInterface)
#pragma alloc_text(PAGE, CxDispatchFailInterface)
#ifdef MM_IN_CLUSNET
#pragma alloc_text(PAGE, CxDispatchSendMmMsg)
#endif // MM_IN_CLUSNET
#endif // DBG
#endif // ALLOC_PRAGMA
NTSTATUS CxDispatchDeviceControl( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp )
/*++
Routine Description:
Dispatch routine for device control ioctls.
Arguments:
Irp - Pointer to I/O request packet IrpSp - Pointer to the current stack location in the Irp.
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
Notes:
Any IRP for which the return value is not STATUS_PENDING will be completed by the calling routine.
--*/
{ NTSTATUS status;
PAGED_CODE();
switch(IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_CX_REGISTER_NODE: status = CxDispatchRegisterNode(Irp, IrpSp); break;
case IOCTL_CX_DEREGISTER_NODE: status = CxDispatchDeregisterNode(Irp, IrpSp); break;
case IOCTL_CX_REGISTER_NETWORK: status = CxDispatchRegisterNetwork(Irp, IrpSp); break;
case IOCTL_CX_DEREGISTER_NETWORK: status = CxDispatchDeregisterNetwork(Irp, IrpSp); break;
case IOCTL_CX_REGISTER_INTERFACE: status = CxDispatchRegisterInterface(Irp, IrpSp); break;
case IOCTL_CX_DEREGISTER_INTERFACE: status = CxDispatchDeregisterInterface(Irp, IrpSp); break;
case IOCTL_CX_ONLINE_NODE_COMM: status = CxDispatchOnlineNodeComm(Irp, IrpSp); break;
case IOCTL_CX_OFFLINE_NODE_COMM: status = CxDispatchOfflineNodeComm(Irp, IrpSp); break;
case IOCTL_CX_ONLINE_NETWORK: status = CxDispatchOnlineNetwork(Irp, IrpSp); break;
case IOCTL_CX_OFFLINE_NETWORK: status = CxDispatchOfflineNetwork(Irp, IrpSp); break;
case IOCTL_CX_SET_NETWORK_RESTRICTION: status = CxDispatchSetNetworkRestriction(Irp, IrpSp); break;
case IOCTL_CX_GET_NETWORK_PRIORITY: status = CxDispatchGetNetworkPriority(Irp, IrpSp); break;
case IOCTL_CX_SET_NETWORK_PRIORITY: status = CxDispatchSetNetworkPriority(Irp, IrpSp); break;
case IOCTL_CX_GET_INTERFACE_PRIORITY: status = CxDispatchGetInterfacePriority(Irp, IrpSp); break;
case IOCTL_CX_SET_INTERFACE_PRIORITY: status = CxDispatchSetInterfacePriority(Irp, IrpSp); break;
case IOCTL_CX_GET_NODE_STATE: status = CxDispatchGetNodeState(Irp, IrpSp); break;
case IOCTL_CX_GET_NETWORK_STATE: status = CxDispatchGetNetworkState(Irp, IrpSp); break;
case IOCTL_CX_GET_INTERFACE_STATE: status = CxDispatchGetInterfaceState(Irp, IrpSp); break;
case IOCTL_CX_IGNORE_NODE_STATE: status = CxDispatchIgnoreNodeState(Irp, IrpSp); break;
case IOCTL_CX_GET_NODE_MMSTATE: status = CxDispatchGetNodeMembershipState(Irp, IrpSp); break;
case IOCTL_CX_SET_NODE_MMSTATE: status = CxDispatchSetNodeMembershipState(Irp, IrpSp); break;
case IOCTL_CX_SEND_POISON_PACKET: status = CxDispatchSendPoisonPacket(Irp, IrpSp); break;
case IOCTL_CX_SET_OUTERSCREEN: status = CxDispatchSetOuterscreen(Irp, IrpSp); break;
case IOCTL_CX_REGROUP_FINISHED: status = CxDispatchRegroupFinished(Irp, IrpSp); break;
case IOCTL_CX_IMPORT_SECURITY_CONTEXTS: status = CxDispatchImportSecurityContext(Irp, IrpSp); break;
case IOCTL_CX_RESERVE_ENDPOINT: status = CxDispatchReserveClusnetEndpoint(Irp, IrpSp); break;
case IOCTL_CX_CONFIGURE_MULTICAST: status = CxDispatchConfigureMulticast(Irp, IrpSp); break;
case IOCTL_CX_GET_MULTICAST_REACHABLE_SET: status = CxDispatchGetMulticastReachableSet(Irp, IrpSp); break;
#if DBG
case IOCTL_CX_ONLINE_PENDING_INTERFACE: status = CxDispatchOnlinePendingInterface(Irp, IrpSp); break;
case IOCTL_CX_ONLINE_INTERFACE: status = CxDispatchOnlineInterface(Irp, IrpSp); break;
case IOCTL_CX_OFFLINE_INTERFACE: status = CxDispatchOfflineInterface(Irp, IrpSp); break;
case IOCTL_CX_FAIL_INTERFACE: status = CxDispatchFailInterface(Irp, IrpSp); break;
#ifdef MM_IN_CLUSNET
case IOCTL_CX_SEND_MM_MSG: status = CxDispatchSendMmMsg(Irp, IrpSp); break; #endif // MM_IN_CLUSNET
#endif // DBG
default: status = STATUS_INVALID_DEVICE_REQUEST; break; }
return(status);
} // CxDispatchDeviceControl
NTSTATUS CxDispatchRegisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NODE_REG_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_NODE_REG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_NODE_REG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxRegisterNode( request->Id );
return(status);
} // CxDispatchRegisterNode
NTSTATUS CxDispatchDeregisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NODE_DEREG_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_NODE_DEREG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_NODE_DEREG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxDeregisterNode(request->Id, Irp, IrpSp);
return(status);
} // CxDispatchDeregisterNode
NTSTATUS CxDispatchRegisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NETWORK_REG_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_NETWORK_REG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_NETWORK_REG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxRegisterNetwork( request->Id, request->Priority, request->Restricted );
return(status);
} // CxDispatchRegisterNetwork
NTSTATUS CxDispatchDeregisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NETWORK_DEREG_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_NETWORK_DEREG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_NETWORK_DEREG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxDeregisterNetwork(request->Id, Irp, IrpSp);
return(status);
} // CxDispatchDeregisterNetwork
NTSTATUS CxDispatchRegisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_INTERFACE_REG_REQUEST request; ULONG requestSize, resid; PCX_INTERFACE_REG_RESPONSE response; ULONG responseSize;
PWCHAR adapterId;
PAGED_CODE();
// Verify that the request buffer has sufficient size, given the
// offsets and lengths.
request = (PCX_INTERFACE_REG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_INTERFACE_REG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
response = (PCX_INTERFACE_REG_RESPONSE) Irp->AssociatedIrp.SystemBuffer; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if (responseSize < sizeof(CX_INTERFACE_REG_RESPONSE)) { return(STATUS_INVALID_PARAMETER); }
resid = requestSize - FIELD_OFFSET(CX_INTERFACE_REG_REQUEST, TdiAddress[0]);
if (resid < request->TdiAddressLength) { return(STATUS_INVALID_PARAMETER); }
resid -= request->TdiAddressLength;
if (request->AdapterIdOffset < FIELD_OFFSET(CX_INTERFACE_REG_REQUEST, TdiAddress[0]) + request->TdiAddressLength || request->AdapterIdOffset > requestSize) { return(STATUS_INVALID_PARAMETER); }
if (resid < request->AdapterIdLength) { return(STATUS_INVALID_PARAMETER); }
// Verify that the string offset is properly aligned
adapterId = (PWCHAR)((PUCHAR)request + request->AdapterIdOffset);
if (!POINTER_IS_ALIGNED(adapterId, TYPE_ALIGNMENT(WCHAR))) { return(STATUS_INVALID_PARAMETER); }
status = CxRegisterInterface( request->NodeId, request->NetworkId, request->Priority, (PUWSTR)((PUCHAR)request + request->AdapterIdOffset), request->AdapterIdLength, request->TdiAddressLength, (PTRANSPORT_ADDRESS) &(request->TdiAddress[0]), &response->MediaStatus );
if (NT_SUCCESS(status)) { Irp->IoStatus.Information = sizeof(CX_INTERFACE_REG_RESPONSE); }
return(status);
} // CxDispatchRegisterInterface
NTSTATUS CxDispatchDeregisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_INTERFACE_DEREG_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_INTERFACE_DEREG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_INTERFACE_DEREG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxDeregisterInterface(request->NodeId, request->NetworkId);
return(status);
} // CxDispatchDeregisterInterface
NTSTATUS CxDispatchOnlineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_NODE_COMM_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_ONLINE_NODE_COMM_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_ONLINE_NODE_COMM_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxOnlineNodeComm(request->Id);
return(status);
} // CxDispatchOnlineNodeComm
NTSTATUS CxDispatchOfflineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_OFFLINE_NODE_COMM_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_OFFLINE_NODE_COMM_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_OFFLINE_NODE_COMM_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxOfflineNodeComm(request->Id, Irp, IrpSp);
return(status);
} // CxDispatchOfflineNodeComm
NTSTATUS CxDispatchOnlineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_NETWORK_REQUEST request; ULONG requestSize; PTDI_ADDRESS_INFO response; ULONG responseSize; ULONG requiredSize = sizeof( CX_ONLINE_NETWORK_REQUEST ); PWCHAR tdiProviderName; PTRANSPORT_ADDRESS tdiBindAddress; PWCHAR adapterName;
PAGED_CODE();
//
// Validate the request buffer
//
// First validate that the request buffer size matches the offsets
// and lengths.
request = (PCX_ONLINE_NETWORK_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < requiredSize) { return(STATUS_INVALID_PARAMETER); }
// Validate that all offset length pairs are within the request
// buffer.
if ( ( request->TdiProviderNameOffset + request->TdiProviderNameLength < request->TdiProviderNameOffset ) || ( request->TdiProviderNameOffset + request->TdiProviderNameLength > requestSize ) || ( request->TdiBindAddressOffset + request->TdiBindAddressLength < request->TdiBindAddressOffset ) || ( request->TdiBindAddressOffset + request->TdiBindAddressLength > requestSize ) || ( request->AdapterNameOffset + request->AdapterNameLength < request->AdapterNameOffset ) || ( request->AdapterNameOffset + request->AdapterNameLength > requestSize ) ) { return(STATUS_INVALID_PARAMETER); }
// Construct pointers to the parameters.
tdiBindAddress = (PTRANSPORT_ADDRESS) ( ((PUCHAR) request) + request->TdiBindAddressOffset );
tdiProviderName = (PWCHAR) ( ((PUCHAR) request) + request->TdiProviderNameOffset );
adapterName = (PWCHAR) ( ((PUCHAR) request) + request->AdapterNameOffset );
// Validate that the resulting pointers are properly aligned and
// within the request buffer.
if ( ( ((PUCHAR) tdiBindAddress) < ((PUCHAR) request) ) || ( ((PUCHAR) tdiBindAddress) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(tdiBindAddress, TYPE_ALIGNMENT(TRANSPORT_ADDRESS)) ) || ( ((PUCHAR) tdiProviderName) < ((PUCHAR) request) ) || ( ((PUCHAR) tdiProviderName) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(tdiProviderName, TYPE_ALIGNMENT(WCHAR)) ) || ( ((PUCHAR) adapterName) < ((PUCHAR) request) ) || ( ((PUCHAR) adapterName) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(adapterName, TYPE_ALIGNMENT(WCHAR)) ) ) { return(STATUS_INVALID_PARAMETER); }
//
// Validate the response buffer
//
response = (PTDI_ADDRESS_INFO) Irp->AssociatedIrp.SystemBuffer; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
requiredSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + request->TdiBindAddressLength;
if (responseSize < requiredSize) { return(STATUS_INVALID_PARAMETER); }
status = CxOnlineNetwork( request->Id, tdiProviderName, request->TdiProviderNameLength, tdiBindAddress, request->TdiBindAddressLength, adapterName, request->AdapterNameLength, response, responseSize, Irp );
if (NT_SUCCESS(status)) { Irp->IoStatus.Information = responseSize; }
return(status);
} // CxDispatchOnlineNetwork
NTSTATUS CxDispatchOfflineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_OFFLINE_NETWORK_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_OFFLINE_NETWORK_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_OFFLINE_NETWORK_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxOfflineNetwork(request->Id, Irp, IrpSp);
return(status);
} // CxDispatchOfflineNetwork
NTSTATUS CxDispatchSetNetworkRestriction( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; ULONG requestSize; PCX_SET_NETWORK_RESTRICTION_REQUEST request;
PAGED_CODE();
request = (PCX_SET_NETWORK_RESTRICTION_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_SET_NETWORK_RESTRICTION_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxSetNetworkRestriction( request->Id, request->Restricted, request->NewPriority );
return(status);
} // CxDispatchSetNetworkRestriction
NTSTATUS CxDispatchGetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NETWORK_PRIORITY_REQUEST request; PCX_GET_NETWORK_PRIORITY_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_NETWORK_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_NETWORK_PRIORITY_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(CX_GET_NETWORK_PRIORITY_REQUEST)) || (responseSize < sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetNetworkPriority( request->Id, &(response->Priority) );
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE); }
return(status);
} // CxDispatchGetNetworkPriority
NTSTATUS CxDispatchSetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; ULONG requestSize; PCX_SET_NETWORK_PRIORITY_REQUEST request;
PAGED_CODE();
request = (PCX_SET_NETWORK_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_SET_NETWORK_PRIORITY_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxSetNetworkPriority( request->Id, request->Priority );
return(status);
} // CxDispatchSetNetworkPriority
NTSTATUS CxDispatchGetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_INTERFACE_PRIORITY_REQUEST request; PCX_GET_INTERFACE_PRIORITY_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_INTERFACE_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_INTERFACE_PRIORITY_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(CX_GET_INTERFACE_PRIORITY_REQUEST)) || (responseSize < sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetInterfacePriority( request->NodeId, request->NetworkId, &(response->InterfacePriority), &(response->NetworkPriority) );
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE); }
return(status);
} // CxDispatchGetInterfacePriority
NTSTATUS CxDispatchSetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; ULONG requestSize; PCX_SET_INTERFACE_PRIORITY_REQUEST request;
PAGED_CODE();
request = (PCX_SET_INTERFACE_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_SET_INTERFACE_PRIORITY_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxSetInterfacePriority( request->NodeId, request->NetworkId, request->Priority );
return(status);
} // CxDispatchSetInterfacePriority
NTSTATUS CxDispatchGetNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NODE_STATE_REQUEST request; PCX_GET_NODE_STATE_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_NODE_STATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_NODE_STATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(CX_GET_NODE_STATE_REQUEST)) || (responseSize < sizeof(CX_GET_NODE_STATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetNodeCommState( request->Id, &(response->State) );
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NODE_STATE_RESPONSE); }
return(status);
} // CxDispatchGetNodeState
NTSTATUS CxDispatchGetNetworkState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NETWORK_STATE_REQUEST request; PCX_GET_NETWORK_STATE_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_NETWORK_STATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_NETWORK_STATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(CX_GET_NETWORK_STATE_REQUEST)) || (responseSize < sizeof(CX_GET_NETWORK_STATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetNetworkState( request->Id, &(response->State) );
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NETWORK_STATE_RESPONSE); }
return(status);
} // CxDispatchGetNetworkState
NTSTATUS CxDispatchGetInterfaceState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_INTERFACE_STATE_REQUEST request; PCX_GET_INTERFACE_STATE_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_INTERFACE_STATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_INTERFACE_STATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(CX_GET_INTERFACE_STATE_REQUEST)) || (responseSize < sizeof(CX_GET_INTERFACE_STATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetInterfaceState( request->NodeId, request->NetworkId, &(response->State) );
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_INTERFACE_STATE_RESPONSE); }
return(status);
} // CxDispatchGetInterfaceState
NTSTATUS CxDispatchIgnoreNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { PCX_ADDROBJ addrObj = (PCX_ADDROBJ) (IrpSp->FileObject->FsContext); CN_IRQL irql;
CnAcquireLock(&(addrObj->Lock), &irql);
IF_CNDBG(CN_DEBUG_ADDROBJ) { CNPRINT(("[CDP] Turning off checkstate flag on AO %p\n", addrObj)); }
addrObj->Flags &= ~(CX_AO_FLAG_CHECKSTATE);
CnReleaseLock(&(addrObj->Lock), irql);
return(STATUS_SUCCESS);
} // CxDispatchIgnoreNodeState
NTSTATUS CxDispatchGetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NODE_MMSTATE_REQUEST request; PCX_GET_NODE_MMSTATE_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_NODE_MMSTATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_NODE_MMSTATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(CX_GET_NODE_MMSTATE_REQUEST)) || (responseSize < sizeof(CX_GET_NODE_MMSTATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetNodeMembershipState( request->Id, &(response->State));
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NODE_MMSTATE_RESPONSE); }
return(status);
} // CxDispatchGetNodeMembershipState
NTSTATUS CxDispatchSetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SET_NODE_MMSTATE_REQUEST request; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_SET_NODE_MMSTATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof( CX_SET_NODE_MMSTATE_REQUEST ) || request->State >= ClusnetNodeStateLastEntry) {
return(STATUS_INVALID_PARAMETER); }
status = CxSetNodeMembershipState( request->NodeId, request->State );
Irp->IoStatus.Information = 0;
return(status);
} // CxDispatchSetNodeMembershipState
VOID CxCompleteSendPoisonPacket( IN NTSTATUS Status, IN ULONG BytesSent, IN PVOID Context, IN PVOID MessageData ) { PIRP irp = Context;
CnAssert(Status != STATUS_PENDING);
IF_CNDBG(( CN_DEBUG_IRP | CN_DEBUG_POISON )) CNPRINT(("[Clusnet] Completing SendPoisonPacket request for " "irp %p, status %08X\n", irp, Status));
//
// The irp is completed in the CNP send completion routine.
//
return;
} // CxCompleteSendPoisonPacket
NTSTATUS CxDispatchSendPoisonPacket( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SEND_POISON_PKT_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_SEND_POISON_PKT_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
//
// request size should exactly equal the size of the request struct plus
// the data passed in
//
if ( requestSize != sizeof(CX_SEND_POISON_PKT_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
//
// We will always return pending, so mark the IRP pending.
// The IRP will be completed by CxCompleteSendPoisonPacket
//
IoMarkIrpPending(Irp); IF_CNDBG(( CN_DEBUG_IRP | CN_DEBUG_POISON )) CNPRINT(("[Clusnet] Posting SendPoisonPacket irp %p\n", Irp));
CxSendPoisonPacket( request->Id, CxCompleteSendPoisonPacket, Irp, Irp );
return(STATUS_PENDING);
} // CxDispatchSendPoisonPacket
NTSTATUS CxDispatchSetOuterscreen( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SET_OUTERSCREEN_REQUEST request; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_SET_OUTERSCREEN_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if ( requestSize < sizeof( CX_SET_OUTERSCREEN_REQUEST )) {
return(STATUS_INVALID_PARAMETER); }
status = CxSetOuterscreen( request->Outerscreen );
Irp->IoStatus.Information = 0;
return(status);
} // CxDispatchSetOuterscreen
NTSTATUS CxDispatchRegroupFinished( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_REGROUP_FINISHED_REQUEST request; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_REGROUP_FINISHED_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if ( requestSize < sizeof( CX_REGROUP_FINISHED_REQUEST )) {
return(STATUS_INVALID_PARAMETER); }
CxRegroupFinished( request->NewEpoch );
Irp->IoStatus.Information = 0;
return( STATUS_SUCCESS );
} // CxDispatchRegroupFinished
NTSTATUS CxDispatchImportSecurityContext( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_IMPORT_SECURITY_CONTEXT_REQUEST request; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_IMPORT_SECURITY_CONTEXT_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if ( requestSize < sizeof( CX_IMPORT_SECURITY_CONTEXT_REQUEST )) {
return(STATUS_INVALID_PARAMETER); }
status = CxImportSecurityContext(request->JoiningNodeId, request->PackageName, request->PackageNameSize, request->SignatureSize, request->ServerContext, request->ClientContext);
Irp->IoStatus.Information = 0;
return( status );
} // CxDispatchImportSecurityContext
NTSTATUS CxDispatchReserveClusnetEndpoint( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; USHORT port; ULONG requestSize;
PAGED_CODE();
requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(USHORT)) {
status = STATUS_INVALID_PARAMETER; } else { port = *((PUSHORT) Irp->AssociatedIrp.SystemBuffer); status = CxReserveClusnetEndpoint(port); } Irp->IoStatus.Information = 0;
return (status); }
NTSTATUS CxDispatchConfigureMulticast( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_CONFIGURE_MULTICAST_REQUEST request; ULONG requestSize; ULONG requiredSize;
PTRANSPORT_ADDRESS tdiMcastAddress; PVOID key; PVOID salt; PAGED_CODE();
//
// Validate the request buffer
//
// First validate that the request buffer size matches the offsets
// and lengths.
request = (PCX_CONFIGURE_MULTICAST_REQUEST)Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
//
// The required 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.
//
requiredSize = sizeof(CX_CONFIGURE_MULTICAST_REQUEST);
//
// Verify that the required size is present.
//
if (requestSize < requiredSize) { return(STATUS_INVALID_PARAMETER); }
//
// Verify that all offset length pairs are within the request size.
//
if ( ( request->MulticastAddress + request->MulticastAddressLength < request->MulticastAddress ) || ( request->MulticastAddress + request->MulticastAddressLength > requestSize ) || ( request->Key + request->KeyLength < request->Key ) || ( request->Key + request->KeyLength > requestSize ) || ( request->Salt + request->SaltLength < request->Salt ) || ( request->Salt + request->SaltLength > requestSize ) ) { return(STATUS_INVALID_PARAMETER); }
//
// Construct pointers using the offsets.
//
tdiMcastAddress = (PTRANSPORT_ADDRESS) ( ((PUCHAR) request) + request->MulticastAddress );
key = (PVOID)( ((PUCHAR) request) + request->Key );
salt = (PVOID)( ((PUCHAR) request) + request->Salt );
//
// Validate that the resulting pointers are properly aligned and
// within the request data structure.
//
if ( ( ((PUCHAR) tdiMcastAddress) < ((PUCHAR) request) ) || ( ((PUCHAR) tdiMcastAddress) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(tdiMcastAddress, TYPE_ALIGNMENT(TRANSPORT_ADDRESS))) || ( ((PUCHAR) key) < ((PUCHAR) request) ) || ( ((PUCHAR) key) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(key, TYPE_ALIGNMENT(PVOID))) || ( ((PUCHAR) salt) < ((PUCHAR) request) ) || ( ((PUCHAR) salt) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(salt, TYPE_ALIGNMENT(PVOID))) ) { return(STATUS_INVALID_PARAMETER); }
status = CxConfigureMulticast( request->NetworkId, request->MulticastNetworkBrand, tdiMcastAddress, request->MulticastAddressLength, key, request->KeyLength, salt, request->SaltLength, Irp );
// No return data.
Irp->IoStatus.Information = 0;
return(status);
} // CxDispatchConfigureMulticast
NTSTATUS CxDispatchGetMulticastReachableSet( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_MULTICAST_REACHABLE_SET_REQUEST request; PCX_GET_MULTICAST_REACHABLE_SET_RESPONSE response; ULONG requestSize; ULONG responseSize;
PAGED_CODE();
request = (PCX_GET_MULTICAST_REACHABLE_SET_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
response = (PCX_GET_MULTICAST_REACHABLE_SET_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if ( (requestSize < sizeof(PCX_GET_MULTICAST_REACHABLE_SET_REQUEST)) || (responseSize < sizeof(PCX_GET_MULTICAST_REACHABLE_SET_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); }
status = CxGetMulticastReachableSet( request->Id, &(response->NodeScreen) );
if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_MULTICAST_REACHABLE_SET_RESPONSE); }
return(status);
} // CxDispatchGetMulticastReachableSet
//
// Test IOCTLs.
//
#if DBG
NTSTATUS CxDispatchOnlinePendingInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxOnlinePendingInterface(request->NodeId, request->NetworkId);
return(status); } // CxDispatchOnlinePendingInterface
NTSTATUS CxDispatchOnlineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxOnlineInterface(request->NodeId, request->NetworkId);
return(status);
} // CxDispatchOnlineInterface
NTSTATUS CxDispatchOfflineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxOfflineInterface(request->NodeId, request->NetworkId);
return(status);
} // CxDispatchOfflineInterface
NTSTATUS CxDispatchFailInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
status = CxFailInterface(request->NodeId, request->NetworkId);
return(status);
} // CxDispatchFailInterface
VOID CxCompleteSendMmMsg( IN NTSTATUS Status, IN ULONG BytesSent, IN PVOID Context, IN PVOID MessageData ) { PIRP irp = Context;
CnAssert(Status != STATUS_PENDING);
CNPRINT(( "[Clusnet] Completing SendMmMsg irp %p, status %lx, bytes sent %u\n", irp, Status, BytesSent ));
//
// Complete the irp.
//
irp->IoStatus.Status = Status; irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
return;
} // CxCompleteSendMmMsg
#ifdef MM_IN_CLUSNET
NTSTATUS CxDispatchSendMmMsg( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SEND_MM_MSG_REQUEST request; ULONG requestSize;
PAGED_CODE();
request = (PCX_SEND_MM_MSG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (requestSize < sizeof(CX_SEND_MM_MSG_REQUEST)) { return(STATUS_INVALID_PARAMETER); }
IoMarkIrpPending(Irp);
CNPRINT(("[Clusnet] Posting SendMmMsg irp %p\n", Irp));
status = CxSendMembershipMessage( request->DestNodeId, &(request->MessageData[0]), CX_MM_MSG_DATA_LEN, CxCompleteSendMmMsg, Irp );
return(status);
} // CxDispatchSendMmMsg
#endif // MM_IN_CLUSNET
#endif // DBG
|