精华内容
下载资源
问答
  • 鼠标驱动程序源代码,windows下WDM开发.zip
  • 入口DriverEntry和键盘过滤类似,在Attach鼠标驱动有些区别 直接上代码: 有个问题:加载鼠标过滤驱动后提示“”连接系统上的设备没有发挥作用“”-虽不影响使用但会影响过滤驱动的卸载,希望某天有大神求解

    入口DriverEntry和键盘过滤类似,在Attach鼠标驱动有些区别 

    直接上代码:


    有个问题:加载鼠标过滤驱动后提示“”连接系统上的设备没有发挥作用“”-虽不影响使用但会影响过滤驱动的卸载,希望某天有大神求解

    展开全文
  • by fanxiushu 2017-10-27 转载或引用请注明原始作者。...于是决定重新开发macbook pro 2017触摸板的windows驱动。 请稍后关注 GITHUB和CSDN提供的源代码和驱动程序。 如下连接, http://blog.csdn.net
                                                         by fanxiushu 2017-10-27 转载或引用请注明原始作者。


    做这个驱动,写这篇文章的目的就是因为macBook pro 2017版的触摸板在windows平台下难用,

    于是决定重新开发macbook pro 2017触摸板的windows驱动。

    已经开发好的驱动和源代码下载地址:

    GITHUB:   https://github.com/fanxiushu/kmouse_filter-AppleSPITrack-driver

    CSDN:   http://download.csdn.net/download/fanxiushu/10047600


    如下连接,
    http://blog.csdn.net/fanxiushu/article/details/78186745
    因为新近换的电脑是macbook pro 2017 13寸带bar的机器,其他还能将就,
    就是触摸板难用,动不动就弹出右键菜单,经常误触,
    而且尤其不爽的是拖动时候,必须按住边缘,另一只手指才能拖动,
    触摸板这么大,基本无法单手进行拖动操作,需要另一个手的手指按住触摸板边缘,然后拖动。
    虽然可以点击两次,第2次不离开触摸板来拖动,但是非常不习惯这种手势。
    还是习惯传统的食指按住触摸板,中指来拖动(因为这种手势更加接近按住鼠标左键移动鼠标的效果)。

    像我这种经常把电脑放到大腿上或者床上的人(反正就是不会老老实实的放到电脑桌上),
    如果带个鼠标是很不方便的,只能依赖触摸板来控制电脑。
    而且我的要求也不高,不需要什么多手势,只要触摸板能尽量模拟鼠标的效果就行了。
    其实个人觉得windows本身的易操作性,使用鼠标的效果就能控制操作系统的所有的东西了,
    手势多了我也记不住,每次切换不同手势还得思考一下也挺累(也许是还没习惯,也懒得去习惯了)。

    基于以上各种原因,于是决定重新开发这款电脑的触摸板驱动。
    首先解释一下“点按”和”轻点“:
    按住或重压,就是按下去,能听到“哒”的一声响;
    ”点按“就是“哒”的一声按下去然后立马弹上来,
    还有一个就是”轻点“,就是手指接触到触摸板然后迅速离开。

    我需要达到的效果也非常简单明了,用两根手指模拟鼠标效果,操作整个系统。
    1,首先一根手指按住触摸板的任意位置(是任意位置而不是触摸板边缘),另一根手指在触摸板上移动来达到拖动效果,
    这就相当于按住鼠标左键,移动鼠标的效果一样。
    2,一根手指轻点,相当于鼠标左键按下去然后立马弹上来。
         一根手指按住触摸板,相当于按下鼠标左键,从触摸板弹上来相当于弹出左键。
    3,两根手指同时轻点,相当于鼠标右键按下去然后立马弹上来。
         一根手指按住触摸板右边四分之三到四分之四部分(是整个右边3/4,而不是右下边缘),相当于按住鼠标右键。
    4,两根手指同时在触摸板移动,相当于滚轮滚动。
    5,另外再附加实现一个功能:三指拖移。等于是第1个功能的效果:一个手指按住,另一个手指移动。
          这样不重压触摸板的也能操作整个系统。

    不模拟鼠标的中间键按下效果,好像中间键没啥用处。

    以上就是我的简单明了的要求,当然习惯各种手势的你可能并不赞同,甚至有点嗤之以鼻,然而这依然是我的简单明了的要求。
    重新开发的触摸板驱动也只实现上边的功能而已。

    要重新开发macbook pro 2017年 13寸带bar(以下简称mbp2017)的触摸板的windows驱动,
    首先需要解决两件事:
    一,采集mbp2017的触摸板数据,
    二,模拟开发鼠标驱动。
    第二个问题100%的确保能解决,使用HID模式的鼠标驱动就可以了。
    关键是第一个问题,如果不能采集和解析触摸板的数据,基本就没戏了,只能老老实实的使用那个难用的原装驱动程序。
    mbp2017的触摸板数据结构格式是没有公开的,而且未来也很可能被苹果公司改变,因此没有通用性,
    我测试的对应bootcamp版本是 6.1.6813,对应的触摸板总线驱动的驱动日期是 2016/05/26, 版本 6.1.6500.0,
    其他版本的没测试过,所以不知道的数据格式是不是不同。

    既然这个数据没有公开,我们就必须要自己来采集和分析触摸板的数据,
    好在触摸板这类设备本身的数据量不大,数据结构也应该不会多复杂,只要Apple公司没变态到做加密,估计是能解析出来的。
    自己动手解析之前,先要搞清楚它的驱动运行流程。
    苹果使用的SPI总线来传输触摸板和键盘的数据,SPI总线接口,也是我在接触mbp2017时候才发现还有这么一个玩意,真是孤陋寡闻了。
    SPI 全称Serial Peripheral Interface--串行外设接口, 最初是Motorola提出和开发的,它使用主从模式通讯,这点跟USB有点像,
    同时通讯也很简单,比RS232(串口)还简单,所以不论软件或硬件成本都比较低。
    但是应付键盘和触摸板这类不需要大量通讯数据的器件完全足够了。更详细的关于SPI介绍,请查询其他资料。
    mbp2017的电脑windows驱动中关于SPI的,首先有个SPI总线驱动,在SPI总线驱动下挂载两个位置,
    位置1是键盘驱动,位置2才是触摸板驱动。详细可看下边的图示:


    画红线的部分,在”系统设备“里边的 “Apple SPI Device ” 就是总线驱动,它负责给键盘和触摸板的功能驱动提供数据,
    在“人体学输入设备”里边的“ Apple SPI Keyboard” 和 “ Apple SPI Trackpad” 对应的就是 键盘的功能驱动和触摸板的功能驱动,
    再看“Apple SPI Trackpad” 的属性, 它在总线驱动的位置是 2, 我们要做的事情,就是替换这个功能驱动,使用我们自己开发的驱动来代替。

    另外我们顺便看看这款电脑内置的USB接口的设备,
    上边的蓝线部分,在 “通用串行总线控制器” 里边存在一个“Apple USB Composite Device”的复合设备,
    这个复合设备管理着三个设备,“Apple Touch Bar”就是其中一个,这个就是multi-touch bar, 在windows平台下没啥用的鸡肋。
    另外两个看下图所示:


    Apple USB Composite Device一共包含三个设备:
    FaceTime HD Camera,
    Apple Touch Bar,
    USB接口的光感氛围器,就是检测环境光线强弱,从而自动调节屏幕的亮度。
    看图示的最下边, bNumConfigurations 是 3, 也就是三个配置描述符,分别对应这三种设备。

    正如上篇文章所说的,在单纯只安装windows系统的时候,这个“Apple USB Composite Device” 设备不能被发现,
    从而造成 摄像头,multi-touch bar,和光感器件找不到,也不知道苹果在设计硬件的时候搞了什么。
    估计得保留安装苹果系统时候的那个EFI Parttion 分区,才能被识别,只是后来没再折腾了,保留了MacOS系统。

    再回到触摸板驱动,我们打开注册表,在 如下的位置:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SPI\VID_05ac&PID_0277&MI_02
    能找到这个驱动的安装信息,
    注意:mbp2017 对应的触摸板的PID是0277, VID是05ac, 不同型号的,可能PID会不同,这个得看具体机器。


    如上图所示,在里边的LowerFilters字段里是 苹果的 AppleSPITrackpad驱动,
    Service字段是 mshidkmdf ,从这信息,
    我们立马就知道 AppleSPITrackpad 是一个KMDF模型的驱动程序,并且属于标准的HID的KMDF程序。
    AppleSPITrackpad负责获取上边提到的 “Apple SPI Device" 总线驱动发上来的触摸板数据,
    并且解析模拟成标准的兼容windows的 HID鼠标驱动数据。


    AppleSPITrackpad在解析触摸板数据时候,提供了让人难以适应(至少我比较难适应)的鼠标动作模拟,
    因此重新开发这个驱动来解决这个问题。
    至此,我们大致知道他们的驱动的工作流程了。

    现在的任务首先就是获取SPI总线驱动发上来的数据结构格式。
    可以开发一个简单的WDM 过滤驱动,挂载到 LowerFilters字段里边的 AppleSPITrackpad 前边。
    这样AppleSPITrackpad跟SPI总线驱动通讯的所有IRP请求都能被截获到,从而就能获取到触摸板数据。
    WDM Filter的开发可以查看我很早前的一篇文章:
    http://blog.csdn.net/fanxiushu/article/details/8834385
    当然如果你能找到其他现成的工具来分析AppleSPITrackpad的通讯数据,会更快捷。

    通过分析,AppleSPITrackpad发给SPI总线驱动四个请求:
    IOCTL_HID_GET_DEVICE_DESCRIPTOR
    IOCTL_HID_GET_DEVICE_ATTRIBUTES
    IOCTL_HID_SET_FEATURE
    IOCTL_HID_READ_REPORT
    都是标准的HID请求命令,其中IOCTL_HID_SET_FEATURE 应该是用于告诉SPI总线驱动开启或者关闭触摸板功能的。
    最主要的就是 IOCTL_HID_READ_REPORT命令,这个就是获取触摸板数据。

    分析在 bootcamp版本是 6.1.6813,对应的触摸板SPI总线驱动的驱动日期是 2016/05/26, 版本 6.1.6500.0,
    (这里再次提到版本和日期,因为不同版本很可能是不同的数据格式,由于本人就一台mac机器,无法测试其他情况)

    数据格式结构大致如下:
    前46个字节是格式头,接着每个手指占据30个字节。
    比如 一个手指在触摸板上,IOCTL_HID_READ_REPORT获取到的数据长度是46 + 30 = 76个字节,
    如果是两个手指在触摸板,IOCTL_HID_READ_REPORT获取的长度是 46 + 30*2 = 106字节,以此类推。

    前46个字节描述成c语言数据结构大致如下:
    typedef unsigned char              u8;
    46 length
    struct tp_protocol
    {
        u8                  type;      // unknown type  =2
        u8                  clicked;   // 按住了触摸板, 不管几个按住,都是 1
        u8                  unknown1[5]; //
        u8                  is_finger;   // 触摸板有手指 1,当离开瞬间,出现 0
        u8                  unknown2[8]; //
        u8                  unknown3[8]; // 未知,固定 00-01-07-97-02-00-06-00
        u8                  finger_data_length; // 手指数据总长度, 手指个数*30
        u8                  unknown4[5]; //
        u8                  finger_number; //手指个数
        u8                  Clicked; // 同上边的clicked
        u8                  state;   // 手指在上边好像是 0x10, 手指离开瞬间最高设置 1,变成 0x80(0x90),最后离开后,还会出现 0x00
        u8                  state2;  // 手指在上边 0x20,离开瞬间 变 0
        u8                  state3;  // 平时0, Clicked为 0x10
        u8                  zero;    // 始终 0
        u8                  unknown5[10]; /
    };

    如上所示,其中unknown字段是 没能解析出来的,不过后来发现就已知的字段已经足够模拟鼠标动作了。

    手指的30个字节的c语言结构如下:
    / 30 length
    struct tp_finger
    {
        short             org_x; //按下后,这个数字不变,
        short             org_y; //
        short             x;     //随着手指移动改变,
        short             y;     //
        short            unknown[11];
    };

    其中unknown未知,org_x,org_y好像没啥用,最有用的是 x,y。表示的是手指在触摸板的坐标位置。
    整个触摸板(13寸机器)测试下来,触摸板范围,最左边大致是 -6300多, 左右边坐标 6800多,
    最上边坐标7700左右,最下边-200左右。这些都是用手指移动到边界得出来的大致数据。

    有了这些原始的触摸板的数据,我们基本就能确定能实现自己的mbp2017的触摸板驱动来模拟鼠标操作了。

    /
    再来看看windows平台下的HID驱动开发过程,
    HID(Human Interface Device,人机接口设备)是一类设备总称,用于提供人和电脑进行交互的接口设备,
    像最常用的鼠标,键盘等,触摸板,还有游戏使用的游戏杆等等。
    像鼠标键盘都是windows提供的标准驱动,我们在开发HID驱动时候,填写适当的HID描述符,
    告诉windows我们开发的是一个HID的鼠标或者HID键盘,windows自动就会给我们加载兼容的鼠标键盘驱动。
    同时我们在自己的HID驱动开发中正确响应 IOCTL_HID_XXX事件(主要是IOCTL_HID_READ_REPORT)
    这个鼠标键盘就能正常工作起来。看起来是非常简单明了的。确实也是如此。
    比如我们要虚拟鼠标键盘,也使用HID来开发,比起挂钩什么PS/2或者HOOK之类的做法,也显得简单和稳定得多,
    这个在以后开发的博客中会继续阐述。

    我们先看看WDM模型的HID开发过程,
    首先在 DriverEntry中注册
    IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_POWER, IRP_MJ_PNP 三个派遣函数,
    然后填写 HID_MINIDRIVER_REGISTRATION 结构的参数,调用HidRegisterMinidriver注册HID的小端口驱动,
    这样总体框架就建立起来了。
    然后在 IRP_MJ_POWER和IRP_MJ_PNP派遣函数中,按部就班的实现电源管理和即插即用事件,
    如果是真实HID设备,则要认真实现这两个功能,如果是虚拟设备,则不用太在意,找个现成框架套上去就行,
    接着就是核心处理事件 IRP_MJ_INTERNAL_DEVICE_CONTROL,
    在这个派遣函数中,一般处理
    IOCTL_HID_GET_DEVICE_DESCRIPTOR
    IOCTL_HID_GET_DEVICE_ATTRIBUTES
    IOCTL_HID_READ_REPORT
    三个事件就能让鼠标键盘跑起来,当然处理的越多,功能越完善,但是HID的IOCTL命令也多不多到哪去。
    是的,就是这么简单的框架,
    但是在这里,我们不打算使用WDM的框架,而使用的是 KMDF(WDF的内核部分,就是对WDM的封装 )来开发。

    KMDF就更加省事了,连 PNP和POWER也省略了,就只要关心
    IRP_MJ_INTERNAL_DEVICE_CONTROL 就可以了。
    但是正如微软自己所说,他们的WDF框架跟HID的minidriver小端口驱动在某些IO请求中存在冲突(IRP_MJ_POWER和IRP_MJ_PNP)
    因此WDF框架不能直接桥接 HID的class driver和mini driver,他们使用了一个折中方案,
    开发一个 mshidkmdf的驱动来桥接WDF框架和classdriver,在此驱动中调用
    HidRegisterMinidriver 来注册HID小端口驱动,
    并且mshidkmdf作为服务安装,而
    我们开发的HID驱动则作为LowerFilters来安装。详细可查看如下链接:
     https://msdn.microsoft.com/en-us/library/windows/hardware/ff540774
     这就是我们为何在上面的图中看到苹果的 AppleSPItrackpad触摸板驱动变成了 Lowerfilters 的底层过滤驱动了。

    最后看看我们开发KMDF模型的这款触摸板驱动的流程:
    首先在DriverEntry中,配置好参数,这里主要关心的是 EvtDeviceAdd 函数,
    调用WdfDriverCreate 来初始化框架。
    在EvtDeviceAdd 函数中,首先调用WdfFdoInitSetFilter 表明我们开发的是一个过滤驱动。
    然后调用WdfDeviceInitAssignWdmIrpPreprocessCallback 注册IRP_MN_QUERY_ID这个特殊查询事件,
    因为我们必须这么做,才能让windows识别到我们的驱动ID,
    对应这块触摸板,我们还得注册两个电源事件,就是D0状态(加电和掉电)转换,
    因为加电情况下,我们得通知SPI总线驱动,开启苹果的触摸板驱动,掉电情况做些停止操作处理,
    大致如下注册电源事件:
    //设置电源回调函数
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
        //设备处于工作(供电D0状态)或者非工作状态
        pnpPowerCallbacks.EvtDeviceD0Entry = EvtDeviceD0Entry ;// 设备加电时候被调用
        pnpPowerCallbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;      // 设备掉电时候被调用
        WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); ///

    然后就是创建过滤设备,创建IO队列,一共两个队列,一个是默认的IO队列,用于处理 InternalDeviceControl请求,
    一个是手动队列,我们在处理 IOCTL_HID_READ_REPORT时候,需要入队等待处理,
    然后就是初始化一些相关变量等数据。
    这里我们读取SPI总线驱动的原始触摸板数据,使用的是串行读取,因此整个驱动创建一个全局的Request来重复使用,
    InternalDeviceControl 的IOCTL_HID_GET_DEVICE_DESCRIPTOR,IOCTL_HID_GET_DEVICE_ATTRIBUTES
    中我们把事先准备好的HID的鼠标描述符,属性等信息报告给classdriver, 
    然后接收到 IOCTL_HID_READ_REPORT命令时候调用WdfRequestForwardToIoQueue 加到手动的IO队列。

    EvtDeviceD0Entry函数被调用(就是设备加电了),发起全局的Request对SPI总线驱动的读取操作,
    同时设置这个Request的完成回调函数,在完成函数中分析处理读取到的触摸板数据,处理完成后接着继续发起对触摸板数据的读取。
     
    更详细的请查看稍后发布到GITHUB和CSDN上的源代码和驱动程序。

    驱动实现的功能一个5个(如上边所说)
    1,一个手指按住触摸板任意位置,另一个手指移动来达到拖动效果
    2,一个手指轻点或者一个手指按下触摸板,模拟鼠标左击
    3,两个手指轻点,或者一个手指按住触摸板右边3/4-4/4位置,模拟鼠标右击
    4,双指同时移动来模拟滚轮滚动
    5,三指拖移。

    如果你已经适应了苹果的触摸板windows的手势行为,则无需留意本文的内容。



    展开全文
  • WindowsCE.NET USB驱动开发基础,WindowsCE下USB驱动开发的资料太少了,这个是微软出的,PPT,提供一个鼠标驱动的编写教程。不要钱
  • windows下的驱动开发(过滤驱动)

    千次阅读 2015-07-16 16:01:53
    最近对驱动比较感兴趣,所以打算做个windows下面的驱动,正好自己电脑的鼠标左键的单击有的时候会变双击,所有打算弄个鼠标的过滤驱动来解决这个问题。 网上找了一下,原来早就有人做了这个功能 ...

    最近对驱动比较感兴趣,所以打算做个windows下面的驱动,正好自己电脑的鼠标左键的单击有的时候会变双击,所有打算弄个鼠标的过滤驱动来解决这个问题。

    网上找了一下,原来早就有人做了这个功能 http://download.csdn.net/detail/guijc1/5263421(不是故意给这个打广告的),所以我的代码基本都是仿照这里的源码。

    这篇文章的重点是如何动手写一个过滤驱动,不是驱动的技术细节。还有就是驱动需要支持32和64系统的问题,安装驱动的问题。

    以下很多都是从网络上面获取的资料。我会把链接都放到文章里面。

    1.开发环境的搭建

     vs2008+GRMWDK_EN_7600_1.ISO,这些直接安装就行了 注意如果要64位版本需要安装vs2008的64编译环境,接下来就是环境的配置了。我参照的是

    http://jacky-dai.iteye.com/blog/1536456  以及 http://blog.csdn.net/huangxy10/article/details/15284881

     

    (1)打开vs2008,选择“工具--选项--项目和解决方案”在右侧平台选择“win32”--“包含文件”,然后在下面添加自己的wdk中的inc相关路径
    D:\WINDDK\7600.16385.1\inc\wdf\kmdf\1.9
    D:\WINDDK\7600.16385.1\inc\api
    D:\WINDDK\7600.16385.1\inc\crt
    D:\WINDDK\7600.16385.1\inc\ddk

    注意:vc包含文件的D:\WinDDK\7600.16385.1\inc\api不一定是放最前面,编译不过去的时候可以放到$(VCInstallDir)include的后面。

    然后选择“win32”--“库文件”添加自己的WDK中LIB路径
    D:\WINDDK\7600.16385.1\lib\wdf\kmdf\i386\1.9
    D:\WINDDK\7600.16385.1\lib\wxp\i386

    如果是64位的需要添加的库文件是

    D:\WINDDK\7600.16385.1\lib\wdf\kmdf\amd64\1.9
    D:\WINDDK\7600.16385.1\lib\win7\amd64

    (2) 工程配置

    新建一个win32的控制台工程,把里面带的文件都删除掉

    右键工程,选择属性

         点击“c/c++”--

         选择“常规”,“调试信息”选:“C7 兼容(/Z7)”,“警告等级”--“3级(/w3)”,“将警告视为错误”--选“是” (这个需要看情况设置)

         选择“优化”,“优化”选“禁用(/0d)”

         选择“预处理器”,“预处理器定义”输入“WIN32=100;_X86_=1;DBG=1”  如果是64的则把_X86_=1 替换为_AMD64_=1

         选择“高级”,“调用约定”选“__stdcall (/Gz)”

         点击“连接器”--

         选择“常规”,“输出文件”输入“$(OutDir)\$(ProjectName)32.sys”(64位的修改为"$(OutDir)\$(ProjectName)64.sys"),“启用增量连接”,选“否(/INCREMENTAL:NO)”,“附加库目录”输入“D:\WINDDK\7600.16385.0\lib\wxp\i386”

    如果是64的修改为"D:\WinDDK\7600.16385.1\lib\win7\amd64”

         选择“输入”,“附加依赖项”输入“ntoskrnl.lib $(NOINHERIT)”,“忽略所有默认库”选“是(/NODEFAULTLIB)”

         选择“清单文件”,“启用用户账户控制(UAC)”选“否”

         选择“调试”,“生成调试信息”选择“是”,“生成程序数据库文件”输入“MyChecked_Driver\$(ProjectName).pdb”

         选择“系统”,“子系统”选“本机(/SUBSYSTEM:NATIVE)”,“堆栈保留大小”输入“40000”,“堆栈提交大小”输入“1000”,“驱动程序”选“驱动程序(/DRIVER)”

         选择“高级”,“入口点”输入“DriverEntry”,“基址”输入“0x10000”,“随机基址”选“默认值”,“数据执行保护(DEP)”选“默认值”,“目标计算机”选“MachineX86 (/MACHINE:X86)”  如果是64的就选择"MachineX64 (/MACHINE:X64)"

     

    2.下面是工程源码  解决鼠标单击变双击的问题
    MouseLeftKeyFilter.h

    #pragma once
    
    #define DEVICE_NAME          L"\\Device\\MouseFilter"
    #define DOS_DEVICE_NAME      L"\\DosDevices\\MouseFilter"
    
    #define POOL_TAG             'tsiL'
    
    #ifdef __cplusplus   
    extern "C"  
    {   
    #endif
    	//一类是不支持即插即用功能的NT式的驱动程序
    	//NT式的驱动程序要导入的头文件时NTDDK.H,而WDM式的驱动要导入的头文件为WDM.H.
    	#include <ntddk.h> 
    
    	typedef NTSTATUS (*READ_DISPATCH)(__in PDEVICE_OBJECT pDeviceObject, __in PIRP Irp);
    
    	typedef struct _DEVICE_EXTENSION {
    		PDEVICE_OBJECT  pDeviceObject;  
    	} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    
    	typedef struct _MOUSE_FILTER_DATA{
    		PDRIVER_OBJECT  pMouseDriverObject; // "\\Driver\\Mouclass" 的指针
    		READ_DISPATCH OldRead; // 原来的IRP_MJ_READ 派遣例程
    		ULONG LeftDownTime; // 上次鼠标左键按下的时刻 
    		KMUTEX ReadMutex; // Read互斥体
    		SINGLE_LIST_ENTRY ListHead;// 保存Pending IRP的链表
    		SINGLE_LIST_ENTRY CancelHead;// 用来对上面链表的进行复制
    	}MOUSE_FILTER_DATA, *PMOUSE_FILTER_DATA;
    
    	typedef struct _PENDING_IRP_LIST{
    		SINGLE_LIST_ENTRY SingleListEntry;    
    		PIRP PendingIrp;
    	}PENDING_IRP_LIST, *PPENDING_IRP_LIST;
    
    	extern POBJECT_TYPE *IoDriverObjectType;
    
    	extern NTSTATUS ObReferenceObjectByName(
    		PUNICODE_STRING ObjectName,
    		ULONG Attributes,
    		PACCESS_STATE AccessState,
    		ACCESS_MASK DesiredAccess,
    		POBJECT_TYPE ObjectType,
    		KPROCESSOR_MODE AccessMode,
    		PVOID ParseContext,
    		PVOID *Object
    		);
    
    	NTSTATUS DriverEntry (IN  PDRIVER_OBJECT  pDeviceObject,
    		IN  PUNICODE_STRING RegistryPath
    		);
    	VOID DriverUnload(IN PDRIVER_OBJECT pDeviceObject);
    
    	NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT pDeviceObject,
    		IN PIRP Irp
    		);
    	NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT pDeviceObject,
    		IN PIRP Irp
    		);
    	NTSTATUS MyDispatchRead(IN PDEVICE_OBJECT pDeviceObject,
    		IN PIRP Irp
    		);
    	NTSTATUS MyDispatchReadComplete(IN PDEVICE_OBJECT pDeviceObject,
    		IN PIRP Irp, 
    		IN PVOID Context ) ;
    
    	VOID CleanUP(IN PDEVICE_OBJECT pDeviceObject);
    	VOID CancelPendingIrp();
    	BOOLEAN IsFakeDoubleClick ();
    	
    #ifdef __cplusplus   
    };   
    #endif 
    
    //#ifdef ALLOC_PRAGMA   
    //#pragma alloc_text(INIT, DriverEntry)   
    //#pragma alloc_text(PAGE, testDriverUnload)   
    //#endif

    下面是MouseLeftKeyFilter.cpp

    #include "MouseLeftKeyFilter.h"
    #include <ntddmou.h>
    
    MOUSE_FILTER_DATA gFilterData = {0};
    
    
    NTSTATUS DriverEntry (IN  PDRIVER_OBJECT  pDeviceObject,
    			 IN  PUNICODE_STRING RegistryPath
    			 )
    {
    	NTSTATUS  status = STATUS_SUCCESS;
    	UNICODE_STRING  DeviceName;
    	UNICODE_STRING  SymbolicLinkName;
    	UNICODE_STRING  MouseDriver;
    	PDEVICE_OBJECT  DeviceObject = NULL;
    	PDEVICE_EXTENSION   deviceExtension = NULL;
    
    	//告诉编译器,已经使用了该变量,不必检测警告
    	UNREFERENCED_PARAMETER (RegistryPath);
    
    	KdPrint(("Entered DriverEntry =================== \n"));
    
    	KeInitializeMutex(&gFilterData.ReadMutex, 0);
    	gFilterData.ListHead.Next = NULL;
    	gFilterData.CancelHead.Next = NULL;
    
    	pDeviceObject->MajorFunction [IRP_MJ_CREATE] =
    	pDeviceObject->MajorFunction [IRP_MJ_CLOSE] =  DispatchCreateClose;
    	pDeviceObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;    
    	pDeviceObject->DriverUnload = DriverUnload;
    
    	//创建设备对象
    	RtlInitUnicodeString(&DeviceName, DEVICE_NAME);    
    	status = IoCreateDevice( 
    		pDeviceObject,
    		sizeof(DEVICE_EXTENSION),
    		&DeviceName,
    		FILE_DEVICE_UNKNOWN,
    		FILE_DEVICE_SECURE_OPEN,
    		FALSE,
    		&DeviceObject
    		);
    	if (!NT_SUCCESS(status))
    	{
    		KdPrint(("IoCreateDevice failed, 0x%0x!\n", status));
    		return status;
    	}   
    
    	//创建符号链接
    	RtlInitUnicodeString(&SymbolicLinkName, DOS_DEVICE_NAME);
    	status = IoCreateSymbolicLink(&SymbolicLinkName, &SymbolicLinkName);
    	if(!NT_SUCCESS(status))
    	{
    		KdPrint(("IoCreateSymbolicLink failed, 0x%0x!\n", status));
    		CleanUP(DeviceObject);
    		return status;
    	}
    
    	deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    	RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
    
    	deviceExtension->pDeviceObject = DeviceObject;
    
    	//DeviceObject->Flags |= DO_BUFFERED_IO;
    	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    
    
    	//取得鼠标驱动对象
    	RtlInitUnicodeString(&MouseDriver, L"\\Driver\\Mouclass");
    	status = ObReferenceObjectByName (
    		&MouseDriver,
    		OBJ_CASE_INSENSITIVE,
    		NULL,
    		0,
    		*IoDriverObjectType,
    		KernelMode,
    		NULL,
    		(PVOID *)&gFilterData.pMouseDriverObject
    		);
    
    	if(!NT_SUCCESS(status))
    	{
    		KdPrint(("Get mouse object failed, 0x%0x\n", status));
    		CleanUP(DeviceObject);
    		return status;
    	}
    
    
    	//保存原来的IRP_MJ_READ 派遣例程
    	gFilterData.OldRead = gFilterData.pMouseDriverObject->MajorFunction[IRP_MJ_READ];
    
    	if(gFilterData.OldRead) // IRP HOOK
    	{
    		InterlockedExchange(
    			(PLONG)&gFilterData.pMouseDriverObject->MajorFunction[IRP_MJ_READ],
    			(LONG)MyDispatchRead
    			);
    	}
    	else
    	{
    		CleanUP(DeviceObject);
    		return STATUS_UNSUCCESSFUL;
    	}    
    
    	return status;
    }
    
    //IRP_MJ_READ 完成函数
    NTSTATUS MyDispatchReadComplete(IN PDEVICE_OBJECT pDeviceObject,
    						IN PIRP Irp, 
    						IN PVOID Context ) 
    {
    	ULONG_PTR i,num;
    	PMOUSE_INPUT_DATA data;
    	PSINGLE_LIST_ENTRY pSingleListEntry = &gFilterData.ListHead;
    	PPENDING_IRP_LIST PendingList = NULL;
    
    	if( NT_SUCCESS( Irp->IoStatus.Status ) ) 
    	{
    		data = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
    		num = Irp->IoStatus.Information / sizeof(MOUSE_INPUT_DATA);
    
    		for( i = 0; i < num; i++ ) 
    		{
    			去除假的鼠标左键双击事件
    			//if(data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN )
    			//{ 
    			//	// 鼠标左键按下
    			//	if(IsFakeDoubleClick() )
    			//	{   //假双击
    			//		KdPrint(("Got a Fake Double CLick!! ================= \r\n"));
    			//		data[i].ButtonFlags = 0; //忽略掉
    			//	}
    			//	else
    			//	{
    			//		//KdPrint(("Left Button Down"));
    			//	}
    			//}
    
    			//下面是实现左右互换的功能
    			if(data[i].ButtonFlags &MOUSE_LEFT_BUTTON_DOWN )
    			{
    				data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
    				data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_RIGHT_BUTTON_DOWN;
    			}
    			else if (data[i].ButtonFlags &MOUSE_LEFT_BUTTON_UP)
    			{
    				data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
    				data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_RIGHT_BUTTON_UP;
    			}
    			else if (data[i].ButtonFlags &MOUSE_RIGHT_BUTTON_DOWN)
    			{
    				data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
    				data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_LEFT_BUTTON_DOWN;
    			}
    			else if (data[i].ButtonFlags &MOUSE_RIGHT_BUTTON_UP)
    			{
    				data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
    				data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_LEFT_BUTTON_UP;
    			}
    		}
    	}
    
    	KeWaitForMutexObject(&gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);
    
    	for(; pSingleListEntry->Next; pSingleListEntry = pSingleListEntry->Next)        
    	{
    		PendingList = CONTAINING_RECORD(pSingleListEntry->Next, PENDING_IRP_LIST, SingleListEntry);
    
    		if(PendingList->PendingIrp == Irp)
    		{// 从链表中移除
    			pSingleListEntry->Next = pSingleListEntry->Next->Next;
    			ExFreePoolWithTag(PendingList, POOL_TAG); 
    			break;
    		}
    	}
    
    	KeReleaseMutex(&gFilterData.ReadMutex, FALSE);       
    
    	//KdPrint(("MyReadComplete ============ Irp= 0x%X, 0x%X", Irp,  Irp->IoStatus.Status));    
    
    	//调用原来的完成函数
    	if ((Irp->StackCount > 1) && (Context != NULL))
    	{
    		return ((PIO_COMPLETION_ROUTINE)Context)(pDeviceObject, Irp, NULL);
    	}
    	else
    	{
    		return Irp->IoStatus.Status;
    	}
    }
    
    
    NTSTATUS MyDispatchRead(IN PDEVICE_OBJECT pDeviceObject,
    	   IN PIRP Irp
    	   )
    {
    	PPENDING_IRP_LIST PendingList = NULL;
    	PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    
    	//KdPrint(("MyDispatchRead ================ Irp= 0x%p ", Irp)); 
    
    	PendingList = (PPENDING_IRP_LIST)ExAllocatePoolWithTag(NonPagedPool, sizeof(PENDING_IRP_LIST), POOL_TAG);    
    
    	if(PendingList)
    	{
    		PendingList->PendingIrp = Irp;
    
    		KeWaitForMutexObject( &gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);    			
    		PushEntryList(&gFilterData.ListHead, &PendingList->SingleListEntry);
    		KeReleaseMutex(&gFilterData.ReadMutex, FALSE); 
    
    		// 按理说,应该调用IoSetCompletionRoutine来设置完成例程的
    		// 但是,那样会导致完成例程根本不会被执行,Why?
    		irpSp->Control = SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR|SL_INVOKE_ON_CANCEL;
    
    		//保留原来的完成函数
    		irpSp->Context = irpSp->CompletionRoutine;
    		irpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)MyDispatchReadComplete;
    	}
    
    	return  gFilterData.OldRead(pDeviceObject, Irp); 
    }
    
    NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT pDeviceObject,
    			IN PIRP Irp
    			)
    {
    	//IoGetCurrentIrpStackLocation 需要在项目设置里面添加 hal.lib
    	PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    
    	UNREFERENCED_PARAMETER(pDeviceObject);
    
    	PAGED_CODE();
    
    	KdPrint(("Entered ================ IRP_MJ_%s\n", (irpStack->MajorFunction == IRP_MJ_CREATE) ? "CREATE" : "CLOSE" ));
    
    	Irp->IoStatus.Status = STATUS_SUCCESS;
    	Irp->IoStatus.Information = 0;
    	IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    	return Irp->IoStatus.Status;
    }
    
    NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT pDeviceObject,
    			  IN PIRP Irp
    			  )
    {
    	PAGED_CODE();
    
    	Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    	Irp->IoStatus.Information = 0;
    	IoCompleteRequest (Irp,IO_NO_INCREMENT);
    
    	return Irp->IoStatus.Status;
    }
    
    VOID DriverUnload(IN PDRIVER_OBJECT pDeviceObject)
    {
    	PAGED_CODE ();
    
    	KdPrint(("Entered ================== Unload\n"));
    
    	CleanUP(pDeviceObject->DeviceObject);
    
    	CancelPendingIrp();
    
    	//等待所有的IRP 完成    
    	while (gFilterData.ListHead.Next) 
    	{
    		LARGE_INTEGER lDelay;
    		lDelay.QuadPart = -10 * 1000 * 1000; // 1秒
    		KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
    	}       
    }
    
    VOID CleanUP(IN PDEVICE_OBJECT pDeviceObject)
    {
    	UNICODE_STRING  SymbolicLinkName;
    
    	if(!pDeviceObject)
    		return;
    
    	// 删除符号链接和设备对象
    	RtlInitUnicodeString(&SymbolicLinkName, DOS_DEVICE_NAME);
    	IoDeleteSymbolicLink(&SymbolicLinkName);       
    	IoDeleteDevice(pDeviceObject);
    
    	//恢复IRP  hook
    	if(gFilterData.OldRead)
    	{
    		InterlockedExchange(
    			(PLONG)&gFilterData.pMouseDriverObject->MajorFunction[IRP_MJ_READ], 
    			(LONG)gFilterData.OldRead
    			);         
    	}  
    
    	if(gFilterData.pMouseDriverObject)
    	{
    		ObDereferenceObject(gFilterData.pMouseDriverObject);  
    	}
    }
    
    // 取消等待的IRP
    VOID CancelPendingIrp()
    {
    	PPENDING_IRP_LIST PendingList = NULL, CancelList = NULL;
    	PSINGLE_LIST_ENTRY pSingleListEntry = NULL;
    
    	// 获取互斥体,保护链表gFilterData.ListHead
    	KeWaitForMutexObject(&gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);
    
    	pSingleListEntry = gFilterData.ListHead.Next;
    	while(pSingleListEntry)
    	{       
    		PendingList = CONTAINING_RECORD(pSingleListEntry, PENDING_IRP_LIST, SingleListEntry);
    		KdPrint(("Copy ================= Single List = 0x%x", PendingList));
    
    		// 复制链表,然后将取消IRP的操作放到新的链表中处理
    		CancelList = (PPENDING_IRP_LIST)ExAllocatePoolWithTag(NonPagedPool, sizeof(PENDING_IRP_LIST), POOL_TAG);
    		if(CancelList)
    		{
    			RtlCopyMemory(CancelList, PendingList, sizeof(PENDING_IRP_LIST));
    			PushEntryList(&gFilterData.CancelHead, &CancelList->SingleListEntry);
    		}           
    
    		pSingleListEntry = pSingleListEntry->Next;
    	}   
    	// 释放互斥体
    	KeReleaseMutex(&gFilterData.ReadMutex, FALSE);
    
    
    	// 之所以要复制一个新的链表来取消IRP (通过调用IoCancelIrp),
    	// 是因为IoCancelIrp 会调用MyDispatchReadComplete 这个完成例程回调,
    	// 而MyDispatchReadComplete里面又对链表进行操作,这样会破坏链表的结构
    	pSingleListEntry = PopEntryList(&gFilterData.CancelHead);
    	while(pSingleListEntry)
    	{
    		CancelList = CONTAINING_RECORD(pSingleListEntry, PENDING_IRP_LIST, SingleListEntry);
    		if(CancelList)
    		{
    			KdPrint(("CancelPendingIrp = 0x%x", CancelList->PendingIrp));
    
    			if(!CancelList->PendingIrp->Cancel)
    			{// 在这里,取出复制链表中的IRP,然后进行取消
    				IoCancelIrp(CancelList->PendingIrp);
    			}
    			ExFreePoolWithTag(CancelList, POOL_TAG);        
    			pSingleListEntry = PopEntryList(&gFilterData.CancelHead);
    		}
    	}
    }
    
    //判断是否是假双击,根据时间间隔判断
    BOOLEAN IsFakeDoubleClick ()
    {
    	LARGE_INTEGER CurrentTime;
    	BOOLEAN Flag = FALSE;
    
    	KeQueryTickCount(&CurrentTime);
    
    	CurrentTime.QuadPart *= KeQueryTimeIncrement();  
    	CurrentTime.QuadPart /=  10000;
    
    	//两次点击时间间隔小于100ms,视为假双击
    	if( CurrentTime.LowPart - gFilterData.LeftDownTime < 100)
    	{
    		Flag = TRUE;
    	}
    
    	InterlockedExchange((volatile LONG *)&gFilterData.LeftDownTime, CurrentTime.LowPart);
    	return Flag;
    }


    上面就是全部的代码。如果编译没有错误就会生成对应的sys文件。

    3.安装驱动

    安装过滤驱动有两种方式,一种是写服务来安装,这个网上也有源码,还有就是inf文件  在cmd里面执行rundll32 SETUPAPI.DLL,InstallHinfSection DefaultInstall 132 +inf路径

    这里贴出来一个完整的inf 鼠标过滤驱动的文件

    ; HHD Software USB Monitoring Filter Driver
    ; Part of Device Monitoring Studio
    ;
    ; Copyright HHD Software Ltd.
    [Version]
    signature = "$Windows NT$"
    DriverPackageType=ClassFilter
    Class=Mouse
    ClassGUID={59D5B0A2-8479-4333-BCFE-3EB1F6BD506D}
    Provider=%ClasFilt.Provider%
    DriverVer=12/03/2010,5.25.0.3036
    
    ;
    [SourceDisksNames]
    1 = %ClasFilt.MediaDesc%
    
    [SourceDisksFiles]
    MyMouseDrive32.sys = 1
    MyMouseDrive64.sys = 1
    
    [DestinationDirs]
    DefaultDestDir = 12	; DIRID_DRIVERS
    
    [DefaultInstall.ntx86]
    CopyFiles = @MyMouseDrive32.sys
    AddReg = ClassFilter_AddReg.ntx86
     
    [DefaultInstall.ntamd64]
    CopyFiles = @MyMouseDrive64.sys
    AddReg = ClassFilter_AddReg.ntamd64
     
    ; 指定过滤驱动对应的注册表项
    [ClassFilter_AddReg.ntx86]
    HKLM, System\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}, UpperFilters, 0x00010008, MyMouseDrive32
    
          
    [ClassFilter_AddReg.ntamd64]
    HKLM, System\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}, UpperFilters, 0x00010008, MyMouseDrive64
    
    
    [DefaultInstall.ntx86.Services]
    AddService = MyMouseDrive32, , clasfilt_Service_Inst.ntx86, clasfilt_EventLog_Inst.ntx86
    
    [DefaultInstall.ntamd64.Services]
    AddService = MyMouseDrive64, , clasfilt_Service_Inst.ntamd64, clasfilt_EventLog_Inst.ntamd64
    
    [clasfilt_Service_Inst.ntx86]
    DisplayName    = %ClasFilt.SvcDesc%
    ServiceType    = %SERVICE_KERNEL_DRIVER%
    StartType      = %SERVICE_DEMAND_START%
    ErrorControl   = %SERVICE_ERROR_IGNORE%
    ServiceBinary  = %12%\MyMouseDrive32.sys
    
    [clasfilt_Service_Inst.ntamd64]
    DisplayName    = %ClasFilt.SvcDesc%
    ServiceType    = %SERVICE_KERNEL_DRIVER%
    StartType      = %SERVICE_DEMAND_START%
    ErrorControl   = %SERVICE_ERROR_IGNORE%
    ServiceBinary  = %12%\MyMouseDrive64.sys
    
    [clasfilt_EventLog_Inst.ntx86]
    AddReg = clasfilt_EventLog_AddReg.ntx86
    
    [clasfilt_EventLog_Inst.ntamd64]
    AddReg = clasfilt_EventLog_AddReg.ntamd64
    
    [clasfilt_EventLog_AddReg.ntx86]
    HKR,,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\MyMouseDrive32.sys"
    HKR,,TypesSupported, %REG_DWORD%, 7
    
    [clasfilt_EventLog_AddReg.ntamd64]
    HKR,,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\MyMouseDrive64.sys"
    HKR,,TypesSupported, %REG_DWORD%, 7
    
    [Strings]
    ; 不同的过滤驱动下面的信息要修改
    ;Note: the following must be modified, if it is other filter drivers 
    ClasFilt.SvcDesc="MyMouse Filter Driver"
    ClasFilt.MediaDesc="MyMouse Filter Package"
    ClasFilt.Provider="MyMouse Software Ltd."
    
    ;下面这个信息不需要修改
    ; Useful constants
    SERVICE_KERNEL_DRIVER = 1
    SERVICE_DEMAND_START  = 3
    SERVICE_ERROR_IGNORE  = 0
    REG_EXPAND_SZ         = 0x00020000
    REG_DWORD             = 0x00010001
        

     

    注意在win7 64上面驱动没有签名是不能正常工作的,还有64上面执行cmd安装命令需要管理员权限

    下面是网上找的解决64驱动签名的办法  参考的为http://blog.csdn.net/sunzhongyuan9/article/details/8084034

    http://blog.hehehehehe.cn/a/17253.htm

    http://blog.hehehehehe.cn/a/17257.htm  最好就安装这个程序签名一下。

    第1种.cmd命令关闭强制驱动签名:

        首先:用管理员身份打开CMD命令行

        然后:输入bcdedit/set testsigning on ,回车

        再:    完成以后将电脑重启。。

    第2种.使用工具dseo13b .exe (点击下载)签名:

        首先:siga a system file  ->next

        再: Enable Test Mode –>next

    4.调试驱动

    直接使用 Dbgview.exe 查看输出,还有网上给的用windbug(我没用过),注意Dbgview.在64位上面需要修改

    http://blog.sina.com.cn/s/blog_7dc3e33a0101exvq.html

     

    5.注意

    过滤驱动是挂载在过滤层,所以测试的时候最好是拿虚拟机来,否则出问题就麻烦了,卸载过滤驱动:找到对应的注册表项删除UpperFilters里面的值就可以了,

    因为是nt的驱动,所以安装之后需要重启才能生效。


    这个只是简单的记录一下驱动的基本开发,为以后驱动开发做铺垫而已,希望对其他的新接触的朋友有帮助,至于说到书籍的话,这个就网上找一些驱动开发书籍看看就可以了,重点是编码调试。

    展开全文
  • 1. 安装VS2010,WDK7.60(GRMWDK_EN_7600_1) 2. 新建VC 控制台项目(选择为空项目) 3. 新建项目配置“driver” ,点击下拉按钮-点击(配置管理器) ...鼠标右击新建的driver属性,会弹出以下窗口! ...

    1.  安装VS2010,WDK7.60(GRMWDK_EN_7600_1)

    2.  新建VC 控制台项目(选择为空项目)

    1_thumb1

    3.  新建项目配置“driver” ,点击下拉按钮-点击(配置管理器)

    6_thumb5

    输入名称(driver)点击确定就可以了,其他的不要动哦!

    3_thumb3

    完成后的效果!

    2_thumb3

    点击确定按钮之后呈现出来的画面

    4_thumb6

    鼠标右击新建的driver属性,会弹出以下窗口!

    5_thumb1
    4.  设置VC++路径

    <我把wdk安装在E盘下>
    a.  配置可执行文件目录:E:\WinDDK\7600.16385.1\bin\x86;
    b.  配置包含目录:E:\WinDDK\7600.16385.1\inc\ddk 
                            E:\WinDDK\7600.16385.1\inc\  
                            E:\WinDDK\7600.16385.1\inc\api  
    c.  配置库目录:    E:\WinDDK\7600.16385.1\lib\win7\i3865

     

    新建C/C++文件 不然无C/C++设置选项

    <刚开始我们创建了一个空的项目所以项目里没有c++文件,现在要做的就是在空的项目-源文件-添加一个新建项c++文件>

    常规 
    目标文件扩展名:.sys          //必选


    6.  设置C/C++选项
    常规选项卡
    1 调试信息格式(C7 兼容(/Z7)        //可选
    2 警告等级     (2 级(/W2)          //可选
    3 将警告视为错误  (是(/wx)         //可选
     
    优化选项卡
    优化(禁用/Od)                          //可选
     
    预处理器
    预处理器定义:WIN32=100;_X86_=1;WINVER=0x501;DBG=1         //必选
     
    代码生成
           启用最小重新生成:否                                        //可选    

           基本运行时检查:默认值                                     //可选
           运行时库:多线程调试(/MTd)  或  多线程(/MT)                 //建议选 <本人选择的是多线程调试(/MTd)>
           缓冲区安全检查:否                                            //可选
      (可避免出现  LINK : error LNK2001:  无法解析外部符号  __security_cookie)
    高级
         调用约定  __stdcall(/Gz)                                       //必选
     
    7.  链接器设置
    常规
         启用增量链接:否(/INCREMENTAL:NO)                           //建议 选上
         忽略导入库:是                                                  // 可选 
         ( 设置为此值时,必须在附加库目录中加: E:\WinDDK\7600.16385.1\lib\win7\i3865  这样项目就不会依赖 IDE 环境的设 置) 

         如果否  (  设置为此值时,将依赖  IDE  的环境的相关设置  )
     
    输入
    附加依赖项
    ntoskrnl.lib;Hal.lib;wdm.lib;wdmsec.lib;wmilib.lib;ndis.lib;MSVCRT.LIB;LIBCMT.LIB       //必选   

    //NT式驱动  ntoskrnl.lib    WDM式驱动    wdm.lib
    ( HalXXX 函数在Hal.lib, WmiXXX 函数在  wmilib.lib  , NdisXXX函数在  ndis.lib )
    (  必要时需要增加微软的标准库  MSVCRT.LIB MSVCRTD.LIB(调试库) LIBCMT.LIBIBCMTD.LIB(调试库) )
      (  如果源码中有  source  文件,那么该文件的  TARGETLIBS  字段会列出该项 目需要的库  )

    忽略所有默认库:    是 (/NODEFAULTLIB)                 //必选  

    清单文件
      启用用户账户控制(UAC)   否  //必选 

    不然会出现  >LINK : fatal error LNK1295: “/MANIFESTUAC”与“/DRIVER”规范不兼容;链接时不使用“/MANIFESTUAC”  
     
         调试
    生成调试信息  是(/DEBUG)                                              //可选
    生成映像文件:是(/MAP)                                               //可选
    映像文件名:$(TargetDir)$(TargetName).map                     //可选
     
        系统(System)
         子系统:  控制台(/SUBSYSTEM:CONSOLE)                                //必选
         堆栈保留大小:4194304                                              //可选
         堆栈提交大小:  4096                                                //可选
         驱动程序:    驱动程序(/DRIVER)                                        //必选  
          高级:
        入口点:DriverEntry                                                    //必选
        随机基址:清空           //把框里的数据删掉。(yes也不是no也不是就是要一个干干净净的文本框)   //必选
        不然会出现  e:\xxx.sys : fatal error LNK1295:
    “/DYNAMICBASE”与“/DRIVER”规范不兼容;链接时不使用“/DYNAMICBASE”


        数据执行保护(DEP):  清空 //把框里的数据删掉。(yes也不是no也不是就是要一个干干净净的文本框) //必选  
         不然会出现  e:\xxx.sys : fatal error LNK1295:       
    “/NXCOMPAT:NO”与“/DRIVER”规范不兼容;链接时不使用“/NXCOMPAT:NO”   

     

    设置效应和:是(/RELEASE)                              //可选

    基址:0x10000                                           //建议选上 
       
     命令行:/SECTION:INIT,D /IGNORE:4078        (建议不要写进去,会报错!)                    

    最后给出一个超级简单的代码来测试一下我们配置的是否成功??

    #include "ntddk.h"

    NTSTATUS
    DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
    {
    return STATUS_UNSUCCESSFUL;
    }

     

    如果没有报错那么恭喜你配置成功了!

    转载于:https://www.cnblogs.com/korykim/archive/2011/02/01/1948771.html

    展开全文
  • 经百度,google加问两位驱动开发高手后,搜集了以下资料,记录下来,以后有新的再补上。 关于开发平台 第一个遇到的问题就是开发平台。一查就发现有一大堆概念了!下面罗列出来: VxD: 啥都不说,先把百度百科的解释...
  • 1. 安装VS2010,WDK7.60(GRMWDK_EN_7600_1) 2. 新建VC 控制台项目(选择为空项目) 3. 新建项目配置“driver” ,点击下拉按钮-点击(配置管理器) 输入名称(driver)点击确定...鼠标右击新建的dr
  • 微软官方有关在windows7下开发第三方键盘、鼠标、触摸板等HID设备驱动的有关建议。 官方文档,已经转成了doc格式,word 2003可以看。
  • 键盘鼠标(PS2)模拟器驱动... C++ 语言驱动包含 WinIO, WinRing0, WindowsAPI:event*.  C# 语言的Demo. 问题描述: 鼠标相对移动存在不正确性,绝对移动没正确性. 基于于Thinkpad E460上的开发及测试. 不支持HID设备.
  • 通常Platform Builder中给出了支持多种CPU常用设备驱动程序,如LCD驱动、鼠标驱动、USB驱动、串口驱动等;但有时由于平台采用了其他特定的硬件设备,其驱动程序在Platform Builder并没有给出,这时就需要用户针对...
  • Windows NT 设备驱动程序开发基础(4)

    千次阅读 2002-03-03 09:20:00
    1.3.4 查找硬件信息 i) 系统自动搜索到的设备 在系统启动时,组件NTDETECT会自动地搜索计算机上已有的硬件,包括串、并行 口,键盘,鼠标,以及大多数PCI和EISA设备。并将它们的信息,包括总线类型,总线号 ,...
  • 作者:bjtuzdq 转自:... USB鼠标的类的定义如下: class CMouse { public: CMouse::CMouse(USB_HANDLE hDevice, LPCUSB_FUNCS lpUsbFuncs, LPCUSB_INTERFACE lp
  • 驱动开发环境之Windows XP DDK2600,VC++ 6.0, Driver Studio 3.2 神秘的驱动开发,神秘的WINDOWS内核,是什么把这些搞得这么神秘呢? 搭Windows驱动开发平台就搭了两天,历经各种找不到,搞不通。我还是学计算机...
  • USB鼠标的类的定义如下: class CMouse { public: CMouse::CMouse(USB_HANDLE hDevice, LPCUSB_FUNCS lpUsbFuncs, LPCUSB_INTERFACE lpInterface); ~CMouse(); BOOL Initialize(); private: // 传输完毕调用
  • 安信考虑到市场和客户的需要,开展Windows驱动程序和应用程序开发定制服务。 多年的技术支持服务为安信积累了一批优秀的Windows开发工程师,能帮助客户满足种种需求,解决各种难题,让贵司产品的研发畅通无阻。 一,...
  • 驱动开发与Win32下的程序开发不同,没有一套智能的IDE环境,点点鼠标框架代码IDE就帮你生成好了。Windows下的开发为什么那么容易上手,Visual studio功不可莫。一帮懒人在MS的“悉心呵护”下产生了,身边很多做Win32...
  • 一, HID类Windows驱动程序和应用程序开发 主要运用领域: 1, 游戏竞技产品(键盘,鼠标,手柄等) 2, 手写板,触控板 3, 扫描设备,扫码枪 4, 其他硬件或虚拟设备 二,4G,5G无线模块,智能手机Windows驱动程序...
  • DriverStudio中的DriverWorks,本质是“DDK类库”,使用C++类库封装的方法简化了NT Driver或者WDM驱动程序的开发,使用DriverWorks代替DDK开发,类似于使用MFC代替SDK开发Windows应用程序。 这个需要序列号和注册...
  • DriverStudio中的DriverWorks,本质是“DDK类库”,使用C++类库封装的方法简化了NT Driver或者WDM驱动程序的开发,使用DriverWorks代替DDK开发,类似于使用MFC代替SDK开发Windows应用程序。 这个需要序列号和注册...
  • DriverStudio中的DriverWorks,本质是“DDK类库”,使用C++类库封装的方法简化了NT Driver或者WDM驱动程序的开发,使用DriverWorks代替DDK开发,类似于使用MFC代替SDK开发Windows应用程序。 这个需要序列号和注册...
  • DriverStudio中的DriverWorks,本质是“DDK类库”,使用C++类库封装的方法简化了NT Driver或者WDM驱动程序的开发,使用DriverWorks代替DDK开发,类似于使用MFC代替SDK开发Windows应用程序。 这个需要序列号和注册...
  • DriverStudio中的DriverWorks,本质是“DDK类库”,使用C++类库封装的方法简化了NT Driver或者WDM驱动程序的开发,使用DriverWorks代替DDK开发,类似于使用MFC代替SDK开发Windows应用程序。 这个需要序列号和注册...
  • DriverStudio中的DriverWorks,本质是“DDK类库”,使用C++类库封装的方法简化了NT Driver或者WDM驱动程序的开发,使用DriverWorks代替DDK开发,类似于使用MFC代替SDK开发Windows应用程序。 这个需要序列号和注册...
  • 概述 MultiTouch Vista是一个输入管理层,处理来自CCV等触点追踪软件和其它设备...使用 这里介绍MultiTouch是因为我们需要用到它的多鼠标操作,也就是当做模拟器来使用和控制Windows 7的驱动。 当做模拟器使用 --...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 382
精华内容 152
关键字:

windows鼠标驱动开发