天天看点

深度剖析WinPcap之(八)——打开与关闭适配器(18)

本文转自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;         }     } ----------------------待续--------------------------

继续阅读