本文转自http://eslxf.blog.51cto.com/918801/210016
< body>
1.6.3 NPF_open函数
函数NPF_Open打开驱动的一个新实例。函数原型如下: NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); 参数DeviceObject指向用户所使用的设备对象,参数Irp指向用户所请求的IRP. 函数返回操作的状态,参见DDK的ntstatus.h文件了解状态值的定义。 当用户的应用程序,在NPF所创建的一个设备上执行一个CreateFile系统调用时,该函数由操作系统调用。 函数NPF_Open分配与初始化一个新实例所需的变量、对象与缓冲区,填充与该实例关联的OPEN_INSTANCE结构体,并调用NdisOpenAdapter打开适配器。 函数的主要代码如下: 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; DeviceExtension = DeviceObject->DeviceExtension; IrpSp = IoGetCurrentIrpStackLocation(Irp); 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; } NdisInitializeEvent(&Open->WriteEvent); NdisInitializeEvent(&Open->NdisRequestEvent); NdisInitializeEvent(&Open->NdisWriteCompleteEvent); NdisInitializeEvent(&Open->DumpEvent); NdisAllocateSpinLock(&Open->MachineLock); NdisAllocateSpinLock(&Open->WriteLock); Open->WriteInProgress = FALSE; 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->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); 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); 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; } } ----------------------待续--------------------------