- Added PDH.Version parameter
[public/netxms.git] / src / agent / subagents / winperf / winperf.cpp
1 /*
2 ** Windows Performance NetXMS subagent
3 ** Copyright (C) 2004 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: winperf.cpp
20 **
21 **/
22
23 #include "winperf.h"
24
25
26 //
27 // Constants
28 //
29
30 #define CFG_BUFFER_SIZE 256000
31
32
33 //
34 // Value of given performance counter
35 //
36
37 static LONG H_PdhVersion(TCHAR *pszParam, TCHAR *pArg, TCHAR *pValue)
38 {
39 DWORD dwVersion;
40
41 if (PdhGetDllVersion(&dwVersion) != ERROR_SUCCESS)
42 return SYSINFO_RC_ERROR;
43 ret_uint(pValue, dwVersion);
44 return SYSINFO_RC_SUCCESS;
45 }
46
47
48 //
49 // Value of given performance counter
50 //
51
52 static LONG H_PdhCounterValue(TCHAR *pszParam, TCHAR *pArg, TCHAR *pValue)
53 {
54 HQUERY hQuery;
55 HCOUNTER hCounter;
56 PDH_RAW_COUNTER rawData1, rawData2;
57 PDH_FMT_COUNTERVALUE counterValue;
58 PDH_STATUS rc;
59 PDH_COUNTER_INFO ci;
60 TCHAR szCounter[MAX_PATH], szBuffer[16];
61 static TCHAR szFName[] = _T("H_PdhCounterValue");
62 DWORD dwSize;
63 BOOL bUseTwoSamples = FALSE;
64
65 if ((!NxGetParameterArg(pszParam, 1, szCounter, MAX_PATH)) ||
66 (!NxGetParameterArg(pszParam, 2, szBuffer, 16)))
67 return SYSINFO_RC_UNSUPPORTED;
68
69 bUseTwoSamples = _tcstol(szBuffer, NULL, 0) ? TRUE : FALSE;
70
71 if ((rc = PdhOpenQuery(NULL, 0, &hQuery)) != ERROR_SUCCESS)
72 {
73 ReportPdhError(szFName, _T("PdhOpenQuery"), rc);
74 return SYSINFO_RC_ERROR;
75 }
76
77 if ((rc = PdhAddCounter(hQuery, szCounter, 0, &hCounter)) != ERROR_SUCCESS)
78 {
79 ReportPdhError(szFName, _T("PdhAddCounter"), rc);
80 PdhCloseQuery(hQuery);
81 return SYSINFO_RC_UNSUPPORTED;
82 }
83
84 // Get first sample
85 if ((rc = PdhCollectQueryData(hQuery)) != ERROR_SUCCESS)
86 {
87 ReportPdhError(szFName, _T("PdhCollectQueryData"), rc);
88 PdhCloseQuery(hQuery);
89 return SYSINFO_RC_ERROR;
90 }
91 PdhGetRawCounterValue(hCounter, NULL, &rawData1);
92
93 // Get second sample if required
94 if (bUseTwoSamples)
95 {
96 Sleep(1000); // We will take second sample after one second
97 if ((rc = PdhCollectQueryData(hQuery)) != ERROR_SUCCESS)
98 {
99 ReportPdhError(szFName, _T("PdhCollectQueryData"), rc);
100 PdhCloseQuery(hQuery);
101 return SYSINFO_RC_ERROR;
102 }
103 PdhGetRawCounterValue(hCounter, NULL, &rawData2);
104 }
105
106 dwSize = sizeof(ci);
107 if ((rc = PdhGetCounterInfo(hCounter, FALSE, &dwSize, &ci)) != ERROR_SUCCESS)
108 {
109 ReportPdhError(szFName, _T("PdhGetCounterInfo"), rc);
110 PdhCloseQuery(hQuery);
111 return SYSINFO_RC_ERROR;
112 }
113
114 if (ci.dwType & PERF_SIZE_LARGE)
115 {
116 if (bUseTwoSamples)
117 PdhCalculateCounterFromRawValue(hCounter, PDH_FMT_LARGE,
118 &rawData2, &rawData1, &counterValue);
119 else
120 PdhCalculateCounterFromRawValue(hCounter, PDH_FMT_LARGE,
121 &rawData1, NULL, &counterValue);
122 ret_int64(pValue, counterValue.largeValue);
123 }
124 else
125 {
126 if (bUseTwoSamples)
127 PdhCalculateCounterFromRawValue(hCounter, PDH_FMT_LONG,
128 &rawData2, &rawData1, &counterValue);
129 else
130 PdhCalculateCounterFromRawValue(hCounter, PDH_FMT_LONG,
131 &rawData1, NULL, &counterValue);
132 ret_int(pValue, counterValue.longValue);
133 }
134 PdhCloseQuery(hQuery);
135 return SYSINFO_RC_SUCCESS;
136 }
137
138
139 //
140 // List of available performance objects
141 //
142
143 static LONG H_PdhObjects(TCHAR *pszParam, TCHAR *pArg, NETXMS_VALUES_LIST *pValue)
144 {
145 TCHAR *pszObject, *pszObjList, szHostName[256];
146 LONG iResult = SYSINFO_RC_ERROR;
147 PDH_STATUS rc;
148 DWORD dwSize;
149
150 dwSize = 256;
151 if (GetComputerName(szHostName, &dwSize))
152 {
153 dwSize = 256000;
154 pszObjList = (TCHAR *)malloc(sizeof(TCHAR) * dwSize);
155 if ((rc = PdhEnumObjects(NULL, szHostName, pszObjList, &dwSize,
156 PERF_DETAIL_WIZARD, TRUE)) == ERROR_SUCCESS)
157 {
158 for(pszObject = pszObjList; *pszObject != 0; pszObject += _tcslen(pszObject) + 1)
159 NxAddResultString(pValue, pszObject);
160 iResult = SYSINFO_RC_SUCCESS;
161 }
162 else
163 {
164 ReportPdhError(_T("H_PdhObjects"), _T("PdhEnumObjects"), rc);
165 }
166 free(pszObjList);
167 }
168 return iResult;
169 }
170
171
172 //
173 // List of available performance items for given object
174 //
175
176 static LONG H_PdhObjectItems(TCHAR *pszParam, TCHAR *pArg, NETXMS_VALUES_LIST *pValue)
177 {
178 TCHAR *pszElement, *pszCounterList, *pszInstanceList, szHostName[256], szObject[256];
179 LONG iResult = SYSINFO_RC_ERROR;
180 DWORD dwSize1, dwSize2;
181 PDH_STATUS rc;
182
183 NxGetParameterArg(pszParam, 1, szObject, 256);
184 if (szObject[0] != 0)
185 {
186 dwSize1 = 256;
187 if (GetComputerName(szHostName, &dwSize1))
188 {
189 dwSize1 = dwSize2 = 256000;
190 pszCounterList = (TCHAR *)malloc(sizeof(TCHAR) * dwSize1);
191 pszInstanceList = (TCHAR *)malloc(sizeof(TCHAR) * dwSize2);
192 rc = PdhEnumObjectItems(NULL, szHostName, szObject,
193 pszCounterList, &dwSize1, pszInstanceList, &dwSize2,
194 PERF_DETAIL_WIZARD, 0);
195 if ((rc == ERROR_SUCCESS) || (rc == PDH_MORE_DATA))
196 {
197 for(pszElement = (pArg[0] == _T('C')) ? pszCounterList : pszInstanceList;
198 *pszElement != 0; pszElement += _tcslen(pszElement) + 1)
199 NxAddResultString(pValue, pszElement);
200 iResult = SYSINFO_RC_SUCCESS;
201 }
202 else
203 {
204 ReportPdhError(_T("H_PdhObjectItems"), _T("PdhEnumObjectItems"), rc);
205 }
206 free(pszCounterList);
207 free(pszInstanceList);
208 }
209 }
210 else
211 {
212 iResult = SYSINFO_RC_UNSUPPORTED;
213 }
214 return iResult;
215 }
216
217
218 //
219 // Subagent information
220 //
221
222 static NETXMS_SUBAGENT_PARAM m_parameters[] =
223 {
224 { _T("PDH.CounterValue(*)"), H_PdhCounterValue, NULL },
225 { _T("PDH.Version"), H_PdhVersion, NULL }
226 };
227 static NETXMS_SUBAGENT_ENUM m_enums[] =
228 {
229 { _T("PDH.ObjectCounters(*)"), H_PdhObjectItems, _T("C") },
230 { _T("PDH.ObjectInstances(*)"), H_PdhObjectItems, _T("I") },
231 { _T("PDH.Objects"), H_PdhObjects, NULL }
232 };
233
234 static NETXMS_SUBAGENT_INFO m_info =
235 {
236 "WinPerf", 0x01000000, NULL,
237 sizeof(m_parameters) / sizeof(NETXMS_SUBAGENT_PARAM),
238 m_parameters,
239 sizeof(m_enums) / sizeof(NETXMS_SUBAGENT_ENUM),
240 m_enums
241 };
242
243
244 //
245 // Configuration file template
246 //
247
248 static NX_CFG_TEMPLATE cfgTemplate[] =
249 {
250 { "Counter", CT_STRING_LIST, ',', 0, CFG_BUFFER_SIZE, 0, NULL },
251 { "", CT_END_OF_LIST, 0, 0, 0, 0, NULL }
252 };
253
254
255 //
256 // Entry point for NetXMS agent
257 //
258
259 extern "C" BOOL __declspec(dllexport) __cdecl
260 NxSubAgentInit(NETXMS_SUBAGENT_INFO **ppInfo, TCHAR *pszConfigFile)
261 {
262 DWORD dwResult;
263
264 // Load configuration
265 cfgTemplate[0].pBuffer = malloc(CFG_BUFFER_SIZE);
266 dwResult = NxLoadConfig(pszConfigFile, _T("WinPerf"), cfgTemplate, FALSE);
267 if (dwResult == NXCFG_ERR_OK)
268 {
269 }
270 free(cfgTemplate[0].pBuffer);
271 *ppInfo = &m_info;
272 return dwResult == NXCFG_ERR_OK;
273 }
274
275
276 //
277 // DLL entry point
278 //
279
280 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
281 {
282 return TRUE;
283 }