一.绑定过程
1. DriverEntry
中间层驱动对上层来说,扮演一个Miniport Driver的角色,它在上边沿向NDIS注册一组Miniportxxx函数;对于下层Miniport Driver来说,中间层驱动扮演一个Protocol Driver的角色,因此它在下边沿向NDIS注册一组Protocolxxx函数。Miniport Driver通过调用NdisMRegisterMiniport向NDIS注册一组MiniportXxx函数;Protocol Driver 通过调用 NdisRegisterProtocol向NDIS注册一组ProtocolXxx函数。
首先通过调用NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);来初始化NdisWrapperHandle,该句柄用来代表IM Driver的自身。
接着调用NdisIMRegisterLayeredMiniport来向NDIS注册一组MiniportXxx函数,返回指向Miniport的DriverHandle。
随后调用NdisRegisterProtocol来向NDIS注册一组Protocolxxx函数,返回指向Protocol的ProtHandle。
然后调用NdisIMAssociateMiniport(DriverHandle, ProtHandle);将两者绑定。
2. PtBindAdapter
NDIS在完成第一步之后,将会调用PtBindAdapter来完成对适配器的绑定(注意:此函数的调用次数是根据用户电脑上的适配器数目而定的,一般至少有两块,会有一块叫NDISWANIP),PtBindAdapter中有用的参数主要是DeviceName和SystemSpecific1,其中DeviceName是下层NIC驱动的服务名,SystemSpecific1可以用来读取注册表中相关的值。(参考注册表HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage下的Bind子键值)
首先调用NdisOpenProtocolConfiguration ,NdisReadConfiguration来读取注册表信息,然后初始化PADAPT pAdapt结构体。
接着调用NdisOpenAdapter来将IM的下层协议驱动(ProtHandle)绑定适配器。
调用NdisIMInitializeDeviceInstanceEx来触发对MPInitialize的调用
3. MPInitialize
在MpInitialize里面主要做三件事情:
1). 判断介质类型
2). 调用NdisMSetAttributesEx设置一些特性
3). 调用PtRegisterDevice函数向NDIS注册设备
4. PtRegisterDevice
在PtRegisterDevice里,主要是设置IM Driver自己要处理的一些派遣例程和注册设备名和设备符号链接名。要注意的是,这个函数提供的功能是为整个设备服务而不是每个适配器都需要注册,所以通过一个全局变量MiniportCount来控制。
在这里,定义了PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
然后如下的设置:DispatchTable[IRP_MJ_CREATE] = DevOpen;…
接着调用NdisMRegisterDevice来注册设备名和设备符号链接名。
二.卸载过程
1. PtUnbindAdapter
针对每个绑定的适配器,首先查看对IM的miniport是否有还在排队的请求,如果有,则先调用PtRequestComplete完成它(返回NDIS_STATUS_FAILURE),然后查看状态是否为pending,是的话则调用NdisIMCancelInitializeDeviceInstance。再调用NdisIMDeInitializeDeviceInstance来卸载设备,在此会触发对MPHalt的调用。
2. MPHalt
在MPHalt里,首先调用PtDeregisterDevice来卸载设备,然后调用NdisCloseAdapter关闭绑定的适配器。
3. PtDeregisterDevice (MiniportCount == 0?)
在PtDeregisterDevice 里,调用NdisMDeregisterDevice来卸载设备。同PtRegisterDevice类似,要注意的是,这个函数提供的功能是为整个设备服务而不是每个适配器都需要注册,所以通过一个全局变量MiniportCount来控制。只有最后一个绑定的适配器卸载时,才调用NdisMDeregisterDevice。
4. PtUnloadProtocol
在CloseAdapterComplete完成后,NDIS会调用PtUnloadProtocol来完成下层绑定的协议驱动(ProtHandle)的卸载,调用NdisDeregisterProtocol函数。
5. PtUnload
首先,要说明的是,在DriverEntry函数里,有注册该函数(NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);)。该函数是整个卸载过程的最后一步,在这里,会继续完成对绑定的上层miniport,下层的protocol的卸载(其实protocol的卸载在第4步已经完成),调用如下两个函数PtUnloadProtocol,NdisIMDeregisterLayeredMiniport。