2020-09-30 17:12:29 +02:00

4609 lines
103 KiB
C

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
io.c
Abstract:
This file contains the procedures to process I/O requests from
a User Mode entity. All OS dependent I/O interface functions
will be conditionally coded, and will be responsible for translating
the I/O functions from the OS format to buffers that are useable by
the main I/O handling routine.
Author:
Tony Bell (TonyBe) June 06, 1995
Environment:
Kernel Mode
Revision History:
TonyBe 06/06/95 Created
--*/
#include "wan.h"
#include "tcpip.h"
#include "vjslip.h"
//
// Local function prototypes
//
NTSTATUS
ExecuteIo(
IN ULONG ulFuncCode,
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
MapConnectionId(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetBundleHandle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetFriendlyName(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
ActivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
BundleLink(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumLinksInBundle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetProtocolPriority(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetBandwidthOnDemand(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetThresholdEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
IoSendPacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
IoReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
FlushReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetStatistics(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetBridgeInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetBridgeInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetCIPXInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetCIPXInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetIdleTime(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetDebugInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumActiveBundles(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetNdisWanCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumWanAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetWanAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetBandwidthUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumProtocolUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
FlushThresholdEvents(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetWanInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
DeactivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
VOID
CancelThresholdEvents(
VOID
);
VOID
CancelIoReceivePackets(
VOID
);
VOID
AddProtocolCBToBundle(
PPROTOCOLCB ProtocolCB,
PBUNDLECB BundleCB
);
VOID
RemoveProtocolCBFromBundle(
PPROTOCOLCB ProtocolCB,
PBUNDLECB BundleCB
);
#ifdef BANDWIDTH_ON_DEMAND
VOID
SortProtocolListByPriority(
IN PBUNDLECB BundleCB
);
#endif
VOID
FlushProtocolPacketQueue(
PPROTOCOLCB ProtocolCB
);
VOID
AssignProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
);
VOID
FreeProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
);
//
// End of local function prototypes
//
IO_DISPATCH_TABLE IoDispatchTable[] =
{
{FUNC_MAP_CONNECTION_ID , MapConnectionId},
{FUNC_GET_BUNDLE_HANDLE , GetBundleHandle},
{FUNC_SET_FRIENDLY_NAME , SetFriendlyName},
{FUNC_ROUTE , ActivateRoute},
{FUNC_ADD_LINK_TO_BUNDLE , BundleLink},
{FUNC_ENUM_LINKS_IN_BUNDLE , EnumLinksInBundle},
{FUNC_SET_PROTOCOL_PRIORITY , SetProtocolPriority},
{FUNC_SET_BANDWIDTH_ON_DEMAND, SetBandwidthOnDemand},
{FUNC_SET_THRESHOLD_EVENT , SetThresholdEvent},
{FUNC_FLUSH_THRESHOLD_EVENTS, FlushThresholdEvents},
{FUNC_SEND_PACKET , IoSendPacket},
{FUNC_RECEIVE_PACKET , IoReceivePacket},
{FUNC_FLUSH_RECEIVE_PACKETS , FlushReceivePacket},
{FUNC_GET_STATS , GetStatistics},
{FUNC_SET_LINK_INFO , SetLinkInfo},
{FUNC_GET_LINK_INFO , GetLinkInfo},
{FUNC_SET_COMPRESSION_INFO , SetCompressionInfo},
{FUNC_GET_COMPRESSION_INFO , GetCompressionInfo},
{FUNC_SET_BRIDGE_INFO , SetBridgeInfo},
{FUNC_GET_BRIDGE_INFO , GetBridgeInfo},
{FUNC_SET_VJ_INFO , SetVJInfo},
{FUNC_GET_VJ_INFO , GetVJInfo},
{FUNC_SET_CIPX_INFO , SetCIPXInfo},
{FUNC_GET_CIPX_INFO , GetCIPXInfo},
{FUNC_SET_ENCRYPTION_INFO , SetEncryptionInfo},
{FUNC_GET_ENCRYPTION_INFO , GetEncryptionInfo},
{FUNC_SET_DEBUG_INFO , SetDebugInfo},
{FUNC_ENUM_ACTIVE_BUNDLES , EnumActiveBundles},
{FUNC_GET_NDISWANCB , GetNdisWanCB},
{FUNC_GET_ADAPTERCB , GetAdapterCB},
{FUNC_GET_WAN_ADAPTERCB , GetWanAdapterCB},
{FUNC_GET_BANDWIDTH_UTILIZATION, GetBandwidthUtilization},
{FUNC_ENUM_PROTOCOL_UTILIZATION, EnumProtocolUtilization},
{FUNC_ENUM_ADAPTERCB , EnumAdapterCB},
{FUNC_ENUM_WAN_ADAPTERCB , EnumWanAdapterCB},
{FUNC_GET_WAN_INFO , GetWanInfo},
{FUNC_GET_IDLE_TIME , GetIdleTime},
{FUNC_UNROUTE , DeactivateRoute}
};
#define MAX_FUNC_CODES sizeof(IoDispatchTable)/sizeof(IO_DISPATCH_TABLE)
#ifdef NT
NTSTATUS
NdisWanIoctl(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status, ReturnStatus;
ULONG ulBytesWritten = 0;
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
//
// Ioctl Function Code
//
ULONG ulFuncCode = (pIrpSp->Parameters.DeviceIoControl.IoControlCode >> 2) & 0x00000FFF ;
ULONG ulDeviceType = (pIrpSp->Parameters.DeviceIoControl.IoControlCode >> 16) & 0x0000FFFF;
//
// Input buffer, Output buffer, and lengths
//
PUCHAR pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;
PUCHAR pOutputBuffer = pInputBuffer;
ULONG ulInputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
ULONG ulOutputBufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanIoctl: FunctionCode: 0x%8.8x, MajorFunction: 0x%8.8x, DeviceType: 0x%8.8x",
ulFuncCode, pIrpSp->MajorFunction, ulDeviceType));
//
// Make sure that this is for us
//
if ((pIrpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL) ||
(ulDeviceType != FILE_DEVICE_NDISWAN) ||
(pDeviceObject != NdisWanCB.pDeviceObject)) {
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
//
// If this is a function code that requires an irp to be pended and completed
// later, we need to queue the irp up somewhere. In order for this to be somewhat
// portable we will pass the irp in as the input buffer and store it in a
// a structure that it has it's own linkage for queueing.
//
if ((ulFuncCode == FUNC_SET_THRESHOLD_EVENT) ||
(ulFuncCode == FUNC_RECEIVE_PACKET)) {
pInputBuffer = (PUCHAR)pIrp;
}
Status = ExecuteIo(ulFuncCode,
pInputBuffer,
ulInputBufferLength,
pOutputBuffer,
ulOutputBufferLength,
&ulBytesWritten);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanIoctl: Status: 0x%8.8x, BytesWritten: %d",
Status, ulBytesWritten));
switch (Status) {
case STATUS_SUCCESS:
ReturnStatus = Status;
break;
case STATUS_PENDING:
return(Status);
case STATUS_INFO_LENGTH_MISMATCH:
//
// See if this was a request to get size needed for
// ioctl.
//
if (ulOutputBufferLength >= sizeof(ULONG)) {
*(PULONG)pOutputBuffer = ulBytesWritten;
ulBytesWritten = sizeof(ULONG);
ReturnStatus =
Status = STATUS_SUCCESS;
}
break;
default:
if (Status < 0xC0000000) {
Status += 0xC0100000;
}
ReturnStatus = STATUS_UNSUCCESSFUL;
break;
}
pIrp->IoStatus.Information = ulBytesWritten;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
return(ReturnStatus);
}
NTSTATUS
NdisWanIrpStub(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Entry"));
//
// Make sure that this is for us
//
if (pDeviceObject != NdisWanCB.pDeviceObject) {
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Exit1"));
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Exit2"));
return (STATUS_SUCCESS);
}
VOID
NdisWanCancelRoutine(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
BOOLEAN Found = FALSE;
WAN_IRQL OldIrql;
//
// Get the pointer to the AsyncEvent from the Irp.
//
PWAN_ASYNC_EVENT pAsyncEvent;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCancelRoutine: Irp 0x%8.8x", pIrp));
// NdisWanRaiseIrql(&OldIrql);
//
// We need to walk the async event queue looking for
// the async event that this irp is associated with
//
NdisAcquireSpinLock(&RecvPacketQueue.Lock);
for (pAsyncEvent = (PWAN_ASYNC_EVENT)RecvPacketQueue.List.Flink;
(PVOID)pAsyncEvent != (PVOID)&RecvPacketQueue.List;
pAsyncEvent = (PWAN_ASYNC_EVENT)pAsyncEvent->Linkage.Flink) {
if (pAsyncEvent->Context == (PVOID)pIrp) {
RecvPacketQueue.ulCount--;
//
// Remove from the list
//
RemoveEntryList(&pAsyncEvent->Linkage);
Found = TRUE;
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->usHandleType = CANCELEDHANDLE;
break;
}
}
NdisReleaseSpinLock(&RecvPacketQueue.Lock);
if (!Found) {
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
for (pAsyncEvent = (PWAN_ASYNC_EVENT)ThresholdEventQueue.List.Flink;
(PVOID)pAsyncEvent != (PVOID)&ThresholdEventQueue.List;
pAsyncEvent = (PWAN_ASYNC_EVENT)pAsyncEvent->Linkage.Flink) {
if (pAsyncEvent->Context == (PVOID)pIrp) {
ThresholdEventQueue.ulCount--;
//
// Remove from the list
//
RemoveEntryList(&pAsyncEvent->Linkage);
Found = TRUE;
break;
}
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
}
ASSERT(Found);
//
// Free the wan_async_event structure
//
NdisWanFreeMemory(pAsyncEvent);
// NdisWanLowerIrql(DISPATCH_LEVEL, &OldIrql);
//
// Complete the irp
//
IoSetCancelRoutine(pIrp, NULL);
pIrp->Cancel = TRUE;
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoReleaseCancelSpinLock(pIrp->CancelIrql);
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
}
#endif
NTSTATUS
ExecuteIo(
IN ULONG ulFuncCode,
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ExecuteIo: FuncCode 0x%8.8x", ulFuncCode));
if (ulFuncCode < MAX_FUNC_CODES) {
Status = (*IoDispatchTable[ulFuncCode].Function)(pInputBuffer,
ulInputBufferLength,
pOutputBuffer,
ulOutputBufferLength,
pulBytesWritten);
}
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ExecuteIo: Status 0x%8.8x", Status));
return (Status);
}
NTSTATUS
MapConnectionId(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
MapConnectionId
Routine Description:
This functions takes a WAN Wrapper connection id, finds the corresponding
LinkCB and BundleCB, and returns handles to these CB's.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_MAP_CONNECTION_ID
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_MAP_CONNECTION_ID)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_MAP_CONNNECTION_ID
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_MAP_CONNECTION_ID)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
STATUS_SUCCESS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_MAP_CONNECTION_ID In = (PNDISWAN_MAP_CONNECTION_ID)pInputBuffer;
PNDISWAN_MAP_CONNECTION_ID Out = (PNDISWAN_MAP_CONNECTION_ID)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_MAP_CONNECTION_ID);
ULONG i;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("MapConnectionId:"));
*pulBytesWritten = SizeNeeded;
if ((ulInputBufferLength >= SizeNeeded) &&
(ulOutputBufferLength >= SizeNeeded)) {
NdisAcquireSpinLock(&ConnectionTable->Lock);
//
// Find the linkcb that has this connection id and return
// both the linkcb index and the bundlecb index
//
for (i = 0; i < ConnectionTable->ulArraySize; i++) {
PLINKCB pLinkCB = *(ConnectionTable->LinkArray + i);
if ((pLinkCB != NULL) &&
(pLinkCB->State == LINK_UP) &&
((pLinkCB->LineUpInfo.ConnectionWrapperID == In->hConnectionID) ||
(pLinkCB->hLinkHandle == In->hConnectionID))) {
PBUNDLECB BundleCB = pLinkCB->BundleCB;
//
// We have found the right link, return the link and bundle handles
//
Out->hLinkHandle = pLinkCB->hLinkHandle;
Out->hBundleHandle = BUNDLEH_FROM_BUNDLECB(BundleCB);
pLinkCB->hLinkContext = In->hLinkContext;
BundleCB->hBundleContext = In->hBundleContext;
//
// Copy the friendly name to the link
//
NdisMoveMemory(pLinkCB->Name,
In->szName,
(In->ulNameLength > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : In->ulNameLength);
break;
}
}
if (i >= ConnectionTable->ulArraySize) {
//
// We did not find a match to the connection id
//
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("MapConnectionId: ConnectionId not found! ConnectionId: 0x%8.8x",
In->hConnectionID));
}
NdisReleaseSpinLock(&ConnectionTable->Lock);
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("MapConnectionId: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
GetBundleHandle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
GetBundleHandle
Routine Description:
This function takes a handle to a linkcb and returns the handle to the bundlecb
that the linkcb belongs to
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_GET_BUNDLE_HANDLE
ulInputBufferLength - Length of the input buffer should be sizeof(NDISWAN_GET_BUNDLE_HANDLE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_GET_BUNDLE_HANDLE
ulOutputBufferLength - Length of the output buffer should be sizeof(NDISWAN_GET_BUNDLE_HANDLE)
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
STATUS_SUCCESS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_GET_BUNDLE_HANDLE In = (PNDISWAN_GET_BUNDLE_HANDLE)pInputBuffer;
PNDISWAN_GET_BUNDLE_HANDLE Out = (PNDISWAN_GET_BUNDLE_HANDLE)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_GET_BUNDLE_HANDLE);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBundleHandle:"));
*pulBytesWritten = SizeNeeded;
NdisAcquireSpinLock(&ConnectionTable->Lock);
if ((ulInputBufferLength >= SizeNeeded) &&
(ulOutputBufferLength >= SizeNeeded)) {
PLINKCB LinkCB;
PBUNDLECB BundleCB;
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
//
// Get the bundle handle that this link belongs to
//
if (LinkCB && LinkCB->State == LINK_UP &&
(BundleCB = LinkCB->BundleCB) != NULL) {
Out->hBundleHandle = BundleCB->hBundleHandle;
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleHandle: Invalid LinkHandle: 0x%8.8x",
In->hLinkHandle));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleHandle: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
NdisReleaseSpinLock(&ConnectionTable->Lock);
return (Status);
}
NTSTATUS
SetFriendlyName(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetFriendlyName
Routine Description:
Sets the friendly name of either a bundlecb or a linkcb
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_SET_FRIENDLY_NAME
ulInputBufferLength - Length of the input buffer should be sizeof(NDISWAN_SET_FRIENDLY_NAME)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_SET_FRIENDLY_NAME
ulOutputBufferLength - Length of the output buffer should be sizeof(NDISWAN_SET_FRIENDLY_NAME)
Return Values:
NDISWAN_ERROR_INVALID_HANDLE_TYPE
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
STATUS_SUCCESS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_SET_FRIENDLY_NAME In = (PNDISWAN_SET_FRIENDLY_NAME)pInputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_SET_FRIENDLY_NAME);
PLINKCB LinkCB;
PBUNDLECB BundleCB;
PUCHAR Dest;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetFriendlyName:"));
*pulBytesWritten = SizeNeeded;
NdisAcquireSpinLock(&ConnectionTable->Lock);
if (ulInputBufferLength >= SizeNeeded) {
if (In->usHandleType == LINKHANDLE) {
//
// Is this a link handle
//
LINKCB_FROM_LINKH(LinkCB, In->hHandle);
if (LinkCB != NULL && LinkCB->State == LINK_UP) {
Dest = LinkCB->Name;
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid LinkHandle: 0x%8.8x",
In->hHandle));
}
} else if (In->usHandleType == BUNDLEHANDLE) {
//
// Or a bundle handle
//
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hHandle);
if (BundleCB != NULL) {
Dest = BundleCB->Name;
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid BundleHandle: 0x%8.8x",
In->hHandle));
}
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE_TYPE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid HandleType: 0x%4.4x",
In->usHandleType));
}
if (Status == STATUS_SUCCESS) {
//
// Copy the friendly name to the link
//
NdisMoveMemory(Dest,
In->szName,
(In->ulNameLength > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : In->ulNameLength);
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
NdisReleaseSpinLock(&ConnectionTable->Lock);
return (Status);
}
NTSTATUS
ActivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
ActivateRoute
Routine Description:
This function routes the bundle given by hbundlehandle to
the protocol give by usprotocoltype.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_ACTIVATE_ROUTE
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_ACTIVATE_ROUTE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_ACTIVATE_ROUTE
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_ACTIVATE_ROUTE)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_ALREADY_ROUTED
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INSUFFICIENT_RESOURCES
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_ROUTE In = (PNDISWAN_ROUTE)pInputBuffer;
PNDISWAN_ROUTE Out = (PNDISWAN_ROUTE)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_ROUTE);
ULONG AllocationSize, i;
PBUNDLECB BundleCB;
BOOLEAN RouteExists = FALSE;
PPROTOCOLCB ProtocolCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ActivateRoute:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
return (STATUS_INFO_LENGTH_MISMATCH);
}
//
// If this is a valid bundle
//
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
if (BundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Invalid BundleHandle: 0x%8.8x, ProtocolType: 0x%4.4x",
In->hBundleHandle, In->usProtocolType));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
//
// Is this a route or unroute call?
//
if (In->usProtocolType == PROTOCOL_UNROUTE) {
//
// This is a call to unroute
//
NdisAcquireSpinLock(&BundleCB->Lock);
if (!(BundleCB->Flags & BUNDLE_ROUTED)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: BundleCB 0x%8.8x not routed!",
BundleCB));
NdisReleaseSpinLock(&BundleCB->Lock);
return(NDISWAN_ERROR_INVALID_HANDLE);
}
//
// Don't accept anymore sends on this bundle
//
BundleCB->Flags &= ~BUNDLE_ROUTED;
//
// Flush the protocol packet queues. This could cause us
// to complete frames to ndis out of order. Ndis should
// handle this.
//
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
FlushProtocolPacketQueue(ProtocolCB);
}
//
// Do we need to wait for any outstanding frames on the bundle?
//
if (BundleCB->OutstandingFrames != 0) {
NdisWanClearSyncEvent(&BundleCB->OutstandingFramesEvent);
BundleCB->Flags |= FRAMES_PENDING;
NdisReleaseSpinLock(&BundleCB->Lock);
NdisWanWaitForSyncEvent(&BundleCB->OutstandingFramesEvent);
NdisAcquireSpinLock(&BundleCB->Lock);
BundleCB->Flags &= ~FRAMES_PENDING;
}
//
// For each protocolcb in the bundle's protocolcb table
// (except for the i/o protocolcb)
//
for (i = 1; i < MAX_PROTOCOLS; i++) {
if (ProtocolCB = BundleCB->ProtocolCBTable[i]) {
//
// Remove the protocolcb from the bundlecb, both the table and
// the list.
//
RemoveProtocolCBFromBundle(ProtocolCB, BundleCB);
NdisReleaseSpinLock(&BundleCB->Lock);
//
// Do a linedown to the protocol
//
NdisWanClearSyncEvent(&BundleCB->IndicationEvent);
Status = DoLineDownToProtocol(ProtocolCB);
if (Status == NDIS_STATUS_PENDING) {
//
// This has been queued because we could not
// get the miniport lock. Wait for notification
// and pick up the route status.
//
NdisWanWaitForSyncEvent(&BundleCB->IndicationEvent);
Status = BundleCB->IndicationStatus;
}
//
// Return the protocolcb
//
NdisWanReturnProtocolCB(ProtocolCB);
NdisAcquireSpinLock(&BundleCB->Lock);
}
}
if (BundleCB->State == BUNDLE_GOING_DOWN) {
NdisReleaseSpinLock(&BundleCB->Lock);
//
// Clean up the connection table
//
RemoveBundleFromConnectionTable(BundleCB);
//
// Return the bundlecb
//
NdisWanReturnBundleCB(BundleCB);
} else {
NdisReleaseSpinLock(&BundleCB->Lock);
}
} else {
//
// This is a call to route
//
NdisAcquireSpinLock(&BundleCB->Lock);
if (BundleCB->State != BUNDLE_UP) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Invalid BundleState: 0x%8.8x, BundleHandle: 0x%8.8x ProtocolType: 0x%4.4x",
BundleCB->State, In->hBundleHandle, In->usProtocolType));
NdisReleaseSpinLock(&BundleCB->Lock);
return (NDISWAN_ERROR_INVALID_HANDLE);
}
//
// First make sure that we don't already have a route to this
// protocol type
//
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
//
// If we already have a route to this protocol type
// flag it as already existing
//
if (ProtocolCB->usProtocolType == In->usProtocolType) {
RouteExists = TRUE;
break;
}
}
if (RouteExists) {
//
// A route already exists for this protocoltype
//
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Route already exists: ProtocolType: 0x%2.2x",
ProtocolCB->usProtocolType));
NdisReleaseSpinLock(&BundleCB->Lock);
return (NDISWAN_ERROR_ALREADY_ROUTED);
}
//
// Create and initialize a ProtocolCB for this new route
//
NdisWanGetProtocolCB(&ProtocolCB,
In->usProtocolType,
In->usBindingNameLength,
In->BindingName,
In->ulBufferLength,
In->Buffer);
if (ProtocolCB == NULL) {
//
// Memory allocation failed
//
NdisReleaseSpinLock(&BundleCB->Lock);
return (STATUS_INSUFFICIENT_RESOURCES);
}
//
// Assign a handle for this protocolcb
//
AssignProtocolCBHandle(BundleCB, ProtocolCB);
//
// Do a new lineup to protocol
//
NdisWanClearSyncEvent(&BundleCB->IndicationEvent);
NdisReleaseSpinLock(&BundleCB->Lock);
Status = DoNewLineUpToProtocol(ProtocolCB);
if (Status == NDIS_STATUS_PENDING) {
//
// This has been queued because we could not
// get the miniport lock. Wait for notification
// and pick up the route status.
//
NdisWanWaitForSyncEvent(&BundleCB->IndicationEvent);
Status = BundleCB->IndicationStatus;
}
if (Status == NDIS_STATUS_SUCCESS) {
Out->usDeviceNameLength =
(ProtocolCB->DeviceName.Length > MAX_NAME_LENGTH) ?
MAX_NAME_LENGTH : ProtocolCB->DeviceName.Length;
NdisMoveMemory(&Out->DeviceName[0],
ProtocolCB->DeviceName.Buffer,
Out->usDeviceNameLength);
//
// Insert the protocolcb in the bundle's protocolcb table
// and list.
//
AddProtocolCBToBundle(ProtocolCB, BundleCB);
} else {
//
// Assign a handle for this protocolcb
//
FreeProtocolCBHandle(BundleCB, ProtocolCB);
NdisWanReturnProtocolCB(ProtocolCB);
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Error during LineUp to ProtocolType: 0x%4.4x",
ProtocolCB->usProtocolType));
}
}
return (NDIS_STATUS_SUCCESS);
}
NTSTATUS
BundleLink(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
BundleLink
Routine Description:
This function bundles the link given by hLinkHandle to the bundle given
by hBundlehandle. The resources used by the bundle that the link used
to belong to are freed.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_ADD_LINK_TO_BUNDLE
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_ADD_LINK_TO_BUNDLE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_ADD_LINK_TO_BUNDLE
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_ADD_LINK_TO_BUNDLE)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_ADD_LINK_TO_BUNDLE);
PBUNDLECB OldBundleCB, NewBundleCB;
PNDISWAN_ADD_LINK_TO_BUNDLE In = (PNDISWAN_ADD_LINK_TO_BUNDLE)pInputBuffer;
PLINKCB LinkCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("BundleLink:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
return (STATUS_INFO_LENGTH_MISMATCH);
}
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid LinkHandle: 0x%8.8x",
In->hLinkHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
BUNDLECB_FROM_BUNDLEH(NewBundleCB, In->hBundleHandle);
if (NewBundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid BundleHandle: 0x%8.8x",
In->hBundleHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
//
// Get the Bundle that this link currently belongs to
//
OldBundleCB = LinkCB->BundleCB;
if (OldBundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: OldBundleCB == NULL! LinkHandle: 0x%8.8x",
In->hLinkHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
if (OldBundleCB == NewBundleCB) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO,
("BundleLink: OldBundle == NewBundle! LinkHandle 0x%8.8x BundleHandle 0x%8.8x",
In->hLinkHandle, In->hBundleHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&OldBundleCB->Lock);
if (OldBundleCB->State != BUNDLE_UP) {
NdisReleaseSpinLock(&OldBundleCB->Lock);
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid BundleState: 0x%8.8x",
OldBundleCB->State));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisReleaseSpinLock(&OldBundleCB->Lock);
NdisAcquireSpinLock(&NewBundleCB->Lock);
if (NewBundleCB->State != BUNDLE_UP) {
NdisReleaseSpinLock(&NewBundleCB->Lock);
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid BundleState: 0x%8.8x",
NewBundleCB->State));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisReleaseSpinLock(&NewBundleCB->Lock);
NdisAcquireSpinLock(&OldBundleCB->Lock);
if (OldBundleCB->OutstandingFrames != 0) {
OldBundleCB->State = BUNDLE_GOING_DOWN;
NdisWanClearSyncEvent(&OldBundleCB->OutstandingFramesEvent);
OldBundleCB->Flags |= FRAMES_PENDING;
NdisReleaseSpinLock(&OldBundleCB->Lock);
NdisWanWaitForSyncEvent(&OldBundleCB->OutstandingFramesEvent);
NdisAcquireSpinLock(&OldBundleCB->Lock);
}
OldBundleCB->State = BUNDLE_DOWN;
//
// Remove the link from the old bundle
//
RemoveLinkFromBundle(OldBundleCB, LinkCB);
NdisReleaseSpinLock(&OldBundleCB->Lock);
RemoveBundleFromConnectionTable(OldBundleCB);
NdisWanReturnBundleCB(OldBundleCB);
//
// Add the link to the new bundle
//
AddLinkToBundle(NewBundleCB, LinkCB);
return (NDIS_STATUS_SUCCESS);
}
NTSTATUS
EnumLinksInBundle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_ENUM_LINKS_IN_BUNDLE In = (PNDISWAN_ENUM_LINKS_IN_BUNDLE)pInputBuffer;
PNDISWAN_ENUM_LINKS_IN_BUNDLE Out = (PNDISWAN_ENUM_LINKS_IN_BUNDLE)pOutputBuffer;
ULONG SizeNeeded, i;
PBUNDLECB BundleCB;
PLINKCB LinkCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("EnumLinksInBundle:"));
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
if (BundleCB != NULL) {
SizeNeeded = sizeof(NDISWAN_ENUM_LINKS_IN_BUNDLE) +
(sizeof(NDIS_HANDLE) * BundleCB->ulLinkCBCount);
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
NdisAcquireSpinLock(&BundleCB->Lock);
Out->ulNumberOfLinks = BundleCB->ulLinkCBCount;
//
// Walk the list of linkcb's and put the handle for each
// cb in the output handle array
//
i = 0;
for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
(PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
Out->hLinkHandleArray[i++] = LinkCB->hLinkHandle;
}
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Invalid BundleHandle: 0x%8.8x",
In->hBundleHandle));
}
return (Status);
}
NTSTATUS
SetProtocolPriority(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetProtocolPriority
Routine Description:
This function sets the the priority, given by uspriority, for the
protocol given by usprotocoltype on the bundle given by hbundlehandle.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_SET_PROTOCOL_PRIORITY
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_SET_PROTOCOL_PRIORITY)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_SET_PROTOCOL_PRIORITY
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_SET_PROTOCOL_PRIORITY)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_PROTOCOL_PRIORITY);
PNDISWAN_SET_PROTOCOL_PRIORITY In = (PNDISWAN_SET_PROTOCOL_PRIORITY)pInputBuffer;
PBUNDLECB BundleCB;
PPROTOCOLCB ProtocolCB;
#ifdef BANDWIDTH_ON_DEMAND
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetProtocolPriority:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
//
// If this is a valid bundle handle
//
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
if (BundleCB != NULL) {
ULONG BytesPerSecond;
//
// Walk the protocolcb list looking for this protocol type
// and set it's priority level
//
NdisAcquireSpinLock(&BundleCB->Lock);
BundleCB->Flags |= PROTOCOL_PRIORITY;
BytesPerSecond = (BundleCB->LineUpInfo.BundleSpeed * 100) / 8;
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
if (ProtocolCB->usProtocolType == In->usProtocolType) {
ProtocolCB->usPriority = In->usPriority;
ProtocolCB->ulByteQuota =
(BytesPerSecond * ProtocolCB->usPriority) / 100;
break;
}
}
//
// Sort the list so that highest priorty protcol is at the head
//
SortProtocolListByPriority(BundleCB);
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetProtocolPriority: Invalid BundleHandle: 0x%8.8x",
In->hBundleHandle));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetProtocolPriority: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
#endif // end of BANDWIDTH_ON_DEMAND
return (Status);
}
NTSTATUS
SetBandwidthOnDemand(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetBandwidthOnDemand
Routine Description:
This function sets the bandwidth on demand parameters for the bundle given by
hbundlehandle.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_SET_BANDWIDTH_ON_DEMAND
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_SET_BANDWIDTH_ON_DEMAND
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PBUNDLECB BundleCB;
ULONG SizeNeeded = sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND);
PNDISWAN_SET_BANDWIDTH_ON_DEMAND In = (PNDISWAN_SET_BANDWIDTH_ON_DEMAND)pInputBuffer;
#ifdef BANDWIDTH_ON_DEMAND
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetBandwidthOnDemand:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
//
// If this is a valid bundle handle
//
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
if (BundleCB != NULL) {
WAN_TIME Temp1, Temp2;
ULONG SecondsInSamplePeriod;
ULONG BytesPerSecond;
ULONG BytesInSamplePeriod;
PSAMPLE_TABLE UpperSampleTable = &BundleCB->UpperBonDInfo.SampleTable;
PSAMPLE_TABLE LowerSampleTable = &BundleCB->LowerBonDInfo.SampleTable;
NdisAcquireSpinLock(&BundleCB->Lock);
//
// We need to init the sample period in 100 nanoseconds
//
NdisWanInitWanTime(&Temp1, MILS_TO_100NANOS);
NdisWanInitWanTime(&Temp2, In->ulUpperSamplePeriod);
NdisWanMultiplyWanTime(&UpperSampleTable->SamplePeriod,
&Temp1,
&Temp2);
NdisWanInitWanTime(&Temp2, In->ulLowerSamplePeriod);
NdisWanMultiplyWanTime(&LowerSampleTable->SamplePeriod,
&Temp1,
&Temp2);
//
// The sample rate is the sample period divided by the number of
// samples in the sample array
//
NdisWanInitWanTime(&Temp1, UpperSampleTable->ulSampleArraySize);
NdisWanDivideWanTime(&UpperSampleTable->SampleRate,
&UpperSampleTable->SamplePeriod,
&Temp1);
//
// The sample rate is the sample period divided by the number of
// samples in the sample array
//
NdisWanInitWanTime(&Temp2, LowerSampleTable->ulSampleArraySize);
NdisWanDivideWanTime(&LowerSampleTable->SampleRate,
&LowerSampleTable->SamplePeriod,
&Temp2);
//
// Convert %bandwidth to Bytes/SamplePeriod
// 100bsp * 100 / 8 = BytesPerSecond
// BytesPerSecond * SecondsInSamplePeriod = BytesInSamplePeriod
// BytesInSamplePeriod * %Bandwidth / 100 = BytesInSamplePeriod
//
BundleCB->UpperBonDInfo.ulSecondsInSamplePeriod =
SecondsInSamplePeriod = In->ulUpperSamplePeriod / 1000;
BytesPerSecond = BundleCB->LineUpInfo.BundleSpeed * 100 / 8;
BytesInSamplePeriod = BytesPerSecond * SecondsInSamplePeriod;
BundleCB->UpperBonDInfo.ulBytesThreshold = BytesInSamplePeriod *
In->usUpperThreshold / 100;
BundleCB->UpperBonDInfo.usPercentBandwidth =
In->usUpperThreshold;
BundleCB->LowerBonDInfo.ulSecondsInSamplePeriod =
SecondsInSamplePeriod = In->ulLowerSamplePeriod / 1000;
BytesInSamplePeriod = BytesPerSecond * SecondsInSamplePeriod;
BundleCB->LowerBonDInfo.ulBytesThreshold = BytesInSamplePeriod *
In->usLowerThreshold / 100;
BundleCB->LowerBonDInfo.usPercentBandwidth =
In->usLowerThreshold;
BundleCB->UpperBonDInfo.State = BonDIdle;
BundleCB->LowerBonDInfo.State = BonDIdle;
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetBandwidthOnDemand: Invalid BundleHandle: 0x%8.8x",
In->hBundleHandle));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetBandwidthOnDemand: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
#endif // end of BANDWIDTH_ON_DEMAND
return (Status);
}
#ifdef NT
NTSTATUS
SetThresholdEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetThresholdEvent
Routine Description:
This function queues up an asyncevent for bandwidth on demand
events.
Arguments:
pInputBuffer - Pointer to the input structure that should be WAN_ASYNC_EVENT
ulInputBufferLength - Length of input buffer should be sizeof(WAN_ASYNC_EVENT)
pOutputBuffer - Pointer to the output structure that should be WAN_ASYNC_EVENT
ulOutputBufferLength - Length of output buffer should be sizeof(WAN_ASYNC_EVENT)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
--*/
{
NTSTATUS Status = STATUS_PENDING;
ULONG SizeNeeded = sizeof(NDISWAN_SET_THRESHOLD_EVENT);
PWAN_ASYNC_EVENT pAsyncEvent;
PIRP pIrp = (PIRP)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetThresholdEvent:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
NdisWanAllocateMemory(&pAsyncEvent, sizeof(WAN_ASYNC_EVENT));
if (pAsyncEvent != NULL) {
KIRQL Irql;
//
// The IRP was pended so setup a cancel routine and let the
// i/o subsystem know about the pend.
//
IoAcquireCancelSpinLock(&Irql);
IoMarkIrpPending(pIrp);
//
// Setup the structure
//
pAsyncEvent->Context = (PVOID)pIrp;
InsertTailGlobalList(ThresholdEventQueue, &(pAsyncEvent->Linkage));
IoSetCancelRoutine(pIrp, NdisWanCancelRoutine);
IoReleaseCancelSpinLock(Irql);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetThresholdEvent: Failed to allocate asyncevent storage"));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetThresholdEvent: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
return (Status);
}
#endif
NTSTATUS
FlushThresholdEvents(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("FlushThresholdEvents:"));
CancelThresholdEvents();
return (Status);
}
NTSTATUS
IoSendPacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_IO_PACKET);
PNDISWAN_IO_PACKET In = (PNDISWAN_IO_PACKET)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("IoSendPacket:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
//
// Verify the handle is a valid link or bundle handle
//
if (IsHandleValid(In->usHandleType, In->hHandle)) {
//
// Queue an Ndis Packet for this send
//
Status = BuildIoPacket(In, FALSE);
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoSendPacket: Invalid Handle: 0x%8.8x, HandleType: 0x%4.4x",
In->hHandle, In->usHandleType));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoSendPacket: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
return (Status);
}
#ifdef NT
NTSTATUS
IoReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_PENDING;
ULONG SizeNeeded = sizeof(NDISWAN_IO_PACKET);
PWAN_ASYNC_EVENT pAsyncEvent;
PIRP pIrp = (PIRP)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("IoReceivePacket:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
NdisWanAllocateMemory(&pAsyncEvent, sizeof(WAN_ASYNC_EVENT));
if (pAsyncEvent != NULL) {
KIRQL Irql;
//
// The IRP was pended so setup a cancel routine and let the
// i/o subsystem know about the pend.
//
IoAcquireCancelSpinLock(&Irql);
IoMarkIrpPending(pIrp);
//
// Setup the structure
//
pAsyncEvent->Context = (PVOID)pIrp;
InsertTailGlobalList(RecvPacketQueue, &(pAsyncEvent->Linkage));
IoSetCancelRoutine(pIrp, NdisWanCancelRoutine);
IoReleaseCancelSpinLock(Irql);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoReceivePacket: Failed to allocate asyncevent storage"));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoReceivePacket: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
return (Status);
}
#endif
NTSTATUS
FlushReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("FlushReceivePacket:"));
CancelIoReceivePackets();
return (Status);
}
NTSTATUS
GetStatistics(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_STATS);
PNDISWAN_GET_STATS In = (PNDISWAN_GET_STATS)pInputBuffer;
PNDISWAN_GET_STATS Out = (PNDISWAN_GET_STATS)pOutputBuffer;
PBUNDLECB BundleCB;
PLINKCB LinkCB;
NDIS_REQUEST NdisRequest;
NDIS_WAN_GET_STATS_INFO WanMiniportStats;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetStatistics:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
return (STATUS_INFO_LENGTH_MISMATCH);
}
NdisZeroMemory(&Out->Stats, sizeof(Out->Stats));
if (In->usHandleType == LINKHANDLE) {
//
// Looking for link stats
//
LINKCB_FROM_LINKH(LinkCB, In->hHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid LinkHandle: 0x%8.8x",
In->hHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
if (BundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid BundleHandle: 0x%8.8x",
In->hHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&BundleCB->Lock);
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.LinkStats,
(PUCHAR)&LinkCB->LinkStats,
sizeof(WAN_STATS));
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&BundleCB->BundleStats,
sizeof(WAN_STATS));
//
// If the wan miniport is doing framing or compression we
// need to get stats from it.
//
if ((BundleCB->FramingInfo.SendFramingBits & PASS_THROUGH_MODE) ||
((BundleCB->SendCompInfo.MSCompType == 0 &&
BundleCB->RecvCompInfo.MSCompType == 0) &&
(BundleCB->SendCompInfo.CompType != COMPTYPE_NONE ||
BundleCB->RecvCompInfo.CompType != COMPTYPE_NONE))) {
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
NdisZeroMemory(&WanMiniportStats, sizeof(NDIS_WAN_GET_STATS_INFO));
WanMiniportStats.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
//
// Submit this to the WAN Miniport
//
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_STATS_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportStats;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_GET_STATS_INFO);
NdisReleaseSpinLock(&BundleCB->Lock);
if (NdisWanSubmitNdisRequest(WanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN) == NDIS_STATUS_SUCCESS){
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.LinkStats,
(PUCHAR)&WanMiniportStats.BytesSent,
sizeof(WAN_STATS));
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&WanMiniportStats.BytesSent,
sizeof(WAN_STATS));
}
} else {
NdisReleaseSpinLock(&BundleCB->Lock);
}
} else if (In->usHandleType == BUNDLEHANDLE) {
//
// Looking for bundle stats
//
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hHandle);
if (BundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid BundleHandle: 0x%8.8x",
In->hHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&BundleCB->Lock);
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&BundleCB->BundleStats,
sizeof(WAN_STATS));
//
// If the wan miniport is doing framing or compression we
// need to get stats from it.
//
if ((BundleCB->LinkCBList.Flink != &BundleCB->LinkCBList) &&
((BundleCB->FramingInfo.SendFramingBits & PASS_THROUGH_MODE) ||
((BundleCB->SendCompInfo.MSCompType == 0 &&
BundleCB->RecvCompInfo.MSCompType == 0) &&
(BundleCB->SendCompInfo.CompType != COMPTYPE_NONE ||
BundleCB->RecvCompInfo.CompType != COMPTYPE_NONE)))) {
PWAN_ADAPTERCB WanAdapterCB;
LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
NdisZeroMemory(&WanMiniportStats, sizeof(NDIS_WAN_GET_STATS_INFO));
//
// If a miniport is doing it's own compression for this release we will
// expect that multilink is not allowed on the connection so the bundle
// will only have one link.
//
WanMiniportStats.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
WanAdapterCB = LinkCB->WanAdapterCB;
//
// Submit this to the WAN Miniport
//
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_STATS_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportStats;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_GET_STATS_INFO);
NdisReleaseSpinLock(&BundleCB->Lock);
if (NdisWanSubmitNdisRequest(WanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN) == NDIS_STATUS_SUCCESS){
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&WanMiniportStats.BytesSent,
sizeof(WAN_STATS));
}
} else {
NdisReleaseSpinLock(&BundleCB->Lock);
}
} else {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid handle type: 0x%4.4x",
In->usHandleType));
return (NDISWAN_ERROR_INVALID_HANDLE_TYPE);
}
return (STATUS_SUCCESS);
}
NTSTATUS
SetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_LINK_INFO);
PLINKCB LinkCB;
PBUNDLECB BundleCB;
NDIS_REQUEST NdisRequest;
PNDISWAN_SET_LINK_INFO In = (PNDISWAN_SET_LINK_INFO)pInputBuffer;
NDIS_WAN_SET_LINK_INFO WanMiniportLinkInfo;
PWAN_LINK_INFO LinkInfo;
PWAN_ADAPTERCB WanAdapterCB;
PLINKCB TempLinkCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetLinkInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
LinkInfo = &LinkCB->LinkInfo;
WanAdapterCB = LinkCB->WanAdapterCB;
NdisZeroMemory(&WanMiniportLinkInfo, sizeof (NDIS_WAN_SET_LINK_INFO));
//
// Copy into buffer to be sent to WAN Miniport this
// skips over the LinkHandle in the NDIS_WAN_SET_LINK_INFO
// structure.
//
WanMiniportLinkInfo.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
WanMiniportLinkInfo.MaxSendFrameSize = In->LinkInfo.MaxSendFrameSize;
WanMiniportLinkInfo.MaxRecvFrameSize = In->LinkInfo.MaxRecvFrameSize;
WanMiniportLinkInfo.SendFramingBits = In->LinkInfo.SendFramingBits;
WanMiniportLinkInfo.RecvFramingBits = In->LinkInfo.RecvFramingBits;
WanMiniportLinkInfo.SendCompressionBits = In->LinkInfo.SendCompressionBits;
WanMiniportLinkInfo.RecvCompressionBits = In->LinkInfo.RecvCompressionBits;
WanMiniportLinkInfo.SendACCM = In->LinkInfo.SendACCM;
WanMiniportLinkInfo.RecvACCM = In->LinkInfo.RecvACCM;
//
// Submit this to the WAN Miniport
//
NdisRequest.RequestType = NdisRequestSetInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_SET_LINK_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportLinkInfo;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_SET_LINK_INFO);
Status = NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN);
if (Status == NDIS_STATUS_SUCCESS) {
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
if (BundleCB == NULL) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
//
// Copy info into our linkcb
//
NdisAcquireSpinLock(&BundleCB->Lock);
LinkInfo->MaxSendFrameSize = In->LinkInfo.MaxSendFrameSize;
LinkInfo->MaxRecvFrameSize = In->LinkInfo.MaxRecvFrameSize;
LinkInfo->SendFramingBits = In->LinkInfo.SendFramingBits;
LinkInfo->RecvFramingBits = In->LinkInfo.RecvFramingBits;
LinkInfo->SendCompressionBits = In->LinkInfo.SendCompressionBits;
LinkInfo->RecvCompressionBits = In->LinkInfo.RecvCompressionBits;
LinkInfo->SendACCM = In->LinkInfo.SendACCM;
LinkInfo->RecvACCM = In->LinkInfo.RecvACCM;
LinkInfo->MaxRRecvFrameSize = In->LinkInfo.MaxRRecvFrameSize;
LinkInfo->MaxRSendFrameSize = In->LinkInfo.MaxRSendFrameSize;
//
// We need to set our bundle framing based on the framing for
// each link in the bundle so we will walk the linkcb list
// and | in each link's framing bits into the bundle.
//
//
BundleCB->FramingInfo.SendFramingBits = 0;
BundleCB->FramingInfo.RecvFramingBits = 0;
for (TempLinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
(PVOID)TempLinkCB != (PVOID)&BundleCB->LinkCBList;
TempLinkCB = (PLINKCB)TempLinkCB->Linkage.Flink) {
BundleCB->FramingInfo.SendFramingBits |= TempLinkCB->LinkInfo.SendFramingBits;
BundleCB->FramingInfo.RecvFramingBits |= TempLinkCB->LinkInfo.RecvFramingBits;
}
BundleCB->FramingInfo.MaxRSendFrameSize = LinkInfo->MaxRSendFrameSize;
//
// Since I use the receive frame size for memory allocation.
//
BundleCB->FramingInfo.MaxRRecvFrameSize = (LinkInfo->MaxRRecvFrameSize) ?
LinkInfo->MaxRRecvFrameSize : DEFAULT_MAX_MRRU;
//
// If VJ header compression has been negotiated allocate
// and initialize resources.
//
if (BundleCB->FramingInfo.SendFramingBits & SLIP_VJ_COMPRESSION ||
BundleCB->FramingInfo.SendFramingBits & SLIP_VJ_AUTODETECT ||
BundleCB->FramingInfo.RecvFramingBits & SLIP_VJ_COMPRESSION ||
BundleCB->FramingInfo.RecvFramingBits & SLIP_VJ_AUTODETECT) {
Status = sl_compress_init(&BundleCB->VJCompress, MAX_VJ_STATES);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Error allocating VJ Info!"));
}
}
//
// Configure multilink variables if needed
//
if (BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) {
if (BundleCB->FramingInfo.SendFramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT) {
BundleCB->SendSeqMask = SHORT_SEQ_MASK;
BundleCB->SendSeqTest = TEST_SHORT_SEQ;
} else {
BundleCB->SendSeqMask = LONG_SEQ_MASK;
BundleCB->SendSeqTest = TEST_LONG_SEQ;
}
}
if (BundleCB->FramingInfo.RecvFramingBits & PPP_MULTILINK_FRAMING) {
if (BundleCB->FramingInfo.RecvFramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT) {
BundleCB->RecvSeqMask = SHORT_SEQ_MASK;
BundleCB->RecvSeqTest = TEST_SHORT_SEQ;
} else {
BundleCB->RecvSeqMask = LONG_SEQ_MASK;
BundleCB->RecvSeqTest = TEST_LONG_SEQ;
}
}
BundleCB->RecvDescMax = ((((BundleCB->LineUpInfo.BundleSpeed * 100) / 8) * 3) /
BundleCB->FramingInfo.MaxRRecvFrameSize) +
BundleCB->ulLinkCBCount;
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = STATUS_UNSUCCESSFUL;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetLinkInfo: Error submitting request to Wan Miniport!"));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetLinkInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
GetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_LINK_INFO);
PNDISWAN_GET_LINK_INFO In = (PNDISWAN_GET_LINK_INFO)pInputBuffer;
PNDISWAN_GET_LINK_INFO Out = (PNDISWAN_GET_LINK_INFO)pOutputBuffer;
PLINKCB LinkCB;
NDIS_REQUEST NdisRequest;
NDIS_WAN_GET_LINK_INFO WanMiniportLinkInfo;
PWAN_LINK_INFO LinkInfo;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetLinkInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Invalid LinkHandle: 0x%8.8x",
In->hLinkHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
LinkInfo = &LinkCB->LinkInfo;
NdisZeroMemory(&WanMiniportLinkInfo, sizeof (NDIS_WAN_GET_LINK_INFO));
//
// Setup the link context for this request
//
WanMiniportLinkInfo.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
//
// Submit this to the WAN Miniport
//
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_LINK_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportLinkInfo;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_GET_LINK_INFO);
Status = NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN);
if (Status == NDIS_STATUS_SUCCESS) {
LinkInfo->MaxSendFrameSize = WanMiniportLinkInfo.MaxSendFrameSize;
LinkInfo->MaxRecvFrameSize = WanMiniportLinkInfo.MaxRecvFrameSize;
LinkInfo->SendFramingBits = WanMiniportLinkInfo.SendFramingBits;
LinkInfo->RecvFramingBits = WanMiniportLinkInfo.RecvFramingBits;
LinkInfo->SendCompressionBits = WanMiniportLinkInfo.SendCompressionBits;
LinkInfo->RecvCompressionBits = WanMiniportLinkInfo.RecvCompressionBits;
LinkInfo->SendACCM = WanMiniportLinkInfo.SendACCM;
LinkInfo->RecvACCM = WanMiniportLinkInfo.RecvACCM;
//
// Fill Recv and Send MRRU
//
LinkInfo->MaxRSendFrameSize = MIN_SEND;
LinkInfo->MaxRRecvFrameSize = MAX_MRRU;
NdisMoveMemory(&Out->LinkInfo,
LinkInfo,
sizeof(WAN_LINK_INFO));
Out->hLinkHandle = LinkCB->hLinkHandle;
} else {
Status = STATUS_UNSUCCESSFUL;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Error submitting request to Wan Miniport!"));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
SetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_COMPRESSION_INFO);
PNDISWAN_SET_COMPRESSION_INFO In = (PNDISWAN_SET_COMPRESSION_INFO)pInputBuffer;
NDIS_REQUEST NdisRequest;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetCompressionInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
PLINKCB LinkCB;
PBUNDLECB BundleCB;
NDIS_WAN_SET_COMP_INFO WanCompressionInfo;
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Invalid LinkHandle: 0x%8.8x",
In->hLinkHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisZeroMemory(&WanCompressionInfo, sizeof(NDIS_WAN_SET_COMP_INFO));
WanCompressionInfo.NdisLinkHandle =
LinkCB->LineUpInfo.NdisLinkHandle;
WanCompressionInfo.SendCapabilities.MSCompType =
In->SendCapabilities.MSCompType;
WanCompressionInfo.SendCapabilities.CompType =
In->SendCapabilities.CompType;
WanCompressionInfo.SendCapabilities.CompLength =
In->SendCapabilities.CompLength;
if (In->SendCapabilities.CompType == 0) {
NdisMoveMemory(&WanCompressionInfo.SendCapabilities.Proprietary,
&In->SendCapabilities.Proprietary,
sizeof(In->SendCapabilities.Proprietary));
} else {
NdisMoveMemory(&WanCompressionInfo.SendCapabilities.Public,
&In->SendCapabilities.Public,
sizeof(In->SendCapabilities.Public));
}
WanCompressionInfo.RecvCapabilities.MSCompType =
In->RecvCapabilities.MSCompType;
WanCompressionInfo.RecvCapabilities.CompType =
In->RecvCapabilities.CompType;
WanCompressionInfo.RecvCapabilities.CompLength =
In->RecvCapabilities.CompLength;
if (In->RecvCapabilities.CompType == 0) {
NdisMoveMemory(&WanCompressionInfo.RecvCapabilities.Proprietary,
&In->RecvCapabilities.Proprietary,
sizeof(In->RecvCapabilities.Proprietary));
} else {
NdisMoveMemory(&WanCompressionInfo.RecvCapabilities.Public,
&In->RecvCapabilities.Public,
sizeof(In->RecvCapabilities.Public));
}
//
// Submit this to the WAN Miniport
//
NdisRequest.RequestType = NdisRequestSetInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_SET_COMP_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanCompressionInfo;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_SET_COMP_INFO);
NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN);
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
if (BundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Invalid LinkHandle: 0x%8.8x",
In->hLinkHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&BundleCB->Lock);
//
// Store the compression info in our bundlecb
//
NdisMoveMemory(&BundleCB->SendCompInfo,
&In->SendCapabilities,
sizeof(COMPRESS_INFO));
NdisMoveMemory(&BundleCB->RecvCompInfo,
&In->RecvCapabilities,
sizeof(COMPRESS_INFO));
WanAllocateCCP(BundleCB);
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
GetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_COMPRESSION_INFO);
PNDISWAN_GET_COMPRESSION_INFO In = (PNDISWAN_GET_COMPRESSION_INFO)pInputBuffer;
PNDISWAN_GET_COMPRESSION_INFO Out = (PNDISWAN_GET_COMPRESSION_INFO)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetCompressionInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
PLINKCB LinkCB;
NDIS_REQUEST NdisRequest;
PBUNDLECB BundleCB;
NDIS_WAN_GET_COMP_INFO WanCompressionInfo;
ULONG i;
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisZeroMemory(&WanCompressionInfo, sizeof(NDIS_WAN_GET_COMP_INFO));
WanCompressionInfo.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
//
// Submit this to the WAN Miniport
//
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_COMP_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanCompressionInfo;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_SET_COMP_INFO);
Status = NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN);
if (Status == NDIS_STATUS_SUCCESS) {
//
// This miniport is doing some kind of compression!
// Fill in the miniport specific stuff
//
Out->SendCapabilities.MSCompType =
WanCompressionInfo.SendCapabilities.MSCompType;
Out->SendCapabilities.CompType =
WanCompressionInfo.SendCapabilities.CompType;
Out->SendCapabilities.CompLength =
WanCompressionInfo.SendCapabilities.CompLength;
if (Out->SendCapabilities.CompType == 0) {
NdisMoveMemory((PUCHAR)&Out->SendCapabilities.Proprietary,
(PUCHAR)&WanCompressionInfo.SendCapabilities.Proprietary,
sizeof(In->SendCapabilities.Proprietary));
} else {
NdisMoveMemory((PUCHAR)&Out->SendCapabilities.Public,
(PUCHAR)&WanCompressionInfo.SendCapabilities.Public,
sizeof(In->SendCapabilities.Public));
}
Out->RecvCapabilities.MSCompType =
WanCompressionInfo.RecvCapabilities.MSCompType;
Out->RecvCapabilities.CompType =
WanCompressionInfo.RecvCapabilities.CompType;
Out->RecvCapabilities.CompLength =
WanCompressionInfo.RecvCapabilities.CompLength;
if (Out->RecvCapabilities.CompType == 0) {
NdisMoveMemory((PUCHAR)&Out->RecvCapabilities.Proprietary,
(PUCHAR)&WanCompressionInfo.RecvCapabilities.Proprietary,
sizeof(In->SendCapabilities.Proprietary));
} else {
NdisMoveMemory((PUCHAR)&Out->RecvCapabilities.Public,
(PUCHAR)&WanCompressionInfo.RecvCapabilities.Public,
sizeof(In->SendCapabilities.Public));
}
} else {
Status = STATUS_SUCCESS;
Out->SendCapabilities.CompType = COMPTYPE_NONE;
Out->SendCapabilities.CompLength = 0;
Out->RecvCapabilities.CompType = COMPTYPE_NONE;
Out->RecvCapabilities.CompLength = 0;
}
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
if (BundleCB == NULL) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&BundleCB->Lock);
//
// Fill in the ndiswan specific stuff
//
NdisMoveMemory(Out->SendCapabilities.LMSessionKey,
BundleCB->SendCompInfo.LMSessionKey,
sizeof(Out->SendCapabilities.LMSessionKey));
NdisMoveMemory(Out->SendCapabilities.UserSessionKey,
BundleCB->SendCompInfo.UserSessionKey,
sizeof(Out->SendCapabilities.UserSessionKey));
NdisMoveMemory(Out->SendCapabilities.Challenge,
BundleCB->SendCompInfo.Challenge,
sizeof(Out->SendCapabilities.Challenge));
NdisMoveMemory(Out->RecvCapabilities.LMSessionKey,
BundleCB->RecvCompInfo.LMSessionKey,
sizeof(Out->RecvCapabilities.LMSessionKey));
NdisMoveMemory(Out->RecvCapabilities.UserSessionKey,
BundleCB->RecvCompInfo.UserSessionKey,
sizeof(Out->RecvCapabilities.UserSessionKey));
NdisMoveMemory(Out->RecvCapabilities.Challenge,
BundleCB->RecvCompInfo.Challenge,
sizeof(Out->RecvCapabilities.Challenge));
//
// We will set encryption capabilities based on session key
// availability. If the LMSessionKey is all zero's we will not
// offer 40bit encryption. If the UserSessionKey is all zero's
// we will not offer 128bit encryption.
//
Out->SendCapabilities.MSCompType = NDISWAN_COMPRESSION;
for (i = 0; i < sizeof(Out->SendCapabilities.LMSessionKey); i++) {
if (Out->SendCapabilities.LMSessionKey[i] != 0) {
Out->SendCapabilities.MSCompType |= (NDISWAN_ENCRYPTION | NDISWAN_40_ENCRYPTION);
break;
}
}
#ifdef ENCRYPT_128BIT
for (i = 0; i < sizeof(Out->SendCapabilities.UserSessionKey); i++) {
if (Out->SendCapabilities.UserSessionKey[i] != 0) {
Out->SendCapabilities.MSCompType |= NDISWAN_128_ENCRYPTION;
break;
}
}
#endif
Out->RecvCapabilities.MSCompType = NDISWAN_COMPRESSION;
for (i = 0; i < sizeof(Out->RecvCapabilities.LMSessionKey); i++) {
if (Out->RecvCapabilities.LMSessionKey[i] != 0) {
Out->RecvCapabilities.MSCompType |= (NDISWAN_ENCRYPTION | NDISWAN_40_ENCRYPTION);
break;
}
}
#ifdef ENCRYPT_128BIT
for (i = 0; i < sizeof(Out->RecvCapabilities.UserSessionKey); i++) {
if (Out->RecvCapabilities.UserSessionKey[i] != 0) {
Out->RecvCapabilities.MSCompType |= NDISWAN_128_ENCRYPTION;
break;
}
}
#endif
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetCompressionInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
SetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_SET_VJ_INFO In = (PNDISWAN_SET_VJ_INFO)pInputBuffer;
PLINKCB LinkCB;
PBUNDLECB BundleCB;
ULONG SizeNeeded = sizeof(NDISWAN_SET_VJ_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetVJInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
if (BundleCB == NULL) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&BundleCB->Lock);
NdisMoveMemory(&BundleCB->RecvVJInfo,
&In->RecvCapabilities,
sizeof(VJ_INFO));
if (In->RecvCapabilities.IPCompressionProtocol == 0x2D) {
if (In->RecvCapabilities.MaxSlotID < MAX_VJ_STATES) {
Status = sl_compress_init(&BundleCB->VJCompress,
(UCHAR)(In->RecvCapabilities.MaxSlotID + 1));
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Error allocating VJ Info!"));
}
}
}
NdisMoveMemory(&BundleCB->SendVJInfo,
&In->SendCapabilities,
sizeof(VJ_INFO));
if (In->SendCapabilities.IPCompressionProtocol == 0x2D) {
if (In->SendCapabilities.MaxSlotID < MAX_VJ_STATES) {
Status = sl_compress_init(&BundleCB->VJCompress,
(UCHAR)(In->SendCapabilities.MaxSlotID + 1));
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Error allocating VJ Info!"));
}
}
}
NdisReleaseSpinLock(&BundleCB->Lock);
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetVJInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
GetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_GET_VJ_INFO In = (PNDISWAN_GET_VJ_INFO)pInputBuffer;
PNDISWAN_GET_VJ_INFO Out = (PNDISWAN_GET_VJ_INFO)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_GET_VJ_INFO);
PLINKCB LinkCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetVJInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
return (NDISWAN_ERROR_INVALID_HANDLE);
}
Out->SendCapabilities.IPCompressionProtocol =
Out->RecvCapabilities.IPCompressionProtocol = 0x2D;
Out->SendCapabilities.MaxSlotID =
Out->RecvCapabilities.MaxSlotID = MAX_VJ_STATES - 1;
Out->SendCapabilities.CompSlotID =
Out->RecvCapabilities.CompSlotID = 1;
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetVJInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
GetBandwidthUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_BANDWIDTH_UTILIZATION);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBandwidthUtilization:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBandwidthUtilization: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
EnumProtocolUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_ENUM_PROTOCOL_UTILIZATION);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("EnumProtocolUtilization:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumProtocolUtilization: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
EnumActiveBundles(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_ENUM_ACTIVE_BUNDLES);
PNDISWAN_ENUM_ACTIVE_BUNDLES Out = (PNDISWAN_ENUM_ACTIVE_BUNDLES)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetNumActiveBundles:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
//
// Does this information need to be protected by the lock?
// I would hate to have things get slowed for this call!
//
Out->ulNumberOfActiveBundles = ConnectionTable->ulNumActiveBundles;
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetNumActiveBundles: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
GetWanInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_WAN_INFO);
PNDISWAN_GET_WAN_INFO In = (PNDISWAN_GET_WAN_INFO)pInputBuffer;
PNDISWAN_GET_WAN_INFO Out = (PNDISWAN_GET_WAN_INFO)pOutputBuffer;
PLINKCB LinkCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetWanInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
if (LinkCB != NULL) {
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
Out->WanInfo.MaxFrameSize = WanAdapterCB->WanInfo.MaxFrameSize;
Out->WanInfo.MaxTransmit = WanAdapterCB->WanInfo.MaxTransmit;
Out->WanInfo.FramingBits = WanAdapterCB->WanInfo.FramingBits;
Out->WanInfo.DesiredACCM = WanAdapterCB->WanInfo.DesiredACCM;
Out->WanInfo.MaxReconstructedFrameSize = MAX_MRRU;
Out->WanInfo.LinkSpeed = LinkCB->LineUpInfo.LinkSpeed * 100;
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetWanInfo: Invalid LinkHandle: 0x%8.8x",
In->hLinkHandle));
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetWanInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
}
return (Status);
}
NTSTATUS
SetDebugInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_SET_DEBUG_INFO pDebugInfo = (PNDISWAN_SET_DEBUG_INFO)pInputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_SET_DEBUG_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetDebugInfo: OldLevel: 0x%8.8x OldMask: 0x%8.8x",
NdisWanCB.ulTraceLevel, NdisWanCB.ulTraceMask));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
NdisWanCB.ulTraceLevel = pDebugInfo->ulTraceLevel;
NdisWanCB.ulTraceMask = pDebugInfo->ulTraceMask;
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
}
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetDebugInfo: NewLevel: 0x%8.8x NewMask: 0x%8.8x",
NdisWanCB.ulTraceLevel, NdisWanCB.ulTraceMask));
return (Status);
}
NTSTATUS
SetBridgeInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_BRIDGE_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetBridgeInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_NOT_IMPLEMENTED;
return (Status);
}
NTSTATUS
GetBridgeInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_BRIDGE_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBridgeInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_NOT_IMPLEMENTED;
return (Status);
}
NTSTATUS
SetCIPXInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_CIPX_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetCIPXInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_NOT_IMPLEMENTED;
return (Status);
}
NTSTATUS
GetCIPXInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_CIPX_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetCIPXInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_NOT_IMPLEMENTED;
return (Status);
}
NTSTATUS
SetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_ENCRYPTION_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetEncryptionInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_NOT_IMPLEMENTED;
return (Status);
}
NTSTATUS
GetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_ENCRYPTION_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetEncryptionInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_NOT_IMPLEMENTED;
return (Status);
}
NTSTATUS
GetIdleTime(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_IDLE_TIME);
PNDISWAN_GET_IDLE_TIME In = (PNDISWAN_GET_IDLE_TIME)pInputBuffer;
PNDISWAN_GET_IDLE_TIME Out = (PNDISWAN_GET_IDLE_TIME)pOutputBuffer;
PBUNDLECB BundleCB = NULL;
PPROTOCOLCB ProtocolCB = NULL;
WAN_TIME CurrentTime, Diff, OneSecond;
WAN_TIME LastNonIdleData;
BOOLEAN Found = FALSE;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetIdleTime:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
return (STATUS_INFO_LENGTH_MISMATCH);
}
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
if (BundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Invalid BundleHandle: 0x%8.8x",
In->hBundleHandle));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
NdisAcquireSpinLock(&BundleCB->Lock);
//
// If this is for the bundle
//
if (In->usProtocolType == BUNDLE_IDLE_TIME) {
LastNonIdleData = BundleCB->LastRecvNonIdleData;
} else {
//
// Find the protocol type
//
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
if (ProtocolCB->usProtocolType == In->usProtocolType) {
Found = TRUE;
break;
}
}
if (!Found) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Invalid ProtocolType: 0x%4.4x",
In->usProtocolType));
NdisReleaseSpinLock(&BundleCB->Lock);
return (NDISWAN_ERROR_NO_ROUTE);
}
LastNonIdleData = ProtocolCB->LastRecvNonIdleData;
}
NdisWanGetSystemTime(&CurrentTime);
NdisWanCalcTimeDiff(&Diff, &CurrentTime, &LastNonIdleData);
NdisWanInitWanTime(&OneSecond, ONE_SECOND);
NdisWanDivideWanTime(&CurrentTime, &Diff, &OneSecond);
Out->ulSeconds = CurrentTime.LowPart;
NdisReleaseSpinLock(&BundleCB->Lock);
return (STATUS_SUCCESS);
}
NTSTATUS
DeactivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
DeactivateRoute
Routine Description:
This function unroutes the protocol given by usprotocoltype
from the bundle given by hbundlehandle.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_UNROUTE
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_UNROUTE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_UNROUTE
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_UNROUTE)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_ALREADY_ROUTED
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INSUFFICIENT_RESOURCES
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_UNROUTE In = (PNDISWAN_UNROUTE)pInputBuffer;
PNDISWAN_UNROUTE Out = (PNDISWAN_UNROUTE)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_UNROUTE);
ULONG AllocationSize, i;
PBUNDLECB BundleCB;
BOOLEAN RouteExists = FALSE;
PPROTOCOLCB ProtocolCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ActivateRoute:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
return (STATUS_INFO_LENGTH_MISMATCH);
}
//
// If this is a valid bundle
//
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
if (BundleCB == NULL) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Invalid BundleHandle: 0x%8.8x, ProtocolType: 0x%4.4x",
In->hBundleHandle, In->usProtocolType));
return (NDISWAN_ERROR_INVALID_HANDLE);
}
//
// If the ProtocolType is PROTOCOL_UNROUTE we will unroute all protocols
// from the bundle, otherwise we will only unroute the protocol = ProtocolType.
// If this is the only protocol on the bundle we will mark the bundle as
// being unrouted.
//
//
if (In->usProtocolType == PROTOCOL_UNROUTE) {
//
// This is a call to unroute
//
NdisAcquireSpinLock(&BundleCB->Lock);
if (!(BundleCB->Flags & BUNDLE_ROUTED)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: BundleCB 0x%8.8x not routed!",
BundleCB));
NdisReleaseSpinLock(&BundleCB->Lock);
return(NDISWAN_ERROR_INVALID_HANDLE);
}
//
// Don't accept anymore sends on this bundle
//
BundleCB->Flags &= ~BUNDLE_ROUTED;
//
// Flush the protocol packet queues. This could cause us
// to complete frames to ndis out of order. Ndis should
// handle this.
//
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
FlushProtocolPacketQueue(ProtocolCB);
}
//
// Do we need to wait for any outstanding frames on the bundle?
//
if (BundleCB->OutstandingFrames != 0) {
NdisWanClearSyncEvent(&BundleCB->OutstandingFramesEvent);
BundleCB->Flags |= FRAMES_PENDING;
NdisReleaseSpinLock(&BundleCB->Lock);
NdisWanWaitForSyncEvent(&BundleCB->OutstandingFramesEvent);
NdisAcquireSpinLock(&BundleCB->Lock);
BundleCB->Flags &= ~FRAMES_PENDING;
}
//
// For each protocolcb in the bundle's protocolcb table
// (except for the i/o protocolcb)
//
for (i = 1; i < MAX_PROTOCOLS; i++) {
if (ProtocolCB = BundleCB->ProtocolCBTable[i]) {
//
// Remove the protocolcb from the bundlecb, both the table and
// the list.
//
RemoveProtocolCBFromBundle(ProtocolCB, BundleCB);
NdisReleaseSpinLock(&BundleCB->Lock);
//
// Do a linedown to the protocol
//
NdisWanClearSyncEvent(&BundleCB->IndicationEvent);
Status = DoLineDownToProtocol(ProtocolCB);
if (Status == NDIS_STATUS_PENDING) {
//
// This has been queued because we could not
// get the miniport lock. Wait for notification
// and pick up the route status.
//
NdisWanWaitForSyncEvent(&BundleCB->IndicationEvent);
Status = BundleCB->IndicationStatus;
}
//
// Return the protocolcb
//
NdisWanReturnProtocolCB(ProtocolCB);
NdisAcquireSpinLock(&BundleCB->Lock);
}
}
if (BundleCB->State == BUNDLE_GOING_DOWN) {
NdisReleaseSpinLock(&BundleCB->Lock);
//
// Clean up the connection table
//
RemoveBundleFromConnectionTable(BundleCB);
//
// Return the bundlecb
//
NdisWanReturnBundleCB(BundleCB);
} else {
NdisReleaseSpinLock(&BundleCB->Lock);
}
}
return (NDIS_STATUS_SUCCESS);
}
NTSTATUS
GetNdisWanCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_DUMPCB Out = (PNDISWAN_DUMPCB)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_DUMPCB) + sizeof(NDISWANCB);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetNdisWanCB:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
Out->Address = (PVOID)&NdisWanCB;
NdisMoveMemory(&Out->Buffer[0],
&NdisWanCB,
sizeof(NDISWANCB));
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
return (Status);
}
NTSTATUS
EnumAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_ENUMCB Out = (PNDISWAN_ENUMCB)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_ENUMCB) + (sizeof(PADAPTERCB) * AdapterCBList.ulCount);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetAdapterCB:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
PADAPTERCB AdapterCB;
ULONG i = 0;
Out->ulNumberOfCBs = AdapterCBList.ulCount;
for (AdapterCB = (PADAPTERCB)AdapterCBList.List.Flink;
(PVOID)AdapterCB != (PVOID)&AdapterCBList.List;
AdapterCB = (PADAPTERCB)AdapterCB->Linkage.Flink) {
Out->Address[i++] = (PVOID)AdapterCB;
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
return (Status);
}
NTSTATUS
GetAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_DUMPCB Out = (PNDISWAN_DUMPCB)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_DUMPCB) + sizeof(ADAPTERCB);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetAdapterCB:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
PADAPTERCB AdapterCB;
for (AdapterCB = (PADAPTERCB)AdapterCBList.List.Flink;
(PVOID)AdapterCB != (PVOID)&AdapterCBList.List;
AdapterCB = (PADAPTERCB)AdapterCB->Linkage.Flink) {
if (AdapterCB == (PADAPTERCB)Out->Address) {
break;
}
}
if ((PVOID)AdapterCB != (PVOID)&AdapterCBList.List) {
NdisMoveMemory(&Out->Buffer[0],
AdapterCB,
sizeof(ADAPTERCB));
} else {
Status = NDISWAN_ERROR_INVALID_ADDRESS;
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
return (Status);
}
NTSTATUS
EnumWanAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_ENUMCB Out = (PNDISWAN_ENUMCB)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_ENUMCB) +
sizeof(PWAN_ADAPTERCB) * WanAdapterCBList.ulCount;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetAdapterCB:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
PWAN_ADAPTERCB WanAdapterCB;
ULONG i = 0;
Out->ulNumberOfCBs = WanAdapterCBList.ulCount;
for (WanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCBList.List.Flink;
(PVOID)WanAdapterCB != (PVOID)&WanAdapterCBList.List;
WanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCB->Linkage.Flink) {
Out->Address[i] = (PVOID)WanAdapterCB;
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
return (Status);
}
NTSTATUS
GetWanAdapterCB(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_DUMPCB) + sizeof(WAN_ADAPTERCB);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetWanAdapterCB:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength >= SizeNeeded) {
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
return (Status);
}
VOID
CancelThresholdEvents(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
#ifdef NT
PWAN_ASYNC_EVENT pAsyncEvent = NULL;
KIRQL Irql;
PIRP pIrp;
for (; ;) {
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
if (!IsListEmpty(&ThresholdEventQueue.List)) {
pAsyncEvent = (PWAN_ASYNC_EVENT)RemoveHeadList(&ThresholdEventQueue.List);
ThresholdEventQueue.ulCount--;
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
if (pAsyncEvent != NULL) {
IoAcquireCancelSpinLock(&Irql);
pIrp = (PIRP)pAsyncEvent->Context;
pIrp->Cancel = TRUE;
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoReleaseCancelSpinLock(Irql);
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
//
// Free the wan_async_event structure
//
NdisWanFreeMemory(pAsyncEvent);
pAsyncEvent = NULL;
} else
break;
}
#endif // End #ifdef NT
}
VOID
CancelIoReceivePackets(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
#ifdef NT
PWAN_ASYNC_EVENT pAsyncEvent = NULL;
KIRQL Irql;
PIRP pIrp;
for (; ;) {
NdisAcquireSpinLock(&RecvPacketQueue.Lock);
if (!IsListEmpty(&RecvPacketQueue.List)) {
pAsyncEvent = (PWAN_ASYNC_EVENT)RemoveHeadList(&RecvPacketQueue.List);
RecvPacketQueue.ulCount--;
}
NdisReleaseSpinLock(&RecvPacketQueue.Lock);
if (pAsyncEvent != NULL) {
IoAcquireCancelSpinLock(&Irql);
pIrp = (PIRP)pAsyncEvent->Context;
pIrp->Cancel = TRUE;
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->usHandleType = CANCELEDHANDLE;
IoReleaseCancelSpinLock(Irql);
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
//
// Free the wan_async_event structure
//
NdisWanFreeMemory(pAsyncEvent);
pAsyncEvent = NULL;
} else
break;
}
#endif // End #ifdef NT
}
VOID
AddProtocolCBToBundle(
PPROTOCOLCB ProtocolCB,
PBUNDLECB BundleCB
)
/*++
Routine Name:
AddProtocolCBToBundle
Routine Description:
This routine adds the protocolcb to the bundlecb protocollist and
protocoltable. It also assigns the protocolcb's handle (index into
the table) and set's the initial priority of all of the protocols
on the list.
Arguments:
ProtocolCB - Pointer to the protocol control block
BundleCB - Pointer to the bundle control block
Return Values:
None
--*/
{
ULONG i, InitialByteQuota;
ULONG InitialPriority;
//
// Add to list
//
InsertTailList(&BundleCB->ProtocolCBList, &ProtocolCB->Linkage);
//
// Insert in table
//
ASSERT(BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] ==
(PPROTOCOLCB)RESERVED_PROTOCOLCB);
BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] = ProtocolCB;
BundleCB->ulNumberOfRoutes++;
//
// Setup the send mask for this protocolcb
//
ProtocolCB->SendMaskBit = BundleCB->SendMask + 0x00000001;
BundleCB->SendMask = (BundleCB->SendMask << 1) | 0x00000001;
BundleCB->Flags |= BUNDLE_ROUTED;
ProtocolCB->Flags |= PROTOCOL_ROUTED;
//
// We want to walk the protocolcblist and assign the intial
// value for each protocol priority and byte quota. The
// initial value for the priority is just 100 divided by the
// number of protocols that we have routed. The initial value
// for the byte quota is the bundle speed in Bps * InitialPriority (%)
// divided by 100.
//
InitialPriority = (BundleCB->ulNumberOfRoutes - 1) ?
100 / (BundleCB->ulNumberOfRoutes - 1) : 100;
InitialByteQuota = (((BundleCB->LineUpInfo.BundleSpeed * 100) / 8) *
InitialPriority) / 100;
//
// Skip the first one on the list since it is the PrivateIo
// protocolcb and always has a priority of 100.
//
ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
for (ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
#ifdef BANDWIDTH_ON_DEMAND
ProtocolCB->usPriority = (USHORT)InitialPriority;
ProtocolCB->ulByteQuota = InitialByteQuota;
#endif // end of BANDWIDTH_ON_DEMAND
}
}
VOID
RemoveProtocolCBFromBundle(
PPROTOCOLCB ProtocolCB,
PBUNDLECB BundleCB
)
{
ProtocolCB->Flags &= ~PROTOCOL_ROUTED;
RemoveEntryList(&ProtocolCB->Linkage);
BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] = NULL;
BundleCB->ulNumberOfRoutes--;
BundleCB->SendMask &= ~ProtocolCB->SendMaskBit;
}
#ifdef BANDWIDTH_ON_DEMAND
VOID
SortProtocolListByPriority(
IN PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PPROTOCOLCB ProtocolCB, NextProtocolCB, IoProtocolCB;
//
// First save the I/O ProtocolCB
//
IoProtocolCB = (PPROTOCOLCB)RemoveHeadList(&BundleCB->ProtocolCBList);
//
// Initial starting conditions
//
ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
NextProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
//
// This is a lousy sorting algorith but it is simple and not called
// very often so we will leave it as is for now.
//
while ((PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList) {
while ((PVOID)NextProtocolCB != (PVOID)&BundleCB->ProtocolCBList) {
if (NextProtocolCB->usPriority > ProtocolCB->usPriority) {
PLIST_ENTRY Prev, Next;
RemoveEntryList(&NextProtocolCB->Linkage);
Prev = (PLIST_ENTRY)ProtocolCB->Linkage.Blink;
Next = (PLIST_ENTRY)ProtocolCB->Linkage.Flink;
//
// Fix up the previous flink
//
Prev->Flink = (PLIST_ENTRY)NextProtocolCB;
//
// Fixup the new insertions flink and blink
//
NextProtocolCB->Linkage.Blink = Prev;
NextProtocolCB->Linkage.Flink = (PLIST_ENTRY)ProtocolCB;
//
// Fixup the next blink
//
ProtocolCB->Linkage.Blink = (PLIST_ENTRY)NextProtocolCB;
//
// Get the new starting point
//
ProtocolCB = NextProtocolCB;
//
// Get the next compare
//
NextProtocolCB = (PPROTOCOLCB)Next;
} else {
NextProtocolCB = (PPROTOCOLCB)NextProtocolCB->Linkage.Flink;
}
}
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
}
//
// Restore I/O ProtocolCB
//
InsertHeadList(&BundleCB->ProtocolCBList, &IoProtocolCB->Linkage);
}
#endif // end of BANDWIDTH_ON_DEMAND
VOID
CompleteThresholdEvent(
PBUNDLECB BundleCB,
ULONG ThresholdType
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
#ifdef NT
KIRQL Irql;
PIRP pIrp;
PWAN_ASYNC_EVENT pAsyncEvent = NULL;
PNDISWAN_SET_THRESHOLD_EVENT ThresholdEvent;
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
if (!IsListEmpty(&ThresholdEventQueue.List)) {
pAsyncEvent = (PWAN_ASYNC_EVENT)RemoveHeadList(&ThresholdEventQueue.List);
ThresholdEventQueue.ulCount--;
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
if (pAsyncEvent != NULL) {
IoAcquireCancelSpinLock(&Irql);
pIrp = (PIRP)pAsyncEvent->Context;
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = sizeof(NDISWAN_SET_THRESHOLD_EVENT);
ThresholdEvent = (PNDISWAN_SET_THRESHOLD_EVENT)pIrp->AssociatedIrp.SystemBuffer;
ThresholdEvent->hBundleHandle = BundleCB->hBundleHandle;
ThresholdEvent->ulThreshold = ThresholdType;
IoSetCancelRoutine(pIrp, NULL);
IoReleaseCancelSpinLock(Irql);
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
//
// Free the wan_async_event structure
//
NdisWanFreeMemory(pAsyncEvent);
}
#endif // End #ifdef NT
}
VOID
FlushProtocolPacketQueue(
PPROTOCOLCB ProtocolCB
)
{
ULONG MagicNumber = 0;
PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
PBUNDLECB BundleCB = ProtocolCB->BundleCB;
if (ProtocolCB->usProtocolType == PROTOCOL_PRIVATE_IO) {
MagicNumber = NDISWAN_MAGIC_NUMBER;
}
while (!IsNdisPacketQueueEmpty(ProtocolCB)) {
PNDIS_PACKET NdisPacket;
NdisPacket = RemoveHeadNdisPacketQueue(ProtocolCB);
//
// Assign the magic number
//
PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber = MagicNumber;
NdisReleaseSpinLock(&BundleCB->Lock);
//
// Complete the NdisPacket
//
TryToCompleteNdisPacket(AdapterCB, NdisPacket);
NdisAcquireSpinLock(&BundleCB->Lock);
}
}
VOID
AssignProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
)
{
ULONG i;
//
// Find the first unused slot in the table
//
for (i = 1; i < MAX_PROTOCOLS; i++) {
if (BundleCB->ProtocolCBTable[i] == NULL) {
ProtocolCB->hProtocolHandle = (NDIS_HANDLE)i;
ProtocolCB->BundleCB = BundleCB;
BundleCB->ProtocolCBTable[i] = (PPROTOCOLCB)RESERVED_PROTOCOLCB;
break;
}
}
ASSERT(i < MAX_PROTOCOLS);
}
VOID
FreeProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
)
{
ASSERT(BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] ==
(PPROTOCOLCB)RESERVED_PROTOCOLCB);
ASSERT((ULONG)ProtocolCB->hProtocolHandle < MAX_PROTOCOLS);
BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] = NULL;
}