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

1.6.3       NPF_open函数

函数NPF_Open打开驱动的一个新实例。函数原型如下:
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
参数DeviceObject指向用户所使用的设备对象,参数Irp指向用户所请求的IRP.
函数返回操作的状态,参见DDKntstatus.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;
 
    /* 获得_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;
        }
    }
----------------------待续--------------------------

你可能感兴趣的:(职场,休闲,winpcap)