Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55718
  • 博文数量: 13
  • 博客积分: 1455
  • 博客等级: 上尉
  • 技术积分: 150
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-09 09:53
文章分类

全部博文(13)

文章存档

2012年(1)

2011年(2)

2010年(10)

我的朋友

分类: WINDOWS

2010-10-28 22:12:25

取得配置权限
 
在对服务进行管理设置前,需要以相应的权限打开服务,可通过下面两个API实现
 
SC_HANDLE OpenSCManager(
 LPCTSTR lpMachineName, // pointer to machine name string
 LPCTSTR lpDatabaseName, // pointer to database name string
 DWORD dwDesiredAccess   // type of access
);
 
SC_HANDLE OpenService(
 SC_HANDLE hSCManager, // handle to service control manager
                         // database
 LPCTSTR lpServiceName, // pointer to name of service to start
 DWORD dwDesiredAccess // type of access to service
);
 
通常我们以完全权限打开,示例代码如下:
 
    SC_HANDLE scm;
    SC_HANDLE service;
 
 
    if((scm=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))==NULL)
    {
        Printf("OpenSCManager Error\n");
    }
 
    service=OpenService(scm,ServerName,SERVICE_ALL_ACCESS);
   
    if(!service)
    {
       Printf("OpenService error!\n");
    }
 
 
这样就可以通过service句柄对服务进行各种操作了
 
 
 
枚举基本服务信息
 
想要对服务进行设置就需要知道服务的当前信息,对我们有用的通常是以下几项
服务名称,显示名称,启动状态,启动方式,程序路径等。
这些信息我们可以通过API函数EnumServicesStatus来实现,它的原形如下:
 
BOOL EnumServicesStatus(
 SC_HANDLE hSCManager, // handle to service control manager database
 DWORD dwServiceType,     // type of services to enumerate
 DWORD dwServiceState,    // state of services to enumerate
 LPENUM_SERVICE_STATUS lpServices,
                           // pointer to service status buffer
 DWORD cbBufSize,         // size of service status buffer
 LPDWORD pcbBytesNeeded, // pointer to variable for bytes needed
 LPDWORD lpServicesReturned,
                           // pointer to variable for number returned
 LPDWORD lpResumeHandle   // pointer to variable for next entry
);
 
 
其中 LPENUM_SERVICE_STATUS lpServices是一个结构,它的原形如下:
 
typedef struct _ENUM_SERVICE_STATUS { // ess
    LPTSTR lpServiceName;
    LPTSTR lpDisplayName;
    SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;
 
结构中包含服务名称,显示名称,启动状态。虽然它所返回的信息是及为有限的,但它是一次枚举所有服务信息
在要求不高的情况下,用它还是相当方便的,下面的示例代码可以枚举系统中所有服务的基本信息,代码如下:
 
    LPENUM_SERVICE_STATUS lpServices    = NULL;
    DWORD    nSize = 0;
    DWORD    n;
    DWORD    nResumeHandle = 0;
 
    lpServices = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, 64 * 1024);      //注意分配足够的空间
    EnumServicesStatus(scm,SERVICE_WIN32,
                       SERVICE_STATE_ALL,
                       (LPENUM_SERVICE_STATUS)lpServices,
                        64 * 1024,
                        &nSize,
                        &n,
                        &nResumeHandle);
    for ( i = 0; i < n; i++)
    {
        Printf("服务名称: %s",lpServices[i].lpServiceName);
        Printf("显示名称: %s",lpServices[i].lpDisplayName);
        if ( lpServices[i].ServiceStatus.dwCurrentState!=SERVICE_STOPPED)
        {
            Printf("启动状态:    已启动\n");
        }
    }
 
 
枚举详细服务信息
 
如果想得到更详细的服务信息,我们可以使用另一个API函数QueryServiceConfig
它的原形如下:
 
BOOL QueryServiceConfig(
 SC_HANDLE hService, // handle of service
 LPQUERY_SERVICE_CONFIG lpServiceConfig,
                       // address of service config. structure
 DWORD cbBufSize,     // size of service configuration buffer
 LPDWORD pcbBytesNeeded   // address of variable for bytes needed
);
 
