1. 简介
Windows系统服务是一个不需要用户登入就可以一直在后台运行的服务程序,
通过服务管理控制器(Service Control Manager, SCM)可以操作系统服务启动、停止、自动运行等。
服务管理控制器(Service Control Manager, SCM) 维护着操作系统所有已安装的服务,
里面有关于服务是如何启动等信息,具有以下功能。
(1)在服务数据库中维护系统已安装的所有服务
(2)以自启动或手动的方式启动系统服务
(3)枚举所有已安装的服务
(4)维护服务的状态
(5)向运行的服务传输控制请求信息
(6)加锁或解锁服务数据库
2. 服务管理控制器数据库
在注册表中点击以下路径查看所有服务
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
2.1 OpenSCManager 打开SCM数据库
在操作服务管理数据库时,必须使用函数 OpenSCManager 打开数据库,获得句柄。
SC_HANDLE WINAPI OpenSCManager(
_In_opt_ LPCTSTR lpMachineName, /* 目标机器名称,NULL为本地机器 */
_In_opt_ LPCTSTR lpDatabaseName, /* 值一般为 SERVICES_ACTIVE_DATABASE */
_In_ DWORD dwDesiredAccess /* 特定权限访问服务数据库 */
);
API 参考链接 https://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx
2.2 CreateService 创建服务
系统服务的名字由 CreateService 函数定义,原型如下
此函数功能: 创建一个名为 lpServiceName 的服务对象,并且安装到服务控制管理器数据库中。
返回特定的已安装的服务对象句柄。
/* 成功返回SC_HANDLE类型的句柄,失败返回NULL */
SC_HANDLE WINAPI CreateService(
_In_ SC_HANDLE hSCManager, /* SCM数据库句柄对象,由 OpenSCManager函数返回 */ _In_ LPCTSTR lpServiceName, /* 安装服务的名称 */ _In_opt_ LPCTSTR lpDisplayName, /* 对用户显示的名称 */ _In_ DWORD dwDesiredAccess, /* 访问进程 */ _In_ DWORD dwServiceType, /* 服务类型 */ _In_ DWORD dwStartType, /* 服务启动选项 */ _In_ DWORD dwErrorControl, /* 错误等级 */ _In_opt_ LPCTSTR lpBinaryPathName, /* exe文件路径 */ _In_opt_ LPCTSTR lpLoadOrderGroup, /* 加载顺序 */ _Out_opt_ LPDWORD lpdwTagId, /* */ _In_opt_ LPCTSTR lpDependencies, _In_opt_ LPCTSTR lpServiceStartName, /* 服务应该在哪个用户下运行 DomainName/UserName */ _In_opt_ LPCTSTR lpPassword /* 用户密码 */ );
CreateService 接口示例代码 参考链接
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682450(v=vs.85).aspx
2.3 StartService 启动服务
服务配置管理器对服务的启动步骤如下
(1) 在 ServiceGroupOrder 列表中的系统将先启动。
(2) 在ServiceOrderList列表中的值也会启动
(3) 启动对于依赖的服务
当服务启动后,SCM执行以下步骤
(1)在数据库中获取用户账户信息
(2)登录服务账户
(3)加载用户信息
(4)创建一个挂起的服务
(5)分配登录口令给进程
(6)允许进程运行
开启服务由 StartService 函数定义
StartService 函数参考文档
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686321(v=vs.85).aspx
每个服务项都会记录相关信息 (ChangeServiceConfig 函数来修改记录)
* 服务名称
* 启动类型
* 服务状态 (SetServiceStatus 函数更新状态)
* 指向依赖服务的列表
CloseServiceHandle 函数关闭服务对象句柄
3. 服务程序
服务程是运行一个或多个系统服务的可执行代码。
3.1 服务程序入口
主函数的服务程序会调用 StartServiceDispatcher 函数连接SCM数据库并且启动dispatcher纯程。
dispacher线程循环等待 dispach 表中的请求控制。
当所有服务都结束时,SCM会发送一个控制请求通知dispacher线程退出。
然后 StartServiceDispacher 函数会退出
StartServiceCtrlDispatcher 使用 SERVICE_TABLE_ENTRY 结构来作为参数。
每个结构都指明了服务名称与服务入口函数
3.2 服务入口函数
服务入口函数会做以下事情
1. 初始化全局变量
2. 调用 RegisterServiceCtrlHandler 函数注册一个句柄来控制服务。
3. 执行初始化。
3.3 服务主函数
3.3 服务控制接收函数
每一个服务都有控制接收函数,一个服务调用 RegisterServiceCrtlHandler 函数注册服务控制器接收函数。
当服务控制器接收函数调用后,服务必须调用 SetServiceStatus 函数通知 SCM 服务状态是否改变。
服务器控制函数必须在30s内返回,否则SCM返回Error错误信息。
如果一个服务收到 SERVICE_CONTROL_STOP 控制代码,必须停止接收控制请求,进入 SERVICE_STOP_PENDING 或 SERVICE_STOPPED 状态。
如果用户关闭系统,则状态码会是 SERVICE_ACCEPT_PRESHUTDOWN, 则调用 SetServiceStatus进入 SERVICE_CONTROL_PRESHUTDOWN 状态。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。