NDIS协议驱动(四)

news2024/11/18 13:38:54

NDIS 定义对象标识符 (OID) 值,以标识适配器参数,其中包括设备特征、可配置设置和统计信息等操作参数。 协议驱动程序可以查询或设置基础驱动程序的操作参数。

NDIS 还为 NDIS 6.1 及更高版本的协议驱动程序提供直接 OID 请求接口。 直接 OID 请求路径支持频繁查询或设置的 OID 请求。 例如,IPsec 卸载版本 2 (IPsecv2) 接口为直接 OID 请求提供 OID_TCP_TASK_IPSEC_OFFLOAD_V2_ADD_SA OID。 直接 OID 请求接口对于 NDIS 驱动程序是可选的。

从 NDIS 协议驱动程序生成 OID 请求

为了向基础驱动程序发出 OID 请求,协议调用 NdisOidRequest 函数。

下图演示了协议驱动程序发起的 OID 请求。

在协议驱动程序调用 NdisOidRequest 函数后,NDIS 将调用下一个基础驱动程序的请求函数。

若要同步完成, NdisOidRequest 将返回NDIS_STATUS_SUCCESS或错误状态。 为了异步完成, NdisOidRequest 返回NDIS_STATUS_PENDING。

如果 NdisOidRequest 返回NDIS_STATUS_PENDING,则 NDIS 在基础驱动程序完成 OID 请求后调用 ProtocolOidRequestComplete 函数。 在这种情况下,NDIS 在 ProtocolOidRequestComplete 的 OidRequest 参数中传递请求的结果。 NDIS 在 ProtocolOidRequestComplete 的 Status 参数中传递请求的最终状态。

如果 NdisOidRequest 返回NDIS_STATUS_SUCCESS,它将在 OidRequest 参数的 NDIS_OID_REQUEST 结构中返回查询请求的结果。 在这种情况下,NDIS 不调用 ProtocolOidRequestComplete 函数。

若要确定基础驱动程序成功处理了哪些信息,发出 OID 请求的协议驱动程序必须在 OID 请求返回后检查NDIS_OID_REQUEST结构中的 SupportedRevision 成员中的值。

如果基础驱动程序应将 OID 请求与后续状态指示相关联,则协议驱动程序应在NDIS_OID_REQUEST结构中设置 RequestId 成员。 当基础驱动程序发出状态指示时,它会将 NDIS_STATUS_INDICATION 结构中的 RequestId 成员设置为 OID 请求中提供的值。

当绑定处于“正在重启”、“正在运行”、“暂停”或“已暂停”状态时,驱动程序可以调用 NdisOidRequest。

协议驱动程序直接 OID 请求

为了支持直接 OID 请求路径,协议驱动程序在 NDIS_PROTOCOL_DRIVER_CHARACTERISTICS 结构中提供 ProtocolXxx 函数入口点,NDIS 为协议驱动程序提供 NdisXxx 函数。

直接 OID 请求接口类似于标准 OID 请求接口。 例如, NdisDirectOidRequest 和 ProtocolDirectOidRequestComplete 函数类似于 NdisOidRequest 和 ProtocolOidRequestComplete 函数。

注意 NDIS 6.1 及更高版本支持用于直接 OID 请求接口的特定 OID。 不支持在 NDIS 6.1 和某些 NDIS 6.1 OID 之前存在的 OID。

协议驱动程序同步 OID 请求

为了支持同步 OID 请求路径,协议驱动程序调用 NdisSynchronousOidRequest 函数来发出同步 OID。

对于协议驱动程序, 同步 OID 请求接口 不同于常规和直接 OID 请求接口,即协议驱动程序不必实现异步 完整 回调函数,这是因为路径的同步性质。

处理协议驱动程序中的状态指示

协议驱动程序必须提供当基础驱动程序报告状态时 NDIS 调用的 ProtocolStatusEx 函数。

在基础驱动程序 (NdisMIndicateStatus 或 NdisFIndicateStatus) 调用状态指示函数后,NDIS 调用协议驱动程序的 ProtocolStatusEx 函数。 

如果状态指示与 OID 请求相关联,则基础驱动程序可以设置 DestinationHandle 和 RequestId 成员,以便 NDIS 可以为特定协议绑定提供状态指示。 

处理协议驱动程序中的 PnP 事件通知

除了特定于 NDIS 6.0 及更高版本的事件通知外,NDIS 6.0 及更高版本的协议驱动程序还处理与 NDIS 5.x 驱动程序相同的即插即用 (PnP) 事件通知。 PnP 事件通知的处理特定于驱动程序。

为了通知协议驱动程序网络 PnP 事件,NDIS 调用驱动程序的 ProtocolNetPnPEvent 函数。 为了定义事件的类型和事件特征,NDIS 在 ProtocolNetPnPEvent 的 NetPnPEvent 事件参数中传递NET_PNP_EVENT_NOTIFICATION结构。

协议驱动程序应处理驱动程序堆栈更改。 不处理堆栈更改通知的协议驱动程序将从适配器取消绑定并反弹。 成功处理驱动程序堆栈通知的协议驱动程序绑定不受影响。

协议驱动程序中的可分页和可丢弃代码

驱动程序开发人员应尽可能将代码指定为可分页代码,为必须驻留在内存中的代码释放系统空间。 可以使用 NDIS_PAGEABLE_FUNCTION 宏将函数标记为可分页。 函数的 IRQL、资源管理功能和其他特征可能会禁止该函数可分页。

每个 ProtocolXxx 函数在 IRQL 上运行,范围从 PASSIVE_LEVEL 到 DISPATCH_LEVEL。 以 IRQL = PASSIVE_LEVEL 独占方式运行的函数应标记为可分页。

只要在 IRQL = PASSIVE_LEVEL 上运行的驱动程序函数既不调用也不由在 IRQL >= DISPATCH_LEVEL运行的任何函数(例如获取旋转锁的函数)调用,就可以使该函数可分页。 获取旋转锁会导致获取线程的 IRQL 提升为DISPATCH_LEVEL。 在 IRQL = PASSIVE_LEVEL运行的驱动程序函数(如 ProtocolBindAdapterEx)不得调用在 IRQL >= DISPATCH_LEVEL下运行的任何 NdisXxx 函数(如果该驱动程序函数被标记为可分页代码)。 有关每个 NdisXxx 函数的 IRQL 的详细信息,请参阅 NDIS 库函数。

应使用 NDIS_INIT_FUNCTION 宏将 NDIS 协议驱动程序的 DriverEntry 函数以及仅从 DriverEntry 调用 的代码 指定为仅初始化代码。 假定使用此宏标识的代码在系统初始化时只运行一次,因此,仅在该时间内映射代码。 在标记为“仅初始化”的函数返回后,该函数将被丢弃。

协议驱动程序重置操作

协议驱动程序无法在 NDIS 6.0 及更高版本中启动重置操作。

通常,基础微型端口驱动程序会重置 NIC,因为 NIC 在发送或请求操作期间超时。 此条件导致 NDIS 调用微型端口驱动程序的 MiniportCheckForHangEx 和随后 的 MiniportResetEx 函数。 或者,微型端口驱动程序确定 NIC 的接收功能功能失调。

如果重置由 NDIS 启动, 并且 MiniportResetEx 返回NDIS_STATUS_PENDING,则 NDIS 调用每个绑定协议驱动程序的 ProtocolStatusEx (或 ProtocolCoStatusEx) 函数,其状态为 NDIS_STATUS_RESET_START。 当微型端口驱动程序调用 NdisMResetComplete 时,NDIS 会再次调用 ProtocolStatusEx (或 ProtocolCoStatusEx) ,其状态为 NDIS_STATUS_RESET_END。

协议驱动程序必须处理在绑定到基础 NIC 上的未完成发送可以取消的可能性,因为 NIC 已重置。 如果绑定的协议驱动程序有任何挂起的传输请求,NDIS 将指示以适当的状态向协议驱动程序发送完成。 当重置操作完成后,协议驱动程序必须重新提交发送请求,前提是 NIC 再次正常运行。

当协议驱动程序收到NDIS_STATUS_RESET_START状态时,它应:

保留已准备好传输的任何网络数据 ,直到协议 Status 收到NDIS_STATUS_RESET_END通知。

不进行任何定向到基础微型端口驱动程序的 NDIS 调用,但返回资源(如使用 NdisReturnNetBufferLists 返回网络数据)的调用除外。

ProtocolStatusEx (或 ProtocolCoStatusEx) 收到NDIS_STATUS_RESET_END消息后,协议驱动程序可以继续发送网络数据和 OID 请求。

处理协议驱动程序中的 PnP 事件和电源管理事件

