枚舉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;
}