枚举NT services
闻怡洋·vchelp
下面的文章提供了访问NT中所有Service的功能,每次列举Services时,函数会返回一个列表。 列表的内容依赖于你所使用的参数。 (我认为这是一种很巧妙的编程方法,它极大的减轻了数据和函数的冗余,利用一个STATIC函数来产生本身对象的列表或者是来产生对象)
Class declaration:声明
class TTrixServiceInfo {
public:
CString ServiceName;
CString DisplayName;
CString BinaryPath;
DWORD ServiceType;
DWORD StartType;
DWORD ErrorControl;
DWORD CurrentState;
public:
TTrixServiceInfo();
TTrixServiceInfo& operator=(const TTrixServiceInfo& source);
CString GetServiceType(void);
CString GetStartType(void);
CString GetErrorControl(void);
CString GetCurrentState(void);
static TTrixServiceInfo *EnumServices(DWORD serviceType,
DWORD serviceState,DWORD *count);
};
Description:类的每一个实例都包含了SERVICE的各种信息,如果想得到SERVICE的列表,请调用TTrixServiceInfo::EnumServices(...)。
参数ServiceType的取值可能是:SERVICE_WIN32 and SERVICE_DRIVER.
参数ServiceState的取值可能是:SERVICE_ACTIVE and SERVICE_INACTIVE.
EnumServices(...)将返回TTrixServiceInfo对象的列表,(如果出错返回NULL)。列表中对象的个数可以通过参数返回时得到。
下面是具体的代码:
TTrixServiceInfo *lpservice = NULL;
DWORD count;
lpservice = TTrixServiceInfo::EnumServices(SERVICE_WIN32,SERVICE_ACTIVE|SERVICE_INACTIVE,&count/*得到个数*/);
if (lpservice) {//如果正确
for (DWORD index = 0; index < count; index ++) {
printf("%d. %s, %s\n", index, lpservice[index].DisplayName,
lpservice[index].GetCurrentState());
}
delete [] lpservice;
}
Source code:
TTrixServiceInfo::TTrixServiceInfo()
{
ServiceName.Empty();
DisplayName.Empty();
BinaryPath.Empty();
ServiceType = 0;
StartType = 0;
ErrorControl = 0;
CurrentState = 0;
}
TTrixServiceInfo& TTrixServiceInfo::operator=(const TTrixServiceInfo& source)
{
ServiceName = source.ServiceName;
DisplayName = source.DisplayName;
BinaryPath = source.BinaryPath;
ServiceType = source.ServiceType;
StartType = source.StartType;
ErrorControl = source.ErrorControl;
CurrentState = source.CurrentState;
return *this;
}
CString TTrixServiceInfo::GetServiceType(void)
{
// Winnt.h
CString str = "UNKNOWN";
if (ServiceType & SERVICE_WIN32) {
if (ServiceType &
SERVICE_WIN32_OWN_PROCESS)
str = "WIN32_OWN_PROCESS";
else if (ServiceType &
SERVICE_WIN32_SHARE_PROCESS)
str = "WIN32_SHARE_PROCESS";
if (ServiceType &
SERVICE_INTERACTIVE_PROCESS)
str += "(INTERACTIVE_PROCESS)";
}
switch (ServiceType) {
case SERVICE_KERNEL_DRIVER:
str = "KERNEL_DRIVER"; break;
case SERVICE_FILE_SYSTEM_DRIVER:
str = "FILE_SYSTEM_DRIVER";
break;
};
return str;
}
CString TTrixServiceInfo::GetStartType(void)
{
// Winnt.h
TCHAR *types[] = {
"BOOT_START", // 0
"SYSTEM_START", // 1
"AUTO_START", // 2
"DEMAND_START", // 3
"DISABLED" // 4
};
return CString(types[StartType]);
}
CString TTrixServiceInfo::GetErrorControl(void)
{
// Winnt.h
TCHAR *types[] = {
"ERROR_IGNORE", // 0
"ERROR_NORMAL", // 1
"ERROR_SEVERE", // 2
"ERROR_CRITICAL" // 3
};
return CString(types[ErrorControl]);
}
CString TTrixServiceInfo::GetCurrentState(void)
{
// Winsvc.h
TCHAR *types[] = {
"UNKNOWN",
"STOPPED", // 1
"START_PENDING", // 2
"STOP_PENDING", // 3
"RUNNING", // 4
"CONTINUE_PENDING", // 5
"PAUSE_PENDING", // 6
"PAUSED" // 7
};
return CString(types[CurrentState]);
}
// ServiceType = bit OR of SERVICE_WIN32, SERVICE_DRIVER
// ServiceState = bit OR of SERVICE_ACTIVE, SERVICE_INACTIVE
TTrixServiceInfo *TTrixServiceInfo::EnumServices(DWORD serviceType,DWORD
serviceState,DWORD *count)
{
// Maybe check if serviceType and serviceState have at least one constant specified
*count = 0;
TTrixServiceInfo *info = NULL;
SC_HANDLE scman = ::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);
if (scman) {
ENUM_SERVICE_STATUS service, *lpservice;
BOOL rc;
DWORD bytesNeeded,servicesReturned,resumeHandle = 0;
rc = ::EnumServicesStatus(scman,serviceType,serviceState,&service,sizeof(service),
&bytesNeeded,&servicesReturned,&resumeHandle);
if ((rc == FALSE) && (::GetLastError() == ERROR_MORE_DATA)) {
DWORD bytes = bytesNeeded + sizeof(ENUM_SERVICE_STATUS);
lpservice = new ENUM_SERVICE_STATUS [bytes];
::EnumServicesStatus(scman,serviceType,serviceState,lpservice,bytes,
&bytesNeeded,&servicesReturned,&resumeHandle);
*count = servicesReturned; // Not a chance that 0 services is returned
info = new TTrixServiceInfo [servicesReturned];
TCHAR Buffer[1024];
// Should be enough for service info
QUERY_SERVICE_CONFIG *lpqch = (QUERY_SERVICE_CONFIG*)Buffer;
for (DWORD ndx = 0; ndx < servicesReturned; ndx++) {
info[ndx].ServiceName = lpservice[ndx].lpServiceName;
info[ndx].DisplayName = lpservice[ndx].lpDisplayName;
info[ndx].ServiceType = lpservice[ndx].ServiceStatus.dwServiceType;
info[ndx].CurrentState = lpservice[ndx].ServiceStatus.dwCurrentState;
SC_HANDLE sh = ::OpenService(scman,lpservice[ndx].lpServiceName,SERVICE_QUERY_CONFIG);
if (::QueryServiceConfig(sh,lpqch,sizeof(Buffer),&bytesNeeded)) {
info[ndx].BinaryPath = lpqch->lpBinaryPathName;
info[ndx].StartType = lpqch->dwStartType;
info[ndx].ErrorControl = lpqch->dwErrorControl;
}
::CloseServiceHandle(sh);
}
delete [] lpservice;
}
::CloseServiceHandle(scman);
}
return info;
}