int SERVICE_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result) { ENUM_SERVICE_STATUS_PROCESS *ssp = NULL; QUERY_SERVICE_CONFIG *qsc = NULL; SERVICE_DESCRIPTION *scd = NULL; SC_HANDLE h_mgr; DWORD sz = 0, szn, i, k, services, resume_handle = 0; char *utf8; struct zbx_json j; if (NULL == (h_mgr = OpenSCManager(NULL, NULL, GENERIC_READ))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain system information.")); return SYSINFO_RET_FAIL; } zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); while (0 != EnumServicesStatusEx(h_mgr, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)ssp, sz, &szn, &services, &resume_handle, NULL) || ERROR_MORE_DATA == GetLastError()) { for (i = 0; i < services; i++) { SC_HANDLE h_srv; DWORD current_state; if (NULL == (h_srv = OpenService(h_mgr, ssp[i].lpServiceName, SERVICE_QUERY_CONFIG))) continue; QueryServiceConfig(h_srv, NULL, 0, &sz); if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { zabbix_log(LOG_LEVEL_DEBUG, "cannot obtain configuration of service \"%s\": %s", ssp[i].lpServiceName, strerror_from_system(GetLastError())); goto next; } qsc = (QUERY_SERVICE_CONFIG *)zbx_malloc(qsc, sz); if (0 == QueryServiceConfig(h_srv, qsc, sz, &sz)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot obtain configuration of service \"%s\": %s", ssp[i].lpServiceName, strerror_from_system(GetLastError())); goto next; } QueryServiceConfig2(h_srv, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &sz); if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { zabbix_log(LOG_LEVEL_DEBUG, "cannot obtain description of service \"%s\": %s", ssp[i].lpServiceName, strerror_from_system(GetLastError())); goto next; } scd = (SERVICE_DESCRIPTION *)zbx_malloc(scd, sz); if (0 == QueryServiceConfig2(h_srv, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)scd, sz, &sz)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot obtain description of service \"%s\": %s", ssp[i].lpServiceName, strerror_from_system(GetLastError())); goto next; } zbx_json_addobject(&j, NULL); utf8 = zbx_unicode_to_utf8(ssp[i].lpServiceName); zbx_json_addstring(&j, "{#SERVICE.NAME}", utf8, ZBX_JSON_TYPE_STRING); zbx_free(utf8); utf8 = zbx_unicode_to_utf8(ssp[i].lpDisplayName); zbx_json_addstring(&j, "{#SERVICE.DISPLAYNAME}", utf8, ZBX_JSON_TYPE_STRING); zbx_free(utf8); if (NULL != scd->lpDescription) { utf8 = zbx_unicode_to_utf8(scd->lpDescription); zbx_json_addstring(&j, "{#SERVICE.DESCRIPTION}", utf8, ZBX_JSON_TYPE_STRING); zbx_free(utf8); } else zbx_json_addstring(&j, "{#SERVICE.DESCRIPTION}", "", ZBX_JSON_TYPE_STRING); current_state = ssp[i].ServiceStatusProcess.dwCurrentState; for (k = 0; k < ARRSIZE(service_states) && current_state != service_states[k]; k++) ; zbx_json_adduint64(&j, "{#SERVICE.STATE}", k); zbx_json_addstring(&j, "{#SERVICE.STATENAME}", get_state_string(current_state), ZBX_JSON_TYPE_STRING); utf8 = zbx_unicode_to_utf8(qsc->lpBinaryPathName); zbx_json_addstring(&j, "{#SERVICE.PATH}", utf8, ZBX_JSON_TYPE_STRING); zbx_free(utf8); utf8 = zbx_unicode_to_utf8(qsc->lpServiceStartName); zbx_json_addstring(&j, "{#SERVICE.USER}", utf8, ZBX_JSON_TYPE_STRING); zbx_free(utf8); if (SERVICE_AUTO_START == qsc->dwStartType) { if (SUCCEED == check_delayed_start(h_srv)) { zbx_json_adduint64(&j, "{#SERVICE.STARTUP}", 1); zbx_json_addstring(&j, "{#SERVICE.STARTUPNAME}", "automatic delayed", ZBX_JSON_TYPE_STRING); } else { zbx_json_adduint64(&j, "{#SERVICE.STARTUP}", 0); zbx_json_addstring(&j, "{#SERVICE.STARTUPNAME}", "automatic", ZBX_JSON_TYPE_STRING); } } else { for (k = 2; k < ARRSIZE(start_types) && qsc->dwStartType != start_types[k]; k++) ; zbx_json_adduint64(&j, "{#SERVICE.STARTUP}", k); zbx_json_addstring(&j, "{#SERVICE.STARTUPNAME}", get_startup_string(qsc->dwStartType), ZBX_JSON_TYPE_STRING); } zbx_json_close(&j); next: zbx_free(scd); zbx_free(qsc); CloseServiceHandle(h_srv); } if (0 == szn) break; if (NULL == ssp) { sz = szn; ssp = (ENUM_SERVICE_STATUS_PROCESS *)zbx_malloc(ssp, sz); } } zbx_free(ssp); CloseServiceHandle(h_mgr); zbx_json_close(&j); SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer)); zbx_json_free(&j); return SYSINFO_RET_OK; }
/* * Get service config information. Returns: * - display_name * - binpath * - username * - startup_type */ PyObject * psutil_winservice_query_config(PyObject *self, PyObject *args) { char *service_name; SC_HANDLE hService = NULL; BOOL ok; DWORD bytesNeeded = 0; DWORD resumeHandle = 0; DWORD dwBytes = 0; QUERY_SERVICE_CONFIG *qsc = NULL; PyObject *py_tuple = NULL; PyObject *py_unicode_display_name = NULL; PyObject *py_unicode_binpath = NULL; PyObject *py_unicode_username = NULL; if (!PyArg_ParseTuple(args, "s", &service_name)) return NULL; hService = psutil_get_service_handler( service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_CONFIG); if (hService == NULL) goto error; // First call to QueryServiceConfig() is necessary to get the // right size. bytesNeeded = 0; QueryServiceConfig(hService, NULL, 0, &bytesNeeded); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { PyErr_SetFromWindowsErr(0); goto error; } qsc = (QUERY_SERVICE_CONFIG *)malloc(bytesNeeded); ok = QueryServiceConfig(hService, qsc, bytesNeeded, &bytesNeeded); if (ok == 0) { PyErr_SetFromWindowsErr(0); goto error; } // Get unicode display name. py_unicode_display_name = PyUnicode_Decode( qsc->lpDisplayName, _tcslen(qsc->lpDisplayName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_display_name == NULL) goto error; // Get unicode bin path. py_unicode_binpath = PyUnicode_Decode( qsc->lpBinaryPathName, _tcslen(qsc->lpBinaryPathName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_binpath == NULL) goto error; // Get unicode username. py_unicode_username = PyUnicode_Decode( qsc->lpServiceStartName, _tcslen(qsc->lpServiceStartName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_username == NULL) goto error; // Construct result tuple. py_tuple = Py_BuildValue( "(OOOs)", py_unicode_display_name, py_unicode_binpath, py_unicode_username, get_startup_string(qsc->dwStartType) // startup ); if (py_tuple == NULL) goto error; // Free resources. Py_DECREF(py_unicode_display_name); Py_DECREF(py_unicode_binpath); Py_DECREF(py_unicode_username); free(qsc); CloseServiceHandle(hService); return py_tuple; error: Py_XDECREF(py_unicode_display_name); Py_XDECREF(py_unicode_binpath); Py_XDECREF(py_unicode_username); Py_XDECREF(py_tuple); if (hService != NULL) CloseServiceHandle(hService); if (qsc != NULL) free(qsc); return NULL; }