//用于windows服务和NT式驱动程序的安装,卸载,运行,停止操作。
//SCM.cpp
///
#define OPER_INSTALL 0x1 //安装
#define OPER_START 0x2 //运行
#define OPER_STOP 0x3 //停止
#define OPER_UNINSTALL 0x4 //卸载
#define OPER_UNKNOWN 0x5
#define IDX_SERV_OPER 1 //argv[1]:operation-type
#define IDX_SERV_NAME 2 //argv[2]:service name
#define IDX_SERV_PATH 3 //argv[3]:service path
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
SC_HANDLE hSCM;
SC_HANDLE hServ;
//提示错误信息
VOID ReportErr(int errCode)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errCode,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPTSTR)&lpMsgBuf,
0,
NULL);
if(lpMsgBuf != NULL)
printf("Err Info:\n%S\n", lpMsgBuf);
else
printf("can't format err message\n");
}
//创建服务
BOOL Create(LPTSTR lpszServiceName, LPTSTR lpszServicePath)
{
hServ = CreateService(hSCM,
lpszServiceName,
lpszServiceName,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE,
lpszServicePath,
NULL,NULL,NULL,NULL,NULL);
if(hServ == NULL)
return FALSE;
return TRUE;
}
//停止所有依赖服务。
BOOL StopDependentServices(SC_HANDLE schServ)
{
DWORD i, dwBytesNeeded, dwCount;
LPENUM_SERVICE_STATUS lpDependencies = NULL;
ENUM_SERVICE_STATUS ess;
SERVICE_STATUS_PROCESS ssp;
SC_HANDLE hDepServ;
if(EnumDependentServices(schServ,
SERVICE_ACTIVE,
lpDependencies,
0,
&dwBytesNeeded,
&dwCount))
{return TRUE;} //没有依赖的服务
else
{
if(GetLastError() != ERROR_MORE_DATA)
return FALSE;
lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBytesNeeded);
if(lpDependencies == NULL)
return FALSE;
__try
{
if(!EnumDependentServices(schServ,
SERVICE_ACTIVE,
lpDependencies,
0,
&dwBytesNeeded,
&dwCount))
return FALSE;
for(i=0; i<dwCount; i++)
{
ess = *(lpDependencies + i);
hDepServ = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
if(hDepServ == NULL)
return FALSE;
__try
{
if ( !ControlService( hDepServ,
SERVICE_CONTROL_STOP,
(LPSERVICE_STATUS) &ssp ) )
return FALSE;
// Wait for the service to stop.
while ( ssp.dwCurrentState != SERVICE_STOPPED )
{
Sleep( ssp.dwWaitHint );
if ( !QueryServiceStatusEx(
hDepServ,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
return FALSE;
if ( ssp.dwCurrentState == SERVICE_STOPPED )
break;
}
}
__finally
{
CloseServiceHandle(hDepServ);
}
}
}
__finally
{
HeapFree(GetProcessHeap(),0,lpDependencies);
}
}
return TRUE;
}
//停止服务
BOOL Stop(SC_HANDLE schServ)
{
SERVICE_STATUS_PROCESS ssp;
DWORD dwBytesNeeded;
if ( !QueryServiceStatusEx( schServ,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded )
)
{
printf("Stop faild.");
ReportErr(GetLastError());
return FALSE;
}
//服务没有运行
if ( ssp.dwCurrentState == SERVICE_STOPPED )
{
printf("Service is already stopped.\n");
return TRUE;
}
//服务处于待决状态
while ( ssp.dwCurrentState == SERVICE_STOP_PENDING )
{
Sleep( ssp.dwWaitHint );
if ( !QueryServiceStatusEx(
schServ,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
{
printf("Stop faild.");
ReportErr(GetLastError());
return FALSE;
}
if ( ssp.dwCurrentState == SERVICE_STOPPED )
{
printf("Service stopped successfully.\n");
return TRUE;
}
}
//停止所有依赖的服务
StopDependentServices(schServ);
if ( !ControlService( schServ,
SERVICE_CONTROL_STOP,
(LPSERVICE_STATUS) &ssp )
)
{
printf("Stop faild.");
ReportErr(GetLastError());
return FALSE;
}
while ( ssp.dwCurrentState != SERVICE_STOPPED )
{
Sleep( ssp.dwWaitHint );
if ( !QueryServiceStatusEx(
schServ,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
{
printf("Stop faild.");
ReportErr(GetLastError());
return FALSE;
}
if ( ssp.dwCurrentState == SERVICE_STOPPED )
break;
}
return TRUE;
}
//检查argv[3]传入的参数是否是有效文件路径
BOOL CheckFilePath(LPTSTR filePath)
{
HANDLE hFile = CreateFile(filePath,
FILE_ALL_ACCESS,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return FALSE;
CloseHandle(hFile);
return TRUE;
}
//获得操作类型
int GetOperation(LPTSTR argv)
{
size_t len = wcslen(argv);
if( _wcsnicmp(argv, L"install", len) == 0) return OPER_INSTALL;
if( _wcsnicmp(argv, L"start", len) == 0) return OPER_START;
if( _wcsnicmp(argv, L"stop", len) == 0) return OPER_STOP;
if( _wcsnicmp(argv, L"uninstall", len) == 0) return OPER_UNINSTALL;
return OPER_UNKNOWN;
}
VOID Usage()
{
printf("******************************************************\n");
printf("Usage: scm operation driverName driverPath.\n");
printf("语法: scm 操作类型 服务名称 服务文件路径.\n\n");
printf("operation: Specified the operation type.\n");
printf(" The operation type is:\n");
printf(" install\n");
printf(" uninstall\n");
printf(" start\n");
printf(" stop\n");
printf("driverName: The name of the driver to install.\n");
printf("driverPath: The fully-qualified path to the driver binary file.\n");
printf("******************************************************\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCM == NULL)
{
printf("Open Service Control Manager faild.\n");
ReportErr(GetLastError());
return 0;
}
//
int operation = OPER_UNKNOWN;
__try
{
// 处理Install
if(argc == 4)
{
operation = GetOperation(argv[IDX_SERV_OPER]);
if(operation == OPER_INSTALL)
{
if(!CheckFilePath(argv[IDX_SERV_PATH]))
{
printf("Install faild.The file path invalid.\n");
ReportErr(GetLastError());
__leave;
}
//
if(!Create(argv[IDX_SERV_NAME], argv[IDX_SERV_PATH]))
{
printf("Install faild.\n");
ReportErr(GetLastError());
__leave;
}
printf("The service '%S' installed successfully\n", argv[IDX_SERV_NAME]);
__leave;
}
operation = OPER_UNKNOWN;
}
//处理start,stop, uninstall
if(argc == 3)
{
operation = GetOperation(argv[IDX_SERV_OPER]);
if(operation != OPER_UNKNOWN)
{
hServ = OpenService(hSCM, argv[IDX_SERV_NAME],SERVICE_ALL_ACCESS);
if(hServ == NULL)
{
printf("Open service faild.\n");
ReportErr(GetLastError());
__leave;
}
switch(operation)
{
case OPER_START:
{
if(!StartService(hServ,0,NULL))
{
printf("Start service faild.\n");
ReportErr(GetLastError());
__leave;
}
printf("The service '%S' start runing...\n", argv[IDX_SERV_NAME]);
}
break;
case OPER_STOP:
if(Stop(hServ))
printf("The Service '%S' stopped successfully\n",argv[IDX_SERV_NAME]);
break;
case OPER_UNINSTALL:
{
Stop(hServ);
if(!DeleteService(hServ))
{
printf("Delete service '%S' faild.\n", argv[IDX_SERV_NAME]);
ReportErr(GetLastError());
__leave;
}
printf("The service '%S' deleted successfully.\n", argv[IDX_SERV_NAME]);
}
break;
default:
operation = OPER_UNKNOWN;
}
}
}
//错误的参数或operation-type
if(argc <2 || operation == OPER_UNKNOWN)
Usage();
}
__finally
{
if(hSCM)
CloseServiceHandle(hSCM);
if(hServ)
CloseServiceHandle(hServ);
}
return 0;
}