Windows驱动开发(6)

今天顺便再解决一下应用层加载卸载驱动的方式。

加载驱动

加载驱动过程

  1. 用OpenSCManager打开服务控制管理器
  2. 用CreateService创建对应服务
  3. 如果驱动服务已经创建过,则用OpenService打开服务
  4. 用StartService加载启动驱动服务
  5. 清理工作,用CloseServiceHandle关闭释放句柄

一个一个介绍一下每一步的详细步骤吧

打开服务控制管理器

使用如下代码获得一个SCM管理器的句柄。

1
SC_HANDLE hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  • 第一个参数是目标计算机的名称。 如果指针为 NULL 或指向空字符串,则该函数将连接到本地计算机上的服务控制管理器。
  • 第二个参数是服务控制管理器数据库的名称。 此参数应设置为SERVICES_ACTIVE_DATABASE。 如果为 NULL,则默认打开SERVICES_ACTIVE_DATABASE数据库。
  • 第三个参数是我们获得句柄的权限,SC_MANAGER_ALL_ACCESS 表示获得所有权限。

创建服务

使用如下代码去创建服务,获得该服务的管理句柄:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hServiceDDK = CreateServiceA(
hServiceMgr,//manager管理句柄
DriverName,//驱动程序的在注册表中的名字
DriverName,//注册表驱动程序的DisplayName值
SERVICE_START,//加载驱动程序的访问权限 SERVICE_START 或者 SERVICE_ALL-ACCESS
SERVICE_KERNEL_DRIVER,//表示加载的服务是驱动程序
SERVICE_DEMAND_START,//注册表驱动程序的Start值
SERVICE_ERROR_NORMAL,//SERVICE_ERROR_IGNORE,//注册表驱动程序的ErrorControl值//指定当进程调用StartService函数时由服务控制管理器启动的服务。
FullPath,//sys完整路径
NULL,
NULL,
NULL,
NULL,
NULL
);

具体参数表示的意思已经标明。

如果已经存在,则打开服务

我们需要判断此服务是否被创建过了,如果创建过了则 GetLastError 会返回一个 ERROR_SERVICE_EXISTS。

1
2
3
4
if (GetLastError() == ERROR_SERVICE_EXISTS) {
printf("Service Already Exists\n");
hServiceDDK = OpenServiceA(hServiceMgr, DriverName, SERVICE_START);
}

用StartService加载启动驱动服务

直接启动:

1
int bRet = StartService(hServiceDDK, NULL, NULL);

如果返回 1,则成功,如果为 0 则表示失败。

完整代码形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <winsvc.h>
void LoadDriver(const char * DriverName, const char * DriverPath) {
char FullPath[256] = { 0 };
GetFullPathNameA(DriverPath, 256, FullPath, NULL);
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
printf("Open SCM handle=%p,GetLastError=%p\n", hServiceMgr, GetLastError());
hServiceDDK = CreateServiceA(
hServiceMgr,
DriverName,//驱动程序的在注册表中的名字
DriverName,//注册表驱动程序的DisplayName值
SERVICE_START,//加载驱动程序的访问权限 SERVICE_START 或者 SERVICE_ALL-ACCESS
SERVICE_KERNEL_DRIVER,//表示加载的服务是驱动程序
SERVICE_DEMAND_START,//注册表驱动程序的Start值
SERVICE_ERROR_NORMAL,//SERVICE_ERROR_IGNORE,//注册表驱动程序的ErrorControl值//指定当进程调用StartService函数时由服务控制管理器启动的服务。
FullPath,//szDriverImagePath注册表驱动程序的路径如:C:\\222\1.sys
NULL,//GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
NULL,
NULL,
NULL,
NULL
);

if (GetLastError() == ERROR_SERVICE_EXISTS) {
printf("Service Already Exists\n");
hServiceDDK = OpenServiceA(hServiceMgr, DriverName, SERVICE_START);
}
printf("hServiceDDK=%p\n", hServiceDDK);
int bRet = StartService(hServiceDDK, NULL, NULL);
if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
printf("Service Already Running\n");
}
else {
if (bRet == 0) {
printf("Service Running Failed\n");
}
else {
printf("Service Start Success\n");
}
}
}

int main()
{
LoadDriver("xia0ji233", ".\\KMDFDriver2.sys");
}

卸载驱动

