在windows驱动开发流程中,写完sys驱动binary之后,为了让OS能够正确的从注册表中读取到对应的信息,并且将其load运行起来,还需要编写inf文件来描述配置驱动文件。不过这也不是必须的,可以通过ServiceControlManager直接创建一个指定驱动binary的Service并且启动。如下code:
HANDLE hSCManager;
HANDLE hService;
hSCManager = OpenSCManagerW(
NULL, // 可以指定一个远端服务器名
SERVICES_ACTIVE_DATABASE, // 目前应当指定SERVICES_ACTIVE_DATABASE
SC_MANAGER_CREATE_SERVICE); // 指定该SCM需要进行的操作
if (hSCManager == NULL)
{
printf("\nOpenSCManager failed");
return false;
}
hService = CreateService(hSCManager, // 之前创建的SCM句柄
"Test", // 服务器名
"TestDriver", // 显示名
SERVICE_START | DELETE | SERVICE_STOP, // 拥有的操作
SERVICE_KERNEL_DRIVER, // 创建的服务类型,和普通的服务不同,指明了创建的服务为内核驱动
SERVICE_DEMAND_START, // 服务的启动选项,可以选择自动启动,手动启动,以及Demand Start,只有在明确调用的时候才会被启动,重启之后不会被启动。
SERVICE_ERROR_IGNORE, // 当服务出现error的时候会怎么处理
"C:\\TestDriver.sys", // 需要被load的binary文件
NULL, NULL, NULL, NULL, NULL // 一些组和权限的参数
);
if(!hService)
{
hService = OpenService(hSCManager,
"Example",
SERVICE_START | DELETE | SERVICE_STOP
);
}
if(hService == NULL)
{
printf("\nCreate or Open Service failed");
return false
}
StartService(hService, 0, NULL); // 启动之前创建的Driver Serivce。如果该服务是驱动,不需要传2,3的参数
而通常我们也会使用服务程序来控制或与驱动程序进行通信。所以先来介绍一下关于服务。
Service Control Manager管理着一个数据库,该数据库管理这所有的服务程序和驱动。并且提供了统一的访问控制方式。通过任务管理器就可以看到
可以看到里面由服务名,描述,以及状态。并且同通过右键可以控制。
同时SCM提供了一系列的API可以让开发者可以开发自己的服务,以及服务控制程序。
值得注意的一点是SCM不止是可以访问本地的服务database,如果具有远端的设备的权限则还能够管理远端的服务数据库。
要了解SCM就需要先知道它所管理的服务的基本信息。
服务程序
服务器程序本质上是一个控制台程序。入口点也是main。不同与普通的桌面应用程序,启动它的不再是用户,而是由服务管理器。当服务程序被服务管理器启动之后需要马上调用StartServiceCtrlDispatcher。从这里开始才是真正区别于桌面程序的地方。普通控制台程序当启动之后,基本就是将所有控制权力交给了开发者。而服务却需要服务启动之后第一时间在主线程中通过StartServiceCtrlDispatcher来注册ServiceMain回调函数。而在其中需要服务程序实现一系列的任务来相应SCM的各种控制指令,从而能够按照SCM的操作来进行响应。主要包含下列操作
- 调用RegisterServiceCtrlHandler来注册一个Handler来相应SCM所发送的所有的控制命令control code。例如SERVICE_CONTROL_SHUTDOWN,SERVICE_CONTROL_SHUTDOWN等。
- 服务本身需要通过SetServiceStatus来报告当前服务的状态,该状态也能在服务管理器中看到。例如初始化需要用较长时间时需要设置SERVICE_START_PENDING来在未初始化完毕时禁止接收来自于SCM的控制。
- 初始化任务完成之后需要将服务状态设置成SERVICE_RUNNING,此时SCM才会正常发送控制命令。
- 最后加入遇到了错误,需要负责设置服务SERVICE_STOP_PENDING和SERVICE_STOP从而报告当前服务停止,将错误码设置到SERVICE_STATUS中向SCM报告具体错误。
如果不考虑复杂场景下的实现,完成一个服务程序,完成上面所述的一些步骤就可以了。不过SCM为SC设计了一系列的状态转换,其中会对应于SCM对应的控制请求。具体如下图。
当实现一个服务程序之后,就能将器注册到服务数据库中,并且由SCM进行管理了。主要分为了配置和管理两种类型。