diff --git a/src/os/win32/sigar_os.h b/src/os/win32/sigar_os.h index 3bf27cac..b1dd6cec 100644 --- a/src/os/win32/sigar_os.h +++ b/src/os/win32/sigar_os.h @@ -576,6 +576,17 @@ int sigar_cpu_info_get(sigar_t *sigar, sigar_cpu_info_t *info); int sigar_service_pid_get(sigar_t *sigar, char *name, sigar_pid_t *pid); +typedef struct { + DWORD size; + DWORD count; + ENUM_SERVICE_STATUS *services; + SC_HANDLE handle; +} sigar_services_status_t; + +int sigar_services_status_get(sigar_services_status_t *ess, DWORD state); + +void sigar_services_status_close(sigar_services_status_t *ess); + #define SIGAR_NO_SUCH_PROCESS (SIGAR_OS_START_ERROR+1) #endif /* SIGAR_OS_H */ diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index 39dd60fb..7915a67d 100644 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -3407,3 +3407,53 @@ int sigar_service_pid_get(sigar_t *sigar, char *name, sigar_pid_t *pid) return rc; } + +int sigar_services_status(sigar_services_status_t *ss, DWORD state) +{ + DWORD bytes, resume=0; + BOOL retval; + + if (!ss->handle) { + ss->handle = + OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); + if (!ss->handle) { + return GetLastError(); + } + } + + retval = EnumServicesStatus(ss->handle, + SERVICE_WIN32, state, + ss->services, ss->size, + &bytes, &ss->count, &resume); + if (retval == FALSE) { + DWORD err = GetLastError(); + if (err != ERROR_MORE_DATA) { + return err; + } + + ss->services = realloc(ss->services, bytes); + ss->size = bytes; + + retval = EnumServicesStatus(ss->handle, + SERVICE_WIN32, state, + ss->services, ss->size, + &bytes, &ss->count, &resume); + + if (retval == FALSE) { + return GetLastError(); + } + } + + return SIGAR_OK; +} + +void sigar_services_status_close(sigar_services_status_t *ss) +{ + if (ss->handle) { + CloseServiceHandle(ss->handle); + } + if (ss->size) { + free(ss->services); + } + SIGAR_ZERO(ss); +}