www.pudn.com > IPsec_Src_Instal.rar > Miniport.c
/*++
Copyright (c) 1992-2000 Microsoft Corporation
--*/
#include "precomp.h"
#include "PktHdr.h"
#include "hmac.h"
/*
Miniport Initialize is Called as a result of the intermediate driver
calling NdisIMInitializeDeviceInstance (in PPBindAdapter) to
initialize its miniport Operations
*/
NDIS_STATUS MPInitialize(OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext)
{
UINT i;
PADAPT pAdapt;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
NDIS_MEDIUM Medium;
do
{
//
// Access the device context area allocate by PPBindAdapter
//
pAdapt = NdisIMGetDeviceContext(MiniportAdapterHandle);
//
// MiniportAdapterHandle specifies a handle identifying the
// miniport's NIC, which is assigned by the NDIS library.
// Save this handle.
//
pAdapt->MiniportHandle = MiniportAdapterHandle;
//
// Usually we export the medium type of the adapter below as
// our virtual miniport's medium type. However if the adapter
// below us is a WAN device, then we claim to be of medium
// type 802.3.
//
Medium = pAdapt->Medium;
if (Medium == NdisMediumWan)
{
Medium = NdisMedium802_3;
}
//
// Making Sure that Selected Medium is the supported Medium
//
for (i = 0; i < MediumArraySize; i++)
{
if (MediumArray[i] == Medium)
{
*SelectedMediumIndex = i;
break;
}
}
if (i == MediumArraySize)
{
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
break;
}
//
// Informs the NDIS library about Virtual NIC
//
NdisMSetAttributesEx(MiniportAdapterHandle,
pAdapt,
0,
NDIS_ATTRIBUTE_DESERIALIZE |
NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND |
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
0);
//
// Initialize LastIndicatedStatus = NDIS_STATUS_MEDIA_CONNECT
//
pAdapt->LastIndicatedStatus = NDIS_STATUS_MEDIA_CONNECT;
//
// Initializing Power Management State
// NdisDeviceStateD0 - Full Powered State
//
pAdapt->MiniportDeviceState = NdisDeviceStateD0;
pAdapt->ProtocolDeviceState = NdisDeviceStateD0;
//
// Add this adapter to the global pAdapt List
//
NdisAcquireSpinLock(&GlobalLock);
pAdapt->Next = pAdaptList;
pAdaptList = pAdapt;
NdisReleaseSpinLock(&GlobalLock);
Status = NDIS_STATUS_SUCCESS;
}
while (FALSE);
pAdapt->MiniportInitPending = FALSE;
NdisSetEvent(&pAdapt->MiniportInitEvent);
*OpenErrorStatus = Status;
return Status;
}
/*
MPSendPackets transfers some number of packets specified as
Array of packet Pointers , over the Network
*/
VOID MPSendPackets(IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets)
{
PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
NDIS_STATUS Status;
UINT i;
PVOID MediaSpecificInfo = NULL;
UINT MediaSpecificInfoSize = 0;
DbgPrint("Send");
for (i = 0; i < NumberOfPackets; i++)
{
PNDIS_PACKET Packet;
PNDIS_PACKET MyPacket;
BOOLEAN bDecision;
PNDIS_BUFFER pNewNdisBfr;
ULONG OrigPayloadl;
ULONG NewPayloadl;
PUCHAR pNewPayload = NULL;
#define szPayloadCopy ETH_MAX_PACKET_SIZE
char PayloadCopy[szPayloadCopy];
//
// Copying a Single packet from the packet Array
//
Packet = PacketArray[i];
// 读取封包中的所有字符串
GetPktPayload(Packet, PayloadCopy, szPayloadCopy, &OrigPayloadl);
//----------------------------------------
NdisAcquireSpinLock(&pAdapt->Lock);
//
// See if packet to be dropped.
// 判断封包是否要被丢弃
//
Status = FilterPacket(pAdapt, Packet, NULL, TRUE, &bDecision);
if (NDIS_STATUS_SUCCESS == Status && TRUE != bDecision)
{
NdisReleaseSpinLock(&pAdapt->Lock);
goto Done;
}
NdisReleaseSpinLock(&pAdapt->Lock);
//------------------------------------------
{
pEthHdr pETH;
pIPHdr pIPH;
pAHHdr pAH;
UCHAR digest[16];
NDIS_STATUS lclStatus;
USHORT IPHdrl, TCPHdrl, NewHdrsl;
int i;
// 获取IP指针
pIPH = (pIPHdr) (PayloadCopy + sizeof(EthHdr));
// 获取IP包头长度
IPHdrl = pIPH->IPHdrLen * 4;
// OrigPayloadl为以太网帧的长度
// 相加后则为新的以太网帧的长度
NewPayloadl = OrigPayloadl + sizeof(AHHdr);
// 计算新IP包的总长(包括IP头)
pIPH->TotalLength = (USHORT)
RtlUlongByteSwap((NewPayloadl - sizeof(EthHdr)) <<
16);
pIPH->Checksum = 0;
// 计算新IP包的校验和
pIPH->Checksum = GetIPChecksum((PUSHORT) pIPH, IPHdrl);
// 初始化新帧的内存空间
lclStatus = NdisAllocateMemoryWithTag(&pNewPayload,
NewPayloadl,
TAG);
if (NDIS_STATUS_SUCCESS != lclStatus)
{
Status = lclStatus;
goto Done;
}
// 拷贝帧头及IP头到新的帧中
NdisMoveMemory(pNewPayload, PayloadCopy, sizeof(EthHdr) + IPHdrl);
// 获取AH头指针
pAH = (pAHHdr) (pNewPayload + sizeof(EthHdr) + IPHdrl);
// 初始化AH结构
pAH->NextHeader = 0;
pAH->PayloadLength = 5;
pAH->Reserved = 0;
pAH->SNF = 0;
pAH->SPI = 0;
for (i = 0; i < 16; i++)
pAH->Auth[i] = 0;
// 将原帧中IP头后的数据部份拷到新帧的AH头后面
NdisMoveMemory(pNewPayload + sizeof(EthHdr) + IPHdrl + sizeof(AHHdr),
PayloadCopy + sizeof(EthHdr) + IPHdrl,
OrigPayloadl - sizeof(EthHdr) - IPHdrl);
{
PUCHAR pHmacPayload = NULL;
pIPHdr pHmacIPH;
UCHAR digest[16];
UCHAR key[] = "Prakash";
NdisZeroMemory(digest, 16);
Status = NdisAllocateMemoryWithTag(&pHmacPayload,
NewPayloadl - sizeof(EthHdr),
TAG);
if (NDIS_STATUS_SUCCESS != Status)
{
goto Done;
}
// 将新帧的IP包拷到pHmacPayload中
NdisMoveMemory(pHmacPayload,
pNewPayload + sizeof(EthHdr),
NewPayloadl - sizeof(EthHdr));
// 获取新IP包的头指针
pHmacIPH = (pIPHdr) pHmacPayload;
pHmacIPH->TTL = 0;
pHmacIPH->FragmentationSummary = 0;
pHmacIPH->Checksum = 0;
// 将新的IP包加密后保存在digest中
// 被加密的IP包结构如下:
// IP头 | AH头 | IP数据
hmac_md5(pHmacPayload,
NewPayloadl - sizeof(EthHdr),
key,
7,
digest);
NdisMoveMemory(pAH->Auth, digest, 16);
DbgPrint("Digest Send:");
for (i = 0; i < 16 ; i++)
{
DbgPrint("%x", digest[i]);
}
}
}
Done:
//
// The driver should fail the send if the virtual miniport is in low
// power state
//
if (pAdapt->MiniportDeviceState > NdisDeviceStateD0)
{
NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
Packet,
NDIS_STATUS_FAILURE);
if (NULL != pNewPayload)
{
//
// Recycle memory.
//
NdisFreeMemory(pNewPayload, NewPayloadl, 0);
pNewPayload = NULL;
}
continue;
}
do
{
NdisAcquireSpinLock(&pAdapt->Lock);
//
// If the below miniport is going to low power state,
// stop sending down any packet.
//
if (pAdapt->ProtocolDeviceState > NdisDeviceStateD0)
{
NdisReleaseSpinLock(&pAdapt->Lock);
if (NULL != pNewPayload)
{
NdisFreeMemory(pNewPayload, NewPayloadl, 0);
pNewPayload = NULL;
}
Status = NDIS_STATUS_FAILURE;
break;
}
pAdapt->OutstandingSends++;
NdisReleaseSpinLock(&pAdapt->Lock);
NdisAllocatePacket(&Status,
&MyPacket,
pAdapt->SendPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
PSEND_RSVD SendRsvd;
//
// NIC drivers and intermediate drivers allocate
// packet descriptors with, at least, 16 bytes of
// ProtocolReserved space to be used by protocols
// for receive indications.
//
SendRsvd = (PSEND_RSVD) (MyPacket->ProtocolReserved);
SendRsvd->OriginalPkt = Packet;
//
// Found desired packet
//
if (NULL != pNewPayload)
{
//
// Build new buffer descriptor.
//
NdisAllocateBuffer(&Status,
&pNewNdisBfr,
pAdapt->hSendBufferPool,
pNewPayload,
NewPayloadl);
if (NDIS_STATUS_SUCCESS != Status)
{
break;
}
//
// Show new NDIS_BUFFER used.
//
SendRsvd->bNewBuffer = TRUE;
//
// Links a given buffer descriptor to the head of
// the buffer-descriptor chain attached to a packet
// descriptor.
//
NdisChainBufferAtFront(MyPacket, pNewNdisBfr);
}
else
{
SendRsvd->bNewBuffer = FALSE; // Original used.
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
}
MyPacket->Private.Flags = NdisGetPacketFlags(Packet);
//
// Copy OOB Data to the New Packet
//
NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
NDIS_OOB_DATA_FROM_PACKET(Packet),
sizeof(NDIS_PACKET_OOB_DATA));
//
// Copy Media Specific Information
//
NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
&MediaSpecificInfo,
&MediaSpecificInfoSize);
if (MediaSpecificInfo || MediaSpecificInfoSize)
{
NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
MediaSpecificInfo,
MediaSpecificInfoSize);
}
//
// Send the packets to Miniport
//
NdisSend(&Status, pAdapt->BindingHandle, MyPacket);
if (Status != NDIS_STATUS_PENDING)
{
if (NULL != pNewPayload)
{
NdisFreeBuffer(pNewNdisBfr);
NdisFreeMemory(pNewPayload, NewPayloadl, 0);
pNewPayload = NULL;
}
NdisFreePacket(MyPacket);
ADAPT_DECR_PENDING_SENDS(pAdapt);
}
}
else
{
//
// The driver cannot allocate a packet.
//
ADAPT_DECR_PENDING_SENDS(pAdapt);
if (NULL != pNewPayload)
{
NdisFreeMemory(pNewPayload, NewPayloadl, 0);
pNewPayload = NULL;
}
}
}
while (FALSE);
if (Status != NDIS_STATUS_PENDING)
{
NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status);
}
}
}
/*
Returns Information about capabilities and status of the driver
*/
NDIS_STATUS MPQueryInformation(IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded)
{
PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
do
{
//
// An Intermediate Driver ,always return success for this OID
//
if (Oid == OID_PNP_QUERY_POWER)
{
Status = NDIS_STATUS_SUCCESS;
break;
}
//
// If the miniport below is unbinding, just fail any request
//
if (Oid == OID_TCP_TASK_OFFLOAD)
{
//
// Fail this -if- this driver performs data transformations
// that can interfere with a lower driver's ability to offload
// TCP tasks.
//
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
//
// OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up
// multiple instances of private GUIDs supported by the underlying miniport.
//
if (Oid == OID_GEN_SUPPORTED_GUIDS)
{
Status = NDIS_STATUS_SUCCESS;
break;
}
NdisAcquireSpinLock(&pAdapt->Lock);
if (pAdapt->UnbindingInProcess == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
NdisReleaseSpinLock(&pAdapt->Lock);
if (pAdapt->MiniportDeviceState > NdisDeviceStateD0)
{
Status = NDIS_STATUS_FAILURE;
break;
}
//
// Setting up request
//
pAdapt->Request.RequestType = NdisRequestQueryInformation;
pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
pAdapt->BytesReadOrWritten = BytesWritten;
pAdapt->BytesNeeded = BytesNeeded;
//
// If the miniport below is binding, fail the request
//
NdisAcquireSpinLock(&pAdapt->Lock);
if (pAdapt->UnbindingInProcess == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
//
// If the Protocol device state is OFF, mark this request
// as being pended. We queue this until the device state is
// back to D0.
//
if (pAdapt->ProtocolDeviceState > NdisDeviceStateD0 &&
pAdapt->StandingBy == FALSE)
{
pAdapt->QueuedRequest = TRUE;
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_PENDING;
break;
}
//
// This is in the process of powering down the system,
// always fail the request
//
if (pAdapt->StandingBy == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
pAdapt->OutstandingRequests = TRUE;
NdisReleaseSpinLock(&pAdapt->Lock);
//
// Forwarding Request to Underlying Miniport
//
NdisRequest(&Status, pAdapt->BindingHandle, &pAdapt->Request);
if (Status != NDIS_STATUS_PENDING)
{
PPRequestComplete(pAdapt, &pAdapt->Request, Status);
Status = NDIS_STATUS_PENDING;
}
}
while (FALSE);
return(Status);
}
/*
Postprocess a request for OID_PNP_CAPABILITIES that was forwarded
down to the underlying miniport, and has been completed by it.
*/
VOID MPQueryPNPCapabilities(IN OUT PADAPT pAdapt,
OUT PNDIS_STATUS pStatus)
{
PNDIS_PNP_CAPABILITIES pPNPCapabilities;
PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >=
sizeof(NDIS_PNP_CAPABILITIES))
{
pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)
(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);
//
// The following fields must be overwritten by an IM driver.
//
pPMstruct = &pPNPCapabilities->WakeUpCapabilities;
pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
*pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);
*pAdapt->BytesNeeded = 0;
//
// Setting our internal flags
// Default, device is ON
//
pAdapt->MiniportDeviceState = NdisDeviceStateD0;
pAdapt->ProtocolDeviceState = NdisDeviceStateD0;
*pStatus = NDIS_STATUS_SUCCESS;
}
else
{
*pAdapt->BytesNeeded = sizeof(NDIS_PNP_CAPABILITIES);
*pStatus = NDIS_STATUS_RESOURCES;
}
}
/*
Called by bound protocols/NDIS to request change of state
*/
NDIS_STATUS MPSetInformation(IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded)
{
PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
do
{
//Should not be propagated
if (Oid == OID_PNP_SET_POWER)
{
MPProcessSetPowerOid(&Status,
pAdapt,
InformationBuffer,
InformationBufferLength,
BytesRead,
BytesNeeded);
break;
}
//
// If the miniport below is unbinding, fail the request
//
NdisAcquireSpinLock(&pAdapt->Lock);
if (pAdapt->UnbindingInProcess == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
NdisReleaseSpinLock(&pAdapt->Lock);
//
//All Set Information Should fail - if Power is not on
//
if (pAdapt->MiniportDeviceState > NdisDeviceStateD0)
{
Status = NDIS_STATUS_FAILURE;
break;
}
//
//Setting up request
//
pAdapt->Request.RequestType = NdisRequestSetInformation;
pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
pAdapt->BytesReadOrWritten = BytesRead;
pAdapt->BytesNeeded = BytesNeeded;
//
// If the miniport below is unbinding, fail the request
//
NdisAcquireSpinLock(&pAdapt->Lock);
if (pAdapt->UnbindingInProcess == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
//
// If the device below is at a low power state, we cannot send it the
// request now, and must pend it.
//
if ((pAdapt->ProtocolDeviceState > NdisDeviceStateD0) &&
(pAdapt->StandingBy == FALSE))
{
pAdapt->QueuedRequest = TRUE;
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_PENDING;
break;
}
//
// This is in the process of powering down the system, always fail the request
//
if (pAdapt->StandingBy == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
pAdapt->OutstandingRequests = TRUE;
NdisReleaseSpinLock(&pAdapt->Lock);
//
// Forward the request to the device below.
//
NdisRequest(&Status, pAdapt->BindingHandle, &pAdapt->Request);
if (Status != NDIS_STATUS_PENDING)
{
*BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead;
*BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;
pAdapt->OutstandingRequests = FALSE;
}
}
while (FALSE);
return(Status);
}
VOID MPProcessSetPowerOid(IN OUT PNDIS_STATUS pNdisStatus,
IN PADAPT pAdapt,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded)
{
NDIS_DEVICE_POWER_STATE NewDeviceState;
*pNdisStatus = NDIS_STATUS_FAILURE;
do
{
//
// Check for invalid length
//
if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
{
*pNdisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) InformationBuffer);
//
// Check for invalid device state
//
if ((pAdapt->MiniportDeviceState > NdisDeviceStateD0) &&
(NewDeviceState != NdisDeviceStateD0))
{
//
// If the miniport is in a non-D0 state, the miniport can
// only receive a Set Power to D0
//
*pNdisStatus = NDIS_STATUS_FAILURE;
break;
}
//
// Is the miniport transitioning from an On (D0) state to an
// Low Power State (>D0).If so, then set the StandingBy Flag -
// (Block all incoming requests)
//
if (pAdapt->MiniportDeviceState == NdisDeviceStateD0 &&
NewDeviceState > NdisDeviceStateD0)
{
pAdapt->StandingBy = TRUE;
}
//
// If the miniport is transitioning from a low power state
// to ON (D0), then clear the StandingBy flag
// All incoming requests will be pended until the physical
// miniport turns ON.
//
if (pAdapt->MiniportDeviceState > NdisDeviceStateD0 &&
NewDeviceState == NdisDeviceStateD0)
{
pAdapt->StandingBy = FALSE;
}
//
// Now update the state in the pAdapt structure;
//
pAdapt->MiniportDeviceState = NewDeviceState;
*pNdisStatus = NDIS_STATUS_SUCCESS;
}
while (FALSE);
if (*pNdisStatus == NDIS_STATUS_SUCCESS)
{
//
// The miniport resume from low power state
//
if (pAdapt->StandingBy == FALSE)
{
//
// If we need to indicate the media connect state
//
if (pAdapt->LastIndicatedStatus != pAdapt->LatestUnIndicateStatus)
{
NdisMIndicateStatus(pAdapt->MiniportHandle,
pAdapt->LatestUnIndicateStatus,
(PVOID) NULL,
0);
NdisMIndicateStatusComplete(pAdapt->MiniportHandle);
pAdapt->LastIndicatedStatus = pAdapt->LatestUnIndicateStatus;
}
}
else
{
//
// Initialize LatestUnIndicatedStatus
//
pAdapt->LatestUnIndicateStatus = pAdapt->LastIndicatedStatus;
}
*BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
*BytesNeeded = 0;
}
else
{
*BytesRead = 0;
*BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
}
}
/*
Called whenever protocols are done with a packet that we had indicated up
and they had queued up for returning later.
*/
VOID MPReturnPacket(IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet)
{
PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
PNDIS_PACKET MyPacket;
PRECV_RSVD RecvRsvd;
//
// This is a packet allocated from this IM's receive packet pool.
// Reclaim our packet, and return the original to the driver below.
//
RecvRsvd = (PRECV_RSVD) (Packet->MiniportReserved);
MyPacket = RecvRsvd->OriginalPkt;
if (TRUE == RecvRsvd->bNewBuffer)
{
PNDIS_BUFFER pNewNdisBfr;
PUCHAR VA;
UINT lVA;
NdisQueryPacket(Packet, NULL, NULL, &pNewNdisBfr, NULL);
NdisQueryBufferSafe(pNewNdisBfr, &VA, // Payload address.
& lVA, // Payload length.
LowPagePriority);
NdisFreeBuffer(pNewNdisBfr);
NdisFreeMemory(VA, lVA, 0);
}
NdisFreePacket(Packet);
NdisReturnPackets(&MyPacket, 1);
}
/*
MPTransferData is a required function if the NIC drivers
that do not indicate multipacket receives and/or media-specific
information with NdisMIndicateReceivePacket
*/
NDIS_STATUS MPTransferData(OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer)
{
PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
NDIS_STATUS Status;
//
// Return, if the device is OFF
//
if (IsIMDeviceStateOn(pAdapt) == FALSE)
{
return NDIS_STATUS_FAILURE;
}
//
// Forwards a request to copy data received on the underlying NIC
// into a protocol-supplied packet.
//
NdisTransferData(&Status,
pAdapt->BindingHandle,
MiniportReceiveContext,
ByteOffset,
BytesToTransfer,
Packet,
BytesTransferred);
return(Status);
}
VOID MPHalt(IN NDIS_HANDLE MiniportAdapterContext)
{
PADAPT pAdapt = (PADAPT) MiniportAdapterContext;
NDIS_STATUS Status;
PADAPT* ppCursor;
//
// Remove this adapter from the global list
//
NdisAcquireSpinLock(&GlobalLock);
for (ppCursor = &pAdaptList;
*ppCursor != NULL;
ppCursor = &(*ppCursor)->Next)
{
if (*ppCursor == pAdapt)
{
*ppCursor = pAdapt->Next;
break;
}
}
NdisReleaseSpinLock(&GlobalLock);
if (pAdapt->BindingHandle != NULL)
{
//
// Close the binding below. and wait for it to complete
//
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(&Status, pAdapt->BindingHandle);
if (Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
Status = pAdapt->Status;
}
pAdapt->BindingHandle = NULL;
}
//
// Free all resources on this adapter structure.
//
MPFreeAllPacketPools(pAdapt);
NdisFreeMemory(pAdapt, 0, 0);
}
/*
Free all packet pools on the specified adapter.
*/
VOID MPFreeAllPacketPools(IN PADAPT pAdapt)
{
if (pAdapt->RecvPacketPoolHandle != NULL)
{
NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
pAdapt->RecvPacketPoolHandle = NULL;
}
if (pAdapt->SendPacketPoolHandle != NULL)
{
NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
pAdapt->SendPacketPoolHandle = NULL;
}
}