9、Windows驱动程序的入口函数规定为_DriverEntry@8,所以用C++编写时要用extern。

驱动程序中,不能使用编译器运行时函数,甚至C语言中的malloc,C++的new函数都不能用,因为他们在VC中的实现都是调用了Win32 API了。要用的话,必须自己重载new等运算符。大部分运行时函数是通过Win32 API实现的。在内核模式下无法调用用户模式的程序,而用户模式下通过参数审核可以调用内核态程序。

内核态的运行时函数来替换用户态的运行时函数,一般形如RtlXXXX。

设备名称用UNICODE字符串指定,且必须是“\Device\[设备名]”形式。用户模式下,通过两种方法找到设备:

法1:符号连接

法2:通过设备接口。

一般虚拟设备用FILE_DEVICE_UNKNOWN类型。

******************

"采用C++编程,所以需要用extern "C",因为我们导入的是C的函数的符号表",系统内核是有C语言编写的,连接时要调用相应的函数,所以应当把驱动头文件编译成C语言形式。

10、用build编译

Build首先设置环境变量,然后调用nmake。nmake解析makefile,调用cl,link来编译程序。

Makefile中依赖关系如下声明:

A:B,C

Action

说明:A依赖于B和C。如果A的最后修改时间早于B和C任一个文件的最后修改时间,则执行action。Action前面是tab。

用VC编译,我们在另一篇中论述。

11、查看调试信息

法一:打印信息

尽量用KdPrint,在free版本中不显示。同prrinf使用,双括号,宽字符用%ws或%S。

法二:用DriverStudio中的DriverMonitor。不过可以用免费的DbgView,下载地址是:

http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx

12、加载驱动

NT式驱动程序的加载,是基本服务的方式加载的。设备驱动程序的动态加载主要由服务控制管理程序(SCM)系统组件完成的。Windows服务应用程序遵循控制管理器。Driver Service是Windows服务的一个特例,它遵守Windows服务的协议。

图 加载 P72

图 卸载驱动流程 P72

代码 加载和卸载驱动代码

代码