大概步骤是这样的:

  1. 获取服务控制管理器句柄
  2. OpenService 打开加载中的服务获取服务句柄
  3. ControlService 停止服务
  4. DeleteService 删除服务

同样也是一步步讲解——

获取服务控制管理器句柄

一样的。

打开服务句柄

跟上面那个,如果服务存在,则打开服务,一样的操作,但是这里需要获取 ALL_ACCESS 的权限

1
hServiceDDK = OpenServiceA(hServiceMgr, ServeName, SERVICE_ALL_ACCESS);

停止服务

用 ControlService API 去先去停止服务。

1
2
3
int bRet = 0;
SERVICE_STATUS status;
bRet = ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &status);

删除服务

最后调用 DeleteService 去删除服务。

1
bRet=DeleteService(hServiceDDK);

大概就是这样的一个过程还挺简单的,加载驱动和卸载驱动都没有特别难。

代码汇总

以下是一个加载驱动和卸载驱动一体的代码,中间相隔 System pause,这里输入一个回车可以直接卸载驱动,用于快速加载驱动,然后再处理一下报错信息就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <winsvc.h>
void LoadDriver(const char * ServeName, const char * DriverPath) {
char FullPath[256] = { 0 };
GetFullPathNameA(DriverPath, 256, FullPath, NULL);
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
printf("Open SCM handle=%p,GetLastError=%p\n", hServiceMgr, GetLastError());
hServiceDDK = CreateServiceA(
hServiceMgr,
ServeName,//驱动程序的在注册表中的名字
ServeName,//注册表驱动程序的DisplayName值
SERVICE_START,//加载驱动程序的访问权限 SERVICE_START 或者 SERVICE_ALL-ACCESS
SERVICE_KERNEL_DRIVER,//表示加载的服务是驱动程序
SERVICE_DEMAND_START,//注册表驱动程序的Start值
SERVICE_ERROR_NORMAL,//SERVICE_ERROR_IGNORE,//注册表驱动程序的ErrorControl值//指定当进程调用StartService函数时由服务控制管理器启动的服务。
FullPath,//szDriverImagePath注册表驱动程序的路径如:C:\\222\1.sys
NULL,//GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
NULL,
NULL,
NULL,
NULL
);



if (GetLastError() == ERROR_SERVICE_EXISTS) {
printf("Service Already Exists\n");
hServiceDDK = OpenServiceA(hServiceMgr, ServeName, SERVICE_START);
}
else if (GetLastError() != 0) {
printf("GetLastError=%p\n", GetLastError());

return;
}
printf("hServiceDDK=%p\n", hServiceDDK);
int bRet = StartService(hServiceDDK, NULL, NULL);
if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
printf("Service Already Running\n");
}
else {
if (bRet == 0) {
printf("Service Running Failed\n");
printf("GetLastError=%p\n", GetLastError());
}
else {
printf("Service Start Success\n");
}
}
}
void UnloadDriver(const char *ServeName) {
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
printf("Open SCM handle=%p,GetLastError=%p\n", hServiceMgr, GetLastError());
hServiceDDK = OpenServiceA(hServiceMgr, ServeName, SERVICE_ALL_ACCESS);
if (hServiceDDK) {
int bRet = 0;
SERVICE_STATUS status;
bRet = ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &status);
if (bRet) {
puts("Stop Service Success");
}
else {
puts("Can't Stop Service");
goto GETLASTERROR;
}
bRet=DeleteService(hServiceDDK);
if (bRet) {
puts("Unload Success");
}
else {
puts("Unload Fail");
}
GETLASTERROR:
printf("GetLastError=%p\n", GetLastError());
}
else {
printf("OpenServe Failed\n");
}
}
int main()
{
LoadDriver("xia0ji233", ".\\KMDFDriver2.sys");
system("pause");
UnloadDriver("xia0ji233");
}

运行结果:

文章目录
  1. 1. 加载驱动
    1. 1.1. 打开服务控制管理器
    2. 1.2. 创建服务
    3. 1.3. 如果已经存在,则打开服务
    4. 1.4. 用StartService加载启动驱动服务
    5. 1.5. 完整代码形式
  2. 2. 卸载驱动
    1. 2.1. 获取服务控制管理器句柄
    2. 2.2. 打开服务句柄
    3. 2.3. 停止服务
    4. 2.4. 删除服务
  3. 3. 代码汇总
|