当操作系统向表示网络接口卡 (NIC) 的目标设备对象发出即插即用 (PnP) I/O 请求数据包 (IRP) 或电源管理 IRP 时,NDIS 会截获该 IRP。 NDIS 通过调用驱动程序的 ProtocolNetPnPEvent 函数,向每个绑定协议驱动程序和每个绑定中间驱动程序指示事件。 在对 ProtocolNetPnPEvent 的调用中,NDIS 传递指向包含NET_PNP_EVENT结构的 NET_PNP_EVENT_NOTIFICATION 的指针。 NET_PNP_EVENT结构描述要指示的 PnP 事件或电源管理事件。 有关协议驱动程序 PnP 接口的详细信息,请参阅 处理协议驱动程序中的 PnP 事件通知。

以下列表包含 PnP 和电源管理事件,如 NET_PNP_EVENT 结构中的 NetEvent 代码所示:

NetEventSetPower: 指示设置电源请求,该请求指定微型端口适配器应转换为特定电源状态。 电源管理感知协议驱动程序应始终通过返回NDIS_STATUS_SUCCESS成功此事件。 旧的协议驱动程序可以返回NDIS_STATUS_NOT_SUPPORTED,以指示 NDIS 应将其与微型端口适配器取消绑定。

发出设置电源请求后,如果微型端口适配器正在转换为低功耗状态,NDIS 将暂停驱动程序堆栈。 如果微型端口适配器正在转换为工作状态 (D0) ,则在设置电源请求之前,NDIS 会重启驱动程序堆栈。 

如果微型端口适配器处于低功耗状态,则协议驱动程序无法发出任何 OID 请求。 此要求是额外的电源管理限制,在驱动程序堆栈处于“已暂停”状态时,将添加到其他限制中。

如果基础微型端口适配器无法识别电源管理,微型端口驱动程序会将NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES的 PowerManagementCapabilities 成员设置为 NULL,NDIS 将 NDIS_BIND_PARAMETERS 的 PowerManagementCapabilities 成员设置为 NULL。

注意 从 NDIS 6.30 开始,在收到此事件的通知后,协议驱动程序必须停止生成新的 I/O 请求,并且不应等待调用 ProtocolNetPnPEvent 的上下文中任何挂起的 I/O 请求完成。

NetEventQueryPower:指示查询电源请求,该请求查询基础微型端口适配器是否可以转换到特定电源状态。 协议驱动程序应始终成功 NetEventQueryPower 。 建立活动连接后,协议驱动程序可以调用 PoRegisterSystemState 来注册连续忙状态。 只要状态注册生效,电源管理器就不会尝试使系统进入睡眠状态。 连接变为非活动状态后,协议驱动程序通过调用 PoUnregisterSystemState 取消状态注册。 协议驱动程序绝不应尝试通过使 NetEventQueryRemoveDevice 失败来阻止系统转换到睡眠状态。 请注意, NetEventQueryPower 始终后跟 NetEventSetPower。 设置设备当前电源状态的 NetEventSetPower 将取消 NetEventQueryPower。

注意 从 NDIS 6.30 开始,在收到此事件的通知后,协议驱动程序不应在调用 ProtocolNetPnPEvent 的上下文中等待任何挂起的 I/O 请求完成。

NetEventQueryRemoveDevice:指示查询删除设备请求,该请求查询是否可以在不中断操作的情况下删除 NIC。 例如,如果协议驱动程序无法释放设备 (因为设备正在使用) ,则必须通过返回NDIS_STATUS_FAILURE来使 NetEventQueryRemoveDevice 失败。

NetEventCancelRemoveDevice:指示取消删除设备请求,该请求取消删除基础 NIC。 协议驱动程序应始终通过返回NDIS_STATUS_SUCCESS成功此事件。

NetEventReconfigure:指示网络组件的配置已更改。 例如,如果用户更改 TCP/IP 的 IP 地址,NDIS 会使用 NetEventReconfigure 代码向 TCP/IP 协议指示此事件。 在极少数情况下,如果协议驱动程序无法应用指示的配置更改并且没有可用的默认值,则可能会返回失败代码。 分配内存的失败尝试是协议返回失败代码的一个示例。 返回错误代码可能会导致提示用户重启系统。协议应验证传递给其 ProtocolNetPnPEvent 函数的 NetEventReconfigure 相关数据。 

NetEventBindList:向协议驱动程序指示其绑定列表处理顺序已重新配置。 此列表指示在处理时应用于协议绑定的相对顺序,例如,可能路由到多个绑定之一的用户请求。 随此事件一起传递的缓冲区包含以 NULL 结尾的 Unicode 字符串格式的设备名称列表。 每个设备名称的格式与传递给 ProtocolBindAdapterEx 调用的 DeviceName 参数相同。协议应验证传递给其 ProtocolNetPnPEvent 函数的 NetEventBindList 相关数据;协议应验证传递给其 ProtocolNetPnPEvent 函数的 NetEventBindList 相关数据。 

NetEventBindsComplete:指示协议驱动程序已绑定到它可以绑定到的所有 NIC。 除非将 PnP NIC 插入系统,否则 NDIS 不会指示与协议驱动程序的更多绑定。

NetEventPnPCapabilities:指示用户启用或禁用基础适配器的唤醒功能。 NDIS 传递给 ProtocolNetPnPEvent 的 ProtocolBindingContext 参数指定绑定。

NetEventPause:指示指定的协议绑定应进入暂停状态。 NDIS 完成绑定的所有未完成发送请求后,绑定将进入“已暂停”状态。

NetEventRestart:指示指定的协议绑定已进入“正在重启”状态。 协议驱动程序准备好恢复绑定的发送和接收操作后,绑定将进入“正在运行”状态。 

NetEventPortActivation: 指示激活与指定绑定关联的端口列表。 

NetEventPortDeactivation:指示停用与指定绑定关联的端口列表。 

NetEventIMReEnableDevice:指示已更改 NDIS 6.0 或更高版本中间驱动程序的虚拟微型端口的配置。 NetEventIMReEnableDevice 类似于 NetEventReconfigure 事件,不同之处在于中间驱动程序接收单个虚拟微型端口的此事件, NetEventReconfigure 事件应用于所有中间驱动程序的虚拟微型端口。 例如,当用户禁用然后从设备管理器或其他源启用单个虚拟微型端口时,中间驱动程序会收到 NetEventIMReEnableDevice 事件。

NET_PNP_EVENT 结构的 Buffer 成员指向包含特定于所指示事件的信息的缓冲区。

协议驱动程序可以使用 NdisCompleteNetPnPEvent 异步完成对 ProtocolNetPnPEvent 的调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1710607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java-文件操作

一、创建文件 1.创建文件夹 创建文件夹时,注意两个条件,该路径对应的是否为目录(dir),该文件夹是否存在。 File Apathnew File("./文件夹A"); //当前路径文件夹的存储路径if(!Apath.exists() &&am…

【研0深度学习】李宏毅2024春《生成式人工智能导论》持续更新...

文章目录 第1讲 什么是生成式人工智慧?第2讲 今日的生成式人工智慧厉害在哪里?第3-5讲 训练不了人工智慧,你可以训练你自己(在不训练模型的情况下强化语言模型的方法)第6讲 大模型修炼史——第一阶段 自我学习 累计实力…

ROS2入门21讲__第08讲__话题:节点间传递数据的桥梁

目录 前言 通信模型 发布/订阅模型 多对多通信 异步通信 消息接口 案例一:Hello World话题通信 运行效果 发布者代码解析 程序实现 流程总结 订阅者代码解析 程序实现 流程总结 案例二:机器视觉识别 运行效果 发布者代码解析 订阅者代…

WebGL学习(一)渲染关系

学习webgl 开发理解渲染关系是必须的,也非常重要,很多人忽视了这个过程。 我这里先简单写一下,后面尽量用通俗易懂的方式,举例讲解。 WebGL,全称Web Graphics Library,是一种在网页上渲染3D图形的技术。它…

FPGA时钟:驱动数字逻辑的核心

一、引言 在FPGA(现场可编程门阵列)设计中,时钟信号是不可或缺的关键要素。时钟信号作为时序逻辑的心跳,推动着FPGA内部各个存储单元的数据流转。无论是实现复杂的逻辑运算还是处理高速数据流,都需要精确的时钟信号来保…

CASS11自定义宗地图框

1、找到CASS11的安装路径,找到如下文件夹: 2、打开【report】文件夹,如下: 3、打开其中一个压缩包,如【标准宗地图】压缩包,结果如下: 4、打开后,将其另存为到桌面,随后关…

Leetcode621. 任务调度器

Every day a Leetcode 题目来源:621. 任务调度器 类似题目:1953. 你可以工作的最大周数 解法1:贪心 本质上来说,我们需要构造一个尽量短的,相同元素间隔 > (n1) 的序列。 用一个数组 cnt 统计每个任务的次数。…

Oracle创建用户时提示ORA-65096:公用用户名或角色名无效

Oracle创建用户时提示“ORA-65096:公用用户名或角色名无效” 如下图所示: 解决方法:在新增用户名前面加上C##或者c##就可以解决无效问题,具体什么原因还不清楚,需要再研究一下。

Discourse 安装后安全配置考虑

防火墙 防火墙是肯定要装机器上的,并且端口只开放了 443 和 22。 22 的端口还只限制了部分 IP 段的访问,通常只允许给内部网络的 SSH。 Web 服务应该只走 443,80 端口的做好自动重定向到 443。 CloudFlare 可以用一个 CloudFlare 的负载…

行为设计模式之状态模式

文章目录 概述定义结构图 2.代码示例小结 概述 定义 状态模式(state pattern)的定义: 允许一个对象在其内部状态改变时改变它的行为。 对象看起来似乎修改了它的类。 状态模式就是用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题.。状态模式将一个对象的状态…

QtCreator调试运行工程报错,无法找到相关库的的解决方案

最新在使用国产化平台做qt应用开发时,总是遇到qtcreator内调试运行 找不到动态库的问题,为什么会出现这种问题呢?明明编译的时候能够正常通过,运行或者调试的时候找不到相关的库呢?先说结论,排除库本身的问…

基于tensorflow的咖啡豆识别

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 一、前期工作 1. 设置GPU import tensorflow as tfgpus tf.config.list_physical_devices("GPU")if gpus:tf.config.experimental.set_memory_gr…

远程桌面连接--“发生身份验证错误。要求的函数不受支持”

出现身份验证错误 要求的函数不受支持的问题,可以通过以下几种方法尝试解决:12 对于Windows 10家庭版用户,需要修改注册表信息。具体步骤如下: 按下WIN R,输入regedit,点击确定,打开注册表编辑…

openresty(Nginx) 隐藏 软包名称及版本号 升级版本

1 访问错误或者异常的URL 2 修改配置,重新编译,升级 #修改版本等 vim ./bundle/nginx-1.13.6/src/core/nginx.h #define nginx_version 1013006 #define NGINX_VERSION "1.13.6" #define NGINX_VER "openresty/&q…

python中的-1是什么意思

python中的-1是什么意思? -1指的是索引,即列表的最后一个元素。 比如你输入一个列表: a = [1,2,3,4,5,6,7] a[-1]就代表索引该列表最后一个值,你可以 b a[-1] print(b) 结果如下: 7 索引从左往右是…

5.28学习总结

java复习总结 hashcode()和equals() hashcode():在Object里这个方法是通过返回地址的整数值来生成哈希值。 equals():在Object里这个方法是通过比较他们的内存地址来确定两个对象是否相同。 运行效率:hashcode的时间复杂度为O(1)(因为只要计算一次哈…

SpringCloud之SSO单点登录-基于Gateway和OAuth2的跨系统统一认证和鉴权详解

单点登录(SSO)是一种身份验证过程,允许用户通过一次登录访问多个系统。本文将深入解析单点登录的原理,并详细介绍如何在Spring Cloud环境中实现单点登录。通过具体的架构图和代码示例,我们将展示SSO的工作机制和优势&a…

mysql 8 [HY000][1114] The table ‘/tmp/#sql4c3_3e5a0_2‘ is full

分组有个比较大的表,出现了临时表空间满了的情况; 试用该sql 语句: SHOW GLOBAL VARIABLES LIKE internal_tmp_mem_storage_engine; 可以看到 默认临时结果是用临时表存的,在mysql的my.cnt可以改临时空间的大小 但是磁盘哪有内…

2、python环境的安装-mac系统下

打开官网,downloads下边有macOS,点击: 选择最新版本,点击,进入下边的页面,一直往下滑,看到files中有个macOS的版本,点击下载 点击下载后是pkg的安装包,点击安装。 一步步…

浙江大学数据结构MOOC-课后习题-第九讲-排序3 Insertion or Heap Sort

题目汇总 浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024 题目描述 测试点 思路分析 和上一题的思路一样&#xff0c;每进行一次迭代&#xff0c;来验证当前序列是否和给定的序列相同 代码展示 #include <cstdlib> #include <iostream> #define MAXSIZE 10…