1.6.4.1        NPF_CloseBinding函数

函数主要释放调用NdisOpenAdapter所建立的绑定与分配的资源。

函数代码实现如下:
VOID NPF_CloseBinding(IN POPEN_INSTANCE pOpen)

{

    NDIS_EVENT Event;

    NDIS_STATUS Status;

 

    ASSERT(pOpen != NULL);

    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

 

    NdisInitializeEvent(&Event);

    NdisResetEvent(&Event);

 

    NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

 

    while(pOpen->AdapterHandleUsageCounter > 0)

    {

        NdisReleaseSpinLock(&pOpen->AdapterHandleLock);

        NdisWaitEvent(&Event,1);

        NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

    }

 

    /*现在使用计数为0*/

    while(pOpen->AdapterBindingStatus == ADAPTER_UNBINDING)

    {

        NdisReleaseSpinLock(&pOpen->AdapterHandleLock);

        NdisWaitEvent(&Event,1);

        NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

    }

 

    /*现在绑定状态可能为绑定也可能为未绑定*/

    if (pOpen->AdapterBindingStatus == ADAPTER_UNBOUND)

    {

        NdisReleaseSpinLock(&pOpen->AdapterHandleLock);

        return;

    }

 

    ASSERT(pOpen->AdapterBindingStatus == ADAPTER_BOUND);

 

    pOpen->AdapterBindingStatus = ADAPTER_UNBINDING;

    NdisReleaseSpinLock(&pOpen->AdapterHandleLock);

   

    /*执行释放过程*/

    NdisResetEvent(&pOpen->NdisOpenCloseCompleteEvent);

 

    //释放调用NdisOpenAdapter所建立的绑定与分配的资源

    NdisCloseAdapter(

        &Status,

        pOpen->AdapterHandle

        );

 

    //检测是否为挂起状态

    if (Status == NDIS_STATUS_PENDING)

       { //挂起,等待NdisOpenCloseCompleteEvent事件,

//在完成函数NPF_CloseAdapterComplete中设置该事件

        NdisWaitEvent(&pOpen->NdisOpenCloseCompleteEvent, 0);

    }

    else

    {

        ;

    }

 

    /*设置绑定状态为未绑定*/

    NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

    pOpen->AdapterBindingStatus = ADAPTER_UNBOUND;

    NdisReleaseSpinLock(&pOpen->AdapterHandleLock);

}

 

1.6.4.2 NPF_CloseAdapterComplete

函数结束适配器的关闭,为NDIS函数NdisCloseAdapter关联的回调函数,当NIC驱动程序完成一个关闭操作(在NPF_CloseBinding中调用NdisCloseAdapter启动关闭操作)后被NDIS调用。

函数原型如下:

VOID

NPF_CloseAdapterComplete(

    IN NDIS_HANDLE  ProtocolBindingContext,

    IN NDIS_STATUS  Status

    );

参数ProtocolBindingContext为函数的上下文,包含一个指向与当前实例关联的OPEN_INSTANCE结构体指针。参数StatusNDIS执行关闭操作的状态。

函数的主要代码如下:

VOID NPF_CloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,

IN NDIS_STATUS  Status)

{

    POPEN_INSTANCE    Open;

    PIRP              Irp;

 

    Open = (POPEN_INSTANCE)ProtocolBindingContext;

     ASSERT(Open != NULL);

/*设置NdisOpenCloseCompleteEvent事件,*/

     NdisSetEvent(&Open->NdisOpenCloseCompleteEvent);

     TRACE_EXIT();

     return;

}

 

1.6.4.3        NPF_CloseOpenInstance函数

//释放调用NdisOpenAdapter所建立的绑定与分配的资源

函数的主要代码如下:
VOID NPF_CloseOpenInstance(POPEN_INSTANCE pOpen)

{

        PKEVENT pEvent;

        UINT i;    

 

        ASSERT(pOpen != NULL);

        ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

 

        TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Open= %p", pOpen);

/*释放为数据包接收与发送所分配的内存缓冲池*/

        NdisFreePacketPool(pOpen->PacketPool);

 

        /*释放过滤器,如果存在*/

        if(pOpen->bpfprogram != NULL)

            ExFreePool(pOpen->bpfprogram);

 

// Jitted 过滤器仅仅被x86(32)架构支持//

#ifdef _X86_

        /*释放jitted过滤器,如果存在*/

        if(pOpen->Filter != NULL)

            BPF_Destroy_JIT_Filter(pOpen->Filter);

#endif //_X86_

 

        /*递减ReadEvent事件对象的引用计数,并执行保留状态检查*/

        if (pOpen->ReadEvent != NULL)

            ObDereferenceObject(pOpen->ReadEvent);

 

        /*释放缓冲区*/

        // 注意:该缓冲区在各CPU间被分割成片,但是所分配的大块内存的基地址仍然存储在第一个位置(pOpen->CpuData[0])

        if (pOpen->Size > 0)

            ExFreePool(pOpen->CpuData[0].Buffer);

 

        /* 释放CPU自旋锁*/

        for (i = 0; i < g_NCpu; i++)

        {

            NdisFreeSpinLock(&Open->CpuData[i].BufferLock);

        }

 

        /*释放存储转储文件名的字符串*/

        if(pOpen->DumpFileName.Buffer!=NULL)

            ExFreePool(pOpen->DumpFileName.Buffer);

       

        /*释放open实例的内存空间*/

        ExFreePool(pOpen);

}

本文出自 “千江月” 博客,请务必保留此出处http://eslxf.blog.51cto.com/918801/211969