Win10Pcap网络驱动学习(3)
对于MSDN上回调函数内容的一些翻译
协议驱动的一些回调函数(2)
PROTOCOL_UNINSTALL 回调函数
原文: https://msdn.microsoft.com/zh-cn/windows/hardware/ff570279(v=vs.85)
在协议驱动卸载之前,NDIS调用协议驱动的ProtocolUninstall 函数来执行清理操作
注意, 该回调函数指针必须声明为PROTOCOL_UNINSTALL 类型
语法
PROTOCOL_UNINSTALL ProtocolUninstall;
VOID ProtocolUninstall(void)
{ ... }
无参数,无返回值
注意
ProtocolUninstall 回调函数是可选的。NDIS调用协议驱动的ProtocolUninstall 函数来响应用户卸载协议驱动的请求。NDIS在为每一个绑定的适配器调用协议驱动的ProtocolUnbindAdapterEx之后会调用ProtocolUninstall 。
ProtocolUninstall 执行驱动指定的清理操作。例如,ProtocolUninstall 可以请求客服户端关闭协议驱动输出的设备对象的句柄。在所有句柄都关闭之前,I/O管理器将不会调用协议驱动注册的卸载程序。在所有句柄关闭之后,ProtocolUninstall 可以调用NdisDeregisterDeviceEx 来删除所有协议驱动创建的设备对象。
一个中间层驱动程序的协议下边缘可能需要ProtocolUninstall 功能。在NDIS调用MiniportDriverUnload 函数之前,中间层驱动可以在ProtocolUninstall 函数中释放它的protocol edge resources,
NDIS calls ProtocolUninstall at IRQL = PASSIVE_LEVEL.
PROTOCOL_OID_REQUEST_COMPLETE 回调函数
原文: https://msdn.microsoft.com/zh-cn/windows/hardware/ff570264(v=vs.85)
在NdisOidRequest 函数返回NDIS_STATUS_PENDING的情况下,ProtocolOidRequestComplete 函数完成协议驱动发起的OID请求的处理。
注意,必须生声明为PROTOCOL_OID_REQUEST_COMPLETE 类型。
语法
PROTOCOL_OID_REQUEST_COMPLETE ProtocolOidRequestComplete;
VOID ProtocolOidRequestComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNDIS_OID_REQUEST OidRequest,
_In_ NDIS_STATUS Status
)
{ ... }
参数
ProtocolBindingContext [in]
协议驱动分配的上下文内容(自定义结构体)的句柄,协议驱动用来保存每个绑定的运行时状态。驱动在调用NdisOpenAdapterEx 时传入该参数。
OidRequest [in]
协议驱动在之前调用NdisOidRequest 函数时传入的NDIS_OID_REQUEST 结构指针。
Status [in]
请求的最终状态。由底层驱动或者NDIS赋值。此参数表示根据OidRequest参数中的信息应该做什么处理。
返回值 无
注意
ProtocolOidRequestComplete 使用以下这些Status值
如果状态是NDIS_STATUS_SUCCESS,那么NDIS_OID_REQUEST 结构体的BytesRead 或者BytesWritten成员已经被NDIS或者底层驱动设置了,以此来指定在一个设置操作中有多少协议驱动提供的信息从InformationBuffer的缓冲区中被传入了网卡或者在一个查询操作中有多少信息返回到InformationBuffer 。
如果协议驱动进行了一个查询,ProtocolOidRequestComplete 可以根据成员Oid的值任意的使用InformationBuffer 中返回的信息。
比如,如果协议驱动最初发起一个OID_GEN_MAXIMUM_SEND_PACKETS 查询,ProtocolOidRequestComplete 可能设置ProtocolBindingContext 中的状态成员来限制协议之后将会通过NdisSendNetBufferLIsts 函数处理的未完成的发送。
如果状态是NDIS_STATUS_INVALID_LENGTH 或者NDIS_STATUS_BUFFER_TOO_SHORT,BytesNeeded 成员指定具体OID请求执行需要的InformationBufferLength成员的值。
在这种情况下,ProtocolOidRequestComplete 可以为请求分配足够的空间,根据需要的InformationBufferLength 新建另一个相同的NDIS_OID_REQUEST 结构体,重新调用NdisOidRequest 方法。
ProtocolOidRequestComplete 可以为某些其它的NDIS_STATUS_ XXX参数重重试请求,就像NdisOidRequest 函数参考中所说的那样
如果状态是一个不可恢复的错误,ProtocolOidRequestComplete 应该释放为NDIS_OID_REQUEST 结构体分配的内存并驱动是否应该关闭绑定或者调整绑定信息来处理接下来的网络I/O请求。
对于全局查询与设置,底层无连接mini端口对于NdisMOidRequestComplete 函数的调用会引起NDIS调用ProtocolOidRequestComplete 方法。NDIS转发mini端口驱动传递给NdisMOidRequestComplete 函数的状态值作为ProtocolOidRequestComplete的输入状态参数。
对于绑定相关的查询,NDIS直接调用ProtocolOidRequestComplete 。因为NDIS库保存了所有mini端口驱动的绑定,NDIS可以返回绑定相关的信息,only about underlying drivers that report their medium-type as one for which the system provides a filter library. 对于协议驱动发起的绑定相关的对于其它mini端口的请求,NDIS返回NDIS_STATUS_NOT_SUPPORTED
更多信息请查询NDIS OIDs。
ProtocolOidRequestComplete 可以在协议驱动有时间检查NdisOidRequest 返回的status状态码之前调用。
NDIS calls ProtocolOidRequestComplete at IRQL <= DISPATCH_LEVEL.
PROTOCOL_STATUS_EX 回调函数
原文: https://msdn.microsoft.com/zh-cn/windows/hardware/ff570270(v=vs.85)
ProtocolStatusEx 函数表示从底层连接的驱动程序或NDIS状态的变化。
注意,必须声明为PROTOCOL_STATUS_EX 类型
语法
PROTOCOL_STATUS_EX ProtocolStatusEx;
VOID ProtocolStatusEx(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNDIS_STATUS_INDICATION StatusIndication
)
{ ... }
参数
ProtocolBindingContext [in]
协议驱动分配的上下文相关区域的句柄。协议驱动在里面把偶操你每个绑定的信息。驱动在调用NdisOpenAdapterEx 时传入NDIS。
StatusIndication [in]
NDIS_STATUS_INDICATION 结构体指针。
返回值 无
注意
对于ProtocolStatusEx 的调用通知协议驱动底层驱动的状态变化了。
为了确定连接状态,使用底层驱动的状态指示而不是OID查询。这些状态指示会提高系统系能并避免可能的竟态条件。
在底层驱动重新设置网卡时,NDIS调用所有绑定的协议驱动的ProtocolStatusEx 函数。首先,NDIS指定NDIS_STATUS_RESET_START 状态,然后,当重设置操作完成之后,NDIS指定NDIS_STATUS_RESET_END 状态。
在重设置操作过程中,NDIS将不会接受发送请求与OID查询,NDIS_STATUS_RESET_START 通知将会警告绑定的协议驱动来停止相关的请求,直到它们收到NDIS_STATUS_RESET_END。
NDIS calls ProtocolStatusEx at IRQL <= DISPATCH_LEVEL.
PROTOCOL_RECEIVE_NET_BUFFER_LISTS 回调函数
原文: https://msdn.microsoft.com/zh-cn/windows/hardware/ff570267(v=vs.85)
ProtocolReceiveNetBufferLists 函数处理底层驱动的接受提示。
注意,必须声明为PROTOCOL_RECEIVE_NET_BUFFER_LISTS 类型
语法
PROTOCOL_RECEIVE_NET_BUFFER_LISTS ProtocolReceiveNetBufferLists;
VOID ProtocolReceiveNetBufferLists(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNET_BUFFER_LIST NetBufferLists,
_In_ NDIS_PORT_NUMBER PortNumber,
_In_ ULONG NumberOfNetBufferLists,
_In_ ULONG ReceiveFlags
)
{ ... }
参数
ProtocolBindingContext [in]
协议驱动分配的上下文区域(自定义结构体)句柄,用来保存绑定的状态信息。这个句柄在调用NdisOpenAdapterEx 函数时传入。
NetBufferLists [in]
一个底层驱动分配的NET_BUFFER_LIST 结构体链表。每一个NET_BUFFER_LIST 结构体通常与一个NET_BUFFER 结构体一起被分配。
PortNumber [in]
标识miniport 的端口。默认的端口为0.协议驱动如果不使用miniport adapter端口,应该忽略该值
NumberOfNetBufferLists [in]
NetBufferLists 列表中NET_BUFFER_LIST 结构体的数量
.
ReceiveFlags [in]
为发送操作定义属性的标志。可以通过或操作组合。可以通过设置为0来清理所有的标志。本函数支持以下这些标志:
1.NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL
指明当前IRQL 是DISPATCH_LEVEL。更多信息请查看Dispatch IRQL Tracking
2.NDIS_RECEIVE_FLAGS_RESOURCES
指明NDIS在ProtocolReceiveNetBufferLists 返回后立刻回收NET_BUFFER_LIST 结构体及其对应的NET_BUFFER 结构体。
3.NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE
指明NetBufferLists 链表中所有的NET_BUFFER_LIST 结构体有着相同的协议类型。
4.NDIS_RECEIVE_FLAGS_SINGLE_VLAN
指明NetBufferLists 链表中的所有NET_BUFFER_LIST 结构属于相同的VLAN
5.NDIS_RECEIVE_FLAGS_PERFECT_FILTERED
指明NetBufferLists 链表中的所有NET_BUFFER_LIST 仅仅只包含符合指定给miniport adapter的包过滤器以及组播列表的数据。
6.NDIS_RECEIVE_FLAGS_SINGLE_QUEUE
指明NetBufferLists 链表中的所有NET_BUFFER_LIST 属于相同的VM队列。当队列被分配时,如果NDIS_RECEIVE_QUEUE_PARAMETERS 结构体中的Flags成员被指定为NDIS_RECEIVE_QUEUE_PARAMETERS_PER_QUEUE_RECEIVE_INDICATION ,miniport驱动必须为队列中的每一个接收指示设置NDIS_RECEIVE_FLAGS_SINGLE_QUEUE标志。
7.NDIS_RECEIVE_FLAGS_SHARED_MEMORY_INFO_VALID
指明NetBufferLists 链表中的所有NET_BUFFER_LIST包含有效的共享内存信息。当设置为该标志时,NDIS将共享内存视为有效。当没有设置该标志时,NDIS与驱动忽略共享内存信息。例如,修改包数据的中间驱动可以使用该标志来指定数据是否用改被拷贝。Miniport驱动可以使用该标志来指定在一个队列被删除时如何释放内存。
NDIS_RECEIVE_FLAGS_MORE_NBLS
保留参数
返回值 无
注意
ProtocolReceiveNetBufferLists 是协议驱动必须的函数。NDIS在一个被绑定的miniport 驱动调用了NdisMIndicateReceiveNetBufferLists 之后调用该函数。调用ProtocolReceiveNetBufferLists 同样可以作为环回的结果而发生。
如果ReceiveFlags 参数不是NDIS_RECEIVE_FLAGS_RESOURCES ,协议驱动在调用NdisReturnNetBufferLists 之前都保有NET_BUFFER_LIST 的使用权。
如果NDIS设置了NDIS_RECEIVE_FLAGS_RESOURCES ,协议驱动不能保留NET_BUFFER_LIST 以及相关的资源。NDIS_RECEIVE_FLAGS_RESOURCES表明一个底层的驱动is running low on receive resources。在这种情况下,ProtocolReceiveNetBufferLists 函数应该拷贝接受到的信息并尽快返回。
注意如果NDIS_RECEIVE_FLAGS_RESOURCES 被设置了,协议驱动必须保留原始的NET_BUFFER_LIST 的设置。比如,当这个标志被设置时,驱动可能处理这些结构体并每次向上显示堆栈,但在函数返回之前,必须还原原始链表。
在一个多进程系统中,这个函数可以被多个进程同时执行。申请保护(例如,使用自旋锁)ProtocolReceiveNetBufferLists可能访问的关键数据结构。
NDIS calls ProtocolReceiveNetBufferLists at IRQL<= DISPATCH_LEVEL.
PROTOCOL_SEND_NET_BUFFER_LISTS_COMPLETE 回调函数
ProtocolSendNetBufferListsComplete 函数完成由协议驱动通过调用NdisSendNetBufferLists 函数发起的发送操作。
注意 必须声明为PROTOCOL_SEND_NET_BUFFER_LISTS_COMPLETE
语法
PROTOCOL_SEND_NET_BUFFER_LISTS_COMPLETE ProtocolSendNetBufferListsComplete;
VOID ProtocolSendNetBufferListsComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNET_BUFFER_LIST NetBufferLists,
_In_ ULONG SendCompleteFlags
)
{ ... }
参数
ProtocolBindingContext [in]
协议驱动自定义结构体句柄(指针)。在调用NdisOpenAdapterEx时传入。
NetBufferLists [in]
协议驱动在调用NdisSendNetBufferLists时传入的NET_BUFFER_LIST 结构体链表的指针。
SendCompleteFlags [in]
NDIS标志,可以通过或操作组合。设置参数为0可以清理所有的标志。本函数支持NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL 标志,如果设置了,表明当前IRQL 是DISPATCH_LEVEL。更多信息请查看Dispatch IRQL Tracking
返回值 无
注意
ProtocolSendNetBufferListsComplete 是协议驱动必须的函数。该函数执行任何必须的处理来完成一个发送操作。比如,协议驱动可以通知请求协议发送网络数据的客户端操作已完成。
NDIS在底层miniport 驱动调用了NdisMSendNetBufferListsComplete 函数之后调用ProtocolSendNetBufferListsComplete 。一个发送操作的完成通常说明底层miniport 驱动已经发出了指定的网络数据。然而,一个miniport 驱动可以在它将数据发送给网卡之后立刻指明一个发送操作已经完成。
当NDIS调用ProtocolSendNetBufferListsComplete时,协议驱动重新获得所有与NET_BUFFER_LIST 相关的资源的所有权。
NDIS总是按照协议驱动传递给NdisSendNetBufferLists的顺序来提交协议驱动传入的网络数据给miniport驱动,然而,底层驱动可能以任意顺序完成发送。也就是说,协议驱动可以依赖NDIS以先进先出的顺序来向底层驱动提交数据。然而,协议驱动不能要求底层驱动以相同的顺序调用NdisMSendNetBufferListsComplete 。
NDIS calls ProtocolSendNetBufferListsComplete at IRQL<= DISPATCH_LEVEL.
PROTOCOL_DIRECT_OID_REQUEST_COMPLETE 回调函数
在NdisDirectOidRequest 函数返回NDIS_STATUS_PENDING的情况下,ProtocolDirectOidRequestComplete 函数完成一个协议驱动发起的直接OID请求。
语法
PROTOCOL_DIRECT_OID_REQUEST_COMPLETE ProtocolDirectOidRequestComplete;
VOID ProtocolDirectOidRequestComplete(
_In_ NDIS_HANDLE ProtocolBindingContext,
_In_ PNDIS_OID_REQUEST OidRequest,
_In_ NDIS_STATUS Status
)
{ ... }
参数
ProtocolBindingContext [in]
协议驱动分配的自定义结构体指针。协议驱动在调用NdisOpenAdapterEx时传入。
OidRequest [in]
协议驱动在调用NdisDirectOidRequest 时传入的NDIS_OID_REQUEST 结构体指针。
Status [in]
请求的最终状态。底层驱动或者NDIS决定该状态。这个参数决定了ProtocolDirectOidRequestComplete 应该对OidRequest中的信息做什么处理。
返回值 无
注意
ProtocolDirectOidRequestComplete 是可选的函数。如果协议驱动不使用直接OID 请求,那么就可以在调用NdisRegisterProtocolDriver 时设置为NULL。
ProtocolDirectOidRequestComplete 以如下方式使用Status 参数:
如果是NDIS_STATUS_SUCCESS,NDIS_OID_REQUEST 中的BytesRead 或者BytesWritten 成员被NDIS或者底层驱动设置。这些值表示对于设置操作有多少协议驱动传入的信息从缓冲区传到网卡或者对于查询操作有多少信息被返回。
如果协议驱动进行了一个查询,根据Oid成员的值,ProtocolDirectOidRequestComplete 可以对InformationBuffer 中返回的信息做任何操作。
例如,协议驱动最初发起一个OID_GEN_MAXIMUM_SEND_PACKETS 查询,ProtocolDirectOidRequestComplete 可能设置ProtocolBindingContext 中的状态成员来限制协议之后将会通过NdisSendNetBufferLIsts 函数处理的未完成的发送。
如果状态是NDIS_STATUS_INVALID_LENGTH 或者NDIS_STATUS_BUFFER_TOO_SHORT,BytesNeeded 成员指定具体OID请求执行需要的InformationBufferLength成员的值。
在这种情况下,ProtocolDirectOidRequestComplete 可以为请求分配足够的空间,根据需要的InformationBufferLength 新建另一个相同的NDIS_OID_REQUEST 结构体,重新调用NdisOidRequest 方法。
ProtocolDirectOidRequestComplete 可以为某些其它的NDIS_STATUS_ XXX参数重重试请求,就像NdisOidRequest 函数参考中所说的那样
ProtocolDirectOidRequestComplete 可以在协议驱动有时间检测NdisDirectOidRequest 返回的状态值之前调用被调用。
NDIS calls ProtocolDirectOidRequestComplete at IRQL <= DISPATCH_LEVEL.