本文转自http://eslxf.blog.51cto.com/918801/211969
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结构体指针。参数Status为NDIS执行关闭操作的状态。
函数的主要代码如下:
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);
}