- Added parameter System.ServiceState(*)
[public/netxms.git] / src / agent / core / win32.cpp
1 /*
2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003, 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: win32.cpp
20 ** Win32 specific parameters or Win32 implementation of common parameters
21 **
22 **/
23
24 #include "nxagentd.h"
25
26
27 //
28 // Handler for System.ProcessCount
29 //
30
31 LONG H_ProcCount(char *cmd, char *arg, char *value)
32 {
33 DWORD dwSize, *pdwProcList;
34 PERFORMANCE_INFORMATION pi;
35
36 // On Windows XP and higher, use new method
37 if (imp_GetPerformanceInfo != NULL)
38 {
39 pi.cb = sizeof(PERFORMANCE_INFORMATION);
40 if (!imp_GetPerformanceInfo(&pi, sizeof(PERFORMANCE_INFORMATION)))
41 return SYSINFO_RC_ERROR;
42 ret_uint(value, pi.ProcessCount);
43 }
44 else
45 {
46 pdwProcList = (DWORD *)malloc(sizeof(DWORD) * MAX_PROCESSES);
47 EnumProcesses(pdwProcList, sizeof(DWORD) * MAX_PROCESSES, &dwSize);
48 free(pdwProcList);
49 ret_int(value, dwSize / sizeof(DWORD));
50 }
51 return SYSINFO_RC_SUCCESS;
52 }
53
54
55 //
56 // Handler for System.ThreadCount
57 //
58
59 LONG H_ThreadCount(char *cmd, char *arg, char *value)
60 {
61 PERFORMANCE_INFORMATION pi;
62
63 if (imp_GetPerformanceInfo != NULL)
64 {
65 pi.cb = sizeof(PERFORMANCE_INFORMATION);
66 if (!imp_GetPerformanceInfo(&pi, sizeof(PERFORMANCE_INFORMATION)))
67 return SYSINFO_RC_ERROR;
68 ret_uint(value, pi.ThreadCount);
69 return SYSINFO_RC_SUCCESS;
70 }
71 else
72 {
73 return SYSINFO_RC_UNSUPPORTED;
74 }
75 }
76
77
78 //
79 // Handler for Process.Count(*)
80 //
81
82 LONG H_ProcCountSpecific(char *cmd, char *arg, char *value)
83 {
84 DWORD dwSize = 0, *pdwProcList;
85 int i, counter, procCount;
86 char procName[MAX_PATH];
87 HANDLE hProcess;
88 HMODULE modList[MAX_MODULES];
89
90 NxGetParameterArg(cmd, 1, procName, MAX_PATH - 1);
91 pdwProcList = (DWORD *)malloc(sizeof(DWORD) * MAX_PROCESSES);
92 EnumProcesses(pdwProcList, sizeof(DWORD) * MAX_PROCESSES, &dwSize);
93 procCount = dwSize / sizeof(DWORD);
94 for(i = 0, counter = 0; i < procCount; i++)
95 {
96 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pdwProcList[i]);
97 if (hProcess != NULL)
98 {
99 if (EnumProcessModules(hProcess, modList, sizeof(HMODULE) * MAX_MODULES, &dwSize))
100 {
101 if (dwSize >= sizeof(HMODULE)) // At least one module exist
102 {
103 char baseName[MAX_PATH];
104
105 GetModuleBaseName(hProcess, modList[0], baseName, sizeof(baseName));
106 if (!stricmp(baseName, procName))
107 counter++;
108 }
109 }
110 CloseHandle(hProcess);
111 }
112 }
113 ret_int(value, counter);
114 free(pdwProcList);
115 return SYSINFO_RC_SUCCESS;
116 }
117
118
119 //
120 // Handler for System.Memory.XXX parameters
121 //
122
123 LONG H_MemoryInfo(char *cmd, char *arg, char *value)
124 {
125 if (imp_GlobalMemoryStatusEx != NULL)
126 {
127 MEMORYSTATUSEX mse;
128
129 mse.dwLength = sizeof(MEMORYSTATUSEX);
130 if (!imp_GlobalMemoryStatusEx(&mse))
131 return SYSINFO_RC_ERROR;
132
133 switch((int)arg)
134 {
135 case MEMINFO_PHYSICAL_FREE:
136 ret_uint64(value, mse.ullAvailPhys);
137 break;
138 case MEMINFO_PHYSICAL_TOTAL:
139 ret_uint64(value, mse.ullTotalPhys);
140 break;
141 case MEMINFO_PHYSICAL_USED:
142 ret_uint64(value, mse.ullTotalPhys - mse.ullAvailPhys);
143 break;
144 case MEMINFO_SWAP_FREE:
145 ret_uint64(value, mse.ullAvailPageFile);
146 break;
147 case MEMINFO_SWAP_TOTAL:
148 ret_uint64(value, mse.ullTotalPageFile);
149 break;
150 case MEMINFO_SWAP_USED:
151 ret_uint64(value, mse.ullTotalPageFile - mse.ullAvailPageFile);
152 break;
153 case MEMINFO_VIRTUAL_FREE:
154 ret_uint64(value, mse.ullAvailVirtual);
155 break;
156 case MEMINFO_VIRTUAL_TOTAL:
157 ret_uint64(value, mse.ullTotalVirtual);
158 break;
159 case MEMINFO_VIRTUAL_USED:
160 ret_uint64(value, mse.ullTotalVirtual - mse.ullAvailVirtual);
161 break;
162 default:
163 return SYSINFO_RC_UNSUPPORTED;
164 }
165 }
166 else
167 {
168 MEMORYSTATUS ms;
169
170 GlobalMemoryStatus(&ms);
171 switch((int)arg)
172 {
173 case MEMINFO_PHYSICAL_FREE:
174 ret_uint(value, ms.dwAvailPhys);
175 break;
176 case MEMINFO_PHYSICAL_TOTAL:
177 ret_uint(value, ms.dwTotalPhys);
178 break;
179 case MEMINFO_PHYSICAL_USED:
180 ret_uint(value, ms.dwTotalPhys - ms.dwAvailPhys);
181 break;
182 case MEMINFO_SWAP_FREE:
183 ret_uint(value, ms.dwAvailPageFile);
184 break;
185 case MEMINFO_SWAP_TOTAL:
186 ret_uint(value, ms.dwTotalPageFile);
187 break;
188 case MEMINFO_SWAP_USED:
189 ret_uint(value, ms.dwTotalPageFile - ms.dwAvailPageFile);
190 break;
191 case MEMINFO_VIRTUAL_FREE:
192 ret_uint(value, ms.dwAvailVirtual);
193 break;
194 case MEMINFO_VIRTUAL_TOTAL:
195 ret_uint(value, ms.dwTotalVirtual);
196 break;
197 case MEMINFO_VIRTUAL_USED:
198 ret_uint(value, ms.dwTotalVirtual - ms.dwAvailVirtual);
199 break;
200 default:
201 return SYSINFO_RC_UNSUPPORTED;
202 }
203 }
204
205 return SYSINFO_RC_SUCCESS;
206 }
207
208
209 //
210 // Handler for System.Hostname parameter
211 //
212
213 LONG H_HostName(char *cmd, char *arg, char *value)
214 {
215 DWORD dwSize;
216 char buffer[MAX_COMPUTERNAME_LENGTH + 1];
217
218 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
219 GetComputerName(buffer, &dwSize);
220 ret_string(value, buffer);
221 return SYSINFO_RC_SUCCESS;
222 }
223
224
225 //
226 // Handler for Disk.Free(*), Disk.Used(*) and Disk.Total(*) parameters
227 //
228
229 LONG H_DiskInfo(char *cmd, char *arg, char *value)
230 {
231 char path[MAX_PATH];
232 ULARGE_INTEGER freeBytes, totalBytes;
233
234 if (!NxGetParameterArg(cmd, 1, path, MAX_PATH - 1))
235 return SYSINFO_RC_UNSUPPORTED;
236 if (!GetDiskFreeSpaceEx(path, &freeBytes, &totalBytes, NULL))
237 return SYSINFO_RC_UNSUPPORTED;
238
239 if (!memicmp(cmd, "Disk.Free",9))
240 ret_uint64(value, freeBytes.QuadPart);
241 else if (!memicmp(cmd, "Disk.Used",9))
242 ret_uint64(value, totalBytes.QuadPart - freeBytes.QuadPart);
243 else
244 ret_uint64(value, totalBytes.QuadPart);
245 return SYSINFO_RC_SUCCESS;
246 }
247
248
249 //
250 // Handler for System.Uname parameter
251 //
252
253 LONG H_SystemUname(char *cmd, char *arg, char *value)
254 {
255 DWORD dwSize;
256 char *cpuType, computerName[MAX_COMPUTERNAME_LENGTH + 1], osVersion[256];
257 SYSTEM_INFO sysInfo;
258 OSVERSIONINFO versionInfo;
259
260 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
261 GetComputerName(computerName, &dwSize);
262
263 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
264 GetVersionEx(&versionInfo);
265 GetSystemInfo(&sysInfo);
266
267 switch(versionInfo.dwPlatformId)
268 {
269 case VER_PLATFORM_WIN32_WINDOWS:
270 sprintf(osVersion,"Windows %s-%s",versionInfo.dwMinorVersion == 0 ? "95" :
271 (versionInfo.dwMinorVersion == 10 ? "98" :
272 (versionInfo.dwMinorVersion == 90 ? "Me" : "Unknown")),versionInfo.szCSDVersion);
273 break;
274 case VER_PLATFORM_WIN32_NT:
275 if (versionInfo.dwMajorVersion != 5)
276 sprintf(osVersion,"Windows NT %d.%d %s",versionInfo.dwMajorVersion,
277 versionInfo.dwMinorVersion,versionInfo.szCSDVersion);
278 else // Windows 2000, Windows XP or Windows Server 2003
279 sprintf(osVersion,"Windows %s%s%s",versionInfo.dwMinorVersion == 0 ? "2000" :
280 (versionInfo.dwMinorVersion == 1 ? "XP" : "Server 2003"),
281 versionInfo.szCSDVersion[0] == 0 ? "" : " ", versionInfo.szCSDVersion);
282 break;
283 default:
284 strcpy(osVersion,"Windows [Unknown Version]");
285 break;
286 }
287
288 switch(sysInfo.wProcessorArchitecture)
289 {
290 case PROCESSOR_ARCHITECTURE_INTEL:
291 cpuType = "Intel IA-32";
292 break;
293 case PROCESSOR_ARCHITECTURE_MIPS:
294 cpuType = "MIPS";
295 break;
296 case PROCESSOR_ARCHITECTURE_ALPHA:
297 cpuType = "Alpha";
298 break;
299 case PROCESSOR_ARCHITECTURE_PPC:
300 cpuType = "PowerPC";
301 break;
302 case PROCESSOR_ARCHITECTURE_IA64:
303 cpuType = "Intel IA-64";
304 break;
305 #ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
306 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
307 cpuType = "IA-32 on IA-64";
308 break;
309 #endif
310 #ifdef PROCESSOR_ARCHITECTURE_AMD64
311 case PROCESSOR_ARCHITECTURE_AMD64:
312 cpuType = "AMD-64";
313 break;
314 #endif
315 default:
316 cpuType = "unknown";
317 break;
318 }
319
320 sprintf(value, "Windows %s %d.%d.%d %s %s\r\n", computerName, versionInfo.dwMajorVersion,
321 versionInfo.dwMinorVersion, versionInfo.dwBuildNumber, osVersion, cpuType);
322 return SYSINFO_RC_SUCCESS;
323 }
324
325
326 //
327 // Handler for System.ServiceState parameter
328 //
329
330 LONG H_ServiceState(char *cmd, char *arg, char *value)
331 {
332 SC_HANDLE hManager, hService;
333 TCHAR szServiceName[MAX_PATH];
334 LONG iResult = SYSINFO_RC_SUCCESS;
335
336 if (!NxGetParameterArg(cmd, 1, szServiceName, MAX_PATH))
337 return SYSINFO_RC_UNSUPPORTED;
338
339 hManager = OpenSCManager(NULL, NULL, GENERIC_READ);
340 if (hManager == NULL)
341 {
342 return SYSINFO_RC_ERROR;
343 }
344
345 hService = OpenService(hManager, szServiceName, SERVICE_QUERY_STATUS);
346 if (hService == NULL)
347 {
348 iResult = SYSINFO_RC_UNSUPPORTED;
349 }
350 else
351 {
352 SERVICE_STATUS status;
353
354 if (QueryServiceStatus(hService, &status))
355 {
356 int i;
357 static DWORD dwStates[7]={ SERVICE_RUNNING, SERVICE_PAUSED, SERVICE_START_PENDING,
358 SERVICE_PAUSE_PENDING, SERVICE_CONTINUE_PENDING,
359 SERVICE_STOP_PENDING, SERVICE_STOPPED };
360
361 for(i = 0; i < 7; i++)
362 if (status.dwCurrentState == dwStates[i])
363 break;
364 ret_uint(value, i);
365 }
366 else
367 {
368 ret_uint(value, 255); // Unable to retrieve information
369 }
370 CloseServiceHandle(hService);
371 }
372
373 CloseServiceHandle(hManager);
374 return iResult;
375 }