1 #include <windows.h>
2 #include <winsvc.h>
3 #include <conio.h>
4 #include <stdio.h>
5
6  #define DRIVER_NAME "HelloDDK"
7  #define DRIVER_PATH "..\\MyDriver\\MyDriver_Check\\HelloDDK.sys"
8
9 //装载NT驱动程序
10 BOOL LoadNTDriver(char* lpszDriverName,char* lpszDriverPath)
11 {
12 char szDriverImagePath[256];
13 //得到完整的驱动路径
14 GetFullPathName(lpszDriverPath, 256, szDriverImagePath, NULL);
15
16 BOOL bRet = FALSE;
17
18 SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
19 SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄
20
21 //打开服务控制管理器
22 hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
23
24 if( hServiceMgr == NULL )
25 {
26 //OpenSCManager失败
27 printf( "OpenSCManager() Faild %d ! \n", GetLastError() );
28 bRet = FALSE;
29 goto BeforeLeave;
30 }
31 else
32 {
33 ////OpenSCManager成功
34 printf( "OpenSCManager() ok ! \n" );
35 }
36
37 //创建驱动所对应的服务
38 hServiceDDK = CreateService( hServiceMgr,
39 lpszDriverName, //驱动程序的在注册表中的名字
40 lpszDriverName, // 注册表驱动程序的 DisplayName 值
41 SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
42 SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序
43 SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值
44 SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值
45 szDriverImagePath, // 注册表驱动程序的 ImagePath 值
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL);
51
52 DWORD dwRtn;
53 //判断服务是否失败
54 if( hServiceDDK == NULL )
55 {
56 dwRtn = GetLastError();
57 if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS )
58 {
59 //由于其他原因创建服务失败
60 printf( "CrateService() Faild %d ! \n", dwRtn );
61 bRet = FALSE;
62 goto BeforeLeave;
63 }
64 else
65 {
66 //服务创建失败,是由于服务已经创立过
67 printf( "CrateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n" );
68 }
69
70 // 驱动程序已经加载,只需要打开
71 hServiceDDK = OpenService( hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS );
72 if( hServiceDDK == NULL )
73 {
74 //如果打开服务也失败,则意味错误
75 dwRtn = GetLastError();
76 printf( "OpenService() Faild %d ! \n", dwRtn );
77 bRet = FALSE;
78 goto BeforeLeave;
79 }
80 else
81 {
82 printf( "OpenService() ok ! \n" );
83 }
84 }
85 else
86 {
87 printf( "CrateService() ok ! \n" );
88 }
89
90 //开启此项服务
91 bRet= StartService( hServiceDDK, NULL, NULL );
92 if( !bRet )
93 {
94 DWORD dwRtn = GetLastError();
95 if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING )
96 {
97 printf( "StartService() Faild %d ! \n", dwRtn );
98 bRet = FALSE;
99 goto BeforeLeave;
100 }
101 else
102 {
103 if( dwRtn == ERROR_IO_PENDING )
104 {
105 //设备被挂住
106 printf( "StartService() Faild ERROR_IO_PENDING ! \n");
107 bRet = FALSE;
108 goto BeforeLeave;
109 }
110 else
111 {
112 //服务已经开启
113 printf( "StartService() Faild ERROR_SERVICE_ALREADY_RUNNING ! \n");
114 bRet = TRUE;
115 goto BeforeLeave;
116 }
117 }
118 }
119 bRet = TRUE;
120 //离开前关闭句柄
121 BeforeLeave:
122 if(hServiceDDK)
123 {
124 CloseServiceHandle(hServiceDDK);
125 }
126 if(hServiceMgr)
127 {
128 CloseServiceHandle(hServiceMgr);
129 }
130 return bRet;
131 }
132
133 //卸载驱动程序
134 BOOL UnloadNTDriver( char * szSvrName )
135 {
136 BOOL bRet = FALSE;
137 SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄
138 SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄
139 SERVICE_STATUS SvrSta;
140 //打开SCM管理器
141 hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
142 if( hServiceMgr == NULL )
143 {
144 //带开SCM管理器失败
145 printf( "OpenSCManager() Faild %d ! \n", GetLastError() );
146 bRet = FALSE;
147 goto BeforeLeave;
148 }
149 else
150 {
151 //带开SCM管理器失败成功
152 printf( "OpenSCManager() ok ! \n" );
153 }
154 //打开驱动所对应的服务
155 hServiceDDK = OpenService( hServiceMgr, szSvrName, SERVICE_ALL_ACCESS );
156
157 if( hServiceDDK == NULL )
158 {
159 //打开驱动所对应的服务失败
160 printf( "OpenService() Faild %d ! \n", GetLastError() );
161 bRet = FALSE;
162 goto BeforeLeave;
163 }
164 else
165 {
166 printf( "OpenService() ok ! \n" );
167 }
168 //停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
169 if( !ControlService( hServiceDDK, SERVICE_CONTROL_STOP , &SvrSta ) )
170 {
171 printf( "ControlService() Faild %d !\n", GetLastError() );
172 }
173 else
174 {
175 //打开驱动所对应的失败
176 printf( "ControlService() ok !\n" );
177 }
178 //动态卸载驱动程序。
179 if( !DeleteService( hServiceDDK ) )
180 {
181 //卸载失败
182 printf( "DeleteSrevice() Faild %d !\n", GetLastError() );
183 }
184 else
185 {
186 //卸载成功
187 printf( "DelServer:eleteSrevice() ok !\n" );
188 }
189 bRet = TRUE;
190 BeforeLeave:
191 //离开前关闭打开的句柄
192 if(hServiceDDK)
193 {
194 CloseServiceHandle(hServiceDDK);
195 }
196 if(hServiceMgr)
197 {
198 CloseServiceHandle(hServiceMgr);
199 }
200 return bRet;
201 }
202
203 void TestDriver()
204 {
205 //测试驱动程序
206 HANDLE hDevice = CreateFile("\\\\.\\HelloDDK",
207 GENERIC_WRITE | GENERIC_READ,
208 0,
209 NULL,
210 OPEN_EXISTING,
211 0,
212 NULL);
213 if( hDevice != INVALID_HANDLE_VALUE )
214 {
215 printf( "Create Device ok ! \n" );
216 }
217 else
218 {
219 printf( "Create Device faild %d ! \n", GetLastError() );
220 }
221 CloseHandle( hDevice );
222 }
223
224 int main(int argc, char* argv[])
225 {
226 //加载驱动
227 BOOL bRet = LoadNTDriver(DRIVER_NAME,DRIVER_PATH);
228 if (!bRet)
229 {
230 printf("LoadNTDriver error\n");
231 return 0;
232 }
233 //加载成功
234
235 printf( "press any to create device!\n" );
236 getch();
237
238 TestDriver();
239
240 //这时候你可以通过注册表,或其他查看符号连接的软件验证。
241 printf( "press any to unload the driver!\n" );
242 getch();
243
244 //卸载驱动
245 UnloadNTDriver(DRIVER_NAME);
246 if (!bRet)
247 {
248 printf("UnloadNTDriver error\n");
249 return 0;
250 }
251
252 return 0;
253 }
254
255

关于WDM驱动的手工加载,见[1]。

13、NT驱动程序的基本结构

1)数据结构

DEVICE_OBJECT

The DEVICE_OBJECT structure is used by the operating system to represent a device object. A device object represents a logical, virtual, or physical device for which a driver handles I/O requests.

http://msdn.microsoft.com/en-us/library/ff543147%28VS.85%29.aspx

每个设备对象指针指向向一个设备对象,最后一个设备对象指向空。

图 设备对象布局图 P92

设备扩展对象定义自己定义的结构体,驱动程序中尽是避免使用全局变量,因为会影响同步,而把全局变量存在设备扩展里。

driver object

Each driver object represents the image of a loaded kernel-mode driver. A pointer to the driver object is an input parameter to a driver's DriverEntry, AddDevice, and optional Reinitialize routines and to its Unload routine, if any.

每个驱动程序与唯一的驱动对象相对应,这个驱动对象是在驱动加载时候,被内核中的对象管理器创建。驱动对象为驱动和个实例被内核加载,并且一个驱动只能加载一个实例。

图 驱动对象布局图 P88

其它参见:

http://www.cnblogs.com/mydomain/archive/2010/10/16/1853235.html

14、DriverEntry主要是对系统进程创建的驱动对象进行初始化。

15、WDM程序的基本结构

一般都是基于分层的,完成一个设备的操作,至少要由两个驱动设备共同完成。一个是PDO(物理设备对象),一个是FDO(功能设备对象),其关系是附加与被附加关系。当PC中插入某个设备时,总线驱动自动创建PDO,由PDO引出FDO。

图 FDO与PDO P103

过滤驱动不是必须的。

与NT的不同:

· 增加了对AddDevice函数的设备。操作系统加载PDO后,调用驱动的AddDevice例程,AddDevice例程负责创建FDO,并且附加到PDO之上。

·设备对象在AddDevice例程中创建。

·必须加入IRP_MJ_PNP的派遣回调函数。

PDO会通过AttachedDevice子域知道它上面的设备是FDO或过滤驱动,但是不知道下面的,可以通过定制自己的设备扩展来记录地址。

16、设备的层次结构

图 设备对象堆栈 P104

图 垂直结构 P111,P113

参考

【1】Windows 驱动开发技术详解

【2】http://msdn.microsoft.com/en-us/library/ff565757%28VS.85%29.aspx
【3】Windows驱动学习笔记,灰狐

