本文转自http://eslxf.blog.51cto.com/918801/210887
/*如果成功,则给全局记录打开实例的计数器原子操作加一,然后获取设备的最大MTU*/
if (returnStatus == STATUS_SUCCESS)
{ //完成打开网络设备
ULONG localNumOpenedInstances;
//给全局记录打开实例的计数器原子操作加一
localNumOpenedInstances = InterlockedIncrement(&g_NumOpenedInstances);
//获得系统启动以来的时间绝对值,用于时间装换
TIME_SYNCHRONIZE(&G_Start_Time);
//获取设备的最大MTU
returnStatus = NPF_GetDeviceMTU(Open, Irp, &Open->MaxFrameSize);
if (!NT_SUCCESS(returnStatus))
{//获取失败,关闭绑定
NPF_CloseBinding(Open);
}
}
/*如果成功,则把Open实例保存到IrpSp->FileObject->FsContext*/
if (!NT_SUCCESS(returnStatus))
{
NPF_CloseOpenInstance(Open);
}
else
{
// 此处保存Open
IrpSp->FileObject->FsContext=Open;
}
Irp->IoStatus.Status = returnStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return returnStatus;
}
函数NPF_open首先获得_DEVICE_EXTENSION结构体指针,在后面赋给Open->DeviceExtension,接着获得IRP中的调用者栈的位置。然后分配内存空间给Open结构体,并对所分配的内存清零,接着为数据包的接收与发送分配一个数据包内存缓冲池。
开始初始化Open结构体的各种事件,与各种自旋锁,初始化设置open实例的其它成员。
然后试图打开网络设备,在调用的协议与一个特定底层NIC驱动程序或NDIS中间层驱动程序之间建立绑定。检查NdisOpenAdapter函数返回是否为挂起状态,如果是,则等待打开完成事件。如果绑定成功,则给全局记录打开实例的计数器原子操作加一,然后调用NPF_GetDeviceMTU函数获取设备的最大MTU。如果该调用成功,则把Open实例保存到IrpSp->FileObject->FsContext,以便其它函数调用。比如在NPF_Cleanup函数中使用Open = IrpSp->FileObject->FsContext;语句获得Open实例。