Prev: Help disabling a device using SetupDiXXX fns after WM_DEVICECHANGE
Next: WDK build error , but XP DDK build ok
From: Peter Schmitz on 25 Oct 2005 17:45 Hi, I'm currently trying to develop a NDIS IM driver, that duplicates every packet it ought to send/receive, kills the original one - and (after some short period) sends/receives the duplicate instead. Therefore, I created a function, that shall duplicate the NDIS_PACKETs, but which, unfortunately, seems to create some memory leaks (I have no idea why). So, here goes some source code: PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter, BOOLEAN tosend) { NDIS_STATUS Status; PNDIS_PACKET MyPacket; PRECV_RSVD RecvRsvd; PSEND_RSVD SendRsvd; //tosend == FALSE -> packet is going to be received if(tosend == FALSE) { NdisDprAllocatePacket(&Status, &MyPacket, Adapter->RecvPacketPoolHandle); RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); RecvRsvd->OriginalPkt = OriginalPacket; } else { NdisDprAllocatePacket(&Status, &MyPacket, Adapter->SendPacketPoolHandle); SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = NULL;//marking packet as crafted } MyPacket->Private.Head = OriginalPacket->Private.Head; MyPacket->Private.Tail = OriginalPacket->Private.Tail; NDIS_SET_ORIGINAL_PACKET(MyPacket,NDIS_GET_ORIGINAL_PACKET(OriginalPacket)); NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(OriginalPacket); Status = NDIS_GET_PACKET_STATUS(OriginalPacket); NDIS_SET_PACKET_STATUS(MyPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); return (MyPacket); } Now, I'm not quite satisfied with this function (although it seems to work) as it seems to me that I don't really copy any packet data... Additionally, if I mark any packet that shall be received later on with a NULL pointer at OriginalPkt, MPReturnPackets crashes, if I enter a pointer to the real original packet, everything works fine. Anyway, the PtSendComplete handler looks as follows: VOID PtSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status ) { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; PNDIS_PACKET Pkt; NDIS_HANDLE PoolHandle; PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); Pkt = SendRsvd->OriginalPkt; if( Pkt ) { PoolHandle = NdisGetPoolFromPacket(Packet); if (PoolHandle != pAdapt->SendPacketPoolHandle) { NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status); } else { NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); NdisDprFreePacket(Packet); NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); } } else { //packet was crafted, just free it NdisDprFreePacket(Packet); } } Any ideas, what could cause the memory leaks? Do you have any comments on the DuplicatePacket function? Could this code really work as expected (although it seems to do so)? There's a second problem: When I additionally start ethereal on the testing machine, the NdisSend call I make to send the packet fails with DRIVER_IRQL_NOT_LESS_OR_EQUAL. Any ideas on that? Greetings, Peter
From: Maxim S. Shatskih on 25 Oct 2005 18:56 IIRC you must also copy the packet's OOB data using some NDIS_xxx macro. -- Maxim Shatskih, Windows DDK MVP StorageCraft Corporation maxim(a)storagecraft.com http://www.storagecraft.com "Peter Schmitz" <PeterSchmitz(a)discussions.microsoft.com> wrote in message news:B7753EC0-EFA8-462F-876B-E857E9BDFFF8(a)microsoft.com... > Hi, > > I'm currently trying to develop a NDIS IM driver, that duplicates every > packet it ought to send/receive, kills the original one - and (after some > short period) sends/receives the duplicate instead. > Therefore, I created a function, that shall duplicate the NDIS_PACKETs, but > which, unfortunately, seems to create some memory leaks (I have no idea > why). > > So, here goes some source code: > > PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter, > BOOLEAN tosend) > { > NDIS_STATUS Status; > PNDIS_PACKET MyPacket; > PRECV_RSVD RecvRsvd; > PSEND_RSVD SendRsvd; > > //tosend == FALSE -> packet is going to be received > if(tosend == FALSE) > { > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->RecvPacketPoolHandle); > RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); > RecvRsvd->OriginalPkt = OriginalPacket; > } > else > { > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->SendPacketPoolHandle); > SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); > SendRsvd->OriginalPkt = NULL;//marking packet as crafted > } > > MyPacket->Private.Head = OriginalPacket->Private.Head; > MyPacket->Private.Tail = OriginalPacket->Private.Tail; > > NDIS_SET_ORIGINAL_PACKET(MyPacket,NDIS_GET_ORIGINAL_PACKET(OriginalPacket)); > > NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(OriginalPacket); > > Status = NDIS_GET_PACKET_STATUS(OriginalPacket); > > NDIS_SET_PACKET_STATUS(MyPacket, Status); > NDIS_SET_PACKET_HEADER_SIZE(MyPacket, > NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); > return (MyPacket); > } > > Now, I'm not quite satisfied with this function (although it seems to work) > as it seems to me that I don't really copy any packet data... > Additionally, if I mark any packet that shall be received later on with a > NULL pointer at OriginalPkt, MPReturnPackets crashes, if I enter a pointer > to the real original packet, everything works fine. > > Anyway, the PtSendComplete handler looks as follows: > > VOID > PtSendComplete( > IN NDIS_HANDLE ProtocolBindingContext, > IN PNDIS_PACKET Packet, > IN NDIS_STATUS Status > ) > { > PADAPT pAdapt =(PADAPT)ProtocolBindingContext; > PNDIS_PACKET Pkt; > NDIS_HANDLE PoolHandle; > > > PSEND_RSVD SendRsvd; > > > SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); > Pkt = SendRsvd->OriginalPkt; > > if( Pkt ) > { > > PoolHandle = NdisGetPoolFromPacket(Packet); > if (PoolHandle != pAdapt->SendPacketPoolHandle) > { > NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status); > } > else > { > NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); > NdisDprFreePacket(Packet); > NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); > } > } > else > { > //packet was crafted, just free it > NdisDprFreePacket(Packet); > } > } > > Any ideas, what could cause the memory leaks? Do you have any comments on > the DuplicatePacket function? Could this code really work as expected > (although it seems to do so)? > > There's a second problem: When I additionally start ethereal on the testing > machine, the NdisSend call I make to send the packet fails with > DRIVER_IRQL_NOT_LESS_OR_EQUAL. Any ideas on that? > > > Greetings, > Peter
From: Stephan Wolf [MVP] on 26 Oct 2005 11:22 Several things to consider here: - Calling NdisDprAllocatePacket() from any IRQL below DISPATCH_LEVEL is a programming fault and can cause unpredictable results. So please use the non-DPR variant NdisAllocatePacket() if you are not 100% sure. Same is true for the free function. - Your local packet uses the same NDIS_BUFFER chain as the original packet. Thus, the lifetime of your local packet cannot be any longer than that of the original. That is, as soon as you "kill" the original packet (i.e. return it back to NDIS), your should also "kill" your local packet. - NDIS_SET_ORIGINAL_PACKET() sets a reference (back-link) in your local packet to the "original" packet of the packet you are making a copy of. (Usually, the packet returned by NDIS_GET_ORIGINAL_PACKET() is just the same as the one passed to the macro but can be different in some cases.) Since you "kill" the original packet, this reference also becomes invalid. So better set as follows: NDIS_SET_ORIGINAL_PACKET(MyPacket, MyPacket); ...which IIRC is the default anyway. - I guess you should set the status of your local packet to NDIS_STATUS_SUCCESS rather than that of the original packet via NDIS_SET_PACKET_STATUS(). - Umm, I have difficulties trying to understand your PtSendComplete(). First you get 'Pkt' from 'Packet->ProtocolReserved'. So this means 'Packet' must be one of your own local packets. But if the pool handle of 'Packet' is not your own - which is is contradictory - you return this packet to NdisMSendComplete(). Stephan --- Peter Schmitz wrote: > Hi, > > I'm currently trying to develop a NDIS IM driver, that duplicates every > packet it ought to send/receive, kills the original one - and (after some > short period) sends/receives the duplicate instead. > Therefore, I created a function, that shall duplicate the NDIS_PACKETs, but > which, unfortunately, seems to create some memory leaks (I have no idea > why). > > So, here goes some source code: > > PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter, > BOOLEAN tosend) > { > NDIS_STATUS Status; > PNDIS_PACKET MyPacket; > PRECV_RSVD RecvRsvd; > PSEND_RSVD SendRsvd; > > //tosend == FALSE -> packet is going to be received > if(tosend == FALSE) > { > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->RecvPacketPoolHandle); > RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); > RecvRsvd->OriginalPkt = OriginalPacket; > } > else > { > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->SendPacketPoolHandle); > SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); > SendRsvd->OriginalPkt = NULL;//marking packet as crafted > } > > MyPacket->Private.Head = OriginalPacket->Private.Head; > MyPacket->Private.Tail = OriginalPacket->Private.Tail; > > NDIS_SET_ORIGINAL_PACKET(MyPacket,NDIS_GET_ORIGINAL_PACKET(OriginalPacket)); > > NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(OriginalPacket); > > Status = NDIS_GET_PACKET_STATUS(OriginalPacket); > > NDIS_SET_PACKET_STATUS(MyPacket, Status); > NDIS_SET_PACKET_HEADER_SIZE(MyPacket, > NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); > return (MyPacket); > } > > Now, I'm not quite satisfied with this function (although it seems to work) > as it seems to me that I don't really copy any packet data... > Additionally, if I mark any packet that shall be received later on with a > NULL pointer at OriginalPkt, MPReturnPackets crashes, if I enter a pointer > to the real original packet, everything works fine. > > Anyway, the PtSendComplete handler looks as follows: > > VOID > PtSendComplete( > IN NDIS_HANDLE ProtocolBindingContext, > IN PNDIS_PACKET Packet, > IN NDIS_STATUS Status > ) > { > PADAPT pAdapt =(PADAPT)ProtocolBindingContext; > PNDIS_PACKET Pkt; > NDIS_HANDLE PoolHandle; > > > PSEND_RSVD SendRsvd; > > > SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); > Pkt = SendRsvd->OriginalPkt; > > if( Pkt ) > { > > PoolHandle = NdisGetPoolFromPacket(Packet); > if (PoolHandle != pAdapt->SendPacketPoolHandle) > { > NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status); > } > else > { > NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); > NdisDprFreePacket(Packet); > NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); > } > } > else > { > //packet was crafted, just free it > NdisDprFreePacket(Packet); > } > } > > Any ideas, what could cause the memory leaks? Do you have any comments on > the DuplicatePacket function? Could this code really work as expected > (although it seems to do so)? > > There's a second problem: When I additionally start ethereal on the testing > machine, the NdisSend call I make to send the packet fails with > DRIVER_IRQL_NOT_LESS_OR_EQUAL. Any ideas on that? > > > Greetings, > Peter
From: Peter Schmitz on 26 Oct 2005 13:02 Thanks for replying! According to your suggestions I rewrote the function to create a real independent copy of any NDIS_PACKET: PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter, BOOLEAN tosend) { PNDIS_PACKET OurPacket = NULL; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PNDIS_BUFFER pNdisBuffer,pOurBuffer; ULONG PacketLength = 0; ULONG bytescopied = 0; PVOID virtualaddr = NULL; PRECV_RSVD RecvRsvd; PSEND_RSVD SendRsvd; if(tosend == FALSE) { NdisAllocatePacket(&Status, &OurPacket, Adapter->RecvPacketPoolHandle); } else { NdisAllocatePacket(&Status,&OurPacket,Adapter->SendPacketPoolHandle); } NdisQueryPacket(OriginalPacket, NULL, NULL,&pNdisBuffer,&PacketLength ); NdisAllocateMemoryWithTag(&virtualaddr,PacketLength,'DMSA'); NdisAllocateBuffer(&Status,&pOurBuffer,Adapter->BufferPool, virtualaddr,PacketLength); NdisChainBufferAtFront(OurPacket,pOurBuffer); NdisCopyFromPacketToPacket(OurPacket,0,PacketLength,OriginalPacket,0, &bytescopied); OurPacket->Private.Head = OriginalPacket->Private.Head; OurPacket->Private.Tail = OriginalPacket->Private.Tail; if(tosend == FALSE) { RecvRsvd = (PRECV_RSVD)(OurPacket->MiniportReserved); RecvRsvd->OriginalPkt = NULL; } else { SendRsvd = (PSEND_RSVD)(OurPacket->ProtocolReserved); SendRsvd->OriginalPkt = NULL; } NdisSetPacketFlags(OurPacket, NdisGetPacketFlags(OriginalPacket)); NdisFreeMemory(virtualaddr,PacketLength,0); NDIS_SET_PACKET_STATUS(OurPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(OurPacket, NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); return OurPacket; } Now, the NULL pointer to OriginalPkt in my ProtocolReserved area is necessary for me to distinguish between real packets - and my own copies (as I need to kill the buffers etc. for them). So, I just test Pkt for being NULL in my PtCompleteSend handler, and if so (my own copy as packet) delete the buffers. Or...would, as a BAD_POOL_CALLER appears at NdisFreeBuffer saying that the memory was already freed....but how? Thanks in advance, Peter "Stephan Wolf [MVP]" wrote: > Several things to consider here: > > - Calling NdisDprAllocatePacket() from any IRQL below DISPATCH_LEVEL is > a programming fault and can cause unpredictable results. So please use > the non-DPR variant NdisAllocatePacket() if you are not 100% sure. Same > is true for the free function. > > - Your local packet uses the same NDIS_BUFFER chain as the original > packet. Thus, the lifetime of your local packet cannot be any longer > than that of the original. That is, as soon as you "kill" the original > packet (i.e. return it back to NDIS), your should also "kill" your > local packet. > > - NDIS_SET_ORIGINAL_PACKET() sets a reference (back-link) in your local > packet to the "original" packet of the packet you are making a copy of. > (Usually, the packet returned by NDIS_GET_ORIGINAL_PACKET() is just the > same as the one passed to the macro but can be different in some > cases.) > Since you "kill" the original packet, this reference also becomes > invalid. So better set as follows: > > NDIS_SET_ORIGINAL_PACKET(MyPacket, MyPacket); > > ...which IIRC is the default anyway. > > - I guess you should set the status of your local packet to > NDIS_STATUS_SUCCESS rather than that of the original packet via > NDIS_SET_PACKET_STATUS(). > > - Umm, I have difficulties trying to understand your PtSendComplete(). > First you get 'Pkt' from 'Packet->ProtocolReserved'. So this means > 'Packet' must be one of your own local packets. But if the pool handle > of 'Packet' is not your own - which is is contradictory - you return > this packet to NdisMSendComplete(). > > Stephan > --- > Peter Schmitz wrote: > > Hi, > > > > I'm currently trying to develop a NDIS IM driver, that duplicates every > > packet it ought to send/receive, kills the original one - and (after some > > short period) sends/receives the duplicate instead. > > Therefore, I created a function, that shall duplicate the NDIS_PACKETs, but > > which, unfortunately, seems to create some memory leaks (I have no idea > > why). > > > > So, here goes some source code: > > > > PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter, > > BOOLEAN tosend) > > { > > NDIS_STATUS Status; > > PNDIS_PACKET MyPacket; > > PRECV_RSVD RecvRsvd; > > PSEND_RSVD SendRsvd; > > > > //tosend == FALSE -> packet is going to be received > > if(tosend == FALSE) > > { > > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->RecvPacketPoolHandle); > > RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); > > RecvRsvd->OriginalPkt = OriginalPacket; > > } > > else > > { > > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->SendPacketPoolHandle); > > SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); > > SendRsvd->OriginalPkt = NULL;//marking packet as crafted > > } > > > > MyPacket->Private.Head = OriginalPacket->Private.Head; > > MyPacket->Private.Tail = OriginalPacket->Private.Tail; > > > > NDIS_SET_ORIGINAL_PACKET(MyPacket,NDIS_GET_ORIGINAL_PACKET(OriginalPacket)); > > > > NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(OriginalPacket); > > > > Status = NDIS_GET_PACKET_STATUS(OriginalPacket); > > > > NDIS_SET_PACKET_STATUS(MyPacket, Status); > > NDIS_SET_PACKET_HEADER_SIZE(MyPacket, > > NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); > > return (MyPacket); > > } > > > > Now, I'm not quite satisfied with this function (although it seems to work) > > as it seems to me that I don't really copy any packet data... > > Additionally, if I mark any packet that shall be received later on with a > > NULL pointer at OriginalPkt, MPReturnPackets crashes, if I enter a pointer > > to the real original packet, everything works fine. > > > > Anyway, the PtSendComplete handler looks as follows: > > > > VOID > > PtSendComplete( > > IN NDIS_HANDLE ProtocolBindingContext, > > IN PNDIS_PACKET Packet, > > IN NDIS_STATUS Status > > ) > > { > > PADAPT pAdapt =(PADAPT)ProtocolBindingContext; > > PNDIS_PACKET Pkt; > > NDIS_HANDLE PoolHandle; > > > > > > PSEND_RSVD SendRsvd; > > > > > > SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); > > Pkt = SendRsvd->OriginalPkt; > > > > if( Pkt ) > > { > > > > PoolHandle = NdisGetPoolFromPacket(Packet); > > if (PoolHandle != pAdapt->SendPacketPoolHandle) > > { > > NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status); > > } > > else > > { > > NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); > > NdisDprFreePacket(Packet); > > NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); > > } > > } > > else > > { > > //packet was crafted, just free it > > NdisDprFreePacket(Packet); > > } > > } > > > > Any ideas, what could cause the memory leaks? Do you have any comments on > > the DuplicatePacket function? Could this code really work as expected > > (although it seems to do so)? > > > > There's a second problem: When I additionally start ethereal on the testing > > machine, the NdisSend call I make to send the packet fails with > > DRIVER_IRQL_NOT_LESS_OR_EQUAL. Any ideas on that? > > > > > > Greetings, > > Peter > >
From: Thomas F. Divine [DDK MVP] on 26 Oct 2005 13:47 Peter, 1.) Why do you do this? OurPacket->Private.Head = OriginalPacket->Private.Head; OurPacket->Private.Tail = OriginalPacket->Private.Tail; You no longer have a real "duplicate". In fact, despite the fact that you have gone to the trouble of allocating your own VM and your own NDIS_BUFFER, these steps (above) completely overwrite your buffer chain with the buffers from the original packet. So, if you try to free your own packet descriptor (NDIS_PACKET) later the buffers that you will try to free will actually be those from the original packet. That will surely cause problems at some point. It is unfortunate that Microsoft exposed the "Private" parts of the NDIS_PACKET in the NDIS IM driver model. These fields should only be tinkered with when simply doing a PassThru of a packet with no modification or duplication. 2.) In your completion routines you are ALWAYS called with YOUR packet. So, you know that you must free the resources associated with your own packet. The OriginalPkt field in the Reserved areas is used to keep track of the original send or receive packet that was passed into your driver in the first place. Basically, if the field is NULL, then there is no original packet to deal with. If it is NOT NULL then you must return the original packet to it's owner. For example, in ProtocolSendComplete you would call NdisMSendComplete ONLY if OriginalPkt was NOT NULL. Good luck, Thomas F. Divine, Windows DDK MVP http://www.pcausa.com "Peter Schmitz" <PeterSchmitz(a)discussions.microsoft.com> wrote in message news:681D17E8-FB64-406C-8D81-421D4C53B9C0(a)microsoft.com... > Thanks for replying! According to your suggestions I rewrote the function > to > create a real independent copy of any NDIS_PACKET: > > PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter, > BOOLEAN tosend) > { > PNDIS_PACKET OurPacket = NULL; > NDIS_STATUS Status = NDIS_STATUS_SUCCESS; > PNDIS_BUFFER pNdisBuffer,pOurBuffer; > ULONG PacketLength = 0; > ULONG bytescopied = 0; > PVOID virtualaddr = NULL; > PRECV_RSVD RecvRsvd; > PSEND_RSVD SendRsvd; > > if(tosend == FALSE) > { > NdisAllocatePacket(&Status, &OurPacket, Adapter->RecvPacketPoolHandle); > } > else > { > NdisAllocatePacket(&Status,&OurPacket,Adapter->SendPacketPoolHandle); > } > NdisQueryPacket(OriginalPacket, NULL, NULL,&pNdisBuffer,&PacketLength ); > > NdisAllocateMemoryWithTag(&virtualaddr,PacketLength,'DMSA'); > > NdisAllocateBuffer(&Status,&pOurBuffer,Adapter->BufferPool, > virtualaddr,PacketLength); > > NdisChainBufferAtFront(OurPacket,pOurBuffer); > NdisCopyFromPacketToPacket(OurPacket,0,PacketLength,OriginalPacket,0, > &bytescopied); > > OurPacket->Private.Head = OriginalPacket->Private.Head; > OurPacket->Private.Tail = OriginalPacket->Private.Tail; > > if(tosend == FALSE) > { > RecvRsvd = (PRECV_RSVD)(OurPacket->MiniportReserved); > RecvRsvd->OriginalPkt = NULL; > } > else > { > SendRsvd = (PSEND_RSVD)(OurPacket->ProtocolReserved); > SendRsvd->OriginalPkt = NULL; > } > NdisSetPacketFlags(OurPacket, NdisGetPacketFlags(OriginalPacket)); > NdisFreeMemory(virtualaddr,PacketLength,0); > > NDIS_SET_PACKET_STATUS(OurPacket, Status); > NDIS_SET_PACKET_HEADER_SIZE(OurPacket, > NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); > return OurPacket; > } > > Now, the NULL pointer to OriginalPkt in my ProtocolReserved area is > necessary for me to distinguish between real packets - and my own copies > (as > I need to kill the buffers etc. for them). > So, I just test Pkt for being NULL in my PtCompleteSend handler, and if so > (my own copy as packet) delete the buffers. > > Or...would, as a BAD_POOL_CALLER appears at NdisFreeBuffer saying that the > memory was already freed....but how? > > Thanks in advance, > > Peter > > > > > > "Stephan Wolf [MVP]" wrote: > >> Several things to consider here: >> >> - Calling NdisDprAllocatePacket() from any IRQL below DISPATCH_LEVEL is >> a programming fault and can cause unpredictable results. So please use >> the non-DPR variant NdisAllocatePacket() if you are not 100% sure. Same >> is true for the free function. >> >> - Your local packet uses the same NDIS_BUFFER chain as the original >> packet. Thus, the lifetime of your local packet cannot be any longer >> than that of the original. That is, as soon as you "kill" the original >> packet (i.e. return it back to NDIS), your should also "kill" your >> local packet. >> >> - NDIS_SET_ORIGINAL_PACKET() sets a reference (back-link) in your local >> packet to the "original" packet of the packet you are making a copy of. >> (Usually, the packet returned by NDIS_GET_ORIGINAL_PACKET() is just the >> same as the one passed to the macro but can be different in some >> cases.) >> Since you "kill" the original packet, this reference also becomes >> invalid. So better set as follows: >> >> NDIS_SET_ORIGINAL_PACKET(MyPacket, MyPacket); >> >> ...which IIRC is the default anyway. >> >> - I guess you should set the status of your local packet to >> NDIS_STATUS_SUCCESS rather than that of the original packet via >> NDIS_SET_PACKET_STATUS(). >> >> - Umm, I have difficulties trying to understand your PtSendComplete(). >> First you get 'Pkt' from 'Packet->ProtocolReserved'. So this means >> 'Packet' must be one of your own local packets. But if the pool handle >> of 'Packet' is not your own - which is is contradictory - you return >> this packet to NdisMSendComplete(). >> >> Stephan >> --- >> Peter Schmitz wrote: >> > Hi, >> > >> > I'm currently trying to develop a NDIS IM driver, that duplicates every >> > packet it ought to send/receive, kills the original one - and (after >> > some >> > short period) sends/receives the duplicate instead. >> > Therefore, I created a function, that shall duplicate the NDIS_PACKETs, >> > but >> > which, unfortunately, seems to create some memory leaks (I have no idea >> > why). >> > >> > So, here goes some source code: >> > >> > PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT >> > Adapter, >> > BOOLEAN tosend) >> > { >> > NDIS_STATUS Status; >> > PNDIS_PACKET MyPacket; >> > PRECV_RSVD RecvRsvd; >> > PSEND_RSVD SendRsvd; >> > >> > //tosend == FALSE -> packet is going to be received >> > if(tosend == FALSE) >> > { >> > NdisDprAllocatePacket(&Status, &MyPacket, >> > Adapter->RecvPacketPoolHandle); >> > RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); >> > RecvRsvd->OriginalPkt = OriginalPacket; >> > } >> > else >> > { >> > NdisDprAllocatePacket(&Status, &MyPacket, >> > Adapter->SendPacketPoolHandle); >> > SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); >> > SendRsvd->OriginalPkt = NULL;//marking packet as crafted >> > } >> > >> > MyPacket->Private.Head = OriginalPacket->Private.Head; >> > MyPacket->Private.Tail = OriginalPacket->Private.Tail; >> > >> > NDIS_SET_ORIGINAL_PACKET(MyPacket,NDIS_GET_ORIGINAL_PACKET(OriginalPacket)); >> > >> > NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(OriginalPacket); >> > >> > Status = NDIS_GET_PACKET_STATUS(OriginalPacket); >> > >> > NDIS_SET_PACKET_STATUS(MyPacket, Status); >> > NDIS_SET_PACKET_HEADER_SIZE(MyPacket, >> > NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket)); >> > return (MyPacket); >> > } >> > >> > Now, I'm not quite satisfied with this function (although it seems to >> > work) >> > as it seems to me that I don't really copy any packet data... >> > Additionally, if I mark any packet that shall be received later on with >> > a >> > NULL pointer at OriginalPkt, MPReturnPackets crashes, if I enter a >> > pointer >> > to the real original packet, everything works fine. >> > >> > Anyway, the PtSendComplete handler looks as follows: >> > >> > VOID >> > PtSendComplete( >> > IN NDIS_HANDLE ProtocolBindingContext, >> > IN PNDIS_PACKET Packet, >> > IN NDIS_STATUS Status >> > ) >> > { >> > PADAPT pAdapt =(PADAPT)ProtocolBindingContext; >> > PNDIS_PACKET Pkt; >> > NDIS_HANDLE PoolHandle; >> > >> > >> > PSEND_RSVD SendRsvd; >> > >> > >> > SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); >> > Pkt = SendRsvd->OriginalPkt; >> > >> > if( Pkt ) >> > { >> > >> > PoolHandle = NdisGetPoolFromPacket(Packet); >> > if (PoolHandle != pAdapt->SendPacketPoolHandle) >> > { >> > NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status); >> > } >> > else >> > { >> > NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); >> > NdisDprFreePacket(Packet); >> > NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); >> > } >> > } >> > else >> > { >> > //packet was crafted, just free it >> > NdisDprFreePacket(Packet); >> > } >> > } >> > >> > Any ideas, what could cause the memory leaks? Do you have any comments >> > on >> > the DuplicatePacket function? Could this code really work as expected >> > (although it seems to do so)? >> > >> > There's a second problem: When I additionally start ethereal on the >> > testing >> > machine, the NdisSend call I make to send the packet fails with >> > DRIVER_IRQL_NOT_LESS_OR_EQUAL. Any ideas on that? >> > >> > >> > Greetings, >> > Peter >> >>
|
Next
|
Last
Pages: 1 2 Prev: Help disabling a device using SetupDiXXX fns after WM_DEVICECHANGE Next: WDK build error , but XP DDK build ok |