从筛选器驱动程序发送数据
筛选器驱动程序可以启动发送请求或筛选过分驱动程序启动的发送请求。 当协议驱动程序调用 NdisSendNetBufferLists 函数时,NDIS 会将指定的 NET_BUFFER_LIST 结构提交到驱动程序堆栈中最顶层的筛选器模块。
发送筛选器驱动程序启动的请求
下图演示了筛选器驱动程序启动的发送操作。
筛选器驱动程序调用 NdisFSendNetBufferLists 函数以发送 在NET_BUFFER_LIST 结构列表中定义的网络数据。
筛选器驱动程序必须将它创建的每个NET_BUFFER_LIST结构的 SourceHandle 成员设置为它传递给 NdisFSendNetBufferLists 的 NdisFilterHandle 参数的相同值。 NDIS 驱动程序不应修改该驱动程序未源自NET_BUFFER_LIST结构的 SourceHandle 成员。
在调用 NdisFSendNetBufferLists 之前,筛选器驱动程序可以设置随 NET_BUFFER_LIST_INFO 宏一起发送请求的信息。 基础驱动程序可以使用 NET_BUFFER_LIST_INFO 宏检索此信息。
筛选器驱动程序一旦调用 NdisFSendNetBufferLists,就会放弃NET_BUFFER_LIST结构和所有关联资源的所有权。 NDIS 可以处理发送请求或将请求传递给基础驱动程序。
NDIS 调用 FilterSendNetBufferListsComplete 函数,将结构和数据返回到筛选器驱动程序。 在将列表传递给 FilterSendNetBufferListsComplete 之前,NDIS 可以将多个发送请求中的结构和数据收集到NET_BUFFER_LIST结构的单个链接列表中
在 NDIS 调用 FilterSendNetBufferListsComplete 之前,发送请求的当前状态是未知的。 在 NDIS 将结构返回到 FilterSendNetBufferListsComplete 之前,筛选器驱动程序绝不应尝试检查NET_BUFFER_LIST结构或任何关联数据。
FilterSendNetBufferListsComplete 执行完成发送操作所需的任何后处理。
当 NDIS 调用 FilterSendNetBufferListsComplete 时,筛选器驱动程序将重新获得与 NetBufferLists 参数指定的NET_BUFFER_LIST结构关联的所有资源的所有权。 FilterSendNetBufferListsComplete 可以释放这些资源 (,例如,通过调用 NdisFreeNetBuffer 和 NdisFreeNetBufferList 函数) ,或者准备在后续调用 NdisFSendNetBufferLists 时重复使用。
NDIS 始终按照传递给 NdisFSendNetBufferLists 的筛选器驱动程序确定的顺序向基础驱动程序提交筛选器提供的网络数据。 但是,按指定顺序发送数据后,基础驱动程序可以按任意顺序返回缓冲区。
筛选器驱动程序可以请求其发起的发送请求的环回。 若要请求环回,驱动程序在 NdisFSendNetBufferLists 的 SendFlags 参数中设置NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK标志。 NDIS 指示包含发送数据的已接收数据包。
注意 筛选器驱动程序应跟踪其发起的发送请求,并确保在此类请求完成时不会调用 NdisFSendNetBufferListsComplete 函数。
筛选发送请求
下图说明了如何筛选由过度分配的驱动程序发起的发送请求。
NDIS 调用筛选器驱动程序的 FilterSendNetBufferLists 函数来筛选过大驱动程序的发送请求。
筛选器驱动程序不得修改从其他驱动程序接收的 NET_BUFFER_LIST 结构中的 SourceHandle 成员。
筛选器驱动程序可以筛选数据并将筛选的数据发送到基础驱动程序。 对于提交到 FilterSendNetBufferLists 的每个NET_BUFFER结构,筛选器驱动程序可以执行以下操作:
通过调用 NdisFSendNetBufferLists 函数,将缓冲区传递到下一个基础驱动程序。 NDIS 保证上下文空间的可用性, (查看筛选器驱动程序 NET_BUFFER_LIST_CONTEXT结构) 。 筛选器驱动程序可以在调用 NdisFSendNetBufferLists 之前修改缓冲区内容。 筛选数据的处理与筛选器驱动程序启动的发送操作一样进行。
通过调用 NdisFSendNetBufferListsComplete 函数删除缓冲区。
在本地数据结构中将缓冲区排队,供以后处理。 筛选器驱动程序的设计决定了导致驱动程序处理排队缓冲区的原因。 一些示例包括超时后的处理或在收到特定缓冲区后进行处理。
注意 如果驱动程序将发送请求排队以供以后处理,则必须支持发送取消请求。 有关发送取消请求的详细信息,请参阅 在筛选器驱动程序中取消发送请求。
复制缓冲区,并使用副本发起发送请求。 发送操作类似于筛选器驱动程序发起的发送请求。 在这种情况下,驱动程序必须通过调用 NdisFSendNetBufferListsComplete 函数,将原始缓冲区返回到上置驱动程序。
完成发送请求会继续上行驱动程序堆栈。 当微型端口驱动程序调用 NdisMSendNetBufferListsComplete 函数时,NDIS 将调用 FilterSendNetBufferListsComplete 函数以获取最低覆盖筛选器模块。
发送操作完成后,筛选器驱动程序将反转对筛选器驱动程序在 FilterSendNetBufferLists 中对过度覆盖驱动程序的缓冲区描述符的修改。 驱动程序调用 NdisFSendNetBufferListsComplete 函数,以将NET_BUFFER_LIST结构的链接列表返回到上部驱动程序,并返回发送请求的最终状态。
当最顶层的筛选器模块调用 NdisFSendNetBufferListsComplete 时,NDIS 将调用原始协议驱动程序的 ProtocolSendNetBufferListsComplete 函数。
不提供 FilterSendNetBufferLists 函数的筛选器 驱动程序仍然可以启动发送请求。 如果此类驱动程序确实启动发送请求,则必须提供 FilterSendNetBufferListsComplete 函数,并且不得在驱动程序堆栈上传递完整事件。
筛选器驱动程序可以传递或筛选过大驱动程序的环回请求。 若要传递环回请求,如果 NDIS 在 FilterSendNetBufferLists 的 SendFlags 参数中设置NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK,筛选器驱动程序在调用 NdisFSendNetBufferLists 时在 SendFlags 参数中设置NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK。 NDIS 指示包含发送数据的已接收数据包。
通常,如果筛选器驱动程序以 NDIS 无法提供标准服务(如环回 () )的方式修改任何行为,则筛选器驱动程序必须为 NDIS 提供该服务。 例如,修改硬件地址请求 (看到 OID_802_3_CURRENT_ADDRESS) 的筛选器驱动程序应处理定向到新硬件地址的缓冲区的环回。 在这种情况下,NDIS 无法提供它通常提供的环回服务,因为筛选器更改了地址。 此外,如果筛选器驱动程序设置杂乱模式 (看到 OID_GEN_CURRENT_PACKET_FILTER) ,则它不应将其收到的额外数据传递给过度覆盖的驱动程序。