LPQUERY_SERVICE_CONFIG lpServiceConfig是一个结构,它包含指定服务的详细资料,它的原形如下
 
typedef struct _QUERY_SERVICE_CONFIG { // qsc
    DWORD dwServiceType;
    DWORD dwStartType;
    DWORD dwErrorControl;
    LPTSTR lpBinaryPathName;
    LPTSTR lpLoadOrderGroup;
    DWORD dwTagId;
    LPTSTR lpDependencies;
    LPTSTR lpServiceStartName;
    LPTSTR lpDisplayName;
} QUERY_SERVICE_CONFIG, LPQUERY_SERVICE_CONFIG;
 
很清楚了吧,服务类型,启动类型,程序路径,服务名称,显示名称尽在其中。
下面的示例代码可以得到程序路径,启动方式,其代码如下:
 
    LPQUERY_SERVICE_CONFIG ServicesInfo = NULL;
 
    for ( i = 0; i < n; i++)
    {
        SC_HANDLE service = NULL;
        DWORD     nResumeHandle = 0;
 
        service=OpenService(scm,lpServices[i].lpServiceName,SERVICE_ALL_ACCESS);
        ServicesInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 64 * 1024);      //注意分配足够的空间
        QueryServiceConfig(service,ServicesInfo,64 * 1024,&nResumeHandle);      //枚举各个服务信息
 
        Printf("程序路径: %s",ServicesInfo->lpBinaryPathName);
        if(2==ServicesInfo->dwStartType)        //启动方式
        {
            Printf("自动\n");
        }
        if(3==ServicesInfo->dwStartType)
        {
            Printf("手动\n");
        }
        if(4==ServicesInfo->dwStartType)
        {
            Printf("禁止\n");
        }
       
    }
 
上面的代码稍加修改就可以用到你的程序中,现在对于服务信息的显示就完成了。
 
 
启动/停止服务
 
 
启动一个服务可以用StartService函数实现,不过在启动前先用QueryServiceStatus检查一下服务的运行状态,如下代码
 
    SERVICE_STATUS status;
        BOOL isSuccess=QueryServiceStatus(service,&status);
        if (!isSuccess)
    {
        Printf("QueryServiceStatus error!\n");
    }
 
        if ( status.dwCurrentState==SERVICE_STOPPED )
    {
        isSuccess=StartService(service,NULL,NULL);
 
        if (!isSuccess)
        {
             Printf("启动服务失败!");
        }
 
    }
下面是停止服务的实现代码:
 
    if ( status.dwCurrentState!=SERVICE_STOPPED )
    {
        isSuccess=ControlService(service,SERVICE_CONTROL_STOP,&status);
        if (!isSuccess )
        {
                 Printf("停止服务失败!");
        }
    }
 
 
创建/删除服务
 
 
创建服务使用的API为CreateService,它的原形为:
 
SC_HANDLE CreateService(
 SC_HANDLE hSCManager, // handle to service control manager
                         // database
 LPCTSTR lpServiceName, // pointer to name of service to start
 LPCTSTR lpDisplayName, // pointer to display name
 DWORD dwDesiredAccess, // type of access to service
 DWORD dwServiceType,   // type of service
 DWORD dwStartType,     // when to start service
 DWORD dwErrorControl, // severity if service fails to start
 LPCTSTR lpBinaryPathName, // pointer to name of binary file
 LPCTSTR lpLoadOrderGroup, // pointer to name of load ordering
                             // group
 LPDWORD lpdwTagId,     // pointer to variable to get tag identifier
 LPCTSTR lpDependencies, // pointer to array of dependency names
 LPCTSTR lpServiceStartName,
                           // pointer to account name of service
 LPCTSTR lpPassword       // pointer to password for service account
);
 
其中 DWORD dwStartType是指动方式,有三种方式
 
