Services
1 概述
1服务程序遵循Service Control Manager(SCM)的接口规则。 启动方式由3种:1 系统启动时自动启动;2 通过服务控制面板;3 通过使用服务函数。2服务可以在没有用户登录到系统的情况下运行。
2 驱动服务:驱动服务遵循设备驱动协议,它与服务程序类似,但是不与SCM交互。
3 The SCM processes service control notifications in a serial fashion
4 The default security descriptor allows the LocalSystem account, and members of the Administrators and Power Users groups to stop and start services.
2 服务在Win7中的新特性
1 可以注册一个服务,在一个特定事件发生时启动或者停止服务。
更新的函数
ChangeServiceConfig
|
Changes the configuration parameters of a service. This function supports managed service accounts and virtual accounts. For more information, see Service Accounts Step-by-Step Guide.
|
ChangeServiceConfig2
|
Changes the optional configuration parameters of a service. This function supports new configuration information levels for processor groups and service trigger events.
|
CreateService
|
Creates a service object and adds it to the specified service control manager database. This function supports managed service accounts and virtual accounts. For more information, see Service Accounts Step-by-Step Guide.
|
HandlerEx
|
An application-defined callback function used with the RegisterServiceCtrlHandlerEx function. This callback function supports new extended control codes for system time changes and service trigger events.
|
QueryServiceConfig2
|
Retrieves the optional configuration parameters of a service. This function supports new configuration information levels for processor groups and service trigger events.
|
SetServiceStatus
|
Updates the service control manager's status information for the calling service. This function supports new extended control codes for system time changes and service trigger events.
|
新的结构
Service Changes for Windows Vista
为了提高性能、可靠性、安全性、可管理性等,在Vista之后,服务提供了很多增强的特性。
Session 0 Isolation
服务总是运行在Session 0,在Vista之前,第一个用户也是运行在Session0,在Vista之后,第一个用户运行在Session1,第二个用户运行在Session2, 等等,这样用户程序和服务就始终运行在不同的Session上。Session 0 不支持与用户交互的进程。这就意味着Service不能向应用程序发送消息,应用程序也不能像Service发送消息。除此之外,Service还不能显示GUI,如对话框,但是Service可以使用WTSSendMessage 函数在另一个Session中显示对话框。
Delayed AutoStart 在系统启动的一小段时间(shortly after)内启动服务。
Failure Detection and Recovery:如果服务失败,SCM可以执行失败action,如重启服务。
Preshutdown Notifications:是服务有足够的时间来优雅的关闭。
Restricted Network Acess:
Running with Least Privilage:
关于服务
SCM维护者已安装的服务和驱动服务的数据库,并且提供了统一的安全的控制它们的方法。数据库信息包括每个服务如何被启动。
下面类型的程序使用SCM提供的函数:
服务程序(Service Program):一个为一个或者多个服务提供可执行代码的程序。服务程序使用连接到SCM的函数以及发送状态信息给SCM的函数。
服务配置程序(Service configuration program):一个查询和修改服务数据库的程序。服务配置程序使用打开数据库的函数,在数据库中安装和删除服务,对安装的服务查询和修改配置参数,安全参数。服务配置程序管理服务以及驱动服务。
服务控制程序(Service Control Program):一个启动并控制服务以及驱动服务的程序。服务控制程序使用发送请求到SCM的函数。
Service Control Manager(服务控制管理器)
1 系统启动时启动;它是一个RPC (Remote procedure call) 服务器。所以服务配置和服务控制程序可以在远程机器上管理服务。
提供接口功能:
管理安装服务的数据库;
启动服务(系统启动时,或者需要时)
枚举安装的服务
为运行的服务维护状态信息
传输控制请求(control request)给正在运行的服务
锁定和解锁服务数据库。
Database of installed service
在注册表中维护着已安装的服务列表。注册表如下
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
这个键值为每一个安装的服务包含一个子键,子键的名字就是服务名。
Database又叫作ServiceActive databse或者SCM database。你必须使用SCM提供的函数,而不能直接修改databse,即不能直接修改注册表。
自动启动服务
在系统启动的时候,SCM将启动所有自启动的服务以及它们依赖的服务。
启动顺序:
1 按加载启动组列表中的顺序;这个信息保存在ServiceGroupOrder值中,
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control
2 GroupOrderList
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control
3 每个服务的依赖列表
当启动完成后,系统执行启动认证程序(boot verification program)根据BootVerificationProgram
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control.
默认情况下,这个值是没有设置的。你可以提供程序来检测系统,调用NotifyBootConfigStatus通知SCM,报告boot 状态。
在成功重启后,系统会将组册表复制一份到下面目录下last-known-good (LKG) configuration
HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Services
按需启动服务
当服务启动之后,SCM执行下列步骤:
获取存储在数据库中的帐户信息
登录到服务帐户
加载用户配置
在暂停状态下创建服务
给进程分配一个Logon的token
允许进程执行
Service Record List
由于每个服务实体是从注册表数据库中读取的,因此SCM为每个服务创建了一个Service Record,
一个Service Record包括:
服务名
启动类型
服务状态(SERVICE_STATUS结构)
指向依赖服务列表的指针
服务在安装的时候用户名和密码是指定好的。SCM在注册表中存放用户名,在Local Security Authority(LSA)中存放密码。
SCM保存两份用户密码。一个当前密码和一个备份密码。在服务第一次安装的时候使用当前密码,备份密码是未初始化的。当用当前密码运行服务成功后,才会将当前密码写入到备份密码。SCM在收到服务状态通知后更新服务状态。
驱动服务的状态是通过查询IO系统获得的,而不是通过状态通知,这点是与Service不同的。
SCM Handles
SCM支持句柄(Handle)来访问下面的对象。
已安装的服务的数据库:用SCManager object来表示
服务:由一个安装的服务代表服务对象。
数据库锁
Service Programs服务程序
Main函数:
调用StartServiceCtrlDispatcher函数连接到SCM并启动control dispatcher线程。Control dispatcher线程循环loop,等待在dispatch table中指定的服务的请求。
例子:
void __cdecl _tmain(int argc, TCHAR *argv[])
{
// If command-line parameter is "install", install the service.
// Otherwise, the service is probably being started by the SCM.
if( lstrcmpi( argv[1], TEXT("install")) == 0 )
{
SvcInstall();
return;
}
// TO_DO: Add any additional services for the process to this table.
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
{ NULL, NULL }
};
// This call returns when the service has stopped.
// The process should simply terminate when the call returns.
if (!StartServiceCtrlDispatcher( DispatchTable ))
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
ServiceMain函数:
首先调用RegisterServiceCtrlHandler函数来注册SvcCtrHandler函数作为服务的处理函数,然后开始初始化。
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
// Register the handler function for the service
gSvcStatusHandle = RegisterServiceCtrlHandler(
SVCNAME,
SvcCtrlHandler);
if( !gSvcStatusHandle )
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
// These SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
// Report initial status to the SCM
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );
// Perform service-specific initialization and work.
SvcInit( dwArgc, lpszArgv );
}
//
// Purpose:
// The service code
//
// Parameters:
// dwArgc - Number of arguments in the lpszArgv array
// lpszArgv - Array of strings. The first string is the name of
// the service and subsequent strings are passed by the process
// that called the StartService function to start the service.
//
// Return value:
// None
//
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
// TO_DO: Declare and set any required variables.
// Be sure to periodically call ReportSvcStatus() with
// SERVICE_START_PENDING. If initialization fails, call
// ReportSvcStatus with SERVICE_STOPPED.
// Create an event. The control handler function, SvcCtrlHandler,
// signals this event when it receives the stop control code.
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
// Report running status when initialization is complete.
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
// TO_DO: Perform work until service stops.
while(1)
{
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
}
//
// Purpose:
// Sets the current service status and reports it to the SCM.
//
// Parameters:
// dwCurrentState - The current state (see SERVICE_STATUS)
// dwWin32ExitCode - The system error code
// dwWaitHint - Estimated time for pending operation,
// in milliseconds
//
// Return value:
// None
//
VOID ReportSvcStatus( DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ( (dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED) )
gSvcStatus.dwCheckPoint = 0;
else gSvcStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the SCM.
SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}
Control Handler函数:
该函数是由dispatcher thread调用的,它处理在OpCode参数中传进来的控制码,然后调用ReportSvcStatus函数来更新服务状态。当Handler收到控制码时,只有当收到的控制码引起服务状态变化时才报告服务状态。
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
{
// Handle the requested control code.
switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// Signal the service to stop.
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
Service Configuration Program Tasks服务配置程序的任务
安装服务
删除服务
改变服务配置
查询服务配置
Service Control Program Tasks服务控制程序任务
启动服务
停止服务
改变一个服务的DACL
Service Functions
The following functions are used or implemented by services.
The following functions are used by programs that control or configure services.
Service Structures
The following structures are used with services: