windows驱动开发详解
文章平均质量分 94
qq_857305819
这个作者很懒,什么都没留下…
展开
-
通过设备接口寻找设备
设备接口在WDM驱动中,一般很少用到设备名,也很少用到符号链接,而是用- 个设备接口来指定设备。设备接口其实就是一-组全局标识,它是一个128位组成的数字,并能保证在全世界范围内不会产生冲突。引入设备接口的主要原因是避免设备名冲突,例如,不同的网卡厂商可能都将自己的设备名命名为“NetCardDevice",当用户插入两块网卡时,就会引起命名冲突。而引入设备接口的概念,各个网卡厂商用自己定义的128位数字指定自己的设备,从小概率意义上,保证了各个设备的设备接口不会一样。WDM驱动中设置接口原创 2020-08-01 07:48:41 · 613 阅读 · 0 评论 -
将IRP分解成多个IRP
IRP可以分解成多个小IRP,例如,需要对某个设备读写大量的数据,但是设备所支持的一次物理读写只有很小的字节数,这样对设备的读写操作就可以分解成多个IRP,每个IRP所读写的字节数都在设备所允许的范围内。...原创 2020-07-31 23:02:36 · 234 阅读 · 0 评论 -
完成例程
在将IRP发送给底层驱动或者其他驱动前,可以对IRP设置-一个完成例程。一旦底层驱动将IRP完成后,IRP完成例程立刻被触发。通过设置完成例程可以方便地使程序员了解其他驱动对IRP进行的处理。完成例程是驱动程序编写中的一种常用技巧。 当驱动程序调用自己的底层驱动,可以通过完成例程获得通知。不管是调用自己的底层驱动或者调用其他驱动,都是使用内核函数loCallDriver.当loCallDriver将IRP的控制权交给被动驱动时,有两种情况。第一种情况, 即调用的设备是同步完成这个IRP的,从lo原创 2020-07-31 02:12:17 · 543 阅读 · 0 评论 -
遍历设备栈
查找设备名内核对象地址-0x18 为OBJECT_HEADER的地址 kd> dt _OBJECT_HEADER +0x000 PointerCount : Int4B +0x004 HandleCount : Int4B +0x004 NextToFree : Ptr32 Void +0x008 Type : Ptr32 _OBJECT_TYPE +0x00c NameInfoOffset : UChar原创 2020-07-31 00:26:20 · 260 阅读 · 0 评论 -
VPB结构
VPB是Windows I/O Manager子系统的一个重要的数据结构,全称为 Volume Parameter Block。它的任务是绑定卷设备(如磁盘分区或虚拟磁盘)和接管此卷设备的文件系统(如FastFat,NTFS)。Windows系统上的挂载点(Mount Point,如盘符C:)只能定位至卷设备(如\Device\HarddiskVolume1),Windows Object Manager(对象管理器)在解析路径名时(即Name Parsing过程)还要通过卷设备的VPB信息进一步定位至接管原创 2020-07-31 00:25:18 · 1849 阅读 · 0 评论 -
分层驱动程序
分层驱动程序的概念分层驱动概念主要是为了区分前面介绍的单层驱动程序。分层驱动是指两个或两个以上的驱动程序,它们分别创建设备对象,并且形成一个由高到低的设备对象栈。IRP请求一-般会被传送到设备栈的最顶层的设备对象,顶层的设备对象可以选择直接结束IRP请求,也可以选择将IRP请求向下层的设备对象转发。如果是向下层设备对象转发IRP请求,当IRP请求结束时,IRP会顺着设备栈的反方向原路返回。当得知下层驱动程序已经结束IRP请求时,本层设备对象可以选择继续将IRP向上返回,或者选择重新将IRP再次传原创 2020-07-30 11:13:24 · 465 阅读 · 0 评论 -
驱动程序调用驱动程序
1原创 2020-07-29 14:30:50 · 858 阅读 · 0 评论 -
IRP的超时处理
很多时候,IRP 被传送到底层驱动程序后,由于硬件设备的问题,IRP 不能得到及时的处理,甚至有可能永远都不会被处理。这时候需要对IRP超时情况做出处理,一旦在规定时间内IRP没有被处理,操作系统就会进入到IRP的超时处理函数中。首先初始一个定时器对象和DPC对象,并将DPC例程和定时器对象进行关联。在每次对IRP操作前,开启定时器,并设置好-定的超时。 如果在指定时间内对IRP的处理没有结束,那么操作系统就会就会进入DPC例程。在DPC例程中取消还在继续处理的IRP。如果驱动程序能在超时前结束原创 2020-07-27 23:55:41 · 477 阅读 · 0 评论 -
内核中的时间相关函数
获取系统当前时间KeQuerySystemTime函数返回当前系统时间,这个时间是以格林尼治时间为准,从1601年1月1日起经过的时间。void KeQuerySystemTime( OUT PLARGE_INTEGER CurrentTime);ExSystemTimeToLocalTime把系统时间转换成当前时区对应的时间,时区可以在控制面板中设置。void ExSystemTimeToLocalTime(IN PLARGE_INTEGER SystemTime, //系统时间OUT原创 2020-07-27 20:36:00 · 951 阅读 · 0 评论 -
内核中的定时等待
第一种方法:使用KeWaitForSingleObject使用KeWaitForSingleObject函数来实现等待,让这个函数等待一个没有信号的内核对象。//单位是微秒 1秒=1000毫秒=1000*1000微秒VOID WaitMicroSecond(ULONG ulMircoSecond){ KEVENT kEvent; //初始化一个未激发的内核事件 KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE); //等原创 2020-07-27 20:05:36 · 1112 阅读 · 0 评论 -
定时器
在驱动程序中,一般有两种方法使用定时器,一种方法是使用I/O定时器例程,另一种方法是使用DPC例程。原创 2020-07-27 17:16:25 · 177 阅读 · 0 评论 -
IRP的串行化处理
StartIO例程能够保证各个并行的IRP顺序执行,即串行化。操作系统为程序员提供了一个IRP队列来实现串行,这个队列用KDEVICE QUEUE数据结构表示。typedef struct _KDEVICE_QUEUE { //IRP队列来实现串行 CSHORT Type; CSHORT Size; LIST_ENTRY devicelisthead; //该队列头保存在DeviceObject->原创 2020-07-27 11:16:17 · 508 阅读 · 0 评论 -
异步操作设备
异步操作设备(方式一)异步操作设备时主要需要设置OVERLAP参数,Windows中用一种数据结构OVERLAPPED表示。typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; union { struct { DWORD Offset; 操作设备会指定一个偏移量,从设备的偏移量进行读取。该偏移量用一个64位整形表示,Offset就是偏移量的低32位整形 DWORD原创 2020-07-26 22:23:52 · 160 阅读 · 0 评论 -
IRPTrace的使用方法
1:点击手型图标或者菜单栏的 Messages=>HOook Setup2:在箭头处点击一下,找到自己的驱动名字3:点击MyDevice 右键 installHook 然后在右边irp消息类型点击all 最后点击OK4:把这3个按钮给按下去 这样就能接收到IRP信息了。...原创 2020-07-26 21:45:50 · 1401 阅读 · 0 评论 -
驱动中设备扩展的使用
驱动的设备对象中有一个字段是扩展设备该扩展设备的大小是不固定的,依据在创建设备对象时给定的大小分配内存例如:typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pDevice; UNICODE_STRING ustrDeviceName; //设备名称 UNICODE_STRING ustrSymLinkName; //符号链接名} DEVICE_EXTENSION, *PDEVICE_EXTENSION;//创建设备对象status = I原创 2020-07-26 00:27:16 · 443 阅读 · 0 评论 -
派遣函数类型
IRP类型IRP类型来源IRP_MJ_ CREATECreateFileIRP_MJ_CLOSECloseHandleIRP_MJ_CLEANUPCloseHandleIRP_MJ_ DEVICE_CONTROLDeviceIoControlIRP_MJ_ PNP即插即用消息,NT驱动不支持此种IRP,只有WDM驱动才支持IRP_MJ_POWER在操作系统处理电源时,产生此IRPIRP_MJ_QUERY_INFORMATIONGetFi原创 2020-07-25 15:29:08 · 267 阅读 · 0 评论 -
内核模式下的同步对象
内核模式下的等待在内核模式下,有两个函数负责等待内核同步对象。 分别是KeWaitForSingleObject和KeWaitForMultipleObject函数。NTSTATUSKeWaitForSingleObject ( PVOID Object, //同步内核对象的指针 KWAIT_REASON WaitReason, //内核模式下设置此值为Executive KPROCESSOR_MODE WaitMode, //驱动中应该设置为KernelMode原创 2020-07-24 04:56:23 · 308 阅读 · 0 评论 -
内核下的注册表操作
注册表的相关概念创建关闭注册表ZwCreateKeyNTSYSAPI NTSTATUS ZwCreateKey( PHANDLE KeyHandle, //获得的注册表句柄 ACCESS_MASK DesiredAccess, //访问权限,一般设置为KEY_ALL_ACCESS POBJECT_ATTRIBUTES ObjectAttributes, //OBJECT_ATTRIBUTES数据结构指针 ULONG Ti原创 2020-07-23 07:59:55 · 1025 阅读 · 0 评论 -
内核下的文件操作
内核下对文件创建和打开都是通过ZwCreateFile,这个内核函数返回一个文件句柄,文件的所有操作都是依靠这个句柄进行操作的。在文件操作完毕后,需要关闭这个句柄。NTSYSAPI NTSTATUS ZwCreateFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBloc原创 2020-07-22 14:41:33 · 453 阅读 · 0 评论 -
快查表Lookaside结构
在内核中,频繁的申请和释放内存。容易造成大量的内存碎片。ddk提供了一种解决方式,使用Lookaside对象。该对象会一次性申请一个大的内存,以后每次需要内存的时候就到这个对象中去拿Lookaside对象内部的内存不够用时,它会向操作系统申请更多的内存。当Lookaside对象内部有大量的未使用的内存时,它会自动让Windows回收一部分内存。 总之,Lookaside是一个自动的内存分配容器。通过对Lookaside对象申请内存,效率要高于直接向Windows申请内存。Lookaside 一-般原创 2020-07-21 19:47:45 · 462 阅读 · 0 评论 -
驱动中链表的使用
DDK中定义了LIST_ENTRY双向链表结构,这样把数据和链表分开的定义方法,降低了耦合度。typedef struct LIST ENTRY {PLIST ENTRY Flink;PLIST_ ENTRY Blink;) LIST ENTRY *PLIST_ ENTRY;链表的使用在自己定义的结构体中包含已经定义好的LIST_ENTRY链表.typedef struct _MYDATASTRUCT { // List Entry需要作为MYDATASTRUCT结构体的一部分 LI原创 2020-07-21 16:43:52 · 650 阅读 · 0 评论 -
驱动对象和设备对象
驱动对象驱动对象,本质就是内核中一块描述驱动信息的内存kd> dt _DRIVER_OBJECT 8988fe20+0x000 Type : 4 //NT式驱动的类型为4+0x002 Size : 168 //该结构体的大小+0x004 DeviceObject : (null) //自己创建的设备对象 该驱动中所有的设备对象会组成一个链表。+0x008 Flags : 0x12 +0x00c Dr原创 2020-07-21 05:20:44 · 483 阅读 · 1 评论