这几天在学习ndis,从网上下了个例子改的驱动,结果自然是BSOD,可是小弱我看了半天也没能理解为什么,各位大牛帮忙给看看:
!analyze -v执行后的部分结果:
DEBUG_FLR_IMAGE_TIMESTAMP: 4a25159a
READ_ADDRESS: fffffffc
CURRENT_IRQL: 2
FAULTING_IP:
NDIS!NdisReturnPackets+2a
f83dc82a 8b47fc mov eax,dword ptr [edi-4]
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0xD1
LAST_CONTROL_TRANSFER: from 804f93fa to 80527da8
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
f6bf8fc8 804f93fa 00000003 fffffffc f83dc82a nt!DbgBreakPointWithStatus+0x4
f6bf93a8 80540853 0000000a fffffffc 00000002 nt!KeRegisterBugCheckReasonCallback+0x77c
f6bf9454 f89a7355 f6bf9464 00000001 00000000 nt!Kei386EoiHelper+0x27db
f6bf9470 f83dc87f 8215eb08 820acf30 821e5950 passthru!MPReturnPacket+0x55 [d:\winddk\3790.1830\src\network\ndis\passthru\driver\miniport.c @ 1145]
f6bf9498 f8260061 f6bf94bc 00000001 820acf78 NDIS!NdisReturnPackets+0x7f
f6bf94b0 f83e9d09 8207a2e0 820acf30 f8265b40 psched!RegisterPsComponent+0x6d33
f6bf9504 f826001d 00140220 821318f0 00000001 NDIS!FddiFilterDprIndicateReceive+0xb11
f6bf9518 f82601b4 821e5950 821318f0 00000001 psched!RegisterPsComponent+0x6cef
f6bf953c f82605f9 8207a2e8 00000000 821e5950 psched!RegisterPsComponent+0x6e86
f6bf9554 f83e9d40 8207a2e0 8209b156 82282226 psched!RegisterPsComponent+0x72cb
f6bf95a4 f89a9557 00140220 f6bf95dc 00000001 NDIS!FddiFilterDprIndicateReceive+0xb48
f6bf960c f83e9ff2 8215eb08 82282040 822820d0 passthru!PtReceive+0x1e7 [d:\winddk\3790.1830\src\network\ndis\passthru\driver\protocol.c @ 1150]
f6bf9674 f83dcec4 c000009a f6bf9694 00000001 NDIS!FddiFilterDprIndicateReceive+0xdfa
f6bf969c f83c799d 82232fb8 82375f60 81e33130 NDIS!NdisRequest+0x559
f6bf96b8 f83df986 8218f6b8 82232f58 f6bf9710 NDIS!NdisDprFreePacketNonInterlocked+0x1c8
f6bf96c8 f89a6a65 f6bf9700 8218f6b8 82232f58 NDIS!NdisSend+0xf
f6bf9710 f83c9f86 8215eb08 f6bf9744 00000001 passthru!MPSendPackets+0x325 [d:\winddk\3790.1830\src\network\ndis\passthru\driver\miniport.c @ 545]
f6bf9738 f8261528 821bd608 82375ed8 82375ea0 NDIS!NdisInitializeString+0x6d1
f6bf9774 f83c7985 8207a2e0 82375ed8 00000002 psched!RegisterPsComponent+0x81fa
f6bf979c f6ea5122 82094428 82375ed8 820dbb58 NDIS!NdisDprFreePacketNonInterlocked+0x1b0
f6bf97c0 f6ea51c6 000dbb0e ffffffff 82375ed8 tcpip!IPTransmit+0x24df
f6bf97ec f6ea370a 820dbb58 f6bf9800 00000001 tcpip!IPTransmit+0x2583
f6bf981c f6eb3910 81dc48e8 ffffffff 82375ed8 tcpip!IPTransmit+0xac7
f6bf9850 f6eaeb9f ffffffff 82375ed8 82099020 tcpip!IPTransmit+0x10ccd
f6bf9988 f6ebd09a f6ee14d4 820cc148 82099020 tcpip!IPTransmit+0xbf5c
f6bf9a28 f6ebce61 820df558 820cc148 8206b8c0 tcpip!IPRegisterProtocol+0x4673
f6bf9a4c f6ebcec7 00bf9a70 8206bfa0 82099060 tcpip!IPRegisterProtocol+0x443a
f6bf9a84 f6ebc713 8206b8c0 8206b978 8206bfa0 tcpip!IPRegisterProtocol+0x44a0
f6bf9aa0 804eedf9 820655d0 8206b8c0 821a22a0 tcpip!IPRegisterProtocol+0x3cec
f6bf9b08 f6e58bce 05d4fb34 f6e58bce 821a22a0 nt!IoBuildPartialMdl+0xed
f6bf9c50 8057564b 820db028 00000001 05d4fa04 afd+0x2bce
f6bf9d00 8056e33c 00001368 0000124c 00000000 nt!NtWriteFile+0x3595
f6bf9d34 8053d808 00001368 0000124c 00000000 nt!NtDeviceIoControlFile+0x2a
f6bf9ddc 80541fa2 f83cdb85 82134a38 00000000 nt!KeReleaseInStackQueuedSpinLockFromDpcLevel+0xb14
f6bf9e54 7c930732 00000002 000906e8 00090000 nt!KiDispatchInterrupt+0x5a2
f6bf9e80 7c930732 7c9306ab 7c9306eb 00000000 ntdll!RtlAllocateHeap+0x15e
f6bf9e84 7c9306ab 7c9306eb 00000000 00100290 ntdll!RtlAllocateHeap+0x15e
f6bf9e88 7c9306eb 00000000 00100290 76d6a140 ntdll!RtlAllocateHeap+0xd7
f6bf9e9c 7c930551 00090778 7c93056d 000b8238 ntdll!RtlAllocateHeap+0x117
f6bf9ea4 7c93056d 000b8238 000b8218 000a35bc ntdll!RtlFreeHeap+0x114
f6bf9ebc 7c9305c8 000b8280 0086fd90 7c930551 ntdll!RtlFreeHeap+0x130
00000000 00000000 00000000 00000000 00000000 ntdll!RtlFreeHeap+0x18b
STACK_COMMAND: kb
FOLLOWUP_IP:
passthru!MPReturnPacket+55 [d:\winddk\3790.1830\src\network\ndis\passthru\driver\miniport.c @ 1145]
f89a7355 8be5 mov esp,ebp
FAULTING_SOURCE_CODE:
No source found for 'd:\winddk\3790.1830\src\network\ndis\passthru\driver\miniport.c'
// miniport.c
VOID
MPReturnPacket(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet
)
/*++
Routine Description:
NDIS Miniport entry point called whenever protocols are done with
a packet that we had indicated up and they had queued up for returning
later.
Arguments:
MiniportAdapterContext - pointer to ADAPT structure
Packet - packet being returned.
Return Value:
None.
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
#ifdef NDIS51
//
// Packet stacking: Check if this packet belongs to us.
//
if (NdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle)
{
//
// We reused the original packet in a receive indication.
// Simply return it to the miniport below us.
//
NdisReturnPackets(&Packet, 1);
}
else
#endif // NDIS51
{
//
// This is a packet allocated from this IM's receive packet pool.
// Reclaim our packet, and return the original to the driver below.
//
PNDIS_PACKET MyPacket;
PRECV_RSVD RecvRsvd;
RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved);
MyPacket = RecvRsvd->OriginalPkt;
NdisFreePacket(Packet);
NdisReturnPackets(&MyPacket, 1);
}
} //这里就是1145行
//protocol.c
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer, // 包头
IN UINT HeaderBufferSize, // 包头大小,以太网环境下为14
IN PVOID LookAheadBuffer, // 前视缓冲
IN UINT LookAheadBufferSize, //
IN UINT PacketSize // 数据包总大小(不包括包头)
)
/*-----------------------------------------------------------------------------------
ProtocolReceive这个函数是在低层面向无连接的NIC驱动程序调用NdisMXxxIndicateReceive 函
数向上Indicate数据包时被 NDIS 调 用 的。 同 时 传 递 了 一 个 LookAheadBuffer,但 这
个LookAheadBuffer 里 面 可 能 不 是 数 据 包 的 全 部 内 容, 如 果 不 是 的 话
(LookAheadBufferSize < PacketSize)则需要调用NdisTransferData来获得这个数据包其余的内
容,NdisTransferData只是传递在LookaheadBuffer中没有出现的数据内容, 不是传递整个数据
包。
-----------------------------------------------------------------------------------*/
{
PADAPT OutAdapt, pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet, MyPacket1;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDIS_BUFFER pPacketBuffer, pBakBuffer;
PUCHAR pPacketContent, pBakContent;
UINT PacketLen;
UINT OffsetSize;
UINT BytesTransferred;
PRSVD Rsvd = NULL;
PVOID MediaSpecificInfo = NULL;
ULONG MediaSpecificSize= 0;
DBGPRINT(("In PtReceive\n"));
if(!pAdapt->MiniportHandle)
{
Status = NDIS_STATUS_FAILURE;
}
else do
{
// Fall through if the miniport below us has either not indicated a packet or we could not
// allocate one
*/
if(FALSE){}
else if(PacketSize <= LookAheadBufferSize) // 如果 LookAheadBuffer 中包含了全部数据
{
// 分配内存
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);
}
// 将包头和 LookAheadBuffer 复制到新分配的内存中
NdisZeroMemory(pPacketContent, BUFFER_SIZE);
NdisMoveMemory(pPacketContent, HeaderBuffer, HeaderBufferSize);
NdisMoveMemory(pPacketContent+ HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize);
PacketLen = PacketSize+HeaderBufferSize;
//if(Monitor_flag)
//{
// if(Check_Packet((char*)pPacketContent))
// {
// return NDIS_STATUS_NOT_ACCEPTED;
// }
//}
//else {}
// 在包池中分配包描述符
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) //这里就是1150行
{
DBGPRINT(("In PtReceive And Free Memory\n"));
NdisFreeBuffer(pPacketBuffer);
NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0);
NdisDprFreePacket(MyPacket);
}
}
break;
}
else // 如果 LookAheadBuffer 中没有包含全部数据
{
// 分配内存 pPacketContent,存放要传输的除 LookAheadBuffer 之外的数据。
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);
// 分配包描述符 MyPacket。
NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle);
// 分配内存 pBakContent,存放HeaderBuffer + LookAheadBuffer。
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);
}
// 将 HeaderBuffer + LookAheadBuffer 复制到 pBakContent 指向的内存中。
NdisZeroMemory(pBakContent, BUFFER_SIZE);
NdisMoveMemory(pBakContent, HeaderBuffer, HeaderBufferSize);
NdisMoveMemory(pBakContent+HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize);
PacketLen = HeaderBufferSize + PacketSize;
// 为要传输的除 LookAheadBuffer 之外的数据分配缓冲描述符(该缓冲描述符与 pPacketContent 指向的内存关联)。
NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent, PacketSize-LookAheadBufferSize);
// 关联包描述符 MyPacket 与缓冲描述符 pPacketBuffer。
NdisChainBufferAtFront(MyPacket, pPacketBuffer);
MyPacket->Private.Head->Next=NULL;
MyPacket->Private.Tail=NULL;
OffsetSize = HeaderBufferSize + LookAheadBufferSize;
// 分配包描述符 MyPacket1。
NdisDprAllocatePacket(&Status, &MyPacket1, pAdapt->RecvPacketPoolHandle);
// 分配缓冲描述符 pBakBuffer,与 pBakContent 指向的内存关联。
NdisAllocateBuffer(&Status, &pBakBuffer, pAdapt->RecvBufferPoolHandle, pBakContent, OffsetSize);
// 关联包描述符 MyPacket1 与缓冲描述符 pBakBuffer。
NdisChainBufferAtFront(MyPacket1, pBakBuffer);
Rsvd = (PRSVD)(MyPacket->MiniportReserved);
Rsvd->OriginalPkt = (PNDIS_PACKET)MyPacket1;
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
// 取得 LookAheadBuffer 之后的数据
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;
} while(FALSE);
return Status;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课