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

之前我们加载驱动都是利用INSTDRV这个应用,其原理是在注册表中写入相应的字段,这一节我们手动编写代码去加载驱动,其原理类似:

设备驱动程序的动态加载主要由服务控制管理程序(Service Control Manager,SCM)系统组件完成。加载和卸载NT驱动分为四个步骤:

为NT驱动创建新的服务;

开启此服务;

关闭此服务;

删除NT驱动所创建的服务。

LoadNTDriver装载驱动代码主要流程如下:

代码如下:

 1 BOOL LoadNTDriver(char*lpszDriverName, char*lpszDriverPath){
 2     char szDriverImagePath[256];
 3     //得到完整的驱动路径
 4     GetFullPathName(lpszDriverPath, 256, szDriverImagePath, NULL);
 5     BOOL bRet = FALSE;
 6     SC_HANDLE hServiceMgr = NULL;
 7     SC_HANDLE hServiceDDK = NULL;
 8     //打开服务控制管理器
 9     hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
10     if (NULL == hServiceMgr){
11         printf("OpenSCManager() failed : %d \n", GetLastError());
12         goto BeforeLeave;
13         bRet = FALSE;
14     }
15     else{
16         printf("OpenSCManager() OK!\n");
17     }
18     //创建驱动所对应的服务
19     hServiceDDK = CreateService(hServiceMgr,
20         lpszDriverName,
21         lpszDriverName,
22         SERVICE_ALL_ACCESS,
23         SERVICE_KERNEL_DRIVER,
24         SERVICE_DEMAND_START,
25         SERVICE_ERROR_IGNORE,
26         szDriverImagePath,
27         NULL, NULL, NULL, NULL, NULL);
28
29     DWORD dwRtn;
30     if (NULL == hServiceDDK){
31         dwRtn = GetLastError();
32         if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS){
33             printf("CreateService failed:%d!\n", dwRtn);
34             bRet = FALSE;
35             goto BeforeLeave;
36         }
37         else{
38             printf("CreateService failed:ERROR_IO_PENDING or ERROR_SERVICE_EXISTS\n");
39         }
40         //创建失败说明服务已经存在,直接打开即可
41         hServiceDDK = OpenService(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
42         if (NULL == hServiceDDK){
43             dwRtn = GetLastError();
44             printf("OpenService() failed:%d!\n", dwRtn);
45             bRet = FALSE;
46             goto BeforeLeave;
47         }
48         else{
49             printf("OpenService OK!\n");
50         }
51     }
52     else{
53         printf("CreateService OK!\n");
54     }
55
56     //创建服务成功,开启此服务
57     bRet = StartService(hServiceDDK, NULL, NULL);
58     if (!bRet){
59         dwRtn = GetLastError();
60         if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING){
61             printf("StartService failed:%d!\n", dwRtn);
62             bRet = FALSE;
63             goto BeforeLeave;
64         }
65         else{
66             if (ERROR_IO_PENDING == dwRtn){
67                 printf("StartService() failed:ERROR_IO_PENDING");
68                 bRet = FALSE;
69                 goto BeforeLeave;
70             }
71             else{
72                 printf("StartService() failed :ERROR_SERVICE_ALREADY_RUNNING");
73                 bRet = TRUE;
74                 goto BeforeLeave;
75             }
76         }
77     }
78     bRet = TRUE;
79 BeforeLeave:
80     if (hServiceDDK){
81         CloseServiceHandle(hServiceDDK);
82     }
83     if (hServiceMgr){
84         CloseServiceHandle(hServiceMgr);
85     }
86     return bRet;
87 }

UnLoadNTDriver卸载驱动主要代码流程如下:

代码如下:

 1 BOOL UnloadNTDriver(char*szSvrName){
 2     BOOL bRet = FALSE;
 3     SC_HANDLE hServiceMgr = NULL;
 4     SC_HANDLE hServiceDDK = NULL;
 5     hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 6     if (NULL == hServiceMgr){
 7         printf("OpenSCManager() failed : %d \n", GetLastError());
 8         goto BeforeLeave;
 9         bRet = FALSE;
10     }
11     else{
12         printf("OpenSCManager() OK!\n");
13     }
14     hServiceDDK = OpenService(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);
15     if (NULL == hServiceDDK){
16         printf("OpenService() failed :%d\n", GetLastError());
17         bRet = FALSE;
18         goto BeforeLeave;
19     }
20     else{
21         printf("OpenService() OK!\n");
22     }
23     SERVICE_STATUS SvrSta;
24     //停止驱动程序
25     if (!ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta)){
26         printf("ControlService() failed:%d\n", GetLastError());
27     }
28     else{
29         printf("ControlService() OK!\n");
30     }
31     //动态卸载驱动程序
32     if (!DeleteService(hServiceDDK)){
33         printf("DeleteService() failed:%d\n", GetLastError());
34     }
35     else{
36         printf("DeleteService() OK!\n");
37     }
38     bRet = TRUE;
39
40 BeforeLeave:
41     if (hServiceDDK){
42         CloseServiceHandle(hServiceDDK);
43     }
44     if (hServiceMgr){
45         CloseServiceHandle(hServiceMgr);
46     }
47     return bRet;
48 }

安装和卸载驱动:

注意,这里的驱动名称和路径应该设置为:

运行成功:

时间: 2024-10-27 08:34:47

