函数的主要代码如下:
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
NDIS_STATUS Status;
NDIS_STATUS ErrorStatus;
UINT i;
PUCHAR tpointer;
PLIST_ENTRY PacketListEntry;
NTSTATUS returnStatus;
/*
获得_DEVICE_EXTENSION结构体指针,在后面赋给Open->DeviceExtension */
DeviceExtension = DeviceObject->DeviceExtension;
/*
获得IRP中的调用者栈的位置*/
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/*
分配内存空间给Open结构体,并对所分配的内存清零*/
Open=ExAllocatePoolWithTag(NonPagedPool,
sizeof
(OPEN_INSTANCE), '0OWA');
if (Open==NULL) {
//
分配内存失败,函数返回
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( Open,sizeof(OPEN_INSTANCE) );
Open->DeviceExtension=DeviceExtension;
/*
为数据包的接收与发送分配一个数据包内存缓冲池*/
NdisAllocatePacketPool(
&Status,
&Open->PacketPool,
TRANSMIT_PACKETS,
sizeof(PACKET_RESERVED));
if (Status != NDIS_STATUS_SUCCESS) {
//
分配数据包缓冲池失败,函数返回
ExFreePool(Open);
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
初始化Open结构体的各种事件*/
NdisInitializeEvent(&Open->WriteEvent);
NdisInitializeEvent(&Open->NdisRequestEvent);
NdisInitializeEvent(&Open->NdisWriteCompleteEvent);
NdisInitializeEvent(&Open->DumpEvent);
/*
初始化Open结构体的各种自旋锁*/
NdisAllocateSpinLock(&Open->MachineLock);
NdisAllocateSpinLock(&Open->WriteLock);
/*
没有执行写操作*/
Open->WriteInProgress = FALSE;
/*
初始化Open结构体的各种自旋锁*/
for
(i = 0; i < g_NCpu; i++)
{
NdisAllocateSpinLock(&Open->CpuData[i].BufferLock);
}
NdisInitializeEvent(&Open->NdisOpenCloseCompleteEvent);
//
初始化存储适配器复位IRP请求的链表
InitializeListHead(&Open->ResetIrpList);
//
初始化请求链表
KeInitializeSpinLock(&Open->RequestSpinLock);
InitializeListHead(&Open->RequestList);
/*
初始化设置open实例的成员*/
Open->bpfprogram = NULL; //
复位过滤器
Open->mode = MODE_CAPT; //
设置为捕获工作模式
Open->Nbytes.QuadPart = 0;
//
把过滤器所接收字节数量为0
Open->Npackets.QuadPart = 0;
//
把过滤器所接收数据包数量为0
Open->Nwrites = 1; //
设置一个数据包需要被重复发送的次数为1次
Open->Multiple_Write_Counter = 0;//
写操作已做的重复次数清零
Open->MinToCopy = 0;//
设置缓冲区中没被锁定的最小可读的数据数量
Open->TimeOut.QuadPart = (LONGLONG)1;//
设置读超时值
Open->DumpFileName.Buffer = NULL;//
初始化文件转储的各参数
Open->DumpFileHandle = NULL;
Open->DumpLimitReached = FALSE;
Open->MaxFrameSize = 0; //
设置底层MAC所能接收的最大帧大小
Open->WriterSN=0; //
下一个将被写入内核缓冲池中的数据包的序号。
Open->ReaderSN=0; //
下一个将被从内核缓冲池中读取的数据包的序号
Open->Size=0; //
包含在CpuData字段中的每个内核缓冲区的大小
Open->SkipSentPackets = FALSE;//
设置该实例捕获自己所传输的数据包
Open->ReadEvent = NULL;//
初始化事件,在该事件上对实例的读调用必须等待
//
初始化统计计数器的自旋锁
NdisAllocateSpinLock(&Open->CountersLock);
/*
连接Open的请求链表*/
for (i = 0 ; i < MAX_REQUESTS ; i++ )
{
NdisInitializeEvent(
&Open->Requests[i].InternalRequestCompletedEvent
);
//
在双向链表的尾部插入一个元素,该插入为原子操作
ExInterlockedInsertTailList(
&Open->RequestList,
&Open->Requests[i].ListElement,
&Open->RequestSpinLock);
}
NdisResetEvent(&Open->NdisOpenCloseCompleteEvent);
//
在打开MAC前,设置正确的邦定标志
Open->AdapterBindingStatus = ADAPTER_BOUND;
Open->AdapterHandleUsageCounter = 0;
NdisAllocateSpinLock(&Open->AdapterHandleLock);
/*
试图打开网络设备,在调用的协议与一个特定底层NIC驱动程序或NDIS中间层驱动程序之间建立绑定。*/
returnStatus = STATUS_SUCCESS;
NdisOpenAdapter(
&Status,
&ErrorStatus,
&Open->AdapterHandle,
&Open->Medium,
MediumArray,
NUM_NDIS_MEDIA,
g_NdisProtocolHandle,
Open,
&DeviceExtension->AdapterName,
0,
NULL);
if (Status == NDIS_STATUS_PENDING)
{ //
打开网络设备返回挂起状态,等待打开完成事件
NdisWaitEvent(&Open->NdisOpenCloseCompleteEvent, 0);
if (!NT_SUCCESS(Open->OpenCloseStatus))
{//
失败
returnStatus = Open->OpenCloseStatus;
}
else
{
returnStatus = STATUS_SUCCESS;
}
}
else
{
//
请求没被挂起,我们已经知道结果,就不调用OpenComplete调用。
if (Status == NDIS_STATUS_SUCCESS)
{
returnStatus = STATUS_SUCCESS;
}
else
{
//
没有完成正确,我们把一个NDIS_STATUS转换为NTSTATUS
returnStatus = Status;
}
}
----------------------待续--------------------------