




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
构造一个简单的USB过滤驱动程序 本文分三部分来介绍如何构造一个简单的USB过滤驱动程序,包括“基本原理”、“程序的实现”、 “使用INF安装”。此文的目的在于希望读者了解基本原理后,可以使用除DDK以外最流行也最方便的驱动开发工具DriverStudio来实现一个自己的过滤驱动,并正确地安装。一、基本原理 我们知道,WDM(和KDM)是分层的,在构造设备栈时,IO管理器可以使一个设备对象附加到另外一个初始驱动程序创建的设备对象上。与初始设备对象相关的驱动程序决定的IRP,也将被发送到附加的设备对象相关的驱动程序上。这个被附加的驱动程序便是过滤驱动程序。如右图,过滤驱动可以在设备栈的任何层次中插入。IO管理器发出的IRP将会沿着右图的顺序从上往下传递并返回。因此,我们可以使用过滤驱动程序来检查、修改、完成它接收到的IRP,或者构造自己的IRP。 上面这种文字是很枯燥的,好在“前人”已经写过一些范例以供我们更好地理解这些概念。读过Waltz Oney的Programming Windows Driver Mode一书的读者大概都知道Waltz Oney提供的范例中有一个关于USB过滤器(第九章)的例子,而在此基础上,USB Design By Example ()的作者John Hyde实现了一个USB键盘过滤驱动程序,即给此程序增加了一个“拦截(Intercept)”功能来处理USB键盘的Report以实现特定的功能:当驱动程序在 IRP_MJ_INTERNAL_DEVICE_CONTROL设置的完成例程从USB设备拦截到一个Get_Report_Descriptor时,拦截程序将此Descriptor中的USAGE值从“Keyboard”改为“UserDefined”,再返回给系统。我们可以从这个例子中获得一些灵感,比如,在Win2k下,键盘是由OS独占访问的,我们可以通过这种方式使之可以让用户自由访问;我们也可以拦截其他 Report_Descriptor,将部分键重新定义,以满足特殊的要求;如果你愿意再做一个用户态的程序,你还可以将你拦截到的键值传递给你的用户态程序,以实现象联想、实达等国内电脑大厂出品的那些键盘上的各种实用的功能。二、程序的实现 Waltz Oney和John Hyde的例子已经写得很详细了,读者可以不用修改一个字节便顺利地编译生成一个过滤驱动程序。本文的目的在于使用DriverStudio组件Driverworks来实现同样的功能。 相信读者读到这篇文章时,已经对DriverStudio有了很多的了解。DriverStudio作为一个以C+为基础的“快速”驱动开发工具,它封装了基本上所有的DDK的函数,其集成在VC+中的DriverWizard,可以很方便地引导你完成设备驱动程序开发的全过程,能根据你的硬件种类自动生成设备驱动程序源代码,并提供了很多范例程序。当然,这些例子中便包含一个USB Filter驱动程序的框架。在不侵犯版权的前提下,充分利用现有共享的、免费的、授权的代码是我们的一贯作法。我们下面便以此范例为基础来作修改。我们的目的是做一个HID小驱动程序hidusb.sys的 Lower Filter,它附加在“人机接口设备” ,通过拦截USB的Get_Report_Descriptor来修改其返回值,当它发现该 Descriptor的Usage 为“Keyboard”时,将其改为“UserDefined”,如此我们便可以完全控制这只键盘。具体做法是,拦截 IRP_MJ_INTERNAL_DEVICE_CONTROL,并检查其IOCTL代码及URB,如果满足IOCTRL功能代码为 IOCTL_INTERNAL_USB_SUBMIT_URB以及URB功能代码为 URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE的条件,即上层驱动发来 Get_Report_Descriptor请求时,设置一个完成例程,在这个完成例程中,我们将判断Usage的值,将Usage由“6 (Keyboard)”时,将其改为“0(UserDefined)”。打开C:Program FilesNuMega DriverStudioDriverWorksExampleswdmusbfilt目录(具体目录依你的DriverStudio所安装的目录不同而不同) ,再打开工程文件usbfilt.dsw,我们先看一下代码。程序由两个类组成,一个是Driver类,一个是Device类。Driver类包括: 入口函数DriverEntry:DECLARE_DRIVER_CLASS(UsbFilterDriver, NULL)/ Driver Entry/NTSTATUS UsbFilterDriver:DriverEntry(PUNICODE_STRING RegistryPath) T UsbFilterDriver:DriverEntryn; m_Unit = 0; return STATUS_SUCCESS; / The following macro simply allows compilation at Warning Level 4 / If you reference this parameter in the function simply remove the macro. UNREFERENCED_PARAMETER(RegistryPath); AddDevice函数NTSTATUS UsbFilterDriver:AddDevice(PDEVICE_OBJECT Pdo) T UsbFilterDriver:AddDevicen; UsbFilterDevice * pFilterDevice = new ( static_cast(NULL), FILE_DEVICE_UNKNOWN, static_cast(NULL), 0, DO_DIRECT_IO ) UsbFilterDevice(Pdo, m_Unit); if (pFilterDevice) NTSTATUS status = pFilterDevice-ConstructorStatus(); if ( !NT_SUCCESS(status) ) T Failed to construct UsbFilterDevice (ULONG) m_Unit status = status n; delete pFilterDevice; else m_Unit+; return status; else T Failed to allocate UsbFilterDevice (ULONG) m_Unit n; return STATUS_INSUFFICIENT_RESOURCES; 这两段代码基本上和自动生成的代码差不多。AddDevice的作用是构造一个过滤器的实例。关键的代码在Device类。在这个类里,我们把过滤器插入设备栈,并拦截IRP,用自己的完成例程来实现特定的功能。Device构造函数UsbFilterDevice:UsbFilterDevice(PDEVICE_OBJECT Pdo, ULONG Unit) : KWdmFilterDevice(Pdo, NULL) T UsbFilterDevice:UsbFilterDevicen; / Check constructor status if ( ! NT_SUCCESS(m_ConstructorStatus) ) return; / Remember our unit number m_Unit = Unit; / initialize the USB lower device m_Usb.Initialize(this, Pdo); NTSTATUS status = AttachFilter(&m_Usb); /Attach the filter if(!NT_SUCCESS(status) m_ConstructorStatus = status; return; SetFilterPowerPolicy(); SetFilterPnpPolicy();在DDK 中,我们用IoAttachDevice将设备对象插入设备栈中。DriverStudio封装了这个函数。在DriverStudio中,其他驱动程序需要用Initialize来初始化设备对象和接口,对于过滤驱动,我们关键是需要Attachfilter将其附加在堆栈中。对于大部分如IRP_MJ_SYSTEM_CONTROL等IRP,我们所做的只需用PassThrough(Irp)将其直接往设备栈下层传递,不需要做任何工作。这些代码我们就不一一列举了。下面的部分才是本文的关键。 我们知道,HIDUSB.SYS是使用内部IOCTRL发出URB给USB类驱动程序(USBD)读取数据的,那么,HIDUSB首先必须构造一个 IRP_MJ_INTERNAL_DEVICE_CONTROL,它的IOCTL功能码为IOCTL_INTERNAL_USB_SUBMIT_URB (发出URB的内部IOCTL)。另外,因为我们要检查并修改的是USB键盘某个接口的报告描述,那么这个URB应该是 URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE,如下:NTSTATUS UsbFilterDevice:InternalDeviceControl(KIrp I) T UrbHeader.Function != URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE) return DefaultPnp(I);/符合要求的IRP才被设置完成例程 return PassThrough(I, LinkTo(DeviceControlComplete), this);在设置好条件以后,再来实现完成例程。所有的检查、修改等动作都是在完成例程里面完成的。NTSTATUS UsbFilterDevice:DeviceControlComplete(KIrp I) PURB p = I.Urb(CURRENT); if(p) /拦截到设备返回的描述表, char* DescriptorBuffer = (char*)p-UrbControlDescriptorRequest.TransferBuffer;/指向第三个字节,表示设备Usage属性的值 DescriptorBuffer += 3;/如果值为6则改成0,6表示hid键盘,0表示未知设备/在设备管理器里面,原来的hid兼容键盘就不复存在了,取而代之的则是hid兼容设备 if (*DescriptorBuffer&0xff) = 6) *DescriptorBuffer = 0; return I.Status(); 读者可以对照DriverWorks中的例子,直接替换掉(或者修改)上面这两个函数,再编译一下,便可以得到一个完整的键盘过滤器驱动程序。其实,只要弄清楚了我们需要做些什么动作,在DriverStudio里面只需要写少量的关键代码,便可实现我们的要求,其余的大部分工作,或有范例可供参考,或有Driver Wizard自动生成。 从上面可以看出,我们只需要修改这两个函数,拦截合适的IRP,便可以在完成例程里面实现我们特定的要求。正如开头所说,我们也可以拦截其他的IRP,拦截其他的URB,或者拦截特定键盘的按键键值,将之传递到用户态,以方便实现联想、实达等随机配备的多功能键盘的功能。三、使用INF安装驱动 在完成了驱动以后,还必须把它安装到系统里面,驱动程序才会起作用。一般来说,我们都必须为我们的驱动程序提供一个inf文件,以便于用户安装或者维护。对于新手来说,过滤驱动程序的inf或许有些棘手。所以,针对本文所描述的驱动,我们提供一个Win98下的安装范例usbkey.inf,范例中“;” 后的文字是注解,以方便读者理解。; usbkey.INF ; Installs Lower Level Filter for a HID keyboard device; (c) Copyright 2001 SINO Co., Ltd.; Version;”CHICAGO”表示Win9x平台Signature=$CHICAGO$;键盘所属类名Class=HIDClassGUID=745a17a0-74d3-11d0-b6fe-00a0c90f57da;驱动程序提供者,此信息会显示在设备属性的“常规”页Provider=%USBDBE%LayoutFile=layout.inf;显示在驱动程序文件详细资料窗口DriverVer=11/12/2001,4.10.2222.12;ControlFlags;ExcludeFromSelect = *;驱动程序安装目录,inf会将我们的驱动程序安装到如下目录;记得Destinationdir后面一定要带一个“s”DestinationDirsDefaultDestDir = 10,system32drivers;要增加的注册表项ClassInstallAddreg=HIDClassRegHIDClassRegHKR,%HID.ClassName%HKR,Icon,-20;制造商Manufacturer%USBDBE%=USBDBEUSBDBE;我们所要附加过滤驱动程序的设备ID。这个ID可以从IC的规范上得来,也可以;用hidview.exe读出,或者从注册表HKLMEnumhid和usb项找出%HID.DeviceDesc% = Keypad_Inst, USBVID_05AF&PID_0805&MI_00;要安装的文件和需要修改的注册表项;Install usbkey driverKeypad_InstCopyFiles=Keypad_Inst.CopyFilesAddReg=Keypad_Inst.AddRegKeypad_Inst.CopyFileshidusb.syshidparse.syshidclass.sysusbfilt.sysKeypad_Inst.AddRegHKR,DevLoader,*ntkernHKR,NTMPDriver,hidusb.sysKeypad_Inst.HWAddReg=Keypa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年XX专业AI应用师认证考试预测题
- 2025年中国香文化中级水平测试试题集萃及解析
- 2025年内蒙古公务员遴选考试面试评分标准和注意事项
- 大班春季班级班务工作计划
- 2025年中国华能集团越南分公司招聘考试复习题库
- 2025年专业资料工业厂区安全员招聘考试模拟试题
- 2025年安装工程造价案例分析面试题集
- 语文5年级上册期末冲刺计划
- 2025年医疗器械网络安全检查总结范文
- 人教版八年级英语期末冲刺计划
- 新生儿气管导管滑脱的应急预案及处理流程
- 建筑模型设计与制作(第三版)
- 部编版一年级语文上册全册教案(表格)
- 商品精修教案项目5服装精修
- 小升初简历模板2020免费
- 19-雾在哪里ppt市公开课金奖市赛课一等奖课件
- 金融统计分析教材课件
- 《社会主义核心价值观》优秀课件
- DDI定向井难度系数
- 河南省家庭经济困难学生认定申请表
- 电催化精品课件
评论
0/150
提交评论