天天看點

深度剖析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;         }     } ----------------------待續--------------------------

繼續閱讀