当前位置: 首页 > news >正文

过滤的基本概念

过滤的基本概念

无论是NT式驱动还是WDM式驱动,都可以看作是分层调用的。这里的分层有两个含义:

  • 垂直的
  • 水平的

垂直结构

这是和过滤息息相关的结构。从第一张图片中可以看到,设备对象中有一个AttachedDevice子域,有它可以找到一个设备对象的上层对象。

通过这样层层的附加,就形成了一个类似栈的结构,我们把这个栈结构称之为设备栈,其中的StackSize表示从本层设备设备对象到最底层设备的距离。

那么我们如何将一个设备对象附加到另一个设备对象上呢?通过IoAttachDeviceToDeviceStack函数就可以做到。

IoAttachDeviceToDeviceStack

PDEVICE_OBJECTIoAttachDeviceToDeviceStack(IN PDEVICE_OBJECT SourceDevice,IN PDEVICE_OBJECT TargetDevice);

该函数将TargetDevice对象的AttachedDevice子域指向SourceDevice对象,并且总是将SourceDevice附加到TargetDevice所在设备栈中对顶层的设备对象上,同时返回TargetDevice所在设备栈中最顶层的那个设备对象指针(SourceDevice附加之前)。

通常,我们将该函数返回的设备对象放在SourceDevice的拓展域中,这样,就形成了拓展域、AttachedDevice这样的双链表结构,便于我们传递IRP。

水平结构

水平结构比较好理解,我们使用IoCreateDevice函数创建设备对象时,该函数就会根据参数中的驱动对象自动完善这个单链表结构。

示例代码

#include<ntddk.h>#defineNTSTRSAFE_LIB#include<ntstrsafe.h>#ifndefSetFlag// 定义设置标志位的宏#defineSetFlag(_F,_SF)((_F)|=(_SF))#endif#ifndefClearFlag// 定义清除标志位的宏#defineClearFlag(_F,_SF)((_F)&=~(_SF))#endif#defineCCP_MAX_COM_ID32// 最大串口数量staticPDEVICE_OBJECT s_fltobj[CCP_MAX_COM_ID]{0};staticPDEVICE_OBJECT s_nextobj[CCP_MAX_COM_ID]{0};PDEVICE_OBJECTccpOpenCom(IN ULONG id,OUT NTSTATUS*status){UNICODE_STRING name_str;staticWCHAR name[32]={0};// 初始化设备的名字memset(name,0,sizeof(WCHAR)*32);RtlStringCchPrintfW(name,32,L"\\Device\\Serial%d",id);RtlInitUnicodeString(&name_str,name);PFILE_OBJECT fileobj=NULL;PDEVICE_OBJECT devobj=NULL;// 从名字获取设备对象*status=IoGetDeviceObjectPointer(&name_str,// 设备的名字FILE_ALL_ACCESS,// 期望的权限&fileobj,// 返回的文件对象,必须把这个文件对象解除引用&devobj// 需要得到的设备对象);returndevobj;}// 附加到设备上NTSTATUSccpAttachDevice(PDRIVER_OBJECT driver,PDEVICE_OBJECT oldobj,PDEVICE_OBJECT*fltobj,PDEVICE_OBJECT*next){NTSTATUS status;PDEVICE_OBJECT topdev=NULL;// 创建一个过滤设备status=IoCreateDevice(driver,0,NULL,oldobj->DeviceType,0,FALSE,fltobj);if(status!=STATUS_SUCCESS){returnstatus;}// 拷贝重要标志位if(oldobj->Flags&DO_BUFFERED_IO)(*fltobj)->Flags|=DO_BUFFERED_IO;if(oldobj->Flags&DO_DIRECT_IO)(*fltobj)->Flags|=DO_DIRECT_IO;if(oldobj->Flags&DO_BUFFERED_IO)(*fltobj)->Flags|=DO_BUFFERED_IO;if(oldobj->Characteristics&FILE_DEVICE_SECURE_OPEN)(*fltobj)->Characteristics|=FILE_DEVICE_SECURE_OPEN;(*fltobj)->Flags|=DO_POWER_PAGABLE;// 将过滤设备绑定到另一个设备上,如果目标设备已经被绑定了,则默认绑定到最上层设备上// 返回值是最终被绑定的设备指针topdev=IoAttachDeviceToDeviceStack(*fltobj,oldobj);if(topdev==NULL){IoDeleteDevice(*fltobj);*fltobj=NULL;status=STATUS_UNSUCCESSFUL;returnstatus;}*next=topdev;(*fltobj)->Flags=(*fltobj)->Flags&~DO_DEVICE_INITIALIZING;returnSTATUS_SUCCESS;}// 该函数绑定所有串口voidccpAttachAllComs(PDRIVER_OBJECT driver){PDEVICE_OBJECT com_ob;// 表示串口设备NTSTATUS status;for(ULONG i=0;i<CCP_MAX_COM_ID;i++){com_ob=ccpOpenCom(i,&status);if(com_ob==NULL){continue;}// 绑定串口ccpAttachDevice(driver,com_ob,&s_fltobj[i],&s_nextobj[i]);}}#defineDELAY_ONE_MICROSECOND(-10)#defineDELAY_ONE_MILLISENCOND(DELAY_ONE_MICROSECOND*1000)#defineDELAY_ONE_SECOND(DELAY_ONE_MILLISENCOND*1000)voidccpUnload(PDRIVER_OBJECT driver){for(ULONG i=0;i<CCP_MAX_COM_ID;i++){if(s_nextobj[i]!=NULL)IoDeleteDevice(s_nextobj[i]);}LARGE_INTEGER interval;interval.QuadPart=(5*1000*DELAY_ONE_MILLISENCOND);KeDelayExecutionThread(KernelMode,FALSE,&interval);}NTSTATUSccpDispatch(PDEVICE_OBJECT device,PIRP pIrp){PIO_STACK_LOCATION irpsp=IoGetCurrentIrpStackLocation(pIrp);NTSTATUS status;for(ULONG i=0;i<CCP_MAX_COM_ID;i++){}}NTSTATUSDriverEntry(PDRIVER_OBJECT driver,UNICODE_STRING RegPath){// 设置分发函数for(size_t i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++){driver->MajorFunction[i]=ccpDispatch;}driver->DriverUnload=ccpUnload;ccpAttachAllComs(driver);returnSTATUS_SUCCESS;}