SERVICE_AUTO_START      //自动
SERVICE_DEMAND_START        //手动
SERVICE_DISABLED        //禁用
 
此函数的参比较多但我们通常只用其中的一部分,如
 SC_HANDLE hSCManager,        //用OpenSCManager打开的句柄
 LPCTSTR lpServiceName,        // 服务名称
 LPCTSTR lpDisplayName,        // 显示名称
 DWORD dwStartType,           // 启动方式
 LPCTSTR lpBinaryPathName,    // 程序路径
 
其它直接赋0或NULL就可以了
例如下面的代码可以创建一个名为 LengFeng 路径为C:\LengFeng.EXE的自启动服务
 
void CreateServer()
{
        SC_HANDLE scm=NULL;
        SC_HANDLE service=NULL;
 
        if((scm=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE))==NULL)
        {
            Printf("OpenSCManager Error");
        }
        service=CreateService(
                scm,"LengFeng" ,"LengFeng" ,
                SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
                "C:\LengFeng.EXE", 0, 0, 0, 0, 0 );
        if(!service)
        Printf("服务创建失败");
 
        CloseServiceHandle(service);
        CloseServiceHandle(scm);
}
 
删除服务更容易些,可以用DeleteService来实现
 
BOOL DeleteService( SC_HANDLE hService);
 
SC_HANDLE hService是我们以前用OpenService打开的服务句柄,在删除前注意先用,启动/停止服务中介绍的方法
停止正在运行的服务。
 
 
配置启动方式
 
 
 
有时候我们需要对服务的启动方式进行更改,比如TELNET改为自动运行,对以存在的服务进行配置
可以用ChangeServiceConfig来实现,它的原形如下:
 
BOOL ChangeServiceConfig(
 SC_HANDLE hService     // handle to service
 DWORD dwServiceType,   // type of service
 DWORD dwStartType,     // when to start service
 DWORD dwErrorControl, // severity if service fails to start
 LPCTSTR lpBinaryPathName, // pointer to service binary file name
 LPCTSTR lpLoadOrderGroup, // pointer to load ordering group name
 LPDWORD lpdwTagId,     // pointer to variable to get tag identifier
 LPCTSTR lpDependencies,    // pointer to array of dependency names
 LPCTSTR lpServiceStartName,
                             // pointer to account name of service
 LPCTSTR lpPassword,   // pointer to password for service account
 LPCTSTR lpDisplayName      // pointer to display name
);
 
揉揉眼睛仔细看一下,是不是有点面熟?嘿它的参数跟创建服务的CreateService就是一样的嘛!这样就好办了
我们把需要的地方改掉,不需要的就放个NULL或SERVICE_NO_CHANGE就行了。
为了安全更新配置信息,微软要求在执行ChangeServiceConfig之前需要用LockServiceDatabase来锁定服务数据
偶测试了一下,有时候会锁定失败,但仍然可以实现对服务配置的更改。
下面的示例代码,可以把上面创建的LengFeng服务的启动方式改为 禁止
其代码如下:
 
    SC_LOCK sclLock;
    sclLock = LockServiceDatabase(scm);
    if (sclLock == NULL)
    {
       
        if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED)
            Printf("LockServiceDatabase error\n");
  
    }
    if (! ChangeServiceConfig(
        service,        // handle of service
        SERVICE_NO_CHANGE, // service type: no change
        SERVICE_DISABLED, // 这里做了更改
        SERVICE_NO_CHANGE, // error control: no change
        NULL,              // binary path: no change
        NULL,              // load order group: no change
        NULL,              // tag ID: no change
        NULL,              // dependencies: no change
        NULL,              // account name: no change
     NULL,          // password: no change
     NULL))     //displayname
    {
        Printf("ChangeServiceConfig error!\n");
    }
    UnlockServiceDatabase(sclLock);

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/houjinfeng210/archive/2010/05/11/5577758.aspx
阅读(701) | 评论(0) | 转发(0) |
0

上一篇:EIP EBP ESP

下一篇:CSOCKT CFILE实现文件传输

给主人留下些什么吧!~~