15、Windows驱动开发技术详解笔记(11) 基本概念相关推荐

  1. 9、Windows驱动开发技术详解笔记(5) 基本语法回顾

    5.在驱动中获取系统时间 1)获取启动毫秒数 在ring3 我们可以通过一个GetTickCount 函数来获得自系统启动开始的毫秒数,在ring0也有一个与之对应的KeQueryTickCount ...

  2. Windows驱动开发技术详解笔记

    EdwardLewisWe的博客--windows内核编程 转载于:https://www.cnblogs.com/forlina/archive/2011/08/11/2134718.html

  3. 《Windows驱动开发技术详解》学习笔记

    Abstract   如果推荐 Windows 驱动开发的入门书,我强烈推荐<Windows驱动开发技术详解>.但是由于成书的时间较早,该书中提到的很多工具和环境都已不可用或找不到,而本文 ...

  4. c语言windows驱动编程入门,Windows驱动开发技术详解 PDF扫描版[175MB]

    Windows驱动开发技术详解由浅入深.循序渐进地介绍了windows驱动程序的开发方法与调试技巧.本书共分23章,内容涵盖了windows操作系统的基本原理.nt驱动程序与wdm驱动程序的构造.驱动 ...

  5. 《Windows驱动开发技术详解》读书笔记(一)

    首先需要安装DDK,这里我选择Microsoft Windows Server 2003 SP1 DDK Windows驱动分成两类,一类是不支持即插即用的NT式驱动,一类是支持即插即用的WDM驱动. ...

  6. 《Windows驱动开发技术详解》之HelloDDK

    编写如下代码: 运行会报错: 这里的原因是有没有引用到的形参,需要添加如下代码即可: 记得在系统启动时按F8禁用掉数字签名: 将编译好的驱动拖入虚拟机,以管理员身份运行DbgView捕捉内核态输出数据 ...

  7. 《Windows驱动开发技术详解》之编程加载NT式驱动

    之前我们加载驱动都是利用INSTDRV这个应用,其原理是在注册表中写入相应的字段,这一节我们手动编写代码去加载驱动,其原理类似: 设备驱动程序的动态加载主要由服务控制管理程序(Service Cont ...

  8. windows驱动开发资料(《windows驱动开发技术详解》)+源码

    链接:https://pan.baidu.com/s/1db1sEsIMf3YWuxQ090ih_g 提取码:m4lz

  9. mfc编程vc6.0实现进程的创建和通信_免费送书:windows黑客编程技术详解

    01 书怎么送 点赞并留言,关注在下面的公众号后台回复「抽奖」,弹出小程序后点击参与. 开奖时间是 7 月 7 号 20:00 ,一定要留意微信消息,如果你中奖了,请尽快在中奖页面提交收件人信息并备注 ...

最新文章

  1. Tomcat Servlet学习
  2. java大量的print影响性能吗_printStackTrace()造成的性能瓶颈
  3. React事件处理函数传参问题
  4. 安装显卡驱动后分辨率低的办法
  5. c++的文件输入/输出
  6. [html] 你知道著名的3像素Bug指的是什么吗?怎么解决呢?
  7. 这一年多来,阿里Blink测试体系如何从0走向成熟?
  8. 最常见的Java框架有哪些?
  9. 后缀数组 倍增法详解
  10. 创建项目连接错误_在不同项目下S7-1200主站模块和 S7-300 CP342-5通信的实现方法...
  11. 你还敢用鼠标吗?黑客在百米之外控制你的鼠标
  12. Linux 服务器网卡驱动安装及故障排除
  13. 《第一桶金怎么赚——淘宝开店创业致富一册通》一一1.1 创业者需具备的素质...
  14. valhalla 插件_Java 15:密封类使Valhalla更加接近
  15. Linux 文件/目录管理
  16. 丛麟环保冲刺科创板:拟募资20亿 年利润超2亿
  17. 微软高层新近对Linux桌面的说法
  18. 基于web的家电维修系统/家电维修管理系统
  19. Creating A Moddable Unity Game
  20. 二维数组的foreach遍历和三种集合的遍历

热门文章

  1. 一起学JUCE之HashMap
  2. VisualSVN Server 修改用户密码
  3. C#中不同窗口之间传递值的两种方法
  4. DotLucene 系列文章
  5. eclipse插件svn账号信息清空重新登陆
  6. 松原哪家计算机学校好,松原高中学校排名2021最新排名,松原高中排名前十
  7. python 获取浏览器句柄下的网页控件,Python获取浏览器窗口句柄过程解析
  8. Linux下用户、组、权限操作
  9. python网页提交表单_用Python的urllib库提交WEB表单
  10. JavaScript与WebAssembly进行比较