本文轉自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; } } ----------------------待續--------------------------