《Windows驱动开发技术详解》之编程加载NT式驱动的相关文章

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

编写如下代码: 运行会报错: 这里的原因是有没有引用到的形参,需要添加如下代码即可: 记得在系统启动时按F8禁用掉数字签名: 将编译好的驱动拖入虚拟机,以管理员身份运行DbgView捕捉内核态输出数据,以管理员身份运行InstDrv以加载驱动,我们就可以看到启动和停止时,DriverEntry和DriverUnload中输出的数据了: 下面,来对上面的实验进行简单的说明: Windows驱动程序的入口函数并不是main函数,而是DriverEntry函数,这个函数由内核中的I/O管理器负责调用.

《Windows驱动开发技术详解》之Windows内存管理

虚拟内存地址 Windows所有的程序(Ring0和Ring3层)可以操作的都是虚拟内存.有一部分单元会和物理内存对应起来,但并非一一对应,多个虚拟内存页可以映射同一个物理内存页.还有一部分单元会被映射成磁盘上的文件,并标记为脏的.读取这段虚拟内存的时候,系统会发出一个异常,此时会出发异常处理函数,异常处理函数会将这个页的磁盘文件读入内存,并将其标记为不脏.可以让那些经常不读写的内存页交换成文件,并设置为脏. Windows之所以如此设计,第一是虚拟的增加了内存的大小:第二是使不同进程的虚拟内存

【原创】《windows驱动开发技术详解》第4章实验总结二

1 实验要求(WDM驱动)   2 编写过程 2.1 确立整体架构 2.1.1 入口函数——DriverEntry (1)作用 设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等 (2)注意 AddDevice在Driver_Object结构体的DriverExtension->AddDevice,原型是NTSTATUS AddDevice (PDRIVER_OBJECT pDriverObject, PDEVIC

《Android底层接口与驱动开发技术详解》digest

第一章:IDE:Eclipse ADT for java developer其它: Apache Ant Java SE Development Kit5或6 Linux和Mac上使用Apache Ant 1.65+,Windows上使用1.7+版本:(单独的JRE是不可以的,必须要有JDK),不兼容Gnu Java编译器(gcj) Java_Home x:\xx\xx\java\JDK1.6.0-17classpath:.;%JAVA_HOME%/lib/rt.jar;%JAVA_HOME%/

《Windows驱动开发技术详解》之IRP的同步

应用程序对设备的同步异步操作: 大部分IRP都是由应用程序的Win32 API函数发起的.这些Win32 API本身就支持同步和异步操作.例如,ReadFile.WriteFile和DeviceIoControl等,它们都有异步和同步两种操作方式.DeviceIoControl的同步操作如图所示: 同步操作时,DeviceIoControl的内部会调用WaitForSingleObject函数去等待一个事件.这个事件直到IRP结束才会触发.如果通过反汇编IoCompleteRequest内核函数

《Windows驱动开发技术详解》之读写操作

缓冲区方式读写操作 读写操作一般是由ReadFile和WriteFile函数引起的,这里先以WriteFile函数为例进行介绍.WriteFile要求用户提供一段缓冲区,并且说明缓冲区的大小,然后WriteFile将这段内存的数据传入到驱动程序中.这种方法,操作系统将应用程序提供缓冲区数据直接复制到内核模式的地址中.这样做,比较简单的解决了将用户地址传入驱动的问题,而缺点是需要在用户模式和内核模式之间复制数据,影响了效率.在少量内存操作时,可以采用这种方法.拷贝到内核模式下的地址由WriteFi

《Windows驱动开发技术详解》之定时器

I/O定时器 I/O定时器是DDK提供的一种定时器.它每个1s钟系统会调用一次I/O定时器例程.I/O定时器例程运行在DISPATCH_LEVEL级别,因此在这个例程中不能使用分页内存,否则会引起页故障从而导致系统崩溃.另外I/O定时器是运行在任一线程的,不一定是IRP发起的线程中,因此不能直接使用应用程序的内存地址. 初始化I/O定时器后,可以开启和停止I/O定时器.开启定时器后,每个1s系统调用一次定时器例程.在听指定是气候,系统就不会进入定时器例程.开启定时器的内核函数是IoStartTi

Windows驱动开发技术详解HelloWDM例子win7下无法安装

HelloWDM例子编译完成之后,在win7下安装显示 查看setupapi.dev看到如下信息 这个C:\MyDriver_Check目录完全不是我指定的,我放到c盘根目录下 查看inf [SourceDisksFiles] HelloWDM.sys = 1,MyDriver_Check, 把该字段修改为 HelloWDM.sys = 1 即可在win7下正确安装,这里“MyDriver_Check”指定了子目录,不过笔者试过在XP下面,没有修改inf安装的话,会弹出一个选择框让你重新选择.s

hadoop应用开发技术详解

<大 数据技术丛书:Hadoop应用开发技术详解>共12章.第1-2章详细地介绍了Hadoop的生态系统.关键技术以及安装和配置:第3章是 MapReduce的使用入门,让读者了解整个开发过程:第4-5章详细讲解了分布式文件系统HDFS和Hadoop的文件I/O:第6章分析了 MapReduce的工作原理:第7章讲解了如何利用Eclipse来编译Hadoop的源代码,以及如何对Hadoop应用进行测试和调试:第8-9章 细致地讲解了MapReduce的开发方法和高级应用:第10-12章系统地讲