/*******************************************************
Copyright (c) 2004 by Michel van Kerkhof, ( michel000@planet.nl http://home.wxs.nl/~wijk0550/ )
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU
General Public License as published by the Free
Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU
General Public License along with this program;
if not, write to:
the Free Software Foundation, Inc.,
59 Temple Place,
Suite 330, Boston,
MA 02111-1307 USA
*******************************************************
This source shows you how to use EnumServicesStatusEx
*******************************************************/
#include <windows.h>
#include <stdio.h>
typedef enum _SC_ENUM_TYPE {
SC_ENUM_PROCESS_INFO=0
} SC_ENUM_TYPE;
typedef BOOL (WINAPI *pEnumServicesStatusExA)(
SC_HANDLE,
SC_ENUM_TYPE,
DWORD,
DWORD,
LPBYTE,
DWORD,
LPDWORD,
LPDWORD,
LPDWORD,
LPCSTR
);
typedef struct _SERVICE_STATUS_PROCESS {
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
DWORD dwProcessId;
DWORD dwServiceFlags;
} SERVICE_STATUS_PROCESS,*LPSERVICE_STATUS_PROCESS;
typedef struct _ENUM_SERVICE_STATUS_PROCESSA {
LPSTR lpServiceName;
LPSTR lpDisplayName;
SERVICE_STATUS_PROCESS ServiceStatusProcess;
} ENUM_SERVICE_STATUS_PROCESSA,*LPENUM_SERVICE_STATUS_PROCESSA;
/*
Function shows all running services including process id and description
lpMachineName = Name of the computer to enum the services for or NULL for the local computer
*/
int EnumServices(LPCTSTR lpMachineName)
{
pEnumServicesStatusExA fnEnumServicesStatusExA;
HMODULE hAdvapi32;
ENUM_SERVICE_STATUS_PROCESSA *lpServiceStatus;
DWORD dwSize=0,
dwNumServices=0,
dwResumeHandle=0;
SC_HANDLE scHandle=NULL;
int iRet;
void *lpBuffer=NULL;
char szBuffer[1024];
try {
//load advapi32.dll
hAdvapi32=LoadLibrary("advapi32.dll");
if (hAdvapi32 == NULL) {
throw("Could not load advapi32.dll");
}
//load EnumServicesStatusExA from advapi32.dll
fnEnumServicesStatusExA=(pEnumServicesStatusExA)GetProcAddress(hAdvapi32,"EnumServicesStatusExA");
if (fnEnumServicesStatusExA == NULL) {
throw("Could not load EnumServicesStatusExA\n");
}
/*
establishes a connection to the service control manager on the specified computer
if lpMachineName == NULL its the local computer
*/
scHandle=OpenSCManager(lpMachineName,NULL,SC_MANAGER_ALL_ACCESS);
if (scHandle == NULL) {
throw("Could not connect to the service control manager\n");
}
do {
/*
First time dwResumeHandle needs to be 0
and dwSize = 0 after return it is set to the size needed
normaly it will only loop 2 times
first time to get size of the buffer
second time to fill the allocated buffer
*/
iRet=fnEnumServicesStatusExA(
scHandle,
SC_ENUM_PROCESS_INFO,
SERVICE_WIN32,
SERVICE_ACTIVE,
(LPBYTE)lpBuffer,
dwSize,
&dwSize,
&dwNumServices,
&dwResumeHandle,
0
);
/*
iRet is always 0 the first time because dwSize was 0
*/
if (iRet == 0 && GetLastError() != ERROR_MORE_DATA) {
throw("Error getting list with services\n");
}
lpServiceStatus=(ENUM_SERVICE_STATUS_PROCESSA *)lpBuffer;
//first time dwNumServices == 0 so we dont loop the first time
if (dwNumServices > 0) {
HKEY hKey,hSubKey;
/*
Connect to registry to get service description
this is not needed if lpMachineName is the local computer or NULL
*/
if (RegConnectRegistry(lpMachineName,HKEY_LOCAL_MACHINE,&hKey) != ERROR_SUCCESS) {
hKey=NULL;
}
for (DWORD dwCount=0;dwCount<dwNumServices;dwCount++)
{
printf("Pid:%i %s: %s\n",
lpServiceStatus[dwCount].ServiceStatusProcess.dwProcessId,
lpServiceStatus[dwCount].lpServiceName,
lpServiceStatus[dwCount].lpDisplayName
);
if (hKey) {
//create registry string
sprintf(szBuffer,"SYSTEM\\CurrentControlSet\\Services\\%s",lpServiceStatus[dwCount].lpServiceName);
if (RegOpenKeyEx(hKey,szBuffer,0,KEY_QUERY_VALUE,&hSubKey) == ERROR_SUCCESS) {
DWORD dwType,dwSize=sizeof(szBuffer);
if (RegQueryValueEx(hSubKey,"Description",NULL,&dwType,(unsigned char *)szBuffer,&dwSize) == ERROR_SUCCESS && dwType == REG_SZ) {
printf("Service description:%s\n",szBuffer);
}
RegCloseKey(hSubKey);
}
}
printf("\n");
}
//close the key opened by RegConnectRegistry
if (hKey) RegCloseKey(hKey);
}
if (lpBuffer) {
free(lpBuffer);
lpBuffer=NULL;
}
if (iRet == 0) { //not all entry's returned normaly this only happens the first time we loop
//allocate memory
lpBuffer=malloc(dwSize);
if (lpBuffer == NULL) throw("Error allocating memory for buffer");
}
} while (iRet == 0);
throw("End EnumServices");
}
catch(char * szError)
{
if (scHandle) CloseServiceHandle(scHandle);
if (lpBuffer) free(lpBuffer);
printf("%s\n",szError);
}
return 0;
}
int main()
{
printf("\nEnumServicesStatusEx example\n");
printf("Refer any questions to michel000@planet.nl\n\n");
EnumServices(NULL); //enum services for the local computer
return 0;
}
|