上面的代码创建了一个具有2层垂直高度、CCP_MAX_COM_ID宽的设备对象树结构。上面的代码使用了s_nextobj数组来维护水平结构的关系。

http://www.jsqmd.com/news/538978/

相关文章:

  • UMLet高效绘图指南:从零开始掌握开源UML工具
  • Qwen3-ForcedAligner-0.6B效果展示:会议记录中决策关键词毫秒级定位截图
  • 如何利用PCA与t-SNE技术提升YOLO目标跟踪的特征降维效果
  • DCT-Net模型服务治理:Spring Cloud集成
  • 新手也能懂:用VMware搭建多网段VPC靶场,复现内网渗透实战(附完整网络配置清单)
  • 别再只会用print调试了!用ESP32的UART2做个串口日志模块,实时监控程序状态(MicroPython版)
  • pdf2htmlEX云成本优化:5个减少云服务支出的终极策略
  • brpc协程调度性能优化:揭秘任务窃取与负载均衡机制
  • FanControl深度指南:重新定义电脑散热系统的智能控制
  • APKMirror:安卓应用安全管理的终极解决方案
  • League-Toolkit:提升英雄联盟游戏体验的智能工具集
  • 如何为你的单片机项目选择最佳通信协议?I²C、SPI、UART全解析
  • 信管毕业设计创新的课题建议
  • ESP8266 AT指令实现Modbus TCP从站的轻量级方案
  • Prothrombin重组兔单抗如何提升凝血酶原检测的精准度与临床价值?
  • Qwen3-0.6B-FP8在.NET生态中的集成应用:开发C#客户端调用库
  • 安卓虚拟摄像头:解锁手机摄像头的无限创意可能
  • RVC训练避坑指南:logs与weights目录结构及模型识别
  • Windows Insider离线管理完全指南:无账户切换方法与命令行操作技巧
  • 别再只堆时间维度了!用X3D的坐标下降法,在低算力下也能高效提升视频动作识别准确率
  • LFM2.5-1.2B-Thinking-GGUF保姆级教程:Web界面汉化+响应式布局适配移动端指南
  • Crystals Kyber算法实战:5分钟搞定密钥封装机制(KEM)配置
  • 突破信息壁垒:bypass-paywalls-chrome-clean智能内容访问工具深度解析
  • 打破协议壁垒:BthPS3如何让PS3手柄在Windows上重生
  • 5分钟解锁AI浏览器自动化:用自然语言控制一切界面
  • ResNet18镜像对比评测:本地部署 vs 云端API,哪个更适合你?
  • 消费级显卡也能跑!cv_resnet101_face-detection_cvpr22papermogface GPU算力适配实战
  • 从 Prompt Engineering 到 Harness Engineering:AI 系统竞争,正在从“会写提示词”转向“会搭执行框架”
  • NEURAL MASK开源镜像升级指南:v2.0 Pro平滑迁移与模型热替换方案
  • 终极指南:如何快速突破Cursor AI编辑器试用限制的完整解决方案