阅读:4933回复:12
部分源码,很精彩。
这是我做的驱动中的一部分,希望对大家有益。
void CopyPacket2Buffer(IN PNDIS_PACKET pPacket,IN OUT PUCHAR pBuff,IN OUT PUINT pLength) { PNDIS_BUFFER BuffDT; PUCHAR BuffVA; UINT BuffLen; *pLength=0; BuffLen=0; NdisQueryPacket(pPacket,NULL,NULL,&BuffDT,NULL); while(BuffDT!=(PNDIS_BUFFER)NULL) { NdisQueryBuffer(BuffDT,&BuffVA,&BuffLen); NdisMoveMemory(pBuff,BuffVA,BuffLen); pBuff=pBuff+BuffLen; *pLength+=BuffLen; NdisGetNextBuffer(BuffDT,&BuffDT); } return; } VOID PtTransferDataComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransferred ) /*++ Routine Description: Same as the Send above, all sends need to be completed on the Primary\'s MiniportHandle Arguments: Return Value: --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; PUCHAR pPacketContent; PRSVD Rsvd; UINT OffsetSize,Result,PacketLen; PNDIS_BUFFER pPacketBuffer; PNDIS_PACKET pBakPacket; PNDIS_BUFFER pBakBuffer; PUCHAR pBakContent; UINT BufferLen; DBGPRINT((\"In PtTransferDataComplete\\n\")); // // Returning the Send on the Primary, will point to itself if there is no LBFO // pAdapt = pAdapt->pPrimaryAdapt; Rsvd =(PRSVD)(Packet->MiniportReserved); pBakPacket=(PNDIS_PACKET)(Rsvd->OriginalPkt); if(pAdapt->MiniportHandle) { if(pBakPacket==NULL) NdisMTransferDataComplete(pAdapt->MiniportHandle,Packet,Status,BytesTransferred); else { Status=NdisAllocateMemory(&pPacketContent,BUFFER_SIZE,0,HighestAcceptableMax); CopyPacket2Buffer(pBakPacket,pPacketContent,&OffsetSize); CopyPacket2Buffer(Packet,pPacketContent+OffsetSize,&PacketLen); PacketLen+=OffsetSize; NdisUnchainBufferAtFront(pBakPacket,&pBakBuffer); NdisQueryBufferSafe(pBakBuffer,&pBakContent,&BufferLen,32); NdisFreeBuffer(pBakBuffer); NdisFreeMemory(pBakContent,BUFFER_SIZE,0); NdisFreePacket(pBakPacket); memset(Packet->MiniportReserved,0,sizeof(Packet->MiniportReserved)); NdisUnchainBufferAtFront(Packet,&pPacketBuffer); NdisQueryBufferSafe(pPacketBuffer,&pBakContent,&BufferLen,32); NdisFreeBuffer(pPacketBuffer); NdisFreeMemory(pBakContent,BUFFER_SIZE,0); NdisAllocateBuffer(&Status,&pPacketBuffer,pAdapt->RecvBufferPoolHandle,pPacketContent,PacketLen); NdisChainBufferAtFront(Packet,pPacketBuffer); Packet->Private.Head->Next=NULL; Packet->Private.Tail=NULL; NDIS_SET_PACKET_HEADER_SIZE(Packet,14); NdisMIndicateReceivePacket(pAdapt->MiniportHandle,&Packet,1); if(NDIS_GET_PACKET_STATUS(Packet)!=NDIS_STATUS_PENDING) { MPReturnPacket((NDIS_HANDLE)pAdapt,Packet); } } } return; } NDIS_STATUS PtReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) /*++ Routine Description: LBFO - need to use primary for all receives Arguments: Return Value: --*/ { PADAPT OutAdapt,pAdapt =(PADAPT)ProtocolBindingContext; PNDIS_PACKET MyPacket, Packet,MyPacket1; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; /* PUCHAR pEnetAddrDest=NULL; UINT nDataSize=0,i; PNDIS_BUFFER pNdisBuffer=NULL; UCHAR *BufferVa=NULL; PMACHEADER pMACHeader=NULL; PIPHEADER pIPHeader=NULL; PICMPHEADER pICMPHeader=NULL; PTCPHEADER pTCPHeader=NULL; PUDPHEADER pUDPHeader=NULL; */ PNDIS_BUFFER pPacketBuffer,pBakBuffer; PUCHAR pPacketContent,pBakContent; UINT PacketLen; UINT OffsetSize; UINT BytesTransferred; PRSVD Rsvd=NULL; PVOID MediaSpecificInfo=NULL; ULONG MediaSpecificSize=0; if(!pAdapt->MiniportHandle) { Status = NDIS_STATUS_FAILURE; } else do { // // We should not be getting Receives on a Secondary, this is just specific to our LBFO driver // if(pAdapt->isSecondary) { DBGPRINT(\"PASSTHRU GETTING RECIEVES ON SECONDARY\\n\"); ASSERT(0); } // // If this was indicated by the miniport below as a packet, then get that packet pointer and indicate // it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the // transport above us. // Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if(Packet != NULL) { // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); if(Status == NDIS_STATUS_SUCCESS) { MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; // // Get the original packet(it could be the same packet as one received or a different one // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible // correctly at the top. // NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize); // // Set Packet Flags // NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); // // Make sure the status is set to NDIS_STATUS_RESOURCES. // NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES); NdisDprFreePacket(MyPacket); break; } } // // Fall through if the miniport below us has either not indicated a packet or we could not // allocate one // else if(PacketSize<=LookAheadBufferSize) { Status=NdisAllocateMemory(&pPacketContent,BUFFER_SIZE,0,HighestAcceptableMax); if(Status!=NDIS_STATUS_SUCCESS) { DbgPrint(\"PTReceive:NdisAllocateMemory Failed\\n\"); return(NDIS_STATUS_NOT_ACCEPTED); } if(pPacketContent==NULL) { DbgPrint(\"PTReceive:pPacketContent==NULL\\n\"); return(NDIS_STATUS_NOT_ACCEPTED); } NdisZeroMemory(pPacketContent,BUFFER_SIZE); NdisMoveMemory(pPacketContent,HeaderBuffer,HeaderBufferSize); NdisMoveMemory(pPacketContent+HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize); PacketLen=PacketSize+HeaderBufferSize; NdisDprAllocatePacket(&Status,&MyPacket,pAdapt->RecvPacketPoolHandle); if(Status==NDIS_STATUS_SUCCESS) { NdisAllocateBuffer(&Status,&pPacketBuffer,pAdapt->RecvBufferPoolHandle,pPacketContent,PacketLen); NdisChainBufferAtFront(MyPacket,pPacketBuffer); MyPacket->Private.Head->Next=NULL; MyPacket->Private.Tail=NULL; Rsvd=(PRSVD)(MyPacket->MiniportReserved); Rsvd->OriginalPkt=NULL; NDIS_SET_PACKET_HEADER_SIZE(MyPacket,HeaderBufferSize); NdisMIndicateReceivePacket(pAdapt->MiniportHandle,&MyPacket,1); if(NDIS_GET_PACKET_STATUS(MyPacket)!=NDIS_STATUS_PENDING) { DBGPRINT((\"In PtReceive And Free Memory\\n\")); NdisFreeBuffer(pPacketBuffer); NdisFreeMemory(pPacketContent,BUFFER_SIZE,0); NdisDprFreePacket(MyPacket); } } break; } else { Status=NdisAllocateMemory(&pPacketContent,BUFFER_SIZE,0,HighestAcceptableMax); if(Status!=NDIS_STATUS_SUCCESS) { DbgPrint(\"PtReceive:NdisAllocateMemory Failed.\\n\"); return(NDIS_STATUS_NOT_ACCEPTED); } if(pPacketContent==NULL) { DbgPrint(\"PTReceive:pPacketContent==NULL\\n\"); return(NDIS_STATUS_NOT_ACCEPTED); } NdisZeroMemory(pPacketContent,BUFFER_SIZE); NdisDprAllocatePacket(&Status,&MyPacket,pAdapt->RecvPacketPoolHandle); Status=NdisAllocateMemory(&pBakContent,BUFFER_SIZE,0,HighestAcceptableMax); if(Status!=NDIS_STATUS_SUCCESS) { DbgPrint(\"PtReceive:NdisAllocateMemory Failed.\\n\"); return(NDIS_STATUS_NOT_ACCEPTED); } if(pBakContent==NULL) { DbgPrint(\"PTReceive:pPacketContent==NULL\\n\"); return(NDIS_STATUS_NOT_ACCEPTED); } NdisZeroMemory(pBakContent,BUFFER_SIZE); NdisMoveMemory(pBakContent,HeaderBuffer,HeaderBufferSize); NdisMoveMemory(pBakContent+HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize); PacketLen=HeaderBufferSize+PacketSize; NdisAllocateBuffer(&Status,&pPacketBuffer,pAdapt->RecvBufferPoolHandle,pPacketContent,PacketSize-LookAheadBufferSize); NdisChainBufferAtFront(MyPacket,pPacketBuffer); MyPacket->Private.Head->Next=NULL; MyPacket->Private.Tail=NULL; OffsetSize=HeaderBufferSize+LookAheadBufferSize; NdisDprAllocatePacket(&Status,&MyPacket1,pAdapt->RecvPacketPoolHandle); NdisAllocateBuffer(&Status,&pBakBuffer,pAdapt->RecvBufferPoolHandle,pBakContent,OffsetSize); NdisChainBufferAtFront(MyPacket1,pBakBuffer); Rsvd=(PRSVD)(MyPacket->MiniportReserved); Rsvd->OriginalPkt=(PNDIS_PACKET)MyPacket1; NDIS_SET_PACKET_HEADER_SIZE(MyPacket,HeaderBufferSize); NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred); if(Status!=NDIS_STATUS_PENDING) { PtTransferDataComplete((NDIS_HANDLE)pAdapt,MyPacket,Status,BytesTransferred); } break; } pAdapt->IndicateRcvComplete = TRUE; /* switch(pAdapt->Medium) { case NdisMedium802_3: { NdisMEthIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; } case NdisMedium802_5: NdisMTrIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; case NdisMediumFddi: NdisMFddiIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; default: ASSERT(0); break; } */ } while(FALSE); DBGPRINT((\"In PtReceive\\n\")); return Status; } VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) /*++ Routine Description: Arguments: Return Value: --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; PNDIS_PACKET MyPacket; PRSVD Resvd; PNDIS_BUFFER pNdisBuffer; PUCHAR pPacketContent; UINT BufferLen; Resvd = (PRSVD)(Packet->MiniportReserved); MyPacket = Resvd->OriginalPkt; if(MyPacket) { NdisFreePacket(Packet); NdisReturnPackets(&MyPacket, 1); } /*========================================================================= I Add This Code for NdisIndicateReceivePacket =========================================================================*/ else { DBGPRINT((\"In MPReturnPacket And Free Memory\\n\")); NdisUnchainBufferAtFront(Packet,&pNdisBuffer); NdisQueryBufferSafe(pNdisBuffer,(PVOID *)&pPacketContent,&BufferLen,32); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pPacketContent,BUFFER_SIZE,0); NdisFreePacket(Packet); DBGPRINT((\"In MPReturnPacket And Free Memory\\n\")); } } |
|
沙发#
发布于:2002-04-24 15:18
不错不错,多贴多贴。
我给你加分!!! |
|
板凳#
发布于:2002-04-25 14:27
太好了!
这里太需要源代码了! 以前我对于OriginalPacket以及NdisBuffer等等的概念都不是很清楚,看了这段代码的具体操作之后明白了一些东西。原来OriginalPacket是用来存放HeaderBuffer+LookaHeadBuffer的,而新分配的Packet则用来存PacketSize-LookAheadBufferSize即需要Transfer的部分;NDIS_BUFFER其实只是一个Descriptor,还需要给它指定VirtualAddress,并且需要先实际地分配一块内存,而它仅仅用来描述这块内存。 给你加分。 [编辑 - 4/25/02 作者: falwind] |
|
地板#
发布于:2002-04-27 16:33
sbni老兄,我按照你写的试了一下,好像不行啊。
能不能把你的源码给我一份 rangzh@sina.com |
|
地下室#
发布于:2002-04-30 22:17
我的程序还有一部分代码,主要是分配缓冲区池用的,比较简单,主要是在PtBindAdapter中做的,主要是调用NdisAllocateBufferPool。
再就是在MpHalt中调用NdisFreeBufferPool。比较简单,但是必须得做,如果不做一定会出问题。 |
|
5楼#
发布于:2002-04-30 23:38
你的程序用在哪里
|
|
|
6楼#
发布于:2002-05-01 11:26
BufferPool和PacketPool我都分配释放了,那没有问题。后来我找到问题了,原来是NdisFreeMemory。我的处理是那样的:在你的程序的思路基础上,在每个NdisMIndicateReceivePacket之前,调用一个自定义的ProcessPacket。后来我发现,在ProcessPacket中的一个NdisFreeMemory存在问题!文档里面明明说当free的是resident memory时,NdisFreeMemory可以在<=IRQL_DISPATCH_LEVEL调用。但是,我发现最好还是在IRQL_PASSIVE_LEVEL调用NdisFreeMemory比较安全。
另外一个问题是:驱动可以正常卸载,但是在PtUnload中设置断点似乎跟踪不到。 |
|
7楼#
发布于:2002-05-05 16:57
怎么看着象是huyg原来贴过的代码,hoho
|
|
|
8楼#
发布于:2002-05-05 20:53
你说的很对,确实是huyg以前曾经贴过的,我只是按照它说的加以整理,同时把他没有说的部分补充而已。
|
|
9楼#
发布于:2002-07-04 22:22
我想请问BUFFER_SIZE定义为多少?
|
|
10楼#
发布于:2002-07-04 22:45
如只作包过滤,则不小于mtu即可。
呵呵 |
|
|
11楼#
发布于:2002-07-15 12:30
NDIS_STATUS_NOT_ACCEPTED指示该包不是其要复制的。这段程序中,在分配资源出错时返回NDIS_STATUS_NOT_ACCEPTED,会不会对驱动程序的性能造成影响
|
|
12楼#
发布于:2003-11-14 11:28
关于上面的代码有点小疑惑。
当判断packetsizse<=lookaheadbuffer时, 为什么不直接调用indicatexxxx函数上去。 还有是关于错误处理的一个问题, 如果我在判断包的过程中发生错误,比如分配内存失败,那么这个包肯定是判断不了了。 这时我是应该把这个包提交上去,还是丢了。 谢谢! |
|