windows-nt/Source/XPSP1/NT/net/ndis/loopback/lbmini.c
2020-09-26 16:20:57 +08:00

1055 lines
22 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
lpmini.c
Abstract:
Loopback miniport
Author:
Jameel Hyder jameelh@microsoft.com
Environment:
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
NDIS_OID LBSupportedOidArray[] =
{
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_MAC_OPTIONS,
OID_GEN_PROTOCOL_OPTIONS,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_RECEIVE_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_CURRENT_LOOKAHEAD,
OID_GEN_DRIVER_VERSION,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_XMIT_OK,
OID_GEN_RCV_OK,
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER,
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_802_3_MULTICAST_LIST,
OID_802_3_MAXIMUM_LIST_SIZE,
OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION,
OID_802_3_XMIT_MORE_COLLISIONS,
OID_802_5_PERMANENT_ADDRESS,
OID_802_5_CURRENT_ADDRESS,
OID_802_5_CURRENT_FUNCTIONAL,
OID_802_5_CURRENT_GROUP,
OID_802_5_LAST_OPEN_STATUS,
OID_802_5_CURRENT_RING_STATUS,
OID_802_5_CURRENT_RING_STATE,
OID_802_5_LINE_ERRORS,
OID_802_5_LOST_FRAMES,
OID_FDDI_LONG_PERMANENT_ADDR,
OID_FDDI_LONG_CURRENT_ADDR,
OID_FDDI_LONG_MULTICAST_LIST,
OID_FDDI_LONG_MAX_LIST_SIZE,
OID_FDDI_SHORT_PERMANENT_ADDR,
OID_FDDI_SHORT_CURRENT_ADDR,
OID_FDDI_SHORT_MULTICAST_LIST,
OID_FDDI_SHORT_MAX_LIST_SIZE,
OID_LTALK_CURRENT_NODE_ID,
OID_ARCNET_PERMANENT_ADDRESS,
OID_ARCNET_CURRENT_ADDRESS
};
UINT LBSupportedOids = sizeof(LBSupportedOidArray)/sizeof(NDIS_OID);
UCHAR LBVendorDescription[] = "MS LoopBack Driver";
UCHAR LBVendorId[3] = {0xFF, 0xFF, 0xFF};
const NDIS_PHYSICAL_ADDRESS physicalConst = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
LONG LoopDebugLevel = DBG_LEVEL_ERR;
LONG LoopDebugComponent = DBG_COMP_ALL;
const MEDIA_INFO MediaParams[] =
{
/* NdisMedium802_3 */ { 1500, 14, PACKET_FILTER_802_3, 100000},
/* NdisMedium802_5 */ { 4082, 14, PACKET_FILTER_802_5, 40000},
/* NdisMediumFddi */ { 4486, 13, PACKET_FILTER_FDDI, 1000000},
/* NdisMediumWan */ { 0, 0, 0, 0},
/* NdisMediumLocalTalk */ { 600, 3, PACKET_FILTER_LTALK, 2300},
/* NdisMediumDix */ { 1500, 14, PACKET_FILTER_DIX, 100000},
/* NdisMediumArcnetRaw */ { 1512, 3, PACKET_FILTER_ARCNET, 25000},
/* NdisMediumArcnet878_2 */ {1512, 3, PACKET_FILTER_ARCNET, 25000}
};
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NDIS_STATUS Status;
NDIS_MINIPORT_CHARACTERISTICS MChars;
NDIS_STRING Name;
NDIS_HANDLE WrapperHandle;
//
// Register the miniport with NDIS.
//
NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
MChars.MajorNdisVersion = NDIS_MAJOR_VERSION;
MChars.MinorNdisVersion = NDIS_MINOR_VERSION;
MChars.InitializeHandler = LBInitialize;
MChars.QueryInformationHandler = LBQueryInformation;
MChars.SetInformationHandler = LBSetInformation;
MChars.ResetHandler = LBReset;
MChars.TransferDataHandler = LBTransferData;
MChars.SendHandler = LBSend;
MChars.HaltHandler = LBHalt;
MChars.CheckForHangHandler = LBCheckForHang;
Status = NdisMRegisterMiniport(WrapperHandle,
&MChars,
sizeof(MChars));
if (Status != NDIS_STATUS_SUCCESS)
{
NdisTerminateWrapper(WrapperHandle, NULL);
}
return(Status);
}
NDIS_STATUS
LBInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE ConfigurationContext
)
/*++
Routine Description:
This is the initialize handler.
Arguments:
OpenErrorStatus Not used by us.
SelectedMediumIndex Place-holder for what media we are using
MediumArray Array of ndis media passed down to us to pick from
MediumArraySize Size of the array
MiniportAdapterHandle The handle NDIS uses to refer to us
WrapperConfigurationContext For use by NdisOpenConfiguration
Return Value:
NDIS_STATUS_SUCCESS unless something goes wrong
--*/
{
UINT i, Length;
PADAPTER pAdapt;
NDIS_MEDIUM AdapterMedium;
NDIS_HANDLE ConfigHandle = NULL;
PNDIS_CONFIGURATION_PARAMETER Parameter;
PUCHAR NetworkAddress;
NDIS_STRING MediumKey = NDIS_STRING_CONST("Medium");
NDIS_STATUS Status;
do
{
//
// Start off by allocating the adapter block
//
NdisAllocateMemory(&pAdapt,
sizeof(ADAPTER),
0,
physicalConst);
if (pAdapt == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
NdisZeroMemory(pAdapt, sizeof(ADAPTER));
pAdapt->MiniportHandle = MiniportAdapterHandle;
NdisOpenConfiguration(&Status,
&ConfigHandle,
ConfigurationContext);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
("Unable to open configuration database!\n"));
break;
}
NdisReadConfiguration(&Status,
&Parameter,
ConfigHandle,
&MediumKey,
NdisParameterInteger);
AdapterMedium = NdisMedium802_3; // Default
if (Status == NDIS_STATUS_SUCCESS)
{
AdapterMedium = (NDIS_MEDIUM)Parameter->ParameterData.IntegerData;
if ((AdapterMedium != NdisMedium802_3) &&
(AdapterMedium != NdisMedium802_5) &&
(AdapterMedium != NdisMediumFddi) &&
(AdapterMedium != NdisMediumLocalTalk) &&
(AdapterMedium != NdisMediumArcnet878_2))
{
DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
("Unable to find 'Medium' keyword or invalid value!\n"));
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
}
switch (AdapterMedium)
{
case NdisMedium802_3:
NdisMoveMemory(pAdapt->PermanentAddress,
ETH_CARD_ADDRESS,
ETH_LENGTH_OF_ADDRESS);
NdisMoveMemory(pAdapt->CurrentAddress,
ETH_CARD_ADDRESS,
ETH_LENGTH_OF_ADDRESS);
break;
case NdisMedium802_5:
NdisMoveMemory(pAdapt->PermanentAddress,
TR_CARD_ADDRESS,
TR_LENGTH_OF_ADDRESS);
NdisMoveMemory(pAdapt->CurrentAddress,
TR_CARD_ADDRESS,
TR_LENGTH_OF_ADDRESS);
break;
case NdisMediumFddi:
NdisMoveMemory(pAdapt->PermanentAddress,
FDDI_CARD_ADDRESS,
FDDI_LENGTH_OF_LONG_ADDRESS);
NdisMoveMemory(pAdapt->CurrentAddress,
FDDI_CARD_ADDRESS,
FDDI_LENGTH_OF_LONG_ADDRESS);
break;
case NdisMediumLocalTalk:
pAdapt->PermanentAddress[0] = LTALK_CARD_ADDRESS;
pAdapt->CurrentAddress[0] = LTALK_CARD_ADDRESS;
break;
case NdisMediumArcnet878_2:
pAdapt->PermanentAddress[0] = ARC_CARD_ADDRESS;
pAdapt->CurrentAddress[0] = ARC_CARD_ADDRESS;
break;
}
pAdapt->Medium = AdapterMedium;
pAdapt->MediumLinkSpeed = MediaParams[(UINT)AdapterMedium].LinkSpeed;
pAdapt->MediumMinPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
pAdapt->MediumMaxPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen+
MediaParams[(UINT)AdapterMedium].MaxFrameLen;
pAdapt->MediumMacHeaderLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
pAdapt->MediumMaxFrameLen = MediaParams[(UINT)AdapterMedium].MaxFrameLen;
pAdapt->MediumPacketFilters = MediaParams[(UINT)AdapterMedium].PacketFilters;
NdisReadNetworkAddress(&Status,
&NetworkAddress,
&Length,
ConfigHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// verify the address is appropriate for the specific media and
// ensure that the locally administered address bit is set
//
switch (AdapterMedium)
{
case NdisMedium802_3:
case NdisMediumFddi:
if ((Length != ETH_LENGTH_OF_ADDRESS) ||
ETH_IS_MULTICAST(NetworkAddress) ||
((NetworkAddress[0] & 0x02) == 0))
{
Length = 0;
}
break;
case NdisMedium802_5:
if ((Length != TR_LENGTH_OF_ADDRESS) ||
(NetworkAddress[0] & 0x80) ||
((NetworkAddress[0] & 0x40) == 0))
{
Length = 0;
}
break;
case NdisMediumLocalTalk:
if ((Length != 1) || LT_IS_BROADCAST(NetworkAddress[0]))
{
Length = 0;
}
break;
case NdisMediumArcnet878_2:
if ((Length != 1) || ARC_IS_BROADCAST(NetworkAddress[0]))
{
Length = 0;
}
break;
}
if (Length == 0)
{
DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
("Invalid NetAddress in registry!\n"));
}
else
{
NdisMoveMemory(pAdapt->CurrentAddress,
NetworkAddress,
Length);
}
}
//
// Make sure the medium saved is one of the ones being offered
//
for (i = 0; i < MediumArraySize; i++)
{
if (MediumArray[i] == AdapterMedium)
{
*SelectedMediumIndex = i;
break;
}
}
if (i == MediumArraySize)
{
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
break;
}
//
// Set the attributes now.
//
NdisMSetAttributesEx(MiniportAdapterHandle,
pAdapt,
0, // CheckForHangTimeInSeconds
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT|NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
0);
Status = NDIS_STATUS_SUCCESS;
} while (FALSE);
if (ConfigHandle != NULL)
{
NdisCloseConfiguration(ConfigHandle);
}
if (Status != NDIS_STATUS_SUCCESS)
{
if (pAdapt != NULL)
{
NdisFreeMemory(pAdapt, sizeof(ADAPTER), 0);
}
}
return Status;
}
VOID
LBHalt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
Halt handler.
Arguments:
MiniportAdapterContext Pointer to the Adapter
Return Value:
None.
--*/
{
PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext;
//
// Free the resources now
//
NdisFreeMemory(pAdapt, sizeof(ADAPTER), 0);
}
NDIS_STATUS
LBReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
Reset Handler. We just don't do anything.
Arguments:
AddressingReset To let NDIS know whether we need help from it with our reset
MiniportAdapterContext Pointer to our adapter
Return Value:
--*/
{
PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext;
*AddressingReset = FALSE;
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
LBSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT Flags
)
/*++
Routine Description:
Send handler. Just re-wrap the packet and send it below. Re-wrapping is necessary since
NDIS uses the WrapperReserved for its own use.
Arguments:
MiniportAdapterContext Pointer to the adapter
Packet Packet to send
Flags Unused, passed down below
Return Value:
Return code from NdisSend
--*/
{
PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext;
pAdapt->SendPackets++;
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS
LBQueryInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Miniport QueryInfo handler.
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesWritten Specifies how much info is written
BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
UINT i;
NDIS_OID MaskOid;
PVOID SourceBuffer;
UINT SourceBufferLength;
ULONG GenericUlong = 0;
USHORT GenericUshort;
*BytesWritten = 0;
*BytesNeeded = 0;
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
("OID = %lx\n", Oid));
for (i = 0;i < LBSupportedOids; i++)
{
if (Oid == LBSupportedOidArray[i])
break;
}
if ((i == LBSupportedOids) ||
(((Oid & OID_TYPE) != OID_TYPE_GENERAL) &&
(((pAdapt->Medium == NdisMedium802_3) && ((Oid & OID_TYPE) != OID_TYPE_802_3)) ||
((pAdapt->Medium == NdisMedium802_5) && ((Oid & OID_TYPE) != OID_TYPE_802_5)) ||
((pAdapt->Medium == NdisMediumFddi) && ((Oid & OID_TYPE) != OID_TYPE_FDDI)) ||
((pAdapt->Medium == NdisMediumLocalTalk) && ((Oid & OID_TYPE) != OID_TYPE_LTALK)) ||
((pAdapt->Medium == NdisMediumArcnet878_2) && ((Oid & OID_TYPE) != OID_TYPE_ARCNET)))))
{
return NDIS_STATUS_INVALID_OID;
}
//
// Initialize these once, since this is the majority of cases.
//
SourceBuffer = (PVOID)&GenericUlong;
SourceBufferLength = sizeof(ULONG);
switch (Oid & OID_TYPE_MASK)
{
case OID_TYPE_GENERAL_OPERATIONAL:
switch (Oid)
{
case OID_GEN_MAC_OPTIONS:
GenericUlong = (ULONG)(NDIS_MAC_OPTION_NO_LOOPBACK);
break;
case OID_GEN_SUPPORTED_LIST:
SourceBuffer = LBSupportedOidArray;
SourceBufferLength = LBSupportedOids * sizeof(ULONG);
break;
case OID_GEN_HARDWARE_STATUS:
GenericUlong = NdisHardwareStatusReady;
break;
case OID_GEN_MEDIA_SUPPORTED:
case OID_GEN_MEDIA_IN_USE:
GenericUlong = pAdapt->Medium;
break;
case OID_GEN_MAXIMUM_LOOKAHEAD:
GenericUlong = MAX_LOOKAHEAD;
break;
case OID_GEN_MAXIMUM_FRAME_SIZE:
GenericUlong = pAdapt->MediumMaxFrameLen;
break;
case OID_GEN_LINK_SPEED:
GenericUlong = pAdapt->MediumLinkSpeed;
break;
case OID_GEN_TRANSMIT_BUFFER_SPACE:
GenericUlong = pAdapt->MediumMaxPacketLen;
break;
case OID_GEN_RECEIVE_BUFFER_SPACE:
GenericUlong = pAdapt->MediumMaxPacketLen;
break;
case OID_GEN_TRANSMIT_BLOCK_SIZE:
GenericUlong = 1;
break;
case OID_GEN_RECEIVE_BLOCK_SIZE:
GenericUlong = 1;
break;
case OID_GEN_VENDOR_ID:
SourceBuffer = LBVendorId;
SourceBufferLength = sizeof(LBVendorId);
break;
case OID_GEN_VENDOR_DESCRIPTION:
SourceBuffer = LBVendorDescription;
SourceBufferLength = sizeof(LBVendorDescription);
break;
case OID_GEN_CURRENT_PACKET_FILTER:
GenericUlong = pAdapt->PacketFilter;
break;
case OID_GEN_CURRENT_LOOKAHEAD:
GenericUlong = pAdapt->MaxLookAhead;
break;
case OID_GEN_DRIVER_VERSION:
GenericUshort = (LOOP_MAJOR_VERSION << 8) + LOOP_MINOR_VERSION;
SourceBuffer = &GenericUshort;
SourceBufferLength = sizeof(USHORT);
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
GenericUlong = pAdapt->MediumMaxPacketLen;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_GENERAL_STATISTICS:
MaskOid = (Oid & OID_INDEX_MASK) - 1;
switch (Oid & OID_REQUIRED_MASK)
{
case OID_REQUIRED_MANDATORY:
switch(Oid)
{
case OID_GEN_XMIT_OK:
SourceBuffer = &(pAdapt->SendPackets);
SourceBufferLength = sizeof(ULONG);
break;
default:
ASSERT (MaskOid < GM_ARRAY_SIZE);
GenericUlong = pAdapt->GeneralMandatory[MaskOid];
break;
}
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_802_3_OPERATIONAL:
switch (Oid)
{
case OID_802_3_PERMANENT_ADDRESS:
SourceBuffer = pAdapt->PermanentAddress;
SourceBufferLength = ETH_LENGTH_OF_ADDRESS;
break;
case OID_802_3_CURRENT_ADDRESS:
SourceBuffer = pAdapt->CurrentAddress;
SourceBufferLength = ETH_LENGTH_OF_ADDRESS;
break;
case OID_802_3_MAXIMUM_LIST_SIZE:
GenericUlong = ETH_MAX_MULTICAST_ADDRESS;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_802_3_STATISTICS:
switch (Oid)
{
case OID_802_3_RCV_ERROR_ALIGNMENT:
case OID_802_3_XMIT_ONE_COLLISION:
case OID_802_3_XMIT_MORE_COLLISIONS:
GenericUlong = 0;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_802_5_OPERATIONAL:
switch (Oid)
{
case OID_802_5_PERMANENT_ADDRESS:
SourceBuffer = pAdapt->PermanentAddress;
SourceBufferLength = TR_LENGTH_OF_ADDRESS;
break;
case OID_802_5_CURRENT_ADDRESS:
SourceBuffer = pAdapt->CurrentAddress;
SourceBufferLength = TR_LENGTH_OF_ADDRESS;
break;
case OID_802_5_LAST_OPEN_STATUS:
GenericUlong = 0;
break;
case OID_802_5_CURRENT_RING_STATUS:
GenericUlong = NDIS_RING_SINGLE_STATION;
break;
case OID_802_5_CURRENT_RING_STATE:
GenericUlong = NdisRingStateOpened;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_802_5_STATISTICS:
switch (Oid)
{
case OID_802_5_LINE_ERRORS:
case OID_802_5_LOST_FRAMES:
GenericUlong = 0;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_FDDI_OPERATIONAL:
switch (Oid)
{
case OID_FDDI_LONG_PERMANENT_ADDR:
SourceBuffer = pAdapt->PermanentAddress;
SourceBufferLength = FDDI_LENGTH_OF_LONG_ADDRESS;
break;
case OID_FDDI_LONG_CURRENT_ADDR:
SourceBuffer = pAdapt->CurrentAddress;
SourceBufferLength = FDDI_LENGTH_OF_LONG_ADDRESS;
break;
case OID_FDDI_LONG_MAX_LIST_SIZE:
GenericUlong = FDDI_MAX_MULTICAST_LONG;
break;
case OID_FDDI_SHORT_PERMANENT_ADDR:
SourceBuffer = pAdapt->PermanentAddress;
SourceBufferLength = FDDI_LENGTH_OF_SHORT_ADDRESS;
break;
case OID_FDDI_SHORT_CURRENT_ADDR:
SourceBuffer = pAdapt->CurrentAddress;
SourceBufferLength = FDDI_LENGTH_OF_SHORT_ADDRESS;
break;
case OID_FDDI_SHORT_MAX_LIST_SIZE:
GenericUlong = FDDI_MAX_MULTICAST_SHORT;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_LTALK_OPERATIONAL:
switch(Oid)
{
case OID_LTALK_CURRENT_NODE_ID:
SourceBuffer = pAdapt->CurrentAddress;
SourceBufferLength = 1;
break;
default:
ASSERT(FALSE);
break;
}
break;
case OID_TYPE_ARCNET_OPERATIONAL:
switch(Oid)
{
case OID_ARCNET_PERMANENT_ADDRESS:
SourceBuffer = pAdapt->PermanentAddress;
SourceBufferLength = 1;
break;
case OID_ARCNET_CURRENT_ADDRESS:
SourceBuffer = pAdapt->CurrentAddress;
SourceBufferLength = 1;
break;
default:
ASSERT(FALSE);
break;
}
break;
default:
ASSERT(FALSE);
break;
}
if (SourceBufferLength > InformationBufferLength)
{
*BytesNeeded = SourceBufferLength;
return NDIS_STATUS_BUFFER_TOO_SHORT;
}
NdisMoveMemory(InformationBuffer, SourceBuffer, SourceBufferLength);
*BytesWritten = SourceBufferLength;
return(Status);
}
NDIS_STATUS
LBSetInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Miniport SetInfo handler.
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesRead Specifies how much info is read
BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
*BytesRead = 0;
*BytesNeeded = 0;
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
("SetInformation: OID = %lx\n", Oid));
switch (Oid)
{
case OID_GEN_CURRENT_PACKET_FILTER:
if (InformationBufferLength != sizeof(ULONG))
{
Status = NDIS_STATUS_INVALID_DATA;
}
else
{
ULONG PacketFilter;
PacketFilter = *(UNALIGNED ULONG *)InformationBuffer;
if (PacketFilter != (PacketFilter & pAdapt->MediumPacketFilters))
{
Status = NDIS_STATUS_NOT_SUPPORTED;
}
else
{
pAdapt->PacketFilter = PacketFilter;
*BytesRead = InformationBufferLength;
}
}
break;
case OID_GEN_CURRENT_LOOKAHEAD:
if (InformationBufferLength != sizeof(ULONG))
{
Status = NDIS_STATUS_INVALID_DATA;
}
else
{
ULONG CurrentLookahead;
CurrentLookahead = *(UNALIGNED ULONG *)InformationBuffer;
if (CurrentLookahead > MAX_LOOKAHEAD)
{
Status = NDIS_STATUS_INVALID_LENGTH;
}
else if (CurrentLookahead >= pAdapt->MaxLookAhead)
{
pAdapt->MaxLookAhead = CurrentLookahead;
*BytesRead = sizeof(ULONG);
Status = NDIS_STATUS_SUCCESS;
}
}
break;
case OID_802_3_MULTICAST_LIST:
if (pAdapt->Medium != NdisMedium802_3)
{
Status = NDIS_STATUS_INVALID_OID;
break;
}
if ((InformationBufferLength % ETH_LENGTH_OF_ADDRESS) != 0)
{
Status = NDIS_STATUS_INVALID_LENGTH;
break;
}
break;
case OID_802_5_CURRENT_FUNCTIONAL:
if (pAdapt->Medium != NdisMedium802_5)
{
Status = NDIS_STATUS_INVALID_OID;
break;
}
if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL)
{
Status = NDIS_STATUS_INVALID_LENGTH;
break;
}
break;
case OID_802_5_CURRENT_GROUP:
if (pAdapt->Medium != NdisMedium802_5)
{
Status = NDIS_STATUS_INVALID_OID;
break;
}
if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL)
{
Status = NDIS_STATUS_INVALID_LENGTH;
break;
}
break;
case OID_FDDI_LONG_MULTICAST_LIST:
if (pAdapt->Medium != NdisMediumFddi)
{
Status = NDIS_STATUS_INVALID_OID;
break;
}
if ((InformationBufferLength % FDDI_LENGTH_OF_LONG_ADDRESS) != 0)
{
Status = NDIS_STATUS_INVALID_LENGTH;
break;
}
break;
case OID_FDDI_SHORT_MULTICAST_LIST:
if (pAdapt->Medium != NdisMediumFddi)
{
Status = NDIS_STATUS_INVALID_OID;
break;
}
if ((InformationBufferLength % FDDI_LENGTH_OF_SHORT_ADDRESS) != 0)
{
Status = NDIS_STATUS_INVALID_LENGTH;
break;
}
break;
case OID_GEN_PROTOCOL_OPTIONS:
Status = NDIS_STATUS_SUCCESS;
break;
default:
Status = NDIS_STATUS_INVALID_OID;
break;
}
return(Status);
}
BOOLEAN
LBCheckForHang(
IN NDIS_HANDLE MiniportAdapterContext
)
{
return FALSE;
}
NDIS_STATUS
LBTransferData(
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer
)
{
ASSERT (0);
return NDIS_STATUS_NOT_SUPPORTED;
}