csigar 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/NOTICE +117 -0
  4. data/README +8 -0
  5. data/Rakefile +105 -0
  6. data/bindings/SigarBuild.pm +301 -0
  7. data/bindings/SigarWrapper.pm +2978 -0
  8. data/bindings/ruby/examples/arp.rb +24 -0
  9. data/bindings/ruby/examples/cpu_info.rb +35 -0
  10. data/bindings/ruby/examples/df.rb +49 -0
  11. data/bindings/ruby/examples/free.rb +36 -0
  12. data/bindings/ruby/examples/ifconfig.rb +101 -0
  13. data/bindings/ruby/examples/logging.rb +58 -0
  14. data/bindings/ruby/examples/net_info.rb +31 -0
  15. data/bindings/ruby/examples/netstat.rb +71 -0
  16. data/bindings/ruby/examples/pargs.rb +35 -0
  17. data/bindings/ruby/examples/penv.rb +31 -0
  18. data/bindings/ruby/examples/route.rb +48 -0
  19. data/bindings/ruby/examples/version.rb +40 -0
  20. data/bindings/ruby/examples/who.rb +30 -0
  21. data/bindings/ruby/extconf.rb +131 -0
  22. data/bindings/ruby/rbsigar.c +938 -0
  23. data/bindings/ruby/test/cpu_test.rb +40 -0
  24. data/bindings/ruby/test/file_system_test.rb +43 -0
  25. data/bindings/ruby/test/helper.rb +57 -0
  26. data/bindings/ruby/test/loadavg_test.rb +30 -0
  27. data/bindings/ruby/test/mem_test.rb +45 -0
  28. data/bindings/ruby/test/swap_test.rb +36 -0
  29. data/bindings/ruby/test/uptime_test.rb +26 -0
  30. data/include/sigar.h +943 -0
  31. data/include/sigar_fileinfo.h +157 -0
  32. data/include/sigar_format.h +65 -0
  33. data/include/sigar_getline.h +18 -0
  34. data/include/sigar_log.h +80 -0
  35. data/include/sigar_private.h +422 -0
  36. data/include/sigar_ptql.h +53 -0
  37. data/include/sigar_util.h +191 -0
  38. data/src/os/aix/aix_sigar.c +2151 -0
  39. data/src/os/aix/sigar_os.h +73 -0
  40. data/src/os/darwin/Info.plist.in +27 -0
  41. data/src/os/darwin/darwin_sigar.c +3711 -0
  42. data/src/os/darwin/sigar_os.h +80 -0
  43. data/src/os/hpux/hpux_sigar.c +1342 -0
  44. data/src/os/hpux/sigar_os.h +49 -0
  45. data/src/os/linux/linux_sigar.c +2782 -0
  46. data/src/os/linux/sigar_os.h +82 -0
  47. data/src/os/solaris/get_mib2.c +321 -0
  48. data/src/os/solaris/get_mib2.h +127 -0
  49. data/src/os/solaris/kstats.c +181 -0
  50. data/src/os/solaris/procfs.c +97 -0
  51. data/src/os/solaris/sigar_os.h +224 -0
  52. data/src/os/solaris/solaris_sigar.c +2717 -0
  53. data/src/os/win32/peb.c +212 -0
  54. data/src/os/win32/sigar.rc.in +40 -0
  55. data/src/os/win32/sigar_os.h +676 -0
  56. data/src/os/win32/sigar_pdh.h +47 -0
  57. data/src/os/win32/win32_sigar.c +3992 -0
  58. data/src/sigar.c +2428 -0
  59. data/src/sigar_cache.c +179 -0
  60. data/src/sigar_fileinfo.c +815 -0
  61. data/src/sigar_format.c +696 -0
  62. data/src/sigar_getline.c +1849 -0
  63. data/src/sigar_ptql.c +1967 -0
  64. data/src/sigar_signal.c +216 -0
  65. data/src/sigar_util.c +1060 -0
  66. data/src/sigar_version.c.in +22 -0
  67. data/src/sigar_version_autoconf.c.in +22 -0
  68. data/version.properties +11 -0
  69. metadata +112 -0
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright (c) 2004, 2006 Hyperic, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef SIGAR_PDH_H
18
+ #define SIGAR_PDH_H
19
+
20
+ /* performance data helpers */
21
+
22
+ #define PdhFirstObject(block) \
23
+ ((PERF_OBJECT_TYPE *)((BYTE *) block + block->HeaderLength))
24
+
25
+ #define PdhNextObject(object) \
26
+ ((PERF_OBJECT_TYPE *)((BYTE *) object + object->TotalByteLength))
27
+
28
+ #define PdhFirstCounter(object) \
29
+ ((PERF_COUNTER_DEFINITION *)((BYTE *) object + object->HeaderLength))
30
+
31
+ #define PdhNextCounter(counter) \
32
+ ((PERF_COUNTER_DEFINITION *)((BYTE *) counter + counter->ByteLength))
33
+
34
+ #define PdhGetCounterBlock(inst) \
35
+ ((PERF_COUNTER_BLOCK *)((BYTE *) inst + inst->ByteLength))
36
+
37
+ #define PdhFirstInstance(object) \
38
+ ((PERF_INSTANCE_DEFINITION *)((BYTE *) object + object->DefinitionLength))
39
+
40
+ #define PdhNextInstance(inst) \
41
+ ((PERF_INSTANCE_DEFINITION *)((BYTE *)inst + inst->ByteLength + \
42
+ PdhGetCounterBlock(inst)->ByteLength))
43
+
44
+ #define PdhInstanceName(inst) \
45
+ ((wchar_t *)((BYTE *)inst + inst->NameOffset))
46
+
47
+ #endif /* SIGAR_PDH_H */
@@ -0,0 +1,3992 @@
1
+ /*
2
+ * Copyright (c) 2004-2009 Hyperic, Inc.
3
+ * Copyright (c) 2009 SpringSource, Inc.
4
+ * Copyright (c) 2009-2010 VMware, Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "sigar.h"
20
+ #include "sigar_private.h"
21
+ #include "sigar_pdh.h"
22
+ #include "sigar_os.h"
23
+ #include "sigar_util.h"
24
+ #include "sigar_format.h"
25
+ #include <shellapi.h>
26
+ #ifndef MSVC
27
+ #include <iphlpapi.h>
28
+ #endif
29
+
30
+ #define USING_WIDE_S(s) (s)->using_wide
31
+ #define USING_WIDE() USING_WIDE_S(sigar)
32
+
33
+ #define PERFBUF_SIZE 8192
34
+
35
+ #define PERF_TITLE_PROC 230
36
+ #define PERF_TITLE_SYS_KEY "2"
37
+ #define PERF_TITLE_MEM_KEY "4"
38
+ #define PERF_TITLE_PROC_KEY "230"
39
+ #define PERF_TITLE_CPU_KEY "238"
40
+ #define PERF_TITLE_DISK_KEY "236"
41
+
42
+ #define PERF_TITLE_CPU_USER 142
43
+ #define PERF_TITLE_CPU_IDLE 1746
44
+ #define PERF_TITLE_CPU_SYS 144
45
+ #define PERF_TITLE_CPU_IRQ 698
46
+
47
+ typedef enum {
48
+ PERF_IX_CPU_USER,
49
+ PERF_IX_CPU_IDLE,
50
+ PERF_IX_CPU_SYS,
51
+ PERF_IX_CPU_IRQ,
52
+ PERF_IX_CPU_MAX
53
+ } perf_cpu_offsets_t;
54
+
55
+ #define PERF_TITLE_CPUTIME 6
56
+ #define PERF_TITLE_PAGE_FAULTS 28
57
+ #define PERF_TITLE_MEM_VSIZE 174
58
+ #define PERF_TITLE_MEM_SIZE 180
59
+ #define PERF_TITLE_THREAD_CNT 680
60
+ #define PERF_TITLE_HANDLE_CNT 952
61
+ #define PERF_TITLE_PID 784
62
+ #define PERF_TITLE_PPID 1410
63
+ #define PERF_TITLE_PRIORITY 682
64
+ #define PERF_TITLE_START_TIME 684
65
+
66
+ typedef enum {
67
+ PERF_IX_CPUTIME,
68
+ PERF_IX_PAGE_FAULTS,
69
+ PERF_IX_MEM_VSIZE,
70
+ PERF_IX_MEM_SIZE,
71
+ PERF_IX_THREAD_CNT,
72
+ PERF_IX_HANDLE_CNT,
73
+ PERF_IX_PID,
74
+ PERF_IX_PPID,
75
+ PERF_IX_PRIORITY,
76
+ PERF_IX_START_TIME,
77
+ PERF_IX_MAX
78
+ } perf_proc_offsets_t;
79
+
80
+ typedef enum {
81
+ PERF_IX_DISK_TIME,
82
+ PERF_IX_DISK_READ_TIME,
83
+ PERF_IX_DISK_WRITE_TIME,
84
+ PERF_IX_DISK_READ,
85
+ PERF_IX_DISK_WRITE,
86
+ PERF_IX_DISK_READ_BYTES,
87
+ PERF_IX_DISK_WRITE_BYTES,
88
+ PERF_IX_DISK_QUEUE,
89
+ PERF_IX_DISK_MAX
90
+ } perf_disk_offsets_t;
91
+
92
+ #define PERF_TITLE_DISK_TIME 200 /* % Disk Time */
93
+ #define PERF_TITLE_DISK_READ_TIME 202 /* % Disk Read Time */
94
+ #define PERF_TITLE_DISK_WRITE_TIME 204 /* % Disk Write Time */
95
+ #define PERF_TITLE_DISK_READ 214 /* Disk Reads/sec */
96
+ #define PERF_TITLE_DISK_WRITE 216 /* Disk Writes/sec */
97
+ #define PERF_TITLE_DISK_READ_BYTES 220 /* Disk Read Bytes/sec */
98
+ #define PERF_TITLE_DISK_WRITE_BYTES 222 /* Disk Write Bytes/sec */
99
+ #define PERF_TITLE_DISK_QUEUE 198 /* Current Disk Queue Length */
100
+
101
+ /*
102
+ * diff is:
103
+ * ExW -> ExA
104
+ * wcounter -> counter
105
+ */
106
+ #define MyRegQueryValue() \
107
+ (USING_WIDE() ? \
108
+ RegQueryValueExW(sigar->handle, \
109
+ wcounter_key, NULL, &type, \
110
+ sigar->perfbuf, \
111
+ &bytes) : \
112
+ RegQueryValueExA(sigar->handle, \
113
+ counter_key, NULL, &type, \
114
+ sigar->perfbuf, \
115
+ &bytes))
116
+
117
+ #define PERF_VAL(ix) \
118
+ perf_offsets[ix] ? \
119
+ *((DWORD *)((BYTE *)counter_block + perf_offsets[ix])) : 0
120
+
121
+ /* 1/100ns units to milliseconds */
122
+ #define NS100_2MSEC(t) ((t) / 10000)
123
+
124
+ #define PERF_VAL_CPU(ix) \
125
+ NS100_2MSEC(PERF_VAL(ix))
126
+
127
+ #define MS_LOOPBACK_ADAPTER "Microsoft Loopback Adapter"
128
+ #define NETIF_LA "la"
129
+
130
+ static int get_proc_info(sigar_t *sigar, sigar_pid_t pid);
131
+ static int netif_hash(char *s);
132
+
133
+ sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft)
134
+ {
135
+ sigar_uint64_t time;
136
+ time = ft->dwHighDateTime;
137
+ time = time << 32;
138
+ time |= ft->dwLowDateTime;
139
+ time /= 10;
140
+ time -= EPOCH_DELTA;
141
+ return time;
142
+ }
143
+
144
+ static DWORD perfbuf_init(sigar_t *sigar)
145
+ {
146
+ if (!sigar->perfbuf) {
147
+ sigar->perfbuf = malloc(PERFBUF_SIZE);
148
+ sigar->perfbuf_size = PERFBUF_SIZE;
149
+ }
150
+
151
+ return sigar->perfbuf_size;
152
+ }
153
+
154
+ static DWORD perfbuf_grow(sigar_t *sigar)
155
+ {
156
+ sigar->perfbuf_size += PERFBUF_SIZE;
157
+
158
+ sigar->perfbuf =
159
+ realloc(sigar->perfbuf, sigar->perfbuf_size);
160
+
161
+ return sigar->perfbuf_size;
162
+ }
163
+
164
+ static char *get_counter_name(char *key)
165
+ {
166
+ if (strEQ(key, PERF_TITLE_MEM_KEY)) {
167
+ return "Memory";
168
+ }
169
+ else if (strEQ(key, PERF_TITLE_PROC_KEY)) {
170
+ return "Process";
171
+ }
172
+ else if (strEQ(key, PERF_TITLE_CPU_KEY)) {
173
+ return "Processor";
174
+ }
175
+ else if (strEQ(key, PERF_TITLE_DISK_KEY)) {
176
+ return "LogicalDisk";
177
+ }
178
+ else {
179
+ return key;
180
+ }
181
+ }
182
+
183
+ static PERF_OBJECT_TYPE *get_perf_object_inst(sigar_t *sigar,
184
+ char *counter_key,
185
+ DWORD inst, DWORD *err)
186
+ {
187
+ DWORD retval, type, bytes;
188
+ WCHAR wcounter_key[MAX_PATH+1];
189
+ PERF_DATA_BLOCK *block;
190
+ PERF_OBJECT_TYPE *object;
191
+
192
+ *err = SIGAR_OK;
193
+
194
+ if (USING_WIDE()) {
195
+ SIGAR_A2W(counter_key, wcounter_key, sizeof(wcounter_key));
196
+ }
197
+
198
+ bytes = perfbuf_init(sigar);
199
+
200
+ while ((retval = MyRegQueryValue()) != ERROR_SUCCESS) {
201
+ if (retval == ERROR_MORE_DATA) {
202
+ bytes = perfbuf_grow(sigar);
203
+ }
204
+ else {
205
+ *err = retval;
206
+ return NULL;
207
+ }
208
+ }
209
+
210
+ block = (PERF_DATA_BLOCK *)sigar->perfbuf;
211
+ if (block->NumObjectTypes == 0) {
212
+ counter_key = get_counter_name(counter_key);
213
+ sigar_strerror_printf(sigar, "No %s counters defined (disabled?)",
214
+ counter_key);
215
+ *err = -1;
216
+ return NULL;
217
+ }
218
+ object = PdhFirstObject(block);
219
+
220
+ /*
221
+ * only seen on windows 2003 server when pdh.dll
222
+ * functions are in use by the same process.
223
+ * confucius say what the fuck.
224
+ */
225
+ if (inst && (object->NumInstances == PERF_NO_INSTANCES)) {
226
+ int i;
227
+
228
+ for (i=0; i<block->NumObjectTypes; i++) {
229
+ if (object->NumInstances != PERF_NO_INSTANCES) {
230
+ return object;
231
+ }
232
+ object = PdhNextObject(object);
233
+ }
234
+ return NULL;
235
+ }
236
+ else {
237
+ return object;
238
+ }
239
+ }
240
+
241
+ #define get_perf_object(sigar, counter_key, err) \
242
+ get_perf_object_inst(sigar, counter_key, 1, err)
243
+
244
+ static int get_mem_counters(sigar_t *sigar, sigar_swap_t *swap, sigar_mem_t *mem)
245
+ {
246
+ int status;
247
+ PERF_OBJECT_TYPE *object =
248
+ get_perf_object_inst(sigar, PERF_TITLE_MEM_KEY, 0, &status);
249
+ PERF_INSTANCE_DEFINITION *inst;
250
+ PERF_COUNTER_DEFINITION *counter;
251
+ BYTE *data;
252
+ DWORD i;
253
+
254
+ if (!object) {
255
+ return status;
256
+ }
257
+
258
+ data = (BYTE *)((BYTE *)object + object->DefinitionLength);
259
+
260
+ for (i=0, counter = PdhFirstCounter(object);
261
+ i<object->NumCounters;
262
+ i++, counter = PdhNextCounter(counter))
263
+ {
264
+ DWORD offset = counter->CounterOffset;
265
+
266
+ switch (counter->CounterNameTitleIndex) {
267
+ case 48: /* "Pages Output/sec" */
268
+ if (swap) swap->page_out = *((DWORD *)(data + offset));
269
+ break;
270
+ case 76: /* "System Cache Resident Bytes" aka file cache */
271
+ if (mem) {
272
+ sigar_uint64_t kern = *((DWORD *)(data + offset));
273
+ mem->actual_free = mem->free + kern;
274
+ mem->actual_used = mem->used - kern;
275
+ return SIGAR_OK;
276
+ }
277
+ case 822: /* "Pages Input/sec" */
278
+ if (swap) swap->page_in = *((DWORD *)(data + offset));
279
+ break;
280
+ default:
281
+ continue;
282
+ }
283
+ }
284
+
285
+ return SIGAR_OK;
286
+ }
287
+
288
+ static void get_sysinfo(sigar_t *sigar)
289
+ {
290
+ SYSTEM_INFO sysinfo;
291
+
292
+ GetSystemInfo(&sysinfo);
293
+
294
+ sigar->ncpu = sysinfo.dwNumberOfProcessors;
295
+ sigar->pagesize = sysinfo.dwPageSize;
296
+ }
297
+
298
+ /* for C# bindings */
299
+ SIGAR_DECLARE(sigar_t *) sigar_new(void)
300
+ {
301
+ sigar_t *sigar;
302
+ if (sigar_open(&sigar) != SIGAR_OK) {
303
+ return NULL;
304
+ }
305
+ return sigar;
306
+ }
307
+
308
+ static sigar_wtsapi_t sigar_wtsapi = {
309
+ "wtsapi32.dll",
310
+ NULL,
311
+ { "WTSEnumerateSessionsA", NULL },
312
+ { "WTSFreeMemory", NULL },
313
+ { "WTSQuerySessionInformationA", NULL },
314
+ { NULL, NULL }
315
+ };
316
+
317
+ static sigar_iphlpapi_t sigar_iphlpapi = {
318
+ "iphlpapi.dll",
319
+ NULL,
320
+ { "GetIpForwardTable", NULL },
321
+ { "GetIpAddrTable", NULL },
322
+ { "GetIfTable", NULL },
323
+ { "GetIfEntry", NULL },
324
+ { "GetNumberOfInterfaces", NULL },
325
+ { "GetTcpTable", NULL },
326
+ { "GetUdpTable", NULL },
327
+ { "AllocateAndGetTcpExTableFromStack", NULL },
328
+ { "AllocateAndGetUdpExTableFromStack", NULL },
329
+ { "GetTcpStatistics", NULL },
330
+ { "GetNetworkParams", NULL },
331
+ { "GetAdaptersInfo", NULL },
332
+ { "GetAdaptersAddresses", NULL },
333
+ { "GetIpNetTable", NULL },
334
+ { NULL, NULL }
335
+ };
336
+
337
+ static sigar_advapi_t sigar_advapi = {
338
+ "advapi32.dll",
339
+ NULL,
340
+ { "ConvertStringSidToSidA", NULL },
341
+ { "QueryServiceStatusEx", NULL },
342
+ { NULL, NULL }
343
+ };
344
+
345
+ static sigar_ntdll_t sigar_ntdll = {
346
+ "ntdll.dll",
347
+ NULL,
348
+ { "NtQuerySystemInformation", NULL },
349
+ { "NtQueryInformationProcess", NULL },
350
+ { NULL, NULL }
351
+ };
352
+
353
+ static sigar_psapi_t sigar_psapi = {
354
+ "psapi.dll",
355
+ NULL,
356
+ { "EnumProcessModules", NULL },
357
+ { "EnumProcesses", NULL },
358
+ { "GetModuleFileNameExA", NULL },
359
+ { NULL, NULL }
360
+ };
361
+
362
+ static sigar_psapi_t sigar_winsta = {
363
+ "winsta.dll",
364
+ NULL,
365
+ { "WinStationQueryInformationW", NULL },
366
+ { NULL, NULL }
367
+ };
368
+
369
+ static sigar_psapi_t sigar_kernel = {
370
+ "kernel32.dll",
371
+ NULL,
372
+ { "GlobalMemoryStatusEx", NULL },
373
+ { NULL, NULL }
374
+ };
375
+
376
+ static sigar_mpr_t sigar_mpr = {
377
+ "mpr.dll",
378
+ NULL,
379
+ { "WNetGetConnectionA", NULL },
380
+ { NULL, NULL }
381
+ };
382
+
383
+ #define DLLMOD_COPY(name) \
384
+ memcpy(&(sigar->name), &sigar_##name, sizeof(sigar_##name))
385
+
386
+ #define DLLMOD_INIT(name, all) \
387
+ sigar_dllmod_init(sigar, (sigar_dll_module_t *)&(sigar->name), all)
388
+
389
+ #define DLLMOD_FREE(name) \
390
+ sigar_dllmod_free((sigar_dll_module_t *)&(sigar->name))
391
+
392
+ static void sigar_dllmod_free(sigar_dll_module_t *module)
393
+ {
394
+ if (module->handle) {
395
+ FreeLibrary(module->handle);
396
+ module->handle = NULL;
397
+ }
398
+ }
399
+
400
+ static int sigar_dllmod_init(sigar_t *sigar,
401
+ sigar_dll_module_t *module,
402
+ int all)
403
+ {
404
+ sigar_dll_func_t *funcs = &module->funcs[0];
405
+ int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
406
+ int rc, success;
407
+
408
+ if (module->handle == INVALID_HANDLE_VALUE) {
409
+ return ENOENT; /* XXX better rc */
410
+ }
411
+
412
+ if (module->handle) {
413
+ return SIGAR_OK;
414
+ }
415
+
416
+ module->handle = LoadLibrary(module->name);
417
+ if (!(success = (module->handle ? TRUE : FALSE))) {
418
+ rc = GetLastError();
419
+ /* dont try again */
420
+ module->handle = INVALID_HANDLE_VALUE;
421
+ }
422
+
423
+ if (is_debug) {
424
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
425
+ "LoadLibrary(%s): %s",
426
+ module->name,
427
+ success ?
428
+ "OK" :
429
+ sigar_strerror(sigar, rc));
430
+ }
431
+
432
+ if (!success) {
433
+ return rc;
434
+ }
435
+
436
+ while (funcs->name) {
437
+ funcs->func = GetProcAddress(module->handle, funcs->name);
438
+
439
+ if (!(success = (funcs->func ? TRUE : FALSE))) {
440
+ rc = GetLastError();
441
+ }
442
+
443
+ if (is_debug) {
444
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
445
+ "GetProcAddress(%s:%s): %s",
446
+ module->name, funcs->name,
447
+ success ?
448
+ "OK" :
449
+ sigar_strerror(sigar, rc));
450
+ }
451
+
452
+ if (all && !success) {
453
+ return rc;
454
+ }
455
+
456
+ funcs++;
457
+ }
458
+
459
+ return SIGAR_OK;
460
+ }
461
+
462
+ int sigar_wsa_init(sigar_t *sigar)
463
+ {
464
+ if (sigar->ws_version == 0) {
465
+ WSADATA data;
466
+
467
+ if (WSAStartup(MAKEWORD(2, 0), &data)) {
468
+ sigar->ws_error = WSAGetLastError();
469
+ WSACleanup();
470
+ return sigar->ws_error;
471
+ }
472
+
473
+ sigar->ws_version = data.wVersion;
474
+ }
475
+
476
+ return SIGAR_OK;
477
+ }
478
+
479
+ static int sigar_enable_privilege(char *name)
480
+ {
481
+ int status;
482
+ HANDLE handle;
483
+ TOKEN_PRIVILEGES tok;
484
+
485
+ SIGAR_ZERO(&tok);
486
+
487
+ if (!OpenProcessToken(GetCurrentProcess(),
488
+ TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
489
+ &handle))
490
+ {
491
+ return GetLastError();
492
+ }
493
+
494
+ if (LookupPrivilegeValue(NULL, name,
495
+ &tok.Privileges[0].Luid))
496
+ {
497
+ tok.PrivilegeCount = 1;
498
+ tok.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
499
+
500
+ if (AdjustTokenPrivileges(handle, FALSE, &tok, 0, NULL, 0)) {
501
+ status = SIGAR_OK;
502
+ }
503
+ else {
504
+ status = GetLastError();
505
+ }
506
+ }
507
+ else {
508
+ status = GetLastError();
509
+ }
510
+
511
+ CloseHandle(handle);
512
+
513
+ return status;
514
+ }
515
+
516
+ static int netif_name_short(void)
517
+ {
518
+ char value[32767]; /* max size from msdn docs */
519
+ DWORD retval =
520
+ GetEnvironmentVariable("SIGAR_NETIF_NAME_SHORT", value, sizeof(value));
521
+ if ((retval > 0) && (strEQ(value, "1") || (strEQ(value, "true")))) {
522
+ return 1;
523
+ }
524
+ else {
525
+ return 0;
526
+ }
527
+ }
528
+
529
+ int sigar_os_open(sigar_t **sigar_ptr)
530
+ {
531
+ LONG result;
532
+ HINSTANCE h;
533
+ OSVERSIONINFO version;
534
+ int i;
535
+ sigar_t *sigar;
536
+
537
+ *sigar_ptr = sigar = malloc(sizeof(*sigar));
538
+ sigar->machine = ""; /* local machine */
539
+ sigar->using_wide = 0; /*XXX*/
540
+
541
+ sigar->perfbuf = NULL;
542
+ sigar->perfbuf_size = 0;
543
+
544
+ version.dwOSVersionInfoSize = sizeof(version);
545
+ GetVersionEx(&version);
546
+
547
+ /*
548
+ * 4 == NT 4.0
549
+ * 5 == 2000, XP, 2003 Server
550
+ */
551
+ sigar->winnt = (version.dwMajorVersion == 4);
552
+
553
+ if (USING_WIDE_S(sigar)) {
554
+ WCHAR wmachine[MAX_PATH+1];
555
+
556
+ SIGAR_A2W(sigar->machine, wmachine, sizeof(wmachine));
557
+
558
+ result = RegConnectRegistryW(wmachine,
559
+ HKEY_PERFORMANCE_DATA,
560
+ &sigar->handle);
561
+ }
562
+ else {
563
+ result = RegConnectRegistryA(sigar->machine,
564
+ HKEY_PERFORMANCE_DATA,
565
+ &sigar->handle);
566
+ }
567
+
568
+ get_sysinfo(sigar);
569
+
570
+ DLLMOD_COPY(wtsapi);
571
+ DLLMOD_COPY(iphlpapi);
572
+ DLLMOD_COPY(advapi);
573
+ DLLMOD_COPY(ntdll);
574
+ DLLMOD_COPY(psapi);
575
+ DLLMOD_COPY(winsta);
576
+ DLLMOD_COPY(kernel);
577
+ DLLMOD_COPY(mpr);
578
+
579
+ sigar->log_level = -1; /* else below segfaults */
580
+ /* XXX init early for use by javasigar.c */
581
+ sigar_dllmod_init(sigar,
582
+ (sigar_dll_module_t *)&sigar->advapi,
583
+ FALSE);
584
+
585
+ sigar->netif_mib_rows = NULL;
586
+ sigar->netif_addr_rows = NULL;
587
+ sigar->netif_adapters = NULL;
588
+ sigar->netif_names = NULL;
589
+ sigar->netif_name_short = netif_name_short();
590
+
591
+ sigar->pinfo.pid = -1;
592
+ sigar->ws_version = 0;
593
+ sigar->lcpu = -1;
594
+
595
+ /* increase process visibility */
596
+ sigar_enable_privilege(SE_DEBUG_NAME);
597
+
598
+ return result;
599
+ }
600
+
601
+ void dllmod_init_ntdll(sigar_t *sigar)
602
+ {
603
+ DLLMOD_INIT(ntdll, FALSE);
604
+ }
605
+
606
+ int sigar_os_close(sigar_t *sigar)
607
+ {
608
+ int retval;
609
+
610
+ DLLMOD_FREE(wtsapi);
611
+ DLLMOD_FREE(iphlpapi);
612
+ DLLMOD_FREE(advapi);
613
+ DLLMOD_FREE(ntdll);
614
+ DLLMOD_FREE(psapi);
615
+ DLLMOD_FREE(winsta);
616
+ DLLMOD_FREE(kernel);
617
+ DLLMOD_FREE(mpr);
618
+
619
+ if (sigar->perfbuf) {
620
+ free(sigar->perfbuf);
621
+ }
622
+
623
+ retval = RegCloseKey(sigar->handle);
624
+
625
+ if (sigar->ws_version != 0) {
626
+ WSACleanup();
627
+ }
628
+
629
+ if (sigar->netif_mib_rows) {
630
+ sigar_cache_destroy(sigar->netif_mib_rows);
631
+ }
632
+
633
+ if (sigar->netif_addr_rows) {
634
+ sigar_cache_destroy(sigar->netif_addr_rows);
635
+ }
636
+
637
+ if (sigar->netif_adapters) {
638
+ sigar_cache_destroy(sigar->netif_adapters);
639
+ }
640
+
641
+ if (sigar->netif_names) {
642
+ sigar_cache_destroy(sigar->netif_names);
643
+ }
644
+
645
+ free(sigar);
646
+
647
+ return retval;
648
+ }
649
+
650
+ char *sigar_os_error_string(sigar_t *sigar, int err)
651
+ {
652
+ switch (err) {
653
+ case SIGAR_NO_SUCH_PROCESS:
654
+ return "No such process";
655
+ break;
656
+ }
657
+ return NULL;
658
+ }
659
+
660
+ #define sigar_GlobalMemoryStatusEx \
661
+ sigar->kernel.memory_status.func
662
+
663
+ SIGAR_DECLARE(int) sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem)
664
+ {
665
+ DLLMOD_INIT(kernel, TRUE);
666
+
667
+ if (sigar_GlobalMemoryStatusEx) {
668
+ MEMORYSTATUSEX memstat;
669
+
670
+ memstat.dwLength = sizeof(memstat);
671
+
672
+ if (!sigar_GlobalMemoryStatusEx(&memstat)) {
673
+ return GetLastError();
674
+ }
675
+
676
+ mem->total = memstat.ullTotalPhys;
677
+ mem->free = memstat.ullAvailPhys;
678
+ }
679
+ else {
680
+ MEMORYSTATUS memstat;
681
+ GlobalMemoryStatus(&memstat);
682
+ mem->total = memstat.dwTotalPhys;
683
+ mem->free = memstat.dwAvailPhys;
684
+ }
685
+
686
+ mem->used = mem->total - mem->free;
687
+
688
+ mem->actual_free = mem->free;
689
+ mem->actual_used = mem->used;
690
+ /* set actual_{free,used} */
691
+ get_mem_counters(sigar, NULL, mem);
692
+
693
+ sigar_mem_calc_ram(sigar, mem);
694
+
695
+ return SIGAR_OK;
696
+ }
697
+
698
+ SIGAR_DECLARE(int) sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap)
699
+ {
700
+ int status;
701
+ DLLMOD_INIT(kernel, TRUE);
702
+
703
+ if (sigar_GlobalMemoryStatusEx) {
704
+ MEMORYSTATUSEX memstat;
705
+
706
+ memstat.dwLength = sizeof(memstat);
707
+
708
+ if (!sigar_GlobalMemoryStatusEx(&memstat)) {
709
+ return GetLastError();
710
+ }
711
+
712
+ swap->total = memstat.ullTotalPageFile;
713
+ swap->free = memstat.ullAvailPageFile;
714
+ }
715
+ else {
716
+ MEMORYSTATUS memstat;
717
+ GlobalMemoryStatus(&memstat);
718
+ swap->total = memstat.dwTotalPageFile;
719
+ swap->free = memstat.dwAvailPageFile;
720
+ }
721
+
722
+ swap->used = swap->total - swap->free;
723
+
724
+ if (get_mem_counters(sigar, swap, NULL) != SIGAR_OK) {
725
+ swap->page_in = SIGAR_FIELD_NOTIMPL;
726
+ swap->page_out = SIGAR_FIELD_NOTIMPL;
727
+ }
728
+
729
+ return SIGAR_OK;
730
+ }
731
+
732
+ static PERF_INSTANCE_DEFINITION *get_cpu_instance(sigar_t *sigar,
733
+ DWORD *perf_offsets,
734
+ DWORD *num, DWORD *err)
735
+ {
736
+ PERF_OBJECT_TYPE *object = get_perf_object(sigar, PERF_TITLE_CPU_KEY, err);
737
+ PERF_INSTANCE_DEFINITION *inst;
738
+ PERF_COUNTER_DEFINITION *counter;
739
+ DWORD i;
740
+
741
+ if (!object) {
742
+ return NULL;
743
+ }
744
+
745
+ for (i=0, counter = PdhFirstCounter(object);
746
+ i<object->NumCounters;
747
+ i++, counter = PdhNextCounter(counter))
748
+ {
749
+ DWORD offset = counter->CounterOffset;
750
+
751
+ switch (counter->CounterNameTitleIndex) {
752
+ case PERF_TITLE_CPU_SYS:
753
+ perf_offsets[PERF_IX_CPU_SYS] = offset;
754
+ break;
755
+ case PERF_TITLE_CPU_USER:
756
+ perf_offsets[PERF_IX_CPU_USER] = offset;
757
+ break;
758
+ case PERF_TITLE_CPU_IDLE:
759
+ perf_offsets[PERF_IX_CPU_IDLE] = offset;
760
+ break;
761
+ case PERF_TITLE_CPU_IRQ:
762
+ perf_offsets[PERF_IX_CPU_IRQ] = offset;
763
+ break;
764
+ }
765
+ }
766
+
767
+ if (num) {
768
+ *num = object->NumInstances;
769
+ }
770
+
771
+ return PdhFirstInstance(object);
772
+ }
773
+
774
+ #define SPPI_MAX 128 /* XXX unhardcode; should move off this api anyhow */
775
+
776
+ #define sigar_NtQuerySystemInformation \
777
+ sigar->ntdll.query_sys_info.func
778
+
779
+ static int get_idle_cpu(sigar_t *sigar, sigar_cpu_t *cpu,
780
+ DWORD idx,
781
+ PERF_COUNTER_BLOCK *counter_block,
782
+ DWORD *perf_offsets)
783
+ {
784
+ cpu->idle = 0;
785
+
786
+ if (perf_offsets[PERF_IX_CPU_IDLE]) {
787
+ cpu->idle = PERF_VAL_CPU(PERF_IX_CPU_IDLE);
788
+ }
789
+ else {
790
+ /* windows NT and 2000 do not have an Idle counter */
791
+ DLLMOD_INIT(ntdll, FALSE);
792
+ if (sigar_NtQuerySystemInformation) {
793
+ DWORD retval, num;
794
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX];
795
+ /* into the lungs of hell */
796
+ sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation,
797
+ &info, sizeof(info), &retval);
798
+
799
+ if (!retval) {
800
+ return GetLastError();
801
+ }
802
+ num = retval/sizeof(info[0]);
803
+
804
+ if (idx == -1) {
805
+ int i;
806
+ for (i=0; i<num; i++) {
807
+ cpu->idle += NS100_2MSEC(info[i].IdleTime.QuadPart);
808
+ }
809
+ }
810
+ else if (idx < num) {
811
+ cpu->idle = NS100_2MSEC(info[idx].IdleTime.QuadPart);
812
+ }
813
+ else {
814
+ return ERROR_INVALID_DATA;
815
+ }
816
+ }
817
+ else {
818
+ return ERROR_INVALID_FUNCTION;
819
+ }
820
+ }
821
+
822
+ return SIGAR_OK;
823
+ }
824
+
825
+ static int sigar_cpu_perflib_get(sigar_t *sigar, sigar_cpu_t *cpu)
826
+ {
827
+ int status;
828
+ PERF_INSTANCE_DEFINITION *inst;
829
+ PERF_COUNTER_BLOCK *counter_block;
830
+ DWORD perf_offsets[PERF_IX_CPU_MAX], err;
831
+
832
+ SIGAR_ZERO(cpu);
833
+ memset(&perf_offsets, 0, sizeof(perf_offsets));
834
+
835
+ inst = get_cpu_instance(sigar, (DWORD*)&perf_offsets, 0, &err);
836
+
837
+ if (!inst) {
838
+ return err;
839
+ }
840
+
841
+ /* first instance is total, rest are per-cpu */
842
+ counter_block = PdhGetCounterBlock(inst);
843
+
844
+ cpu->sys = PERF_VAL_CPU(PERF_IX_CPU_SYS);
845
+ cpu->user = PERF_VAL_CPU(PERF_IX_CPU_USER);
846
+ status = get_idle_cpu(sigar, cpu, -1, counter_block, perf_offsets);
847
+ cpu->irq = PERF_VAL_CPU(PERF_IX_CPU_IRQ);
848
+ cpu->nice = 0; /* no nice here */
849
+ cpu->wait = 0; /*N/A?*/
850
+ cpu->total = cpu->sys + cpu->user + cpu->idle + cpu->wait + cpu->irq;
851
+
852
+ if (status != SIGAR_OK) {
853
+ sigar_log_printf(sigar, SIGAR_LOG_WARN,
854
+ "unable to determine idle cpu time: %s",
855
+ sigar_strerror(sigar, status));
856
+ }
857
+
858
+ return SIGAR_OK;
859
+ }
860
+
861
+ static int sigar_cpu_ntsys_get(sigar_t *sigar, sigar_cpu_t *cpu)
862
+ {
863
+ DWORD retval, num;
864
+ int i;
865
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX];
866
+ /* into the lungs of hell */
867
+ sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation,
868
+ &info, sizeof(info), &retval);
869
+
870
+ if (!retval) {
871
+ return GetLastError();
872
+ }
873
+ num = retval/sizeof(info[0]);
874
+ SIGAR_ZERO(cpu);
875
+
876
+ for (i=0; i<num; i++) {
877
+ cpu->idle += NS100_2MSEC(info[i].IdleTime.QuadPart);
878
+ cpu->user += NS100_2MSEC(info[i].UserTime.QuadPart);
879
+ cpu->sys += NS100_2MSEC(info[i].KernelTime.QuadPart -
880
+ info[i].IdleTime.QuadPart);
881
+ cpu->irq += NS100_2MSEC(info[i].InterruptTime.QuadPart);
882
+ cpu->total += cpu->idle + cpu->user + cpu->sys;
883
+ }
884
+
885
+ return SIGAR_OK;
886
+ }
887
+
888
+ SIGAR_DECLARE(int) sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu)
889
+ {
890
+ DLLMOD_INIT(ntdll, FALSE);
891
+ if (sigar_NtQuerySystemInformation) {
892
+ return sigar_cpu_ntsys_get(sigar, cpu);
893
+ }
894
+ else {
895
+ return sigar_cpu_perflib_get(sigar, cpu);
896
+ }
897
+ }
898
+
899
+ static int sigar_cpu_list_perflib_get(sigar_t *sigar,
900
+ sigar_cpu_list_t *cpulist)
901
+ {
902
+ int status, i, j;
903
+ PERF_INSTANCE_DEFINITION *inst;
904
+ DWORD perf_offsets[PERF_IX_CPU_MAX], num, err;
905
+ int core_rollup = sigar_cpu_core_rollup(sigar);
906
+
907
+ memset(&perf_offsets, 0, sizeof(perf_offsets));
908
+
909
+ /* first instance is total, rest are per-cpu */
910
+ inst = get_cpu_instance(sigar, (DWORD*)&perf_offsets, &num, &err);
911
+
912
+ if (!inst) {
913
+ return err;
914
+ }
915
+
916
+ if (!sigar->winnt) {
917
+ /* skip Processor _Total instance (NT doesnt have one) */
918
+ --num;
919
+ inst = PdhNextInstance(inst);
920
+ }
921
+
922
+ sigar_cpu_list_create(cpulist);
923
+
924
+ /* verify there's a counter for each logical cpu */
925
+ if (core_rollup && (sigar->ncpu != num)) {
926
+ core_rollup = 0;
927
+ }
928
+
929
+ for (i=0; i<num; i++) {
930
+ PERF_COUNTER_BLOCK *counter_block;
931
+ sigar_cpu_t *cpu;
932
+
933
+ if (core_rollup && (i % sigar->lcpu)) {
934
+ /* merge times of logical processors */
935
+ cpu = &cpulist->data[cpulist->number-1];
936
+ }
937
+ else {
938
+ SIGAR_CPU_LIST_GROW(cpulist);
939
+ cpu = &cpulist->data[cpulist->number++];
940
+ SIGAR_ZERO(cpu);
941
+ }
942
+
943
+ counter_block = PdhGetCounterBlock(inst);
944
+
945
+ cpu->sys += PERF_VAL_CPU(PERF_IX_CPU_SYS);
946
+ cpu->user += PERF_VAL_CPU(PERF_IX_CPU_USER);
947
+ cpu->irq += PERF_VAL_CPU(PERF_IX_CPU_IRQ);
948
+ get_idle_cpu(sigar, cpu, i, counter_block, perf_offsets);
949
+ cpu->nice = cpu->wait = 0; /*N/A*/
950
+
951
+ /*XXX adding up too much here if xeon, but not using this atm*/
952
+ cpu->total += cpu->sys + cpu->user + cpu->idle + cpu->irq;
953
+
954
+ inst = PdhNextInstance(inst);
955
+ }
956
+
957
+ return SIGAR_OK;
958
+ }
959
+
960
+ static int sigar_cpu_list_ntsys_get(sigar_t *sigar,
961
+ sigar_cpu_list_t *cpulist)
962
+ {
963
+ DWORD retval, num;
964
+ int status, i, j;
965
+ int core_rollup = sigar_cpu_core_rollup(sigar);
966
+
967
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX];
968
+ /* into the lungs of hell */
969
+ sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation,
970
+ &info, sizeof(info), &retval);
971
+
972
+ if (!retval) {
973
+ return GetLastError();
974
+ }
975
+ num = retval/sizeof(info[0]);
976
+
977
+ sigar_cpu_list_create(cpulist);
978
+
979
+ /* verify there's a counter for each logical cpu */
980
+ if (core_rollup && (sigar->ncpu != num)) {
981
+ core_rollup = 0;
982
+ }
983
+
984
+ for (i=0; i<num; i++) {
985
+ sigar_cpu_t *cpu;
986
+ sigar_uint64_t idle, user, sys;
987
+
988
+ if (core_rollup && (i % sigar->lcpu)) {
989
+ /* merge times of logical processors */
990
+ cpu = &cpulist->data[cpulist->number-1];
991
+ }
992
+ else {
993
+ SIGAR_CPU_LIST_GROW(cpulist);
994
+ cpu = &cpulist->data[cpulist->number++];
995
+ SIGAR_ZERO(cpu);
996
+ }
997
+
998
+ idle = NS100_2MSEC(info[i].IdleTime.QuadPart);
999
+ user = NS100_2MSEC(info[i].UserTime.QuadPart);
1000
+ sys = NS100_2MSEC(info[i].KernelTime.QuadPart -
1001
+ info[i].IdleTime.QuadPart);
1002
+ cpu->idle += idle;
1003
+ cpu->user += user;
1004
+ cpu->sys += sys;
1005
+ cpu->nice = cpu->wait = 0; /*N/A*/
1006
+ cpu->total += idle + user + sys;
1007
+ }
1008
+
1009
+ return SIGAR_OK;
1010
+ }
1011
+
1012
+ SIGAR_DECLARE(int) sigar_cpu_list_get(sigar_t *sigar,
1013
+ sigar_cpu_list_t *cpulist)
1014
+ {
1015
+ DLLMOD_INIT(ntdll, FALSE);
1016
+ if (sigar_NtQuerySystemInformation) {
1017
+ return sigar_cpu_list_ntsys_get(sigar, cpulist);
1018
+ }
1019
+ else {
1020
+ return sigar_cpu_list_perflib_get(sigar, cpulist);
1021
+ }
1022
+ }
1023
+
1024
+ #define PERF_TITLE_UPTIME_KEY 674 /* System Up Time */
1025
+
1026
+ SIGAR_DECLARE(int) sigar_uptime_get(sigar_t *sigar,
1027
+ sigar_uptime_t *uptime)
1028
+ {
1029
+ int status;
1030
+ PERF_OBJECT_TYPE *object =
1031
+ get_perf_object_inst(sigar, PERF_TITLE_SYS_KEY, 0, &status);
1032
+ PERF_INSTANCE_DEFINITION *inst;
1033
+ PERF_COUNTER_DEFINITION *counter;
1034
+ BYTE *data;
1035
+ DWORD i;
1036
+
1037
+ if (!object) {
1038
+ return status;
1039
+ }
1040
+
1041
+ data = (BYTE *)((BYTE *)object + object->DefinitionLength);
1042
+
1043
+ for (i=0, counter = PdhFirstCounter(object);
1044
+ i<object->NumCounters;
1045
+ i++, counter = PdhNextCounter(counter))
1046
+ {
1047
+ if (counter->CounterNameTitleIndex == PERF_TITLE_UPTIME_KEY) {
1048
+ DWORD offset = counter->CounterOffset;
1049
+ LONGLONG time = object->PerfTime.QuadPart;
1050
+ LONGLONG freq = object->PerfFreq.QuadPart;
1051
+ LONGLONG counter = *((LONGLONG *)(data + offset));
1052
+ uptime->uptime = (time - counter) / freq;
1053
+ return SIGAR_OK;
1054
+ }
1055
+ }
1056
+
1057
+ /* http://msdn.microsoft.com/en-us/library/ms724408.aspx */
1058
+ return GetTickCount() / 1000;
1059
+ }
1060
+
1061
+ /*
1062
+ * there is no api for this info.
1063
+ * closest i've seen is enumerating the entire process table
1064
+ * and calculating an average based on process times.
1065
+ */
1066
+ SIGAR_DECLARE(int) sigar_loadavg_get(sigar_t *sigar,
1067
+ sigar_loadavg_t *loadavg)
1068
+ {
1069
+ return SIGAR_ENOTIMPL;
1070
+ }
1071
+
1072
+ #define get_process_object(sigar, err) \
1073
+ get_perf_object(sigar, PERF_TITLE_PROC_KEY, err)
1074
+
1075
+ static int sigar_proc_list_get_perf(sigar_t *sigar,
1076
+ sigar_proc_list_t *proclist)
1077
+ {
1078
+
1079
+ PERF_OBJECT_TYPE *object;
1080
+ PERF_INSTANCE_DEFINITION *inst;
1081
+ PERF_COUNTER_DEFINITION *counter;
1082
+ DWORD i, err;
1083
+ DWORD perf_offsets[PERF_IX_MAX];
1084
+
1085
+ perf_offsets[PERF_IX_PID] = 0;
1086
+
1087
+ object = get_process_object(sigar, &err);
1088
+
1089
+ if (!object) {
1090
+ return err;
1091
+ }
1092
+
1093
+ /*
1094
+ * note we assume here:
1095
+ * block->NumObjectTypes == 1
1096
+ * object->ObjectNameTitleIndex == PERF_TITLE_PROC
1097
+ *
1098
+ * which should always be the case.
1099
+ */
1100
+
1101
+ for (i=0, counter = PdhFirstCounter(object);
1102
+ i<object->NumCounters;
1103
+ i++, counter = PdhNextCounter(counter))
1104
+ {
1105
+ DWORD offset = counter->CounterOffset;
1106
+
1107
+ switch (counter->CounterNameTitleIndex) {
1108
+ case PERF_TITLE_PID:
1109
+ perf_offsets[PERF_IX_PID] = offset;
1110
+ break;
1111
+ }
1112
+ }
1113
+
1114
+ for (i=0, inst = PdhFirstInstance(object);
1115
+ i<object->NumInstances;
1116
+ i++, inst = PdhNextInstance(inst))
1117
+ {
1118
+ PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst);
1119
+ DWORD pid = PERF_VAL(PERF_IX_PID);
1120
+
1121
+ if (pid == 0) {
1122
+ continue; /* dont include the system Idle process */
1123
+ }
1124
+
1125
+ SIGAR_PROC_LIST_GROW(proclist);
1126
+
1127
+ proclist->data[proclist->number++] = pid;
1128
+ }
1129
+
1130
+ return SIGAR_OK;
1131
+ }
1132
+
1133
+ #define sigar_EnumProcesses \
1134
+ sigar->psapi.enum_processes.func
1135
+
1136
+ int sigar_os_proc_list_get(sigar_t *sigar,
1137
+ sigar_proc_list_t *proclist)
1138
+ {
1139
+ DLLMOD_INIT(psapi, FALSE);
1140
+
1141
+ if (sigar_EnumProcesses) {
1142
+ DWORD retval, *pids;
1143
+ DWORD size = 0, i;
1144
+
1145
+ do {
1146
+ /* re-use the perfbuf */
1147
+ if (size == 0) {
1148
+ size = perfbuf_init(sigar);
1149
+ }
1150
+ else {
1151
+ size = perfbuf_grow(sigar);
1152
+ }
1153
+
1154
+ if (!sigar_EnumProcesses((DWORD *)sigar->perfbuf,
1155
+ sigar->perfbuf_size,
1156
+ &retval))
1157
+ {
1158
+ return GetLastError();
1159
+ }
1160
+ } while (retval == sigar->perfbuf_size); //unlikely
1161
+
1162
+ pids = (DWORD *)sigar->perfbuf;
1163
+
1164
+ size = retval / sizeof(DWORD);
1165
+
1166
+ for (i=0; i<size; i++) {
1167
+ DWORD pid = pids[i];
1168
+ if (pid == 0) {
1169
+ continue; /* dont include the system Idle process */
1170
+ }
1171
+ SIGAR_PROC_LIST_GROW(proclist);
1172
+ proclist->data[proclist->number++] = pid;
1173
+ }
1174
+
1175
+ return SIGAR_OK;
1176
+ }
1177
+ else {
1178
+ return sigar_proc_list_get_perf(sigar, proclist);
1179
+ }
1180
+ }
1181
+
1182
+ #define PROCESS_DAC (PROCESS_QUERY_INFORMATION|PROCESS_VM_READ)
1183
+
1184
+ static HANDLE open_process(sigar_pid_t pid)
1185
+ {
1186
+ return OpenProcess(PROCESS_DAC, 0, (DWORD)pid);
1187
+ }
1188
+
1189
+ /*
1190
+ * Pretty good explanation of counters:
1191
+ * http://www.semack.net/wiki/default.asp?db=SemackNetWiki&o=VirtualMemory
1192
+ */
1193
+ SIGAR_DECLARE(int) sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
1194
+ sigar_proc_mem_t *procmem)
1195
+ {
1196
+ int status = get_proc_info(sigar, pid);
1197
+ sigar_win32_pinfo_t *pinfo = &sigar->pinfo;
1198
+
1199
+ if (status != SIGAR_OK) {
1200
+ return status;
1201
+ }
1202
+
1203
+ procmem->size = pinfo->size; /* "Virtual Bytes" */
1204
+ procmem->resident = pinfo->resident; /* "Working Set" */
1205
+ procmem->share = SIGAR_FIELD_NOTIMPL;
1206
+ procmem->page_faults = pinfo->page_faults;
1207
+ procmem->minor_faults = SIGAR_FIELD_NOTIMPL;
1208
+ procmem->major_faults = SIGAR_FIELD_NOTIMPL;
1209
+
1210
+ return SIGAR_OK;
1211
+ }
1212
+
1213
+ #define TOKEN_DAC (STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY)
1214
+
1215
+ SIGAR_DECLARE(int)
1216
+ sigar_proc_cred_name_get(sigar_t *sigar, sigar_pid_t pid,
1217
+ sigar_proc_cred_name_t *proccredname)
1218
+ {
1219
+ HANDLE proc, token;
1220
+ DWORD len;
1221
+ int success;
1222
+ TOKEN_USER *user = NULL;
1223
+ TOKEN_PRIMARY_GROUP *group = NULL;
1224
+ SID_NAME_USE type;
1225
+ char domain[SIGAR_CRED_NAME_MAX];
1226
+
1227
+ /* XXX cache lookup */
1228
+
1229
+ if (!(proc = open_process(pid))) {
1230
+ return GetLastError();
1231
+ }
1232
+
1233
+ if (!OpenProcessToken(proc, TOKEN_DAC, &token)) {
1234
+ CloseHandle(proc);
1235
+ return GetLastError();
1236
+ }
1237
+
1238
+ CloseHandle(proc);
1239
+
1240
+ success =
1241
+ !GetTokenInformation(token, TokenUser, NULL, 0, &len) &&
1242
+ (GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
1243
+ (user = malloc(len)) &&
1244
+ GetTokenInformation(token, TokenUser, user, len, &len);
1245
+
1246
+ if (success) {
1247
+ DWORD domain_len = sizeof(domain);
1248
+ DWORD user_len = sizeof(proccredname->user);
1249
+
1250
+ success = LookupAccountSid(NULL, user->User.Sid,
1251
+ proccredname->user, &user_len,
1252
+ domain, &domain_len, &type);
1253
+ }
1254
+
1255
+ if (user != NULL) {
1256
+ free(user);
1257
+ }
1258
+ if (!success) {
1259
+ CloseHandle(token);
1260
+ return GetLastError();
1261
+ }
1262
+
1263
+ success =
1264
+ !GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &len) &&
1265
+ (GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
1266
+ (group = malloc(len)) &&
1267
+ GetTokenInformation(token, TokenPrimaryGroup, group, len, &len);
1268
+
1269
+ if (success) {
1270
+ DWORD domain_len = sizeof(domain);
1271
+ DWORD group_len = sizeof(proccredname->group);
1272
+
1273
+ success = LookupAccountSid(NULL, group->PrimaryGroup,
1274
+ proccredname->group, &group_len,
1275
+ domain, &domain_len, &type);
1276
+ }
1277
+
1278
+ if (group != NULL) {
1279
+ free(group);
1280
+ }
1281
+
1282
+ CloseHandle(token);
1283
+
1284
+ if (!success) {
1285
+ return GetLastError();
1286
+ }
1287
+
1288
+ return SIGAR_OK;
1289
+ }
1290
+
1291
+ SIGAR_DECLARE(int) sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
1292
+ sigar_proc_cred_t *proccred)
1293
+ {
1294
+ return SIGAR_ENOTIMPL;
1295
+ }
1296
+
1297
+ #define FILETIME2MSEC(ft) \
1298
+ NS100_2MSEC(((ft.dwHighDateTime << 32) | ft.dwLowDateTime))
1299
+
1300
+ sigar_int64_t sigar_time_now_millis(void)
1301
+ {
1302
+ SYSTEMTIME st;
1303
+ FILETIME time;
1304
+
1305
+ GetSystemTime(&st);
1306
+ SystemTimeToFileTime(&st, &time);
1307
+
1308
+ return sigar_FileTimeToTime(&time) / 1000;
1309
+ }
1310
+
1311
+ SIGAR_DECLARE(int) sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid,
1312
+ sigar_proc_time_t *proctime)
1313
+ {
1314
+ HANDLE proc = open_process(pid);
1315
+ FILETIME start_time, exit_time, system_time, user_time;
1316
+ int status = ERROR_SUCCESS;
1317
+
1318
+ if (!proc) {
1319
+ return GetLastError();
1320
+ }
1321
+
1322
+ if (!GetProcessTimes(proc,
1323
+ &start_time, &exit_time,
1324
+ &system_time, &user_time))
1325
+ {
1326
+ status = GetLastError();
1327
+ }
1328
+
1329
+ CloseHandle(proc);
1330
+
1331
+ if (status != ERROR_SUCCESS) {
1332
+ return status;
1333
+ }
1334
+
1335
+ if (start_time.dwHighDateTime) {
1336
+ proctime->start_time =
1337
+ sigar_FileTimeToTime(&start_time) / 1000;
1338
+ }
1339
+ else {
1340
+ proctime->start_time = 0;
1341
+ }
1342
+
1343
+ proctime->user = FILETIME2MSEC(user_time);
1344
+ proctime->sys = FILETIME2MSEC(system_time);
1345
+ proctime->total = proctime->user + proctime->sys;
1346
+
1347
+ return SIGAR_OK;
1348
+ }
1349
+
1350
+ SIGAR_DECLARE(int) sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
1351
+ sigar_proc_state_t *procstate)
1352
+ {
1353
+ int status = get_proc_info(sigar, pid);
1354
+ sigar_win32_pinfo_t *pinfo = &sigar->pinfo;
1355
+
1356
+ if (status != SIGAR_OK) {
1357
+ return status;
1358
+ }
1359
+
1360
+ memcpy(procstate->name, pinfo->name, sizeof(procstate->name));
1361
+ procstate->state = pinfo->state;
1362
+ procstate->ppid = pinfo->ppid;
1363
+ procstate->priority = pinfo->priority;
1364
+ procstate->nice = SIGAR_FIELD_NOTIMPL;
1365
+ procstate->tty = SIGAR_FIELD_NOTIMPL;
1366
+ procstate->threads = pinfo->threads;
1367
+ procstate->processor = SIGAR_FIELD_NOTIMPL;
1368
+
1369
+ return SIGAR_OK;
1370
+ }
1371
+
1372
+ static int get_proc_info(sigar_t *sigar, sigar_pid_t pid)
1373
+ {
1374
+ PERF_OBJECT_TYPE *object;
1375
+ PERF_INSTANCE_DEFINITION *inst;
1376
+ PERF_COUNTER_DEFINITION *counter;
1377
+ DWORD i, err;
1378
+ DWORD perf_offsets[PERF_IX_MAX];
1379
+ sigar_win32_pinfo_t *pinfo = &sigar->pinfo;
1380
+ time_t timenow = time(NULL);
1381
+
1382
+ if (pinfo->pid == pid) {
1383
+ if ((timenow - pinfo->mtime) < SIGAR_LAST_PROC_EXPIRE) {
1384
+ return SIGAR_OK;
1385
+ }
1386
+ }
1387
+
1388
+ memset(&perf_offsets, 0, sizeof(perf_offsets));
1389
+
1390
+ object = get_process_object(sigar, &err);
1391
+
1392
+ if (object == NULL) {
1393
+ return err;
1394
+ }
1395
+
1396
+ pinfo->pid = pid;
1397
+ pinfo->mtime = timenow;
1398
+
1399
+ /*
1400
+ * note we assume here:
1401
+ * block->NumObjectTypes == 1
1402
+ * object->ObjectNameTitleIndex == PERF_TITLE_PROC
1403
+ *
1404
+ * which should always be the case.
1405
+ */
1406
+
1407
+ for (i=0, counter = PdhFirstCounter(object);
1408
+ i<object->NumCounters;
1409
+ i++, counter = PdhNextCounter(counter))
1410
+ {
1411
+ DWORD offset = counter->CounterOffset;
1412
+
1413
+ switch (counter->CounterNameTitleIndex) {
1414
+ case PERF_TITLE_CPUTIME:
1415
+ perf_offsets[PERF_IX_CPUTIME] = offset;
1416
+ break;
1417
+ case PERF_TITLE_PAGE_FAULTS:
1418
+ perf_offsets[PERF_IX_PAGE_FAULTS] = offset;
1419
+ break;
1420
+ case PERF_TITLE_MEM_VSIZE:
1421
+ perf_offsets[PERF_IX_MEM_VSIZE] = offset;
1422
+ break;
1423
+ case PERF_TITLE_MEM_SIZE:
1424
+ perf_offsets[PERF_IX_MEM_SIZE] = offset;
1425
+ break;
1426
+ case PERF_TITLE_THREAD_CNT:
1427
+ perf_offsets[PERF_IX_THREAD_CNT] = offset;
1428
+ break;
1429
+ case PERF_TITLE_HANDLE_CNT:
1430
+ perf_offsets[PERF_IX_HANDLE_CNT] = offset;
1431
+ break;
1432
+ case PERF_TITLE_PID:
1433
+ perf_offsets[PERF_IX_PID] = offset;
1434
+ break;
1435
+ case PERF_TITLE_PPID:
1436
+ perf_offsets[PERF_IX_PPID] = offset;
1437
+ break;
1438
+ case PERF_TITLE_PRIORITY:
1439
+ perf_offsets[PERF_IX_PRIORITY] = offset;
1440
+ break;
1441
+ case PERF_TITLE_START_TIME:
1442
+ perf_offsets[PERF_IX_START_TIME] = offset;
1443
+ break;
1444
+ }
1445
+ }
1446
+
1447
+ for (i=0, inst = PdhFirstInstance(object);
1448
+ i<object->NumInstances;
1449
+ i++, inst = PdhNextInstance(inst))
1450
+ {
1451
+ PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst);
1452
+ sigar_pid_t this_pid = PERF_VAL(PERF_IX_PID);
1453
+
1454
+ if (this_pid != pid) {
1455
+ continue;
1456
+ }
1457
+
1458
+ pinfo->state = 'R'; /* XXX? */
1459
+ SIGAR_W2A(PdhInstanceName(inst),
1460
+ pinfo->name, sizeof(pinfo->name));
1461
+
1462
+ pinfo->size = PERF_VAL(PERF_IX_MEM_VSIZE);
1463
+ pinfo->resident = PERF_VAL(PERF_IX_MEM_SIZE);
1464
+ pinfo->ppid = PERF_VAL(PERF_IX_PPID);
1465
+ pinfo->priority = PERF_VAL(PERF_IX_PRIORITY);
1466
+ pinfo->handles = PERF_VAL(PERF_IX_HANDLE_CNT);
1467
+ pinfo->threads = PERF_VAL(PERF_IX_THREAD_CNT);
1468
+ pinfo->page_faults = PERF_VAL(PERF_IX_PAGE_FAULTS);
1469
+
1470
+ return SIGAR_OK;
1471
+ }
1472
+
1473
+ return SIGAR_NO_SUCH_PROCESS;
1474
+ }
1475
+
1476
+ static int sigar_remote_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
1477
+ sigar_proc_args_t *procargs)
1478
+ {
1479
+ int status;
1480
+ char cmdline[SIGAR_CMDLINE_MAX], *ptr = cmdline, *arg;
1481
+ HANDLE proc = open_process(pid);
1482
+
1483
+ if (proc) {
1484
+ status = sigar_proc_args_peb_get(sigar, proc, procargs);
1485
+
1486
+ CloseHandle(proc);
1487
+
1488
+ if (status == SIGAR_OK) {
1489
+ return status;
1490
+ }
1491
+ }
1492
+
1493
+ /* likely we are 32-bit, pid process is 64-bit */
1494
+ #ifdef MSVC
1495
+ status = sigar_proc_args_wmi_get(sigar, pid, procargs);
1496
+ #endif
1497
+ if (status == ERROR_NOT_FOUND) {
1498
+ status = SIGAR_NO_SUCH_PROCESS;
1499
+ }
1500
+ return status;
1501
+ }
1502
+
1503
+ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
1504
+ sigar_proc_args_t *procargs)
1505
+ {
1506
+ if (pid == sigar->pid) {
1507
+ return sigar_parse_proc_args(sigar, NULL, procargs);
1508
+ }
1509
+ else {
1510
+ return sigar_remote_proc_args_get(sigar, pid, procargs);
1511
+ }
1512
+ }
1513
+
1514
+ static int sigar_proc_env_parse(UCHAR *ptr, sigar_proc_env_t *procenv,
1515
+ int multi)
1516
+ {
1517
+ while (*ptr) {
1518
+ char *val;
1519
+ int klen, vlen, status;
1520
+ char key[128]; /* XXX is there a max key size? */
1521
+
1522
+ if (*ptr == '=') {
1523
+ ptr += strlen(ptr)+1;
1524
+ continue;
1525
+ }
1526
+
1527
+ val = strchr(ptr, '=');
1528
+
1529
+ if (val == NULL) {
1530
+ break; /*XXX*/
1531
+ }
1532
+
1533
+ klen = val - (char*)ptr;
1534
+ SIGAR_SSTRCPY(key, ptr);
1535
+ key[klen] = '\0';
1536
+ ++val;
1537
+
1538
+ vlen = strlen(val);
1539
+
1540
+ status = procenv->env_getter(procenv->data,
1541
+ key, klen, val, vlen);
1542
+
1543
+ if (status != SIGAR_OK) {
1544
+ /* not an error; just stop iterating */
1545
+ return status;
1546
+ }
1547
+
1548
+ if (!multi) {
1549
+ break; /* caller only provided 1 key=val pair */
1550
+ }
1551
+
1552
+ ptr += klen + 1 + vlen + 1;
1553
+ }
1554
+
1555
+ return SIGAR_OK;
1556
+ }
1557
+
1558
+ static int sigar_local_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
1559
+ sigar_proc_env_t *procenv)
1560
+ {
1561
+ UCHAR *env = (UCHAR*)GetEnvironmentStrings();
1562
+
1563
+ sigar_proc_env_parse(env, procenv, TRUE);
1564
+
1565
+ FreeEnvironmentStrings(env);
1566
+
1567
+ return SIGAR_OK;
1568
+ }
1569
+
1570
+ static int sigar_remote_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
1571
+ sigar_proc_env_t *procenv)
1572
+ {
1573
+ int status;
1574
+ HANDLE proc = open_process(pid);
1575
+ WCHAR env[4096];
1576
+
1577
+ if (!proc) {
1578
+ return GetLastError();
1579
+ }
1580
+
1581
+ status = sigar_proc_env_peb_get(sigar, proc, env, sizeof(env));
1582
+
1583
+ CloseHandle(proc);
1584
+
1585
+ if (status == SIGAR_OK) {
1586
+ LPBYTE ptr = (LPBYTE)env;
1587
+ DWORD size = sizeof(env);
1588
+ UCHAR ent[4096];
1589
+
1590
+ while ((size > 0) && (*ptr != L'\0')) {
1591
+ DWORD len = (wcslen((LPWSTR)ptr) + 1) * sizeof(WCHAR);
1592
+ /* multi=FALSE so no need to: memset(ent, '\0', sizeof(ent)) */
1593
+ SIGAR_W2A((WCHAR *)ptr, ent, sizeof(ent));
1594
+ if (sigar_proc_env_parse(ent, procenv, FALSE) != SIGAR_OK) {
1595
+ break;
1596
+ }
1597
+ size -= len;
1598
+ ptr += len;
1599
+ }
1600
+ }
1601
+
1602
+ return status;
1603
+ }
1604
+
1605
+ SIGAR_DECLARE(int) sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
1606
+ sigar_proc_env_t *procenv)
1607
+ {
1608
+ if (pid == sigar->pid) {
1609
+ if (procenv->type == SIGAR_PROC_ENV_KEY) {
1610
+ char value[32767]; /* max size from msdn docs */
1611
+ DWORD retval =
1612
+ GetEnvironmentVariable(procenv->key, value, sizeof(value));
1613
+
1614
+ if (retval == 0) {
1615
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
1616
+ return SIGAR_OK;
1617
+ }
1618
+ return GetLastError();
1619
+ }
1620
+ else if (retval > sizeof(value)) {
1621
+ /* XXX shouldnt happen */
1622
+ return GetLastError();
1623
+ }
1624
+
1625
+ procenv->env_getter(procenv->data,
1626
+ procenv->key, procenv->klen,
1627
+ value, retval);
1628
+ return SIGAR_OK;
1629
+ }
1630
+ else {
1631
+ return sigar_local_proc_env_get(sigar, pid, procenv);
1632
+ }
1633
+ }
1634
+ else {
1635
+ return sigar_remote_proc_env_get(sigar, pid, procenv);
1636
+ }
1637
+ }
1638
+
1639
+ SIGAR_DECLARE(int) sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid,
1640
+ sigar_proc_fd_t *procfd)
1641
+ {
1642
+ int status;
1643
+ sigar_win32_pinfo_t *pinfo = &sigar->pinfo;
1644
+
1645
+ pinfo->pid = -1; /* force update */
1646
+ if ((status = get_proc_info(sigar, pid)) != SIGAR_OK) {
1647
+ return status;
1648
+ }
1649
+
1650
+ procfd->total = pinfo->handles;
1651
+
1652
+ return SIGAR_OK;
1653
+ }
1654
+
1655
+ SIGAR_DECLARE(int) sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
1656
+ sigar_proc_exe_t *procexe)
1657
+ {
1658
+ int status = SIGAR_OK;
1659
+ HANDLE proc = open_process(pid);
1660
+
1661
+ if (!proc) {
1662
+ return GetLastError();
1663
+ }
1664
+
1665
+ status = sigar_proc_exe_peb_get(sigar, proc, procexe);
1666
+ #ifdef MSVC
1667
+ if (procexe->name[0] == '\0') {
1668
+ /* likely we are 32-bit, pid process is 64-bit */
1669
+ /* procexe->cwd[0] = XXX where else can we try? */
1670
+ status = sigar_proc_exe_wmi_get(sigar, pid, procexe);
1671
+ if (status == ERROR_NOT_FOUND) {
1672
+ status = SIGAR_NO_SUCH_PROCESS;
1673
+ }
1674
+ }
1675
+ #endif
1676
+ if (procexe->cwd[0] != '\0') {
1677
+ /* strip trailing '\' */
1678
+ int len = strlen(procexe->cwd);
1679
+ if (procexe->cwd[len-1] == '\\') {
1680
+ procexe->cwd[len-1] = '\0';
1681
+ }
1682
+ /* uppercase driver letter */
1683
+ procexe->cwd[0] = toupper(procexe->cwd[0]);
1684
+ /* e.g. C:\ */
1685
+ strncpy(procexe->root, procexe->cwd, 3);
1686
+ procexe->root[3] = '\0';
1687
+ }
1688
+ else {
1689
+ procexe->root[0] = '\0';
1690
+ }
1691
+
1692
+ if (procexe->name[0] != '\0') {
1693
+ /* uppercase driver letter */
1694
+ procexe->name[0] = toupper(procexe->name[0]);
1695
+ }
1696
+
1697
+ CloseHandle(proc);
1698
+
1699
+ return status;
1700
+ }
1701
+
1702
+ #define sigar_EnumProcessModules \
1703
+ sigar->psapi.enum_modules.func
1704
+
1705
+ #define sigar_GetModuleFileNameEx \
1706
+ sigar->psapi.get_module_name.func
1707
+
1708
+ SIGAR_DECLARE(int) sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid,
1709
+ sigar_proc_modules_t *procmods)
1710
+ {
1711
+ HANDLE proc;
1712
+ HMODULE modules[1024];
1713
+ DWORD size = 0;
1714
+ unsigned int i;
1715
+
1716
+ if (DLLMOD_INIT(psapi, TRUE) != SIGAR_OK) {
1717
+ return SIGAR_ENOTIMPL;
1718
+ }
1719
+
1720
+ if (!(proc = open_process(pid))) {
1721
+ return GetLastError();
1722
+ }
1723
+
1724
+ if (!sigar_EnumProcessModules(proc, modules, sizeof(modules), &size)) {
1725
+ CloseHandle(proc);
1726
+ return GetLastError();
1727
+ }
1728
+
1729
+ for (i=0; i<(size/sizeof(HMODULE)); i++) {
1730
+ int status;
1731
+ char name[MAX_PATH];
1732
+
1733
+ if (!sigar_GetModuleFileNameEx(proc, modules[i],
1734
+ name, sizeof(name)))
1735
+ {
1736
+ continue;
1737
+ }
1738
+
1739
+ status = procmods->module_getter(procmods->data,
1740
+ name, strlen(name));
1741
+
1742
+ if (status != SIGAR_OK) {
1743
+ /* not an error; just stop iterating */
1744
+ break;
1745
+ }
1746
+ }
1747
+
1748
+ CloseHandle(proc);
1749
+
1750
+ return SIGAR_OK;
1751
+ }
1752
+
1753
+ #define FT2INT64(ft) \
1754
+ ((__int64)((__int64)(ft).dwHighDateTime << 32 | \
1755
+ (__int64)(ft).dwLowDateTime))
1756
+
1757
+ SIGAR_DECLARE(int) sigar_thread_cpu_get(sigar_t *sigar,
1758
+ sigar_uint64_t id,
1759
+ sigar_thread_cpu_t *cpu)
1760
+ {
1761
+ FILETIME start, exit, sys, user;
1762
+ DWORD retval;
1763
+
1764
+ if (id != 0) {
1765
+ return SIGAR_ENOTIMPL;
1766
+ }
1767
+
1768
+ retval = GetThreadTimes(GetCurrentThread(),
1769
+ &start, &exit, &sys, &user);
1770
+
1771
+ if (retval == 0) {
1772
+ return GetLastError();
1773
+ }
1774
+
1775
+ cpu->user = FT2INT64(user) * 100;
1776
+ cpu->sys = FT2INT64(sys) * 100;
1777
+ cpu->total = (FT2INT64(user) + FT2INT64(sys)) * 100;
1778
+
1779
+ return SIGAR_OK;
1780
+ }
1781
+
1782
+ int sigar_os_fs_type_get(sigar_file_system_t *fsp)
1783
+ {
1784
+ return fsp->type;
1785
+ }
1786
+
1787
+ #ifndef FILE_READ_ONLY_VOLUME
1788
+ #define FILE_READ_ONLY_VOLUME 0x00080000
1789
+ #endif
1790
+ #ifndef FILE_NAMED_STREAMS
1791
+ #define FILE_NAMED_STREAMS 0x00040000
1792
+ #endif
1793
+ #ifndef FILE_SEQUENTIAL_WRITE_ONCE
1794
+ #define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
1795
+ #endif
1796
+ #ifndef FILE_SUPPORTS_TRANSACTIONS
1797
+ #define FILE_SUPPORTS_TRANSACTIONS 0x00200000
1798
+ #endif
1799
+
1800
+ static void get_fs_options(char *opts, int osize, long flags)
1801
+ {
1802
+ *opts = '\0';
1803
+ if (flags & FILE_READ_ONLY_VOLUME) strncat(opts, "ro", osize);
1804
+ else strncat(opts, "rw", osize);
1805
+ #if 0 /*XXX*/
1806
+ if (flags & FILE_CASE_PRESERVED_NAMES) strncat(opts, ",casepn", osize);
1807
+ if (flags & FILE_CASE_SENSITIVE_SEARCH) strncat(opts, ",casess", osize);
1808
+ if (flags & FILE_FILE_COMPRESSION) strncat(opts, ",fcomp", osize);
1809
+ if (flags & FILE_NAMED_STREAMS) strncat(opts, ",streams", osize);
1810
+ if (flags & FILE_PERSISTENT_ACLS) strncat(opts, ",acls", osize);
1811
+ if (flags & FILE_SEQUENTIAL_WRITE_ONCE) strncat(opts, ",wronce", osize);
1812
+ if (flags & FILE_SUPPORTS_ENCRYPTION) strncat(opts, ",efs", osize);
1813
+ if (flags & FILE_SUPPORTS_OBJECT_IDS) strncat(opts, ",oids", osize);
1814
+ if (flags & FILE_SUPPORTS_REPARSE_POINTS) strncat(opts, ",reparse", osize);
1815
+ if (flags & FILE_SUPPORTS_SPARSE_FILES) strncat(opts, ",sparse", osize);
1816
+ if (flags & FILE_SUPPORTS_TRANSACTIONS) strncat(opts, ",trans", osize);
1817
+ if (flags & FILE_UNICODE_ON_DISK) strncat(opts, ",unicode", osize);
1818
+ if (flags & FILE_VOLUME_IS_COMPRESSED) strncat(opts, ",vcomp", osize);
1819
+ if (flags & FILE_VOLUME_QUOTAS) strncat(opts, ",quota", osize);
1820
+ #endif
1821
+ }
1822
+
1823
+ #define sigar_WNetGetConnection \
1824
+ sigar->mpr.get_net_connection.func
1825
+
1826
+ SIGAR_DECLARE(int) sigar_file_system_list_get(sigar_t *sigar,
1827
+ sigar_file_system_list_t *fslist)
1828
+ {
1829
+ char name[256];
1830
+ char *ptr = name;
1831
+ /* XXX: hmm, Find{First,Next}Volume not available in my sdk */
1832
+ DWORD len = GetLogicalDriveStringsA(sizeof(name), name);
1833
+
1834
+ DLLMOD_INIT(mpr, TRUE);
1835
+
1836
+ if (len == 0) {
1837
+ return GetLastError();
1838
+ }
1839
+
1840
+ sigar_file_system_list_create(fslist);
1841
+
1842
+ while (*ptr) {
1843
+ sigar_file_system_t *fsp;
1844
+ DWORD flags, serialnum=0;
1845
+ char fsname[1024];
1846
+ UINT drive_type = GetDriveType(ptr);
1847
+ int type;
1848
+
1849
+ switch (drive_type) {
1850
+ case DRIVE_FIXED:
1851
+ type = SIGAR_FSTYPE_LOCAL_DISK;
1852
+ break;
1853
+ case DRIVE_REMOTE:
1854
+ type = SIGAR_FSTYPE_NETWORK;
1855
+ break;
1856
+ case DRIVE_CDROM:
1857
+ type = SIGAR_FSTYPE_CDROM;
1858
+ break;
1859
+ case DRIVE_RAMDISK:
1860
+ type = SIGAR_FSTYPE_RAM_DISK;
1861
+ break;
1862
+ case DRIVE_REMOVABLE:
1863
+ /* skip floppy, usb, etc. drives */
1864
+ ptr += strlen(ptr)+1;
1865
+ continue;
1866
+ default:
1867
+ type = SIGAR_FSTYPE_NONE;
1868
+ break;
1869
+ }
1870
+
1871
+ fsname[0] = '\0';
1872
+
1873
+ GetVolumeInformation(ptr, NULL, 0, &serialnum, NULL,
1874
+ &flags, fsname, sizeof(fsname));
1875
+
1876
+ if (!serialnum && (drive_type == DRIVE_FIXED)) {
1877
+ ptr += strlen(ptr)+1;
1878
+ continue; /* ignore unformatted partitions */
1879
+ }
1880
+
1881
+ SIGAR_FILE_SYSTEM_LIST_GROW(fslist);
1882
+
1883
+ fsp = &fslist->data[fslist->number++];
1884
+
1885
+ fsp->type = type;
1886
+ SIGAR_SSTRCPY(fsp->dir_name, ptr);
1887
+ SIGAR_SSTRCPY(fsp->dev_name, ptr);
1888
+
1889
+ if ((drive_type == DRIVE_REMOTE) && sigar_WNetGetConnection) {
1890
+ DWORD len = sizeof(fsp->dev_name);
1891
+ char drive[3] = {'\0', ':', '\0'}; /* e.g. "X:" w/o trailing "\" */
1892
+ drive[0] = fsp->dir_name[0];
1893
+ sigar_WNetGetConnection(drive, fsp->dev_name, &len);
1894
+ /* ignoring failure, leaving dev_name as dir_name */
1895
+ }
1896
+
1897
+ /* we set fsp->type, just looking up sigar.c:fstype_names[type] */
1898
+ sigar_fs_type_get(fsp);
1899
+
1900
+ if (*fsname == '\0') {
1901
+ SIGAR_SSTRCPY(fsp->sys_type_name, fsp->type_name);
1902
+ }
1903
+ else {
1904
+ SIGAR_SSTRCPY(fsp->sys_type_name, fsname); /* CDFS, NTFS, etc */
1905
+ }
1906
+
1907
+ get_fs_options(fsp->options, sizeof(fsp->options)-1, flags);
1908
+
1909
+ ptr += strlen(ptr)+1;
1910
+ }
1911
+
1912
+ return SIGAR_OK;
1913
+ }
1914
+
1915
+ static PERF_INSTANCE_DEFINITION *get_disk_instance(sigar_t *sigar,
1916
+ DWORD *perf_offsets,
1917
+ DWORD *num, DWORD *err)
1918
+ {
1919
+ PERF_OBJECT_TYPE *object =
1920
+ get_perf_object(sigar, PERF_TITLE_DISK_KEY, err);
1921
+ PERF_INSTANCE_DEFINITION *inst;
1922
+ PERF_COUNTER_DEFINITION *counter;
1923
+ DWORD i, found=0;
1924
+
1925
+ if (!object) {
1926
+ return NULL;
1927
+ }
1928
+
1929
+ for (i=0, counter = PdhFirstCounter(object);
1930
+ i<object->NumCounters;
1931
+ i++, counter = PdhNextCounter(counter))
1932
+ {
1933
+ DWORD offset = counter->CounterOffset;
1934
+
1935
+ switch (counter->CounterNameTitleIndex) {
1936
+ case PERF_TITLE_DISK_TIME:
1937
+ perf_offsets[PERF_IX_DISK_TIME] = offset;
1938
+ found = 1;
1939
+ break;
1940
+ case PERF_TITLE_DISK_READ_TIME:
1941
+ perf_offsets[PERF_IX_DISK_READ_TIME] = offset;
1942
+ found = 1;
1943
+ break;
1944
+ case PERF_TITLE_DISK_WRITE_TIME:
1945
+ perf_offsets[PERF_IX_DISK_WRITE_TIME] = offset;
1946
+ found = 1;
1947
+ break;
1948
+ case PERF_TITLE_DISK_READ:
1949
+ perf_offsets[PERF_IX_DISK_READ] = offset;
1950
+ found = 1;
1951
+ break;
1952
+ case PERF_TITLE_DISK_WRITE:
1953
+ perf_offsets[PERF_IX_DISK_WRITE] = offset;
1954
+ found = 1;
1955
+ break;
1956
+ case PERF_TITLE_DISK_READ_BYTES:
1957
+ perf_offsets[PERF_IX_DISK_READ_BYTES] = offset;
1958
+ found = 1;
1959
+ break;
1960
+ case PERF_TITLE_DISK_WRITE_BYTES:
1961
+ perf_offsets[PERF_IX_DISK_WRITE_BYTES] = offset;
1962
+ found = 1;
1963
+ break;
1964
+ case PERF_TITLE_DISK_QUEUE:
1965
+ perf_offsets[PERF_IX_DISK_QUEUE] = offset;
1966
+ found = 1;
1967
+ break;
1968
+ }
1969
+ }
1970
+
1971
+ if (!found) {
1972
+ *err = ENOENT;
1973
+ return NULL;
1974
+ }
1975
+
1976
+ if (num) {
1977
+ *num = object->NumInstances;
1978
+ }
1979
+
1980
+ return PdhFirstInstance(object);
1981
+ }
1982
+
1983
+ SIGAR_DECLARE(int) sigar_disk_usage_get(sigar_t *sigar,
1984
+ const char *dirname,
1985
+ sigar_disk_usage_t *disk)
1986
+ {
1987
+ DWORD i, err;
1988
+ PERF_OBJECT_TYPE *object =
1989
+ get_perf_object(sigar, PERF_TITLE_DISK_KEY, &err);
1990
+ PERF_INSTANCE_DEFINITION *inst;
1991
+ PERF_COUNTER_DEFINITION *counter;
1992
+ DWORD perf_offsets[PERF_IX_DISK_MAX];
1993
+
1994
+ SIGAR_DISK_STATS_INIT(disk);
1995
+
1996
+ if (!object) {
1997
+ return err;
1998
+ }
1999
+
2000
+ memset(&perf_offsets, 0, sizeof(perf_offsets));
2001
+ inst = get_disk_instance(sigar, (DWORD*)&perf_offsets, 0, &err);
2002
+
2003
+ if (!inst) {
2004
+ return err;
2005
+ }
2006
+
2007
+ for (i=0, inst = PdhFirstInstance(object);
2008
+ i<object->NumInstances;
2009
+ i++, inst = PdhNextInstance(inst))
2010
+ {
2011
+ char drive[MAX_PATH];
2012
+ PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst);
2013
+ wchar_t *name = (wchar_t *)((BYTE *)inst + inst->NameOffset);
2014
+
2015
+ SIGAR_W2A(name, drive, sizeof(drive));
2016
+
2017
+ if (sigar_isdigit(*name)) {
2018
+ char *ptr = strchr(drive, ' '); /* 2000 Server "0 C:" */
2019
+
2020
+ if (ptr) {
2021
+ ++ptr;
2022
+ SIGAR_SSTRCPY(drive, ptr);
2023
+ }
2024
+ else {
2025
+ /* XXX NT is a number only "0", how to map? */
2026
+ }
2027
+ }
2028
+
2029
+ if (strnEQ(drive, dirname, 2)) {
2030
+ disk->time = PERF_VAL(PERF_IX_DISK_TIME);
2031
+ disk->rtime = PERF_VAL(PERF_IX_DISK_READ_TIME);
2032
+ disk->wtime = PERF_VAL(PERF_IX_DISK_WRITE_TIME);
2033
+ disk->reads = PERF_VAL(PERF_IX_DISK_READ);
2034
+ disk->writes = PERF_VAL(PERF_IX_DISK_WRITE);
2035
+ disk->read_bytes = PERF_VAL(PERF_IX_DISK_READ_BYTES);
2036
+ disk->write_bytes = PERF_VAL(PERF_IX_DISK_WRITE_BYTES);
2037
+ disk->queue = PERF_VAL(PERF_IX_DISK_QUEUE);
2038
+ return SIGAR_OK;
2039
+ }
2040
+ }
2041
+
2042
+ return ENXIO;
2043
+ }
2044
+
2045
+ SIGAR_DECLARE(int)
2046
+ sigar_file_system_usage_get(sigar_t *sigar,
2047
+ const char *dirname,
2048
+ sigar_file_system_usage_t *fsusage)
2049
+ {
2050
+ BOOL retval;
2051
+ ULARGE_INTEGER avail, total, free;
2052
+ int status;
2053
+
2054
+ /* prevent dialog box if A:\ drive is empty */
2055
+ UINT errmode = SetErrorMode(SEM_FAILCRITICALERRORS);
2056
+
2057
+ retval = GetDiskFreeSpaceEx(dirname,
2058
+ &avail, &total, &free);
2059
+
2060
+ /* restore previous error mode */
2061
+ SetErrorMode(errmode);
2062
+
2063
+ if (!retval) {
2064
+ return GetLastError();
2065
+ }
2066
+
2067
+ fsusage->total = total.QuadPart / 1024;
2068
+ fsusage->free = free.QuadPart / 1024;
2069
+ fsusage->avail = avail.QuadPart / 1024;
2070
+ fsusage->used = fsusage->total - fsusage->free;
2071
+ fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
2072
+
2073
+ /* N/A */
2074
+ fsusage->files = SIGAR_FIELD_NOTIMPL;
2075
+ fsusage->free_files = SIGAR_FIELD_NOTIMPL;
2076
+
2077
+ status = sigar_disk_usage_get(sigar, dirname, &fsusage->disk);
2078
+
2079
+ return SIGAR_OK;
2080
+ }
2081
+
2082
+ static int sigar_cpu_info_get(sigar_t *sigar, sigar_cpu_info_t *info)
2083
+ {
2084
+ HKEY key, cpu;
2085
+ int i = 0;
2086
+ char id[MAX_PATH + 1];
2087
+ DWORD size = 0, rc;
2088
+
2089
+ RegOpenKey(HKEY_LOCAL_MACHINE,
2090
+ "HARDWARE\\DESCRIPTION\\System\\CentralProcessor", &key);
2091
+
2092
+ //just lookup the first id, then assume all cpus are the same.
2093
+ rc = RegEnumKey(key, 0, id, sizeof(id));
2094
+ if (rc != ERROR_SUCCESS) {
2095
+ RegCloseKey(key);
2096
+ return rc;
2097
+ }
2098
+
2099
+ rc = RegOpenKey(key, id, &cpu);
2100
+ if (rc != ERROR_SUCCESS) {
2101
+ RegCloseKey(key);
2102
+ return rc;
2103
+ }
2104
+
2105
+ size = sizeof(info->vendor);
2106
+ if (RegQueryValueEx(cpu, "VendorIdentifier", NULL, NULL,
2107
+ (LPVOID)&info->vendor, &size) ||
2108
+ strEQ(info->vendor, "GenuineIntel"))
2109
+ {
2110
+ SIGAR_SSTRCPY(info->vendor, "Intel");
2111
+ }
2112
+ else {
2113
+ if (strEQ(info->vendor, "AuthenticAMD")) {
2114
+ SIGAR_SSTRCPY(info->vendor, "AMD");
2115
+ }
2116
+ }
2117
+
2118
+ size = sizeof(info->model);
2119
+ if (RegQueryValueEx(cpu, "ProcessorNameString", NULL, NULL,
2120
+ (LPVOID)&info->model, &size))
2121
+ {
2122
+ size = sizeof(info->model);
2123
+ if (RegQueryValueEx(cpu, "Identifier", NULL, NULL,
2124
+ (LPVOID)&info->model, &size))
2125
+ {
2126
+ SIGAR_SSTRCPY(info->model, "x86");
2127
+ }
2128
+ }
2129
+ else {
2130
+ sigar_cpu_model_adjust(sigar, info);
2131
+ }
2132
+
2133
+ size = sizeof(info->mhz); // == sizeof(DWORD)
2134
+ if (RegQueryValueEx(cpu, "~MHz", NULL, NULL,
2135
+ (LPVOID)&info->mhz, &size))
2136
+ {
2137
+ info->mhz = -1;
2138
+ }
2139
+
2140
+ info->cache_size = -1; //XXX
2141
+ RegCloseKey(key);
2142
+ RegCloseKey(cpu);
2143
+
2144
+ info->total_cores = sigar->ncpu;
2145
+ info->cores_per_socket = sigar->lcpu;
2146
+ info->total_sockets = sigar_cpu_socket_count(sigar);
2147
+
2148
+ return SIGAR_OK;
2149
+ }
2150
+
2151
+ SIGAR_DECLARE(int) sigar_cpu_info_list_get(sigar_t *sigar,
2152
+ sigar_cpu_info_list_t *cpu_infos)
2153
+ {
2154
+ int i, status;
2155
+ sigar_cpu_info_t info;
2156
+ int core_rollup = sigar_cpu_core_rollup(sigar);
2157
+
2158
+ sigar_cpu_info_list_create(cpu_infos);
2159
+
2160
+ status = sigar_cpu_info_get(sigar, &info);
2161
+
2162
+ if (status != SIGAR_OK) {
2163
+ return status;
2164
+ }
2165
+
2166
+ for (i=0; i<sigar->ncpu; i++) {
2167
+ SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
2168
+
2169
+ if (core_rollup && (i % sigar->lcpu)) {
2170
+ continue; /* fold logical processors */
2171
+ }
2172
+
2173
+ memcpy(&cpu_infos->data[cpu_infos->number++],
2174
+ &info, sizeof(info));
2175
+ }
2176
+
2177
+ return SIGAR_OK;
2178
+ }
2179
+
2180
+ #define sigar_GetNetworkParams \
2181
+ sigar->iphlpapi.get_net_params.func
2182
+
2183
+ #define sigar_GetAdaptersInfo \
2184
+ sigar->iphlpapi.get_adapters_info.func
2185
+
2186
+ #define sigar_GetAdaptersAddresses \
2187
+ sigar->iphlpapi.get_adapters_addrs.func
2188
+
2189
+ #define sigar_GetNumberOfInterfaces \
2190
+ sigar->iphlpapi.get_num_if.func
2191
+
2192
+ static sigar_cache_t *sigar_netif_cache_new(sigar_t *sigar)
2193
+ {
2194
+ DWORD num = 0;
2195
+
2196
+ DLLMOD_INIT(iphlpapi, FALSE);
2197
+
2198
+ if (sigar_GetNumberOfInterfaces) {
2199
+ DWORD rc = sigar_GetNumberOfInterfaces(&num);
2200
+
2201
+ if (rc == NO_ERROR) {
2202
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2203
+ "GetNumberOfInterfaces=%d",
2204
+ num);
2205
+ }
2206
+ else {
2207
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2208
+ "GetNumberOfInterfaces failed: %s",
2209
+ sigar_strerror(sigar, rc));
2210
+ }
2211
+ }
2212
+
2213
+ if (num == 0) {
2214
+ num = 10; /* reasonable default */
2215
+ }
2216
+
2217
+ return sigar_cache_new(num);
2218
+ }
2219
+
2220
+ static int sigar_get_adapters_info(sigar_t *sigar,
2221
+ PIP_ADAPTER_INFO *adapter)
2222
+ {
2223
+ ULONG size = sigar->ifconf_len;
2224
+ DWORD rc;
2225
+
2226
+ DLLMOD_INIT(iphlpapi, FALSE);
2227
+
2228
+ if (!sigar_GetAdaptersInfo) {
2229
+ return SIGAR_ENOTIMPL;
2230
+ }
2231
+
2232
+ *adapter = (PIP_ADAPTER_INFO)sigar->ifconf_buf;
2233
+ rc = sigar_GetAdaptersInfo(*adapter, &size);
2234
+
2235
+ if (rc == ERROR_BUFFER_OVERFLOW) {
2236
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2237
+ "GetAdaptersInfo "
2238
+ "realloc ifconf_buf old=%d, new=%d",
2239
+ sigar->ifconf_len, size);
2240
+ sigar->ifconf_len = size;
2241
+ sigar->ifconf_buf = realloc(sigar->ifconf_buf,
2242
+ sigar->ifconf_len);
2243
+
2244
+ *adapter = (PIP_ADAPTER_INFO)sigar->ifconf_buf;
2245
+ rc = sigar_GetAdaptersInfo(*adapter, &size);
2246
+ }
2247
+
2248
+ if (rc != NO_ERROR) {
2249
+ return rc;
2250
+ }
2251
+ else {
2252
+ return SIGAR_OK;
2253
+ }
2254
+ }
2255
+
2256
+ static int sigar_get_adapter_info(sigar_t *sigar,
2257
+ DWORD index,
2258
+ IP_ADAPTER_INFO **adapter)
2259
+ {
2260
+ sigar_cache_entry_t *entry;
2261
+ *adapter = NULL;
2262
+
2263
+ if (sigar->netif_adapters) {
2264
+ entry = sigar_cache_get(sigar->netif_adapters, index);
2265
+ if (entry->value) {
2266
+ *adapter = (IP_ADAPTER_INFO *)entry->value;
2267
+ }
2268
+ }
2269
+ else {
2270
+ int status;
2271
+ IP_ADAPTER_INFO *info;
2272
+
2273
+ sigar->netif_adapters =
2274
+ sigar_netif_cache_new(sigar);
2275
+
2276
+ status = sigar_get_adapters_info(sigar, &info);
2277
+ if (status != SIGAR_OK) {
2278
+ return status;
2279
+ }
2280
+
2281
+ while (info) {
2282
+ entry = sigar_cache_get(sigar->netif_adapters,
2283
+ info->Index);
2284
+ if (!entry->value) {
2285
+ entry->value = malloc(sizeof(*info));
2286
+ }
2287
+ memcpy(entry->value, info, sizeof(*info));
2288
+ if (info->Index == index) {
2289
+ *adapter = info;
2290
+ }
2291
+
2292
+ info = info->Next;
2293
+ }
2294
+ }
2295
+
2296
+ if (*adapter) {
2297
+ return SIGAR_OK;
2298
+ }
2299
+ else {
2300
+ return ENOENT;
2301
+ }
2302
+ }
2303
+
2304
+ static int sigar_get_adapters_addresses(sigar_t *sigar,
2305
+ ULONG family, ULONG flags,
2306
+ PIP_ADAPTER_ADDRESSES *addrs,
2307
+ ULONG *size)
2308
+ {
2309
+ ULONG rc;
2310
+
2311
+ DLLMOD_INIT(iphlpapi, FALSE);
2312
+
2313
+ if (!sigar_GetAdaptersAddresses) {
2314
+ return SIGAR_ENOTIMPL;
2315
+ }
2316
+
2317
+ rc = sigar_GetAdaptersAddresses(family,
2318
+ flags,
2319
+ NULL,
2320
+ *addrs,
2321
+ size);
2322
+
2323
+ if (rc == ERROR_BUFFER_OVERFLOW) {
2324
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2325
+ "GetAdaptersAddresses realloc to %d", size);
2326
+
2327
+ *addrs = realloc(*addrs, *size);
2328
+
2329
+ rc = sigar_GetAdaptersAddresses(family,
2330
+ flags,
2331
+ NULL,
2332
+ (PIP_ADAPTER_ADDRESSES)*addrs,
2333
+ size);
2334
+ }
2335
+
2336
+ if (rc != ERROR_SUCCESS) {
2337
+ return rc;
2338
+ }
2339
+ else {
2340
+ return SIGAR_OK;
2341
+ }
2342
+ }
2343
+
2344
+ #define sigar_GetIpAddrTable \
2345
+ sigar->iphlpapi.get_ipaddr_table.func
2346
+
2347
+ static int sigar_get_ipaddr_table(sigar_t *sigar,
2348
+ PMIB_IPADDRTABLE *ipaddr)
2349
+ {
2350
+ ULONG size = sigar->ifconf_len;
2351
+ DWORD rc;
2352
+
2353
+ DLLMOD_INIT(iphlpapi, FALSE);
2354
+
2355
+ if (!sigar_GetIpAddrTable) {
2356
+ return SIGAR_ENOTIMPL;
2357
+ }
2358
+
2359
+ *ipaddr = (PMIB_IPADDRTABLE)sigar->ifconf_buf;
2360
+ rc = sigar_GetIpAddrTable(*ipaddr, &size, FALSE);
2361
+
2362
+ if (rc == ERROR_INSUFFICIENT_BUFFER) {
2363
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2364
+ "GetIpAddrTable "
2365
+ "realloc ifconf_buf old=%d, new=%d",
2366
+ sigar->ifconf_len, size);
2367
+ sigar->ifconf_len = size;
2368
+ sigar->ifconf_buf = realloc(sigar->ifconf_buf,
2369
+ sigar->ifconf_len);
2370
+
2371
+ *ipaddr = (PMIB_IPADDRTABLE)sigar->ifconf_buf;
2372
+ rc = sigar_GetIpAddrTable(*ipaddr, &size, FALSE);
2373
+ }
2374
+
2375
+ if (rc != NO_ERROR) {
2376
+ return rc;
2377
+ }
2378
+ else {
2379
+ return SIGAR_OK;
2380
+ }
2381
+ }
2382
+
2383
+ #ifndef MIB_IPADDR_PRIMARY
2384
+ #define MIB_IPADDR_PRIMARY 0x0001
2385
+ #endif
2386
+
2387
+ static int sigar_get_netif_ipaddr(sigar_t *sigar,
2388
+ DWORD index,
2389
+ MIB_IPADDRROW **ipaddr)
2390
+ {
2391
+ sigar_cache_entry_t *entry;
2392
+ *ipaddr = NULL;
2393
+
2394
+ if (sigar->netif_addr_rows) {
2395
+ entry = sigar_cache_get(sigar->netif_addr_rows, index);
2396
+ if (entry->value) {
2397
+ *ipaddr = (MIB_IPADDRROW *)entry->value;
2398
+ }
2399
+ }
2400
+ else {
2401
+ int status, i;
2402
+ MIB_IPADDRTABLE *mib;
2403
+
2404
+ sigar->netif_addr_rows =
2405
+ sigar_netif_cache_new(sigar);
2406
+
2407
+ status = sigar_get_ipaddr_table(sigar, &mib);
2408
+ if (status != SIGAR_OK) {
2409
+ return status;
2410
+ }
2411
+
2412
+ for (i=0; i<mib->dwNumEntries; i++) {
2413
+ MIB_IPADDRROW *row = &mib->table[i];
2414
+ short type;
2415
+
2416
+ #if HAVE_MIB_IPADDRROW_WTYPE
2417
+ type = row->wType;
2418
+ #else
2419
+ type = row->unused2;
2420
+ #endif
2421
+ if (!(type & MIB_IPADDR_PRIMARY)) {
2422
+ continue;
2423
+ }
2424
+
2425
+ entry = sigar_cache_get(sigar->netif_addr_rows,
2426
+ row->dwIndex);
2427
+ if (!entry->value) {
2428
+ entry->value = malloc(sizeof(*row));
2429
+ }
2430
+ memcpy(entry->value, row, sizeof(*row));
2431
+
2432
+ if (row->dwIndex == index) {
2433
+ *ipaddr = row;
2434
+ }
2435
+ }
2436
+ }
2437
+
2438
+ if (*ipaddr) {
2439
+ return SIGAR_OK;
2440
+ }
2441
+ else {
2442
+ return ENOENT;
2443
+ }
2444
+ }
2445
+
2446
+ SIGAR_DECLARE(int) sigar_net_info_get(sigar_t *sigar,
2447
+ sigar_net_info_t *netinfo)
2448
+ {
2449
+ PIP_ADAPTER_INFO adapter;
2450
+ FIXED_INFO *info;
2451
+ ULONG len = 0;
2452
+ IP_ADDR_STRING *ip;
2453
+ DWORD rc;
2454
+
2455
+ DLLMOD_INIT(iphlpapi, FALSE);
2456
+
2457
+ if (!sigar_GetNetworkParams) {
2458
+ return SIGAR_ENOTIMPL;
2459
+ }
2460
+
2461
+ SIGAR_ZERO(netinfo);
2462
+
2463
+ rc = sigar_GetNetworkParams(NULL, &len);
2464
+ if (rc != ERROR_BUFFER_OVERFLOW) {
2465
+ return rc;
2466
+ }
2467
+
2468
+ info = malloc(len);
2469
+ rc = sigar_GetNetworkParams(info, &len);
2470
+ if (rc != NO_ERROR) {
2471
+ free(info);
2472
+ return rc;
2473
+ }
2474
+
2475
+ SIGAR_SSTRCPY(netinfo->host_name, info->HostName);
2476
+ SIGAR_SSTRCPY(netinfo->domain_name, info->DomainName);
2477
+ SIGAR_SSTRCPY(netinfo->primary_dns,
2478
+ info->DnsServerList.IpAddress.String);
2479
+
2480
+ if ((ip = info->DnsServerList.Next)) {
2481
+ SIGAR_SSTRCPY(netinfo->secondary_dns,
2482
+ ip->IpAddress.String);
2483
+ }
2484
+
2485
+ free(info);
2486
+
2487
+ if (sigar_get_adapters_info(sigar, &adapter) != SIGAR_OK) {
2488
+ return SIGAR_OK;
2489
+ }
2490
+
2491
+ while (adapter) {
2492
+ /* should only be 1 */
2493
+ if (adapter->GatewayList.IpAddress.String[0]) {
2494
+ SIGAR_SSTRCPY(netinfo->default_gateway,
2495
+ adapter->GatewayList.IpAddress.String);
2496
+ }
2497
+ #if 0
2498
+ if (apapters->DhcpEnabled) {
2499
+ SIGAR_SSTRCPY(netinfo->dhcp_server,
2500
+ apdaters->DhcpServer.IpAddress.String);
2501
+ }
2502
+ #endif
2503
+ adapter = adapter->Next;
2504
+ }
2505
+
2506
+ return SIGAR_OK;
2507
+ }
2508
+
2509
+ #define sigar_GetIpForwardTable \
2510
+ sigar->iphlpapi.get_ipforward_table.func
2511
+
2512
+ SIGAR_DECLARE(int) sigar_net_route_list_get(sigar_t *sigar,
2513
+ sigar_net_route_list_t *routelist)
2514
+ {
2515
+ PMIB_IPFORWARDTABLE buffer = NULL;
2516
+ ULONG bufsize = 0;
2517
+ DWORD rc, i;
2518
+ MIB_IPFORWARDTABLE *ipt;
2519
+ sigar_net_route_t *route;
2520
+
2521
+ DLLMOD_INIT(iphlpapi, FALSE);
2522
+ if (!sigar_GetIpForwardTable) {
2523
+ return SIGAR_ENOTIMPL;
2524
+ }
2525
+
2526
+ rc = sigar_GetIpForwardTable(buffer, &bufsize, FALSE);
2527
+ if (rc != ERROR_INSUFFICIENT_BUFFER) {
2528
+ return GetLastError();
2529
+ }
2530
+
2531
+ buffer = malloc(bufsize);
2532
+ rc = sigar_GetIpForwardTable(buffer, &bufsize, FALSE);
2533
+ if (rc != NO_ERROR) {
2534
+ free(buffer);
2535
+ return GetLastError();
2536
+ }
2537
+
2538
+ if (!sigar->netif_names) {
2539
+ sigar_net_interface_list_get(sigar, NULL);
2540
+ }
2541
+
2542
+ sigar_net_route_list_create(routelist);
2543
+ routelist->size = routelist->number = 0;
2544
+
2545
+ ipt = buffer;
2546
+
2547
+ for (i=0; i<ipt->dwNumEntries; i++) {
2548
+ MIB_IPFORWARDROW *ipr = ipt->table + i;
2549
+ sigar_cache_entry_t *entry;
2550
+
2551
+ SIGAR_NET_ROUTE_LIST_GROW(routelist);
2552
+
2553
+ route = &routelist->data[routelist->number++];
2554
+ SIGAR_ZERO(route); /* XXX: other fields */
2555
+
2556
+ sigar_net_address_set(route->destination,
2557
+ ipr->dwForwardDest);
2558
+
2559
+ sigar_net_address_set(route->mask,
2560
+ ipr->dwForwardMask);
2561
+
2562
+ sigar_net_address_set(route->gateway,
2563
+ ipr->dwForwardNextHop);
2564
+
2565
+ route->metric = ipr->dwForwardMetric1;
2566
+
2567
+ route->flags = SIGAR_RTF_UP;
2568
+ if ((ipr->dwForwardDest == 0) &&
2569
+ (ipr->dwForwardMask == 0))
2570
+ {
2571
+ route->flags |= SIGAR_RTF_GATEWAY;
2572
+ }
2573
+
2574
+ entry = sigar_cache_get(sigar->netif_names, ipr->dwForwardIfIndex);
2575
+ if (entry->value) {
2576
+ SIGAR_SSTRCPY(route->ifname, (char *)entry->value);
2577
+ }
2578
+ }
2579
+
2580
+ free(buffer);
2581
+
2582
+ return SIGAR_OK;
2583
+ }
2584
+
2585
+ #define sigar_GetIfTable \
2586
+ sigar->iphlpapi.get_if_table.func
2587
+
2588
+ #define sigar_GetIfEntry \
2589
+ sigar->iphlpapi.get_if_entry.func
2590
+
2591
+ static int sigar_get_if_table(sigar_t *sigar, PMIB_IFTABLE *iftable)
2592
+ {
2593
+ ULONG size = sigar->ifconf_len;
2594
+ DWORD rc;
2595
+
2596
+ DLLMOD_INIT(iphlpapi, FALSE);
2597
+
2598
+ if (!sigar_GetIfTable) {
2599
+ return SIGAR_ENOTIMPL;
2600
+ }
2601
+
2602
+ *iftable = (PMIB_IFTABLE)sigar->ifconf_buf;
2603
+ rc = sigar_GetIfTable(*iftable, &size, FALSE);
2604
+
2605
+ if (rc == ERROR_INSUFFICIENT_BUFFER) {
2606
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2607
+ "GetIfTable "
2608
+ "realloc ifconf_buf old=%d, new=%d",
2609
+ sigar->ifconf_len, size);
2610
+ sigar->ifconf_len = size;
2611
+ sigar->ifconf_buf = realloc(sigar->ifconf_buf,
2612
+ sigar->ifconf_len);
2613
+
2614
+ *iftable = (PMIB_IFTABLE)sigar->ifconf_buf;
2615
+ rc = sigar_GetIfTable(*iftable, &size, FALSE);
2616
+ }
2617
+
2618
+ if (rc != NO_ERROR) {
2619
+ return rc;
2620
+ }
2621
+ else {
2622
+ return SIGAR_OK;
2623
+ }
2624
+ }
2625
+
2626
+ static int get_mib_ifrow(sigar_t *sigar,
2627
+ const char *name,
2628
+ MIB_IFROW **ifrp)
2629
+ {
2630
+ int status, key, cached=0;
2631
+ sigar_cache_entry_t *entry;
2632
+
2633
+ if (sigar->netif_mib_rows) {
2634
+ cached = 1;
2635
+ }
2636
+ else {
2637
+ status = sigar_net_interface_list_get(sigar, NULL);
2638
+ if (status != SIGAR_OK) {
2639
+ return status;
2640
+ }
2641
+ }
2642
+ key = netif_hash(name);
2643
+ entry = sigar_cache_get(sigar->netif_mib_rows, key);
2644
+ if (!entry->value) {
2645
+ return ENOENT;
2646
+ }
2647
+
2648
+ *ifrp = (MIB_IFROW *)entry->value;
2649
+ if (cached) {
2650
+ /* refresh */
2651
+ if ((status = sigar_GetIfEntry(*ifrp)) != NO_ERROR) {
2652
+ return status;
2653
+ }
2654
+ }
2655
+
2656
+ return SIGAR_OK;
2657
+ }
2658
+
2659
+ static int netif_hash(char *s)
2660
+ {
2661
+ int hash = 0;
2662
+ while (*s) {
2663
+ hash = 31*hash + *s++;
2664
+ }
2665
+ return hash;
2666
+ }
2667
+
2668
+ /* Vista and later, wireless network cards are reported as IF_TYPE_IEEE80211 */
2669
+ #ifndef IF_TYPE_IEEE80211
2670
+ #define IF_TYPE_IEEE80211 71
2671
+ #endif
2672
+
2673
+ static int
2674
+ sigar_net_interface_name_get(sigar_t *sigar, MIB_IFROW *ifr, PIP_ADAPTER_ADDRESSES address_list, char *name)
2675
+ {
2676
+ PIP_ADAPTER_ADDRESSES iter;
2677
+ int lpc = 0;
2678
+
2679
+ if (address_list == NULL) {
2680
+ return SIGAR_ENOTIMPL;
2681
+ }
2682
+
2683
+ for (iter = address_list; iter != NULL; iter = iter->Next) {
2684
+ for (lpc = 0; lpc < iter->PhysicalAddressLength; lpc++) {
2685
+ if (iter->PhysicalAddress[lpc] != ifr->bPhysAddr[lpc]) {
2686
+ break;
2687
+ }
2688
+ }
2689
+
2690
+ if (lpc == iter->PhysicalAddressLength) {
2691
+ wcstombs(name, iter->FriendlyName, MAX_INTERFACE_NAME_LEN);
2692
+ name[MAX_INTERFACE_NAME_LEN-1] = '\0';
2693
+ return SIGAR_OK;
2694
+ }
2695
+ }
2696
+
2697
+ return SIGAR_ENOENT;
2698
+ }
2699
+
2700
+ SIGAR_DECLARE(int)
2701
+ sigar_net_interface_list_get(sigar_t *sigar,
2702
+ sigar_net_interface_list_t *iflist)
2703
+ {
2704
+ MIB_IFTABLE *ift;
2705
+ int i, status;
2706
+ int lo=0, eth=0, la=0;
2707
+ PIP_ADAPTER_ADDRESSES address_list = NULL;
2708
+ ULONG size = 0;
2709
+
2710
+ status = sigar_get_adapters_addresses(sigar, AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, &address_list, &size);
2711
+
2712
+ if (status != SIGAR_OK) {
2713
+ address_list = NULL;
2714
+ }
2715
+
2716
+ if (!sigar->netif_mib_rows) {
2717
+ sigar->netif_mib_rows =
2718
+ sigar_netif_cache_new(sigar);
2719
+ }
2720
+
2721
+ if (!sigar->netif_names) {
2722
+ sigar->netif_names =
2723
+ sigar_netif_cache_new(sigar);
2724
+ }
2725
+
2726
+ if ((status = sigar_get_if_table(sigar, &ift)) != SIGAR_OK) {
2727
+ if (address_list) {
2728
+ free(address_list);
2729
+ }
2730
+ return status;
2731
+ }
2732
+
2733
+ if (iflist) {
2734
+ iflist->number = 0;
2735
+ iflist->size = ift->dwNumEntries;
2736
+ iflist->data =
2737
+ malloc(sizeof(*(iflist->data)) * iflist->size);
2738
+ }
2739
+
2740
+ for (i=0; i<ift->dwNumEntries; i++) {
2741
+ char name[MAX_INTERFACE_NAME_LEN];
2742
+ int key;
2743
+ MIB_IFROW *ifr = ift->table + i;
2744
+ sigar_cache_entry_t *entry;
2745
+
2746
+ status = SIGAR_ENOENT;
2747
+
2748
+ if (strEQ(ifr->bDescr, MS_LOOPBACK_ADAPTER)) {
2749
+ /* special-case */
2750
+ sprintf(name, NETIF_LA "%d", la++);
2751
+ }
2752
+ else if (ifr->dwType == MIB_IF_TYPE_LOOPBACK) {
2753
+ if (!sigar->netif_name_short) {
2754
+ status = sigar_net_interface_name_get(sigar, ifr, address_list, name);
2755
+ }
2756
+ if (status != SIGAR_OK) {
2757
+ sprintf(name, "lo%d", lo++);
2758
+ }
2759
+ }
2760
+ else if ((ifr->dwType == MIB_IF_TYPE_ETHERNET) ||
2761
+ (ifr->dwType == IF_TYPE_IEEE80211))
2762
+ {
2763
+ if (!sigar->netif_name_short &&
2764
+ (strstr(ifr->bDescr, "Scheduler") == NULL) &&
2765
+ (strstr(ifr->bDescr, "Filter") == NULL))
2766
+ {
2767
+ status = sigar_net_interface_name_get(sigar, ifr, address_list, name);
2768
+ }
2769
+
2770
+ if (status != SIGAR_OK) {
2771
+ if (sigar->netif_name_short) {
2772
+ sprintf(name, "eth%d", eth++);
2773
+ }
2774
+ else {
2775
+ snprintf(name, ifr->dwDescrLen, "%s", ifr->bDescr);
2776
+ }
2777
+ }
2778
+ }
2779
+ else {
2780
+ continue; /*XXX*/
2781
+ }
2782
+
2783
+ if (iflist) {
2784
+ iflist->data[iflist->number++] = sigar_strdup(name);
2785
+ }
2786
+
2787
+ key = netif_hash(name);
2788
+ entry = sigar_cache_get(sigar->netif_mib_rows, key);
2789
+ if (!entry->value) {
2790
+ entry->value = malloc(sizeof(*ifr));
2791
+ }
2792
+ memcpy(entry->value, ifr, sizeof(*ifr));
2793
+
2794
+ /* save dwIndex -> name mapping for use by route_list */
2795
+ entry = sigar_cache_get(sigar->netif_names, ifr->dwIndex);
2796
+ if (!entry->value) {
2797
+ entry->value = sigar_strdup(name);
2798
+ }
2799
+ }
2800
+
2801
+ if (address_list != NULL) {
2802
+ free(address_list);
2803
+ }
2804
+
2805
+ return SIGAR_OK;
2806
+ }
2807
+
2808
+ static int sigar_net_interface_ipv6_config_find(sigar_t *sigar, int index,
2809
+ sigar_net_interface_config_t *ifconfig)
2810
+ {
2811
+ #ifdef SIGAR_USING_MSC6
2812
+ return SIGAR_ENOTIMPL;
2813
+ #else
2814
+ int status;
2815
+ PIP_ADAPTER_ADDRESSES aa = (PIP_ADAPTER_ADDRESSES)sigar->ifconf_buf, addrs;
2816
+ ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
2817
+ status = sigar_get_adapters_addresses(sigar, AF_UNSPEC, flags, &aa, &sigar->ifconf_len);
2818
+
2819
+ if (status != SIGAR_OK) {
2820
+ return status;
2821
+ }
2822
+
2823
+ for (addrs = aa; addrs; addrs = addrs->Next) {
2824
+ PIP_ADAPTER_UNICAST_ADDRESS addr;
2825
+ if (addrs->IfIndex != index) {
2826
+ continue;
2827
+ }
2828
+ for (addr = addrs->FirstUnicastAddress; addr; addr = addr->Next) {
2829
+ struct sockaddr *sa = addr->Address.lpSockaddr;
2830
+
2831
+ if (sa->sa_family == AF_INET6) {
2832
+ struct in6_addr *inet6 = SIGAR_SIN6_ADDR(sa);
2833
+
2834
+ sigar_net_address6_set(ifconfig->address6, inet6);
2835
+ sigar_net_interface_scope6_set(ifconfig, inet6);
2836
+ if (addrs->FirstPrefix) {
2837
+ ifconfig->prefix6_length = addrs->FirstPrefix->PrefixLength;
2838
+ }
2839
+ return SIGAR_OK;
2840
+ }
2841
+ }
2842
+ }
2843
+ return SIGAR_ENOENT;
2844
+ #endif
2845
+ }
2846
+
2847
+ SIGAR_DECLARE(int)
2848
+ sigar_net_interface_config_get(sigar_t *sigar,
2849
+ const char *name,
2850
+ sigar_net_interface_config_t *ifconfig)
2851
+ {
2852
+ MIB_IFROW *ifr;
2853
+ MIB_IPADDRROW *ipaddr;
2854
+ int status;
2855
+
2856
+ if (!name) {
2857
+ return sigar_net_interface_config_primary_get(sigar, ifconfig);
2858
+ }
2859
+
2860
+ status = get_mib_ifrow(sigar, name, &ifr);
2861
+ if (status != SIGAR_OK) {
2862
+ return status;
2863
+ }
2864
+
2865
+ SIGAR_ZERO(ifconfig);
2866
+
2867
+ SIGAR_SSTRCPY(ifconfig->name, name);
2868
+
2869
+ ifconfig->mtu = ifr->dwMtu;
2870
+
2871
+ sigar_net_address_mac_set(ifconfig->hwaddr,
2872
+ ifr->bPhysAddr,
2873
+ SIGAR_IFHWADDRLEN);
2874
+
2875
+ SIGAR_SSTRCPY(ifconfig->description,
2876
+ ifr->bDescr);
2877
+
2878
+ if (ifr->dwOperStatus & MIB_IF_OPER_STATUS_OPERATIONAL) {
2879
+ ifconfig->flags |= SIGAR_IFF_UP|SIGAR_IFF_RUNNING;
2880
+ }
2881
+
2882
+ status = sigar_get_netif_ipaddr(sigar,
2883
+ ifr->dwIndex,
2884
+ &ipaddr);
2885
+
2886
+ if (status == SIGAR_OK) {
2887
+ sigar_net_address_set(ifconfig->address,
2888
+ ipaddr->dwAddr);
2889
+
2890
+ sigar_net_address_set(ifconfig->netmask,
2891
+ ipaddr->dwMask);
2892
+
2893
+ if (ifr->dwType != MIB_IF_TYPE_LOOPBACK) {
2894
+ if (ipaddr->dwBCastAddr) {
2895
+ long bcast =
2896
+ ipaddr->dwAddr & ipaddr->dwMask;
2897
+
2898
+ bcast |= ~ipaddr->dwMask;
2899
+ ifconfig->flags |= SIGAR_IFF_BROADCAST;
2900
+
2901
+ sigar_net_address_set(ifconfig->broadcast,
2902
+ bcast);
2903
+ }
2904
+ }
2905
+ }
2906
+
2907
+ /* hack for MS_LOOPBACK_ADAPTER */
2908
+ if (strnEQ(name, NETIF_LA, sizeof(NETIF_LA)-1)) {
2909
+ ifr->dwType = MIB_IF_TYPE_LOOPBACK;
2910
+ }
2911
+
2912
+ if (ifr->dwType == MIB_IF_TYPE_LOOPBACK) {
2913
+ ifconfig->flags |= SIGAR_IFF_LOOPBACK;
2914
+
2915
+ SIGAR_SSTRCPY(ifconfig->type,
2916
+ SIGAR_NIC_LOOPBACK);
2917
+ }
2918
+ else {
2919
+ if (ipaddr) {
2920
+ ifconfig->flags |= SIGAR_IFF_MULTICAST;
2921
+ }
2922
+
2923
+ SIGAR_SSTRCPY(ifconfig->type,
2924
+ SIGAR_NIC_ETHERNET);
2925
+ }
2926
+
2927
+ sigar_net_interface_ipv6_config_init(ifconfig);
2928
+ sigar_net_interface_ipv6_config_find(sigar, ifr->dwIndex, ifconfig);
2929
+
2930
+ return SIGAR_OK;
2931
+ }
2932
+
2933
+ SIGAR_DECLARE(int)
2934
+ sigar_net_interface_stat_get(sigar_t *sigar, const char *name,
2935
+ sigar_net_interface_stat_t *ifstat)
2936
+ {
2937
+ MIB_IFROW *ifr;
2938
+ int status;
2939
+
2940
+ status = get_mib_ifrow(sigar, name, &ifr);
2941
+ if (status != SIGAR_OK) {
2942
+ return status;
2943
+ }
2944
+
2945
+ ifstat->rx_bytes = ifr->dwInOctets;
2946
+ ifstat->rx_packets = ifr->dwInUcastPkts + ifr->dwInNUcastPkts;
2947
+ ifstat->rx_errors = ifr->dwInErrors;
2948
+ ifstat->rx_dropped = ifr->dwInDiscards;
2949
+ ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL;
2950
+ ifstat->rx_frame = SIGAR_FIELD_NOTIMPL;
2951
+
2952
+ ifstat->tx_bytes = ifr->dwOutOctets;
2953
+ ifstat->tx_packets = ifr->dwOutUcastPkts + ifr->dwOutNUcastPkts;
2954
+ ifstat->tx_errors = ifr->dwOutErrors;
2955
+ ifstat->tx_dropped = ifr->dwOutDiscards;
2956
+ ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL;
2957
+ ifstat->tx_collisions = SIGAR_FIELD_NOTIMPL;
2958
+ ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL;
2959
+
2960
+ ifstat->speed = ifr->dwSpeed;
2961
+
2962
+ return SIGAR_OK;
2963
+ }
2964
+
2965
+ #define IS_TCP_SERVER(state, flags) \
2966
+ ((flags & SIGAR_NETCONN_SERVER) && (state == MIB_TCP_STATE_LISTEN))
2967
+
2968
+ #define IS_TCP_CLIENT(state, flags) \
2969
+ ((flags & SIGAR_NETCONN_CLIENT) && (state != MIB_TCP_STATE_LISTEN))
2970
+
2971
+ #define sigar_GetTcpTable \
2972
+ sigar->iphlpapi.get_tcp_table.func
2973
+
2974
+ static int net_conn_get_tcp(sigar_net_connection_walker_t *walker)
2975
+ {
2976
+ sigar_t *sigar = walker->sigar;
2977
+ int flags = walker->flags;
2978
+ int status, i;
2979
+ DWORD rc, size=0;
2980
+ PMIB_TCPTABLE tcp;
2981
+
2982
+ DLLMOD_INIT(iphlpapi, FALSE);
2983
+
2984
+ if (!sigar_GetTcpTable) {
2985
+ return SIGAR_ENOTIMPL;
2986
+ }
2987
+
2988
+ rc = sigar_GetTcpTable(NULL, &size, FALSE);
2989
+ if (rc != ERROR_INSUFFICIENT_BUFFER) {
2990
+ return GetLastError();
2991
+ }
2992
+ tcp = malloc(size);
2993
+ rc = sigar_GetTcpTable(tcp, &size, FALSE);
2994
+ if (rc) {
2995
+ free(tcp);
2996
+ return GetLastError();
2997
+ }
2998
+
2999
+ /* go in reverse to get LISTEN states first */
3000
+ for (i = (tcp->dwNumEntries-1); i >= 0; i--) {
3001
+ sigar_net_connection_t conn;
3002
+ DWORD state = tcp->table[i].dwState;
3003
+
3004
+ if (!(IS_TCP_SERVER(state, flags) ||
3005
+ IS_TCP_CLIENT(state, flags)))
3006
+ {
3007
+ continue;
3008
+ }
3009
+
3010
+ conn.local_port = htons((WORD)tcp->table[i].dwLocalPort);
3011
+ conn.remote_port = htons((WORD)tcp->table[i].dwRemotePort);
3012
+
3013
+ conn.type = SIGAR_NETCONN_TCP;
3014
+
3015
+ sigar_net_address_set(conn.local_address,
3016
+ tcp->table[i].dwLocalAddr);
3017
+
3018
+ sigar_net_address_set(conn.remote_address,
3019
+ tcp->table[i].dwRemoteAddr);
3020
+
3021
+ conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL;
3022
+
3023
+ switch (state) {
3024
+ case MIB_TCP_STATE_CLOSED:
3025
+ conn.state = SIGAR_TCP_CLOSE;
3026
+ break;
3027
+ case MIB_TCP_STATE_LISTEN:
3028
+ conn.state = SIGAR_TCP_LISTEN;
3029
+ break;
3030
+ case MIB_TCP_STATE_SYN_SENT:
3031
+ conn.state = SIGAR_TCP_SYN_SENT;
3032
+ break;
3033
+ case MIB_TCP_STATE_SYN_RCVD:
3034
+ conn.state = SIGAR_TCP_SYN_RECV;
3035
+ break;
3036
+ case MIB_TCP_STATE_ESTAB:
3037
+ conn.state = SIGAR_TCP_ESTABLISHED;
3038
+ break;
3039
+ case MIB_TCP_STATE_FIN_WAIT1:
3040
+ conn.state = SIGAR_TCP_FIN_WAIT1;
3041
+ break;
3042
+ case MIB_TCP_STATE_FIN_WAIT2:
3043
+ conn.state = SIGAR_TCP_FIN_WAIT2;
3044
+ break;
3045
+ case MIB_TCP_STATE_CLOSE_WAIT:
3046
+ conn.state = SIGAR_TCP_CLOSE_WAIT;
3047
+ break;
3048
+ case MIB_TCP_STATE_CLOSING:
3049
+ conn.state = SIGAR_TCP_CLOSING;
3050
+ break;
3051
+ case MIB_TCP_STATE_LAST_ACK:
3052
+ conn.state = SIGAR_TCP_LAST_ACK;
3053
+ break;
3054
+ case MIB_TCP_STATE_TIME_WAIT:
3055
+ conn.state = SIGAR_TCP_TIME_WAIT;
3056
+ break;
3057
+ case MIB_TCP_STATE_DELETE_TCB:
3058
+ default:
3059
+ conn.state = SIGAR_TCP_UNKNOWN;
3060
+ break;
3061
+ }
3062
+
3063
+ if (walker->add_connection(walker, &conn) != SIGAR_OK) {
3064
+ break;
3065
+ }
3066
+ }
3067
+
3068
+ free(tcp);
3069
+ return SIGAR_OK;
3070
+ }
3071
+
3072
+ #define IS_UDP_SERVER(conn, flags) \
3073
+ ((flags & SIGAR_NETCONN_SERVER) && !conn.remote_port)
3074
+
3075
+ #define IS_UDP_CLIENT(state, flags) \
3076
+ ((flags & SIGAR_NETCONN_CLIENT) && conn.remote_port)
3077
+
3078
+ #define sigar_GetUdpTable \
3079
+ sigar->iphlpapi.get_udp_table.func
3080
+
3081
+ static int net_conn_get_udp(sigar_net_connection_walker_t *walker)
3082
+ {
3083
+ sigar_t *sigar = walker->sigar;
3084
+ int flags = walker->flags;
3085
+ int status;
3086
+ DWORD rc, size=0, i;
3087
+ PMIB_UDPTABLE udp;
3088
+
3089
+ DLLMOD_INIT(iphlpapi, FALSE);
3090
+
3091
+ if (!sigar_GetUdpTable) {
3092
+ return SIGAR_ENOTIMPL;
3093
+ }
3094
+
3095
+ rc = sigar_GetUdpTable(NULL, &size, FALSE);
3096
+ if (rc != ERROR_INSUFFICIENT_BUFFER) {
3097
+ return GetLastError();
3098
+ }
3099
+ udp = malloc(size);
3100
+ rc = sigar_GetUdpTable(udp, &size, FALSE);
3101
+ if (rc) {
3102
+ free(udp);
3103
+ return GetLastError();
3104
+ }
3105
+
3106
+ for (i = 0; i < udp->dwNumEntries; i++) {
3107
+ sigar_net_connection_t conn;
3108
+
3109
+ if (!(IS_UDP_SERVER(conn, flags) ||
3110
+ IS_UDP_CLIENT(conn, flags)))
3111
+ {
3112
+ continue;
3113
+ }
3114
+
3115
+ conn.local_port = htons((WORD)udp->table[i].dwLocalPort);
3116
+ conn.remote_port = 0;
3117
+
3118
+ conn.type = SIGAR_NETCONN_UDP;
3119
+
3120
+ sigar_net_address_set(conn.local_address,
3121
+ udp->table[i].dwLocalAddr);
3122
+
3123
+ sigar_net_address_set(conn.remote_address, 0);
3124
+
3125
+ conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL;
3126
+
3127
+ if (walker->add_connection(walker, &conn) != SIGAR_OK) {
3128
+ break;
3129
+ }
3130
+ }
3131
+
3132
+ free(udp);
3133
+ return SIGAR_OK;
3134
+ }
3135
+
3136
+ SIGAR_DECLARE(int)
3137
+ sigar_net_connection_walk(sigar_net_connection_walker_t *walker)
3138
+ {
3139
+ int status;
3140
+
3141
+ if (walker->flags & SIGAR_NETCONN_TCP) {
3142
+ status = net_conn_get_tcp(walker);
3143
+
3144
+ if (status != SIGAR_OK) {
3145
+ return status;
3146
+ }
3147
+ }
3148
+
3149
+ if (walker->flags & SIGAR_NETCONN_UDP) {
3150
+ status = net_conn_get_udp(walker);
3151
+
3152
+ if (status != SIGAR_OK) {
3153
+ return status;
3154
+ }
3155
+ }
3156
+
3157
+ return SIGAR_OK;
3158
+ }
3159
+
3160
+ #define sigar_GetTcpStatistics \
3161
+ sigar->iphlpapi.get_tcp_stats.func
3162
+
3163
+ SIGAR_DECLARE(int)
3164
+ sigar_tcp_get(sigar_t *sigar,
3165
+ sigar_tcp_t *tcp)
3166
+ {
3167
+ MIB_TCPSTATS mib;
3168
+ int status;
3169
+
3170
+ DLLMOD_INIT(iphlpapi, FALSE);
3171
+
3172
+ if (!sigar_GetTcpStatistics) {
3173
+ return SIGAR_ENOTIMPL;
3174
+ }
3175
+
3176
+ status = sigar_GetTcpStatistics(&mib);
3177
+
3178
+ if (status != NO_ERROR) {
3179
+ return status;
3180
+ }
3181
+
3182
+ tcp->active_opens = mib.dwActiveOpens;
3183
+ tcp->passive_opens = mib.dwPassiveOpens;
3184
+ tcp->attempt_fails = mib.dwAttemptFails;
3185
+ tcp->estab_resets = mib.dwEstabResets;
3186
+ tcp->curr_estab = mib.dwCurrEstab;
3187
+ tcp->in_segs = mib.dwInSegs;
3188
+ tcp->out_segs = mib.dwOutSegs;
3189
+ tcp->retrans_segs = mib.dwRetransSegs;
3190
+ tcp->in_errs = mib.dwInErrs;
3191
+ tcp->out_rsts = mib.dwOutRsts;
3192
+
3193
+ return SIGAR_OK;
3194
+ }
3195
+
3196
+ SIGAR_DECLARE(int)
3197
+ sigar_nfs_client_v2_get(sigar_t *sigar,
3198
+ sigar_nfs_client_v2_t *nfs)
3199
+ {
3200
+ return SIGAR_ENOTIMPL;
3201
+ }
3202
+
3203
+ SIGAR_DECLARE(int)
3204
+ sigar_nfs_server_v2_get(sigar_t *sigar,
3205
+ sigar_nfs_server_v2_t *nfs)
3206
+ {
3207
+ return SIGAR_ENOTIMPL;
3208
+ }
3209
+
3210
+ SIGAR_DECLARE(int)
3211
+ sigar_nfs_client_v3_get(sigar_t *sigar,
3212
+ sigar_nfs_client_v3_t *nfs)
3213
+ {
3214
+ return SIGAR_ENOTIMPL;
3215
+ }
3216
+
3217
+ SIGAR_DECLARE(int)
3218
+ sigar_nfs_server_v3_get(sigar_t *sigar,
3219
+ sigar_nfs_server_v3_t *nfs)
3220
+ {
3221
+ return SIGAR_ENOTIMPL;
3222
+ }
3223
+
3224
+ #define sigar_GetTcpExTable \
3225
+ sigar->iphlpapi.get_tcpx_table.func
3226
+
3227
+ #define sigar_GetUdpExTable \
3228
+ sigar->iphlpapi.get_udpx_table.func
3229
+
3230
+ SIGAR_DECLARE(int) sigar_proc_port_get(sigar_t *sigar,
3231
+ int protocol,
3232
+ unsigned long port,
3233
+ sigar_pid_t *pid)
3234
+ {
3235
+ DWORD rc, i;
3236
+
3237
+ DLLMOD_INIT(iphlpapi, FALSE);
3238
+
3239
+ if (protocol == SIGAR_NETCONN_TCP) {
3240
+ PMIB_TCPEXTABLE tcp;
3241
+
3242
+ if (!sigar_GetTcpExTable) {
3243
+ return SIGAR_ENOTIMPL;
3244
+ }
3245
+
3246
+ rc = sigar_GetTcpExTable(&tcp, FALSE, GetProcessHeap(),
3247
+ 2, 2);
3248
+
3249
+ if (rc) {
3250
+ return GetLastError();
3251
+ }
3252
+
3253
+ for (i=0; i<tcp->dwNumEntries; i++) {
3254
+ if (tcp->table[i].dwState != MIB_TCP_STATE_LISTEN) {
3255
+ continue;
3256
+ }
3257
+
3258
+ if (htons((WORD)tcp->table[i].dwLocalPort) != port) {
3259
+ continue;
3260
+ }
3261
+
3262
+ *pid = tcp->table[i].dwProcessId;
3263
+
3264
+ return SIGAR_OK;
3265
+ }
3266
+ }
3267
+ else if (protocol == SIGAR_NETCONN_UDP) {
3268
+ PMIB_UDPEXTABLE udp;
3269
+
3270
+ if (!sigar_GetUdpExTable) {
3271
+ return SIGAR_ENOTIMPL;
3272
+ }
3273
+
3274
+ rc = sigar_GetUdpExTable(&udp, FALSE, GetProcessHeap(),
3275
+ 2, 2);
3276
+
3277
+ if (rc) {
3278
+ return GetLastError();
3279
+ }
3280
+
3281
+ for (i=0; i<udp->dwNumEntries; i++) {
3282
+ if (htons((WORD)udp->table[i].dwLocalPort) != port) {
3283
+ continue;
3284
+ }
3285
+
3286
+ *pid = udp->table[i].dwProcessId;
3287
+
3288
+ return SIGAR_OK;
3289
+ }
3290
+ }
3291
+ else {
3292
+ return SIGAR_ENOTIMPL;
3293
+ }
3294
+
3295
+ return ENOENT;
3296
+ }
3297
+
3298
+ #define sigar_GetIpNetTable \
3299
+ sigar->iphlpapi.get_ipnet_table.func
3300
+
3301
+ SIGAR_DECLARE(int) sigar_arp_list_get(sigar_t *sigar,
3302
+ sigar_arp_list_t *arplist)
3303
+ {
3304
+ int status;
3305
+ DWORD rc, size=0, i;
3306
+ PMIB_IPNETTABLE ipnet;
3307
+
3308
+ DLLMOD_INIT(iphlpapi, FALSE);
3309
+
3310
+ if (!sigar_GetIpNetTable) {
3311
+ return SIGAR_ENOTIMPL;
3312
+ }
3313
+
3314
+ rc = sigar_GetIpNetTable(NULL, &size, FALSE);
3315
+ if (rc != ERROR_INSUFFICIENT_BUFFER) {
3316
+ return GetLastError();
3317
+ }
3318
+ ipnet = malloc(size);
3319
+ rc = sigar_GetIpNetTable(ipnet, &size, FALSE);
3320
+ if (rc) {
3321
+ free(ipnet);
3322
+ return GetLastError();
3323
+ }
3324
+
3325
+ sigar_arp_list_create(arplist);
3326
+
3327
+ if (!sigar->netif_names) {
3328
+ /* dwIndex -> name map */
3329
+ sigar_net_interface_list_get(sigar, NULL);
3330
+ }
3331
+
3332
+ for (i = 0; i < ipnet->dwNumEntries; i++) {
3333
+ sigar_arp_t *arp;
3334
+ PMIB_IPNETROW entry;
3335
+ sigar_cache_entry_t *ifname;
3336
+
3337
+ entry = &ipnet->table[i];
3338
+ SIGAR_ARP_LIST_GROW(arplist);
3339
+ arp = &arplist->data[arplist->number++];
3340
+
3341
+ sigar_net_address_set(arp->address,
3342
+ entry->dwAddr);
3343
+
3344
+ sigar_net_address_mac_set(arp->hwaddr,
3345
+ entry->bPhysAddr,
3346
+ entry->dwPhysAddrLen);
3347
+
3348
+ ifname = sigar_cache_get(sigar->netif_names, entry->dwIndex);
3349
+ if (ifname->value) {
3350
+ SIGAR_SSTRCPY(arp->ifname, (char *)ifname->value);
3351
+ }
3352
+
3353
+ arp->flags = 0; /*XXX*/
3354
+ SIGAR_SSTRCPY(arp->type, "ether"); /*XXX*/
3355
+ }
3356
+
3357
+ free(ipnet);
3358
+
3359
+ return SIGAR_OK;
3360
+ }
3361
+
3362
+ #include <lm.h>
3363
+
3364
+ static int sigar_who_net_sessions(sigar_t *sigar,
3365
+ sigar_who_list_t *wholist)
3366
+ {
3367
+ NET_API_STATUS status;
3368
+ LPSESSION_INFO_10 buffer=NULL, ptr;
3369
+ DWORD entries=0, total_entries=0;
3370
+ DWORD resume_handle=0;
3371
+ DWORD i;
3372
+
3373
+ do {
3374
+ status = NetSessionEnum(NULL, /* server name */
3375
+ NULL, /* client name */
3376
+ NULL, /* user name */
3377
+ 10, /* level */
3378
+ (LPBYTE*)&buffer,
3379
+ MAX_PREFERRED_LENGTH,
3380
+ &entries,
3381
+ &total_entries,
3382
+ &resume_handle);
3383
+
3384
+ if ((status == NERR_Success) || (status == ERROR_MORE_DATA)) {
3385
+ if ((ptr = buffer)) {
3386
+ for (i=0; i<entries; i++) {
3387
+ sigar_who_t *who;
3388
+
3389
+ if (!ptr) {
3390
+ break;
3391
+ }
3392
+
3393
+ SIGAR_WHO_LIST_GROW(wholist);
3394
+ who = &wholist->data[wholist->number++];
3395
+
3396
+ who->time = (time(NULL) - ptr->sesi10_time);
3397
+ SIGAR_W2A((LPCWSTR)ptr->sesi10_username,
3398
+ who->user, sizeof(who->user));
3399
+ SIGAR_W2A((LPCWSTR)ptr->sesi10_cname,
3400
+ who->host, sizeof(who->host));
3401
+ SIGAR_SSTRCPY(who->device, "network share");
3402
+
3403
+ ptr++;
3404
+ }
3405
+ }
3406
+ }
3407
+ else {
3408
+ break;
3409
+ }
3410
+
3411
+ if (buffer) {
3412
+ NetApiBufferFree(buffer);
3413
+ buffer = NULL;
3414
+ }
3415
+ } while (status == ERROR_MORE_DATA);
3416
+
3417
+ if (buffer) {
3418
+ NetApiBufferFree(buffer);
3419
+ }
3420
+
3421
+ return SIGAR_OK;
3422
+ }
3423
+
3424
+ static int get_logon_info(HKEY users,
3425
+ char *username,
3426
+ sigar_who_t *who)
3427
+ {
3428
+ DWORD status, size, type;
3429
+ HKEY key;
3430
+ char key_name[MAX_PATH];
3431
+ char value[256];
3432
+ FILETIME wtime;
3433
+
3434
+ who->time = 0;
3435
+
3436
+ sprintf(key_name, "%s\\Volatile Environment", username);
3437
+ if (RegOpenKey(users, key_name, &key) != ERROR_SUCCESS) {
3438
+ return ENOENT;
3439
+ }
3440
+
3441
+ status = RegQueryInfoKey(key,
3442
+ NULL, NULL, NULL, NULL, NULL,
3443
+ NULL, NULL, NULL, NULL, NULL,
3444
+ &wtime);
3445
+
3446
+ if (status == ERROR_SUCCESS) {
3447
+ FileTimeToLocalFileTime(&wtime, &wtime);
3448
+ who->time = sigar_FileTimeToTime(&wtime) / 1000000;
3449
+ }
3450
+
3451
+ size = sizeof(value);
3452
+ status = RegQueryValueEx(key, "CLIENTNAME",
3453
+ NULL, &type, value, &size);
3454
+ if (status == ERROR_SUCCESS) {
3455
+ if ((value[0] != '\0') && !strEQ(value, "Console")) {
3456
+ SIGAR_SSTRCPY(who->host, value);
3457
+ }
3458
+ }
3459
+
3460
+ size = sizeof(value);
3461
+ status = RegQueryValueEx(key, "SESSIONNAME",
3462
+ NULL, &type, value, &size);
3463
+ if (status == ERROR_SUCCESS) {
3464
+ SIGAR_SSTRCPY(who->device, value);
3465
+ }
3466
+
3467
+ RegCloseKey(key);
3468
+
3469
+ return SIGAR_OK;
3470
+ }
3471
+
3472
+ #define sigar_ConvertStringSidToSid \
3473
+ sigar->advapi.convert_string_sid.func
3474
+
3475
+ static int sigar_who_registry(sigar_t *sigar,
3476
+ sigar_who_list_t *wholist)
3477
+ {
3478
+ HKEY users;
3479
+ DWORD index=0, status;
3480
+
3481
+ if (!sigar_ConvertStringSidToSid) {
3482
+ return ENOENT;
3483
+ }
3484
+
3485
+ status = RegOpenKey(HKEY_USERS, NULL, &users);
3486
+ if (status != ERROR_SUCCESS) {
3487
+ return status;
3488
+ }
3489
+
3490
+ while (1) {
3491
+ char subkey[MAX_PATH];
3492
+ char username[SIGAR_CRED_NAME_MAX];
3493
+ char domain[SIGAR_CRED_NAME_MAX];
3494
+ DWORD subkey_len = sizeof(subkey);
3495
+ DWORD username_len = sizeof(username);
3496
+ DWORD domain_len = sizeof(domain);
3497
+ PSID sid;
3498
+ SID_NAME_USE type;
3499
+
3500
+ status = RegEnumKeyEx(users, index, subkey, &subkey_len,
3501
+ NULL, NULL, NULL, NULL);
3502
+
3503
+ if (status != ERROR_SUCCESS) {
3504
+ break;
3505
+ }
3506
+
3507
+ index++;
3508
+
3509
+ if ((subkey[0] == '.') || strstr(subkey, "_Classes")) {
3510
+ continue;
3511
+ }
3512
+
3513
+ if (!sigar_ConvertStringSidToSid(subkey, &sid)) {
3514
+ continue;
3515
+ }
3516
+
3517
+ if (LookupAccountSid(NULL, /* server */
3518
+ sid,
3519
+ username, &username_len,
3520
+ domain, &domain_len,
3521
+ &type))
3522
+ {
3523
+ sigar_who_t *who;
3524
+
3525
+ SIGAR_WHO_LIST_GROW(wholist);
3526
+ who = &wholist->data[wholist->number++];
3527
+
3528
+ SIGAR_SSTRCPY(who->user, username);
3529
+ SIGAR_SSTRCPY(who->host, domain);
3530
+ SIGAR_SSTRCPY(who->device, "console");
3531
+
3532
+ get_logon_info(users, subkey, who);
3533
+ }
3534
+
3535
+ LocalFree(sid);
3536
+ }
3537
+
3538
+ RegCloseKey(users);
3539
+
3540
+ return SIGAR_OK;
3541
+ }
3542
+
3543
+ #define sigar_WTSEnumerateSessions \
3544
+ sigar->wtsapi.enum_sessions.func
3545
+
3546
+ #define sigar_WTSFreeMemory \
3547
+ sigar->wtsapi.free_mem.func
3548
+
3549
+ #define sigar_WTSQuerySessionInformation \
3550
+ sigar->wtsapi.query_session.func
3551
+
3552
+ #define sigar_WinStationQueryInformation \
3553
+ sigar->winsta.query_info.func
3554
+
3555
+ static int sigar_who_wts(sigar_t *sigar,
3556
+ sigar_who_list_t *wholist)
3557
+ {
3558
+ DWORD count=0, i;
3559
+ WTS_SESSION_INFO *sessions = NULL;
3560
+
3561
+ if (DLLMOD_INIT(wtsapi, TRUE) != SIGAR_OK) {
3562
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
3563
+ "Terminal Services api functions not available");
3564
+ return ENOENT;
3565
+ }
3566
+
3567
+ DLLMOD_INIT(winsta, FALSE);
3568
+
3569
+ if (!sigar_WTSEnumerateSessions(0, 0, 1, &sessions, &count)) {
3570
+ return GetLastError();
3571
+ }
3572
+
3573
+ for (i=0; i<count; i++) {
3574
+ DWORD bytes;
3575
+ LPTSTR buffer;
3576
+ DWORD sessionId = sessions[i].SessionId;
3577
+ WINSTATION_INFO station_info;
3578
+ sigar_who_t *who;
3579
+
3580
+ if (sessions[i].State != WTSActive) {
3581
+ continue;
3582
+ }
3583
+
3584
+ buffer = NULL;
3585
+ bytes = 0;
3586
+ if (sigar_WTSQuerySessionInformation(0,
3587
+ sessionId,
3588
+ WTSClientProtocolType,
3589
+ &buffer,
3590
+ &bytes))
3591
+ {
3592
+ int isConsole =
3593
+ (*buffer == WTS_PROTOCOL_TYPE_CONSOLE);
3594
+
3595
+ sigar_WTSFreeMemory(buffer);
3596
+
3597
+ if (isConsole) {
3598
+ continue;
3599
+ }
3600
+ }
3601
+
3602
+ SIGAR_WHO_LIST_GROW(wholist);
3603
+ who = &wholist->data[wholist->number++];
3604
+
3605
+ SIGAR_SSTRCPY(who->device, sessions[i].pWinStationName);
3606
+
3607
+ buffer = NULL;
3608
+ bytes = 0;
3609
+ if (sigar_WTSQuerySessionInformation(0,
3610
+ sessionId,
3611
+ WTSClientAddress,
3612
+ &buffer,
3613
+ &bytes))
3614
+ {
3615
+ PWTS_CLIENT_ADDRESS client =
3616
+ (PWTS_CLIENT_ADDRESS)buffer;
3617
+
3618
+ sprintf(who->host, "%u.%u.%u.%u",
3619
+ client->Address[2],
3620
+ client->Address[3],
3621
+ client->Address[4],
3622
+ client->Address[5]);
3623
+
3624
+ sigar_WTSFreeMemory(buffer);
3625
+ }
3626
+ else {
3627
+ SIGAR_SSTRCPY(who->host, "unknown");
3628
+ }
3629
+
3630
+ buffer = NULL;
3631
+ bytes = 0;
3632
+ if (sigar_WTSQuerySessionInformation(0,
3633
+ sessionId,
3634
+ WTSUserName,
3635
+ &buffer,
3636
+ &bytes))
3637
+ {
3638
+ SIGAR_SSTRCPY(who->user, buffer);
3639
+ sigar_WTSFreeMemory(buffer);
3640
+ }
3641
+ else {
3642
+ SIGAR_SSTRCPY(who->user, "unknown");
3643
+ }
3644
+
3645
+ buffer = NULL;
3646
+ bytes = 0;
3647
+ if (sigar_WinStationQueryInformation &&
3648
+ sigar_WinStationQueryInformation(0,
3649
+ sessionId,
3650
+ WinStationInformation,
3651
+ &station_info,
3652
+ sizeof(station_info),
3653
+ &bytes))
3654
+ {
3655
+ who->time =
3656
+ sigar_FileTimeToTime(&station_info.ConnectTime) / 1000000;
3657
+ }
3658
+ else {
3659
+ who->time = 0;
3660
+ }
3661
+ }
3662
+
3663
+ sigar_WTSFreeMemory(sessions);
3664
+
3665
+ return SIGAR_OK;
3666
+ }
3667
+
3668
+ int sigar_who_list_get_win32(sigar_t *sigar,
3669
+ sigar_who_list_t *wholist)
3670
+ {
3671
+ sigar_who_net_sessions(sigar, wholist);
3672
+
3673
+ sigar_who_registry(sigar, wholist);
3674
+
3675
+ sigar_who_wts(sigar, wholist);
3676
+
3677
+ return SIGAR_OK;
3678
+ }
3679
+
3680
+ /* see: http://msdn2.microsoft.com/en-us/library/ms724833.aspx */
3681
+ #ifndef VER_NT_WORKSTATION
3682
+ #define VER_NT_WORKSTATION 0x0000001
3683
+ #endif
3684
+
3685
+ #ifdef SIGAR_USING_MSC6
3686
+ #define sigar_wProductType wReserved[1]
3687
+ #else
3688
+ #define sigar_wProductType wProductType
3689
+ #endif
3690
+ #ifdef _M_X64
3691
+ #define SIGAR_ARCH "x64"
3692
+ #else
3693
+ #define SIGAR_ARCH "x86"
3694
+ #endif
3695
+
3696
+ int sigar_os_sys_info_get(sigar_t *sigar,
3697
+ sigar_sys_info_t *sysinfo)
3698
+ {
3699
+ OSVERSIONINFOEX version;
3700
+ char *vendor_name, *vendor_version, *code_name=NULL;
3701
+
3702
+ version.dwOSVersionInfoSize = sizeof(version);
3703
+ GetVersionEx((OSVERSIONINFO *)&version);
3704
+
3705
+ if (version.dwMajorVersion == 4) {
3706
+ vendor_name = "Windows NT";
3707
+ vendor_version = "NT";
3708
+ }
3709
+ else if (version.dwMajorVersion == 5) {
3710
+ switch (version.dwMinorVersion) {
3711
+ case 0:
3712
+ vendor_name = "Windows 2000";
3713
+ vendor_version = "2000";
3714
+ break;
3715
+ case 1:
3716
+ vendor_name = "Windows XP";
3717
+ vendor_version = "XP";
3718
+ code_name = "Whistler";
3719
+ break;
3720
+ case 2:
3721
+ vendor_name = "Windows 2003";
3722
+ vendor_version = "2003";
3723
+ code_name = "Whistler Server";
3724
+ break;
3725
+ default:
3726
+ vendor_name = "Windows Unknown";
3727
+ break;
3728
+ }
3729
+ }
3730
+ else if (version.dwMajorVersion == 6) {
3731
+ if (version.sigar_wProductType == VER_NT_WORKSTATION) {
3732
+ if (version.dwMinorVersion == 0) {
3733
+ vendor_name = "Windows Vista";
3734
+ vendor_version = "Vista";
3735
+ code_name = "Longhorn";
3736
+ }
3737
+ else {
3738
+ vendor_name = "Windows 7";
3739
+ vendor_version = "7";
3740
+ code_name = "Vienna";
3741
+ }
3742
+ }
3743
+ else {
3744
+ vendor_name = "Windows 2008";
3745
+ vendor_version = "2008";
3746
+ code_name = "Longhorn Server";
3747
+ }
3748
+ }
3749
+
3750
+ SIGAR_SSTRCPY(sysinfo->name, "Win32");
3751
+ SIGAR_SSTRCPY(sysinfo->vendor, "Microsoft");
3752
+ SIGAR_SSTRCPY(sysinfo->vendor_name, vendor_name);
3753
+ SIGAR_SSTRCPY(sysinfo->vendor_version, vendor_version);
3754
+ if (code_name) {
3755
+ SIGAR_SSTRCPY(sysinfo->vendor_code_name, code_name);
3756
+ }
3757
+
3758
+ SIGAR_SSTRCPY(sysinfo->arch, SIGAR_ARCH);
3759
+
3760
+ sprintf(sysinfo->version, "%d.%d",
3761
+ version.dwMajorVersion,
3762
+ version.dwMinorVersion);
3763
+
3764
+ SIGAR_SSTRCPY(sysinfo->patch_level,
3765
+ version.szCSDVersion);
3766
+
3767
+ sprintf(sysinfo->description, "%s %s",
3768
+ sysinfo->vendor, sysinfo->vendor_name);
3769
+
3770
+ return SIGAR_OK;
3771
+ }
3772
+
3773
+ #define sigar_QueryServiceStatusEx \
3774
+ sigar->advapi.query_service_status.func
3775
+
3776
+ int sigar_service_pid_get(sigar_t *sigar, char *name, sigar_pid_t *pid)
3777
+ {
3778
+ DWORD rc = ERROR_SUCCESS, len;
3779
+ SC_HANDLE mgr;
3780
+ HANDLE svc;
3781
+ SERVICE_STATUS_PROCESS status;
3782
+
3783
+ if (!sigar_QueryServiceStatusEx) {
3784
+ return SIGAR_ENOTIMPL;
3785
+ }
3786
+
3787
+ mgr = OpenSCManager(NULL,
3788
+ SERVICES_ACTIVE_DATABASE,
3789
+ SC_MANAGER_ALL_ACCESS);
3790
+
3791
+ if (!mgr) {
3792
+ return GetLastError();
3793
+ }
3794
+
3795
+ if (!(svc = OpenService(mgr, name, SERVICE_ALL_ACCESS))) {
3796
+ CloseServiceHandle(mgr);
3797
+ return GetLastError();
3798
+ }
3799
+
3800
+ if (sigar_QueryServiceStatusEx(svc,
3801
+ SC_STATUS_PROCESS_INFO,
3802
+ (LPBYTE)&status,
3803
+ sizeof(status), &len))
3804
+ {
3805
+ *pid = status.dwProcessId;
3806
+ }
3807
+ else {
3808
+ *pid = -1;
3809
+ rc = GetLastError();
3810
+ }
3811
+
3812
+ CloseServiceHandle(svc);
3813
+ CloseServiceHandle(mgr);
3814
+
3815
+ return rc;
3816
+ }
3817
+
3818
+ int sigar_services_status_get(sigar_services_status_t *ss, DWORD state)
3819
+ {
3820
+ DWORD bytes, resume=0;
3821
+ BOOL retval;
3822
+
3823
+ if (!ss->handle) {
3824
+ ss->handle =
3825
+ OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
3826
+ if (!ss->handle) {
3827
+ return GetLastError();
3828
+ }
3829
+ }
3830
+
3831
+ retval = EnumServicesStatus(ss->handle,
3832
+ SERVICE_WIN32, state,
3833
+ ss->services, ss->size,
3834
+ &bytes, &ss->count, &resume);
3835
+ if (retval == FALSE) {
3836
+ DWORD err = GetLastError();
3837
+ if (err != ERROR_MORE_DATA) {
3838
+ return err;
3839
+ }
3840
+
3841
+ ss->services = realloc(ss->services, bytes);
3842
+ ss->size = bytes;
3843
+
3844
+ retval = EnumServicesStatus(ss->handle,
3845
+ SERVICE_WIN32, state,
3846
+ ss->services, ss->size,
3847
+ &bytes, &ss->count, &resume);
3848
+
3849
+ if (retval == FALSE) {
3850
+ return GetLastError();
3851
+ }
3852
+ }
3853
+
3854
+ return SIGAR_OK;
3855
+ }
3856
+
3857
+ void sigar_services_status_close(sigar_services_status_t *ss)
3858
+ {
3859
+ if (ss->handle) {
3860
+ CloseServiceHandle(ss->handle);
3861
+ }
3862
+ if (ss->size) {
3863
+ free(ss->services);
3864
+ }
3865
+ SIGAR_ZERO(ss);
3866
+ }
3867
+
3868
+ /* extract exe from QUERY_SERVICE_CONFIG.lpBinaryPathName
3869
+ * leaves behind command-line arguments and quotes (if any)
3870
+ */
3871
+ char *sigar_service_exe_get(char *path, char *buffer, int basename)
3872
+ {
3873
+ char *ptr;
3874
+
3875
+ if (path) {
3876
+ strncpy(buffer, path, SIGAR_CMDLINE_MAX);
3877
+ }
3878
+ path = buffer;
3879
+
3880
+ if (*path == '"') {
3881
+ ++path;
3882
+ if ((ptr = strchr(path, '"'))) {
3883
+ *ptr = '\0';
3884
+ }
3885
+ }
3886
+ else {
3887
+ ptr = sigar_strcasestr(path, ".exe");
3888
+
3889
+ if (ptr) {
3890
+ *(ptr+4) = '\0';
3891
+ }
3892
+ else {
3893
+ if ((ptr = strchr(path, ' '))) {
3894
+ *ptr = '\0';
3895
+ }
3896
+ }
3897
+ }
3898
+
3899
+ if (basename && (ptr = strrchr(path, '\\'))) {
3900
+ path = ++ptr;
3901
+ }
3902
+
3903
+ return path;
3904
+ }
3905
+
3906
+ static char *string_file_info_keys[] = {
3907
+ "Comments",
3908
+ "CompanyName",
3909
+ "FileDescription",
3910
+ "FileVersion",
3911
+ "InternalName",
3912
+ "LegalCopyright",
3913
+ "LegalTrademarks",
3914
+ "OriginalFilename",
3915
+ "ProductName",
3916
+ "ProductVersion",
3917
+ "PrivateBuild",
3918
+ "SpecialBuild",
3919
+ NULL
3920
+ };
3921
+
3922
+ int sigar_file_version_get(sigar_file_version_t *version,
3923
+ char *name,
3924
+ sigar_proc_env_t *infocb)
3925
+ {
3926
+ DWORD handle, len;
3927
+ LPTSTR data;
3928
+ VS_FIXEDFILEINFO *info;
3929
+ int status;
3930
+
3931
+ if (!(len = GetFileVersionInfoSize(name, &handle))) {
3932
+ return GetLastError();
3933
+ }
3934
+
3935
+ if (len == 0) {
3936
+ return !SIGAR_OK;
3937
+ }
3938
+ data = malloc(len);
3939
+
3940
+ if (GetFileVersionInfo(name, handle, len, data)) {
3941
+ if (VerQueryValue(data, "\\", &info, &len)) {
3942
+ version->product_major = HIWORD(info->dwProductVersionMS);
3943
+ version->product_minor = LOWORD(info->dwProductVersionMS);
3944
+ version->product_build = HIWORD(info->dwProductVersionLS);
3945
+ version->product_revision = LOWORD(info->dwProductVersionLS);
3946
+ version->file_major = HIWORD(info->dwFileVersionMS);
3947
+ version->file_minor = LOWORD(info->dwFileVersionMS);
3948
+ version->file_build = HIWORD(info->dwFileVersionLS);
3949
+ version->file_revision = LOWORD(info->dwFileVersionLS);
3950
+ status = SIGAR_OK;
3951
+ }
3952
+ else {
3953
+ status = GetLastError();
3954
+ }
3955
+ }
3956
+ else {
3957
+ status = GetLastError();
3958
+ }
3959
+
3960
+ if (infocb && (status == SIGAR_OK)) {
3961
+ struct {
3962
+ WORD lang;
3963
+ WORD code_page;
3964
+ } *trans;
3965
+
3966
+ if (VerQueryValue(data, "\\VarFileInfo\\Translation",
3967
+ &trans, &len))
3968
+ {
3969
+ int i;
3970
+ char buf[1024];
3971
+ void *ptr;
3972
+
3973
+ for (i=0; string_file_info_keys[i]; i++) {
3974
+ char *key = string_file_info_keys[i];
3975
+ sprintf(buf, "\\StringFileInfo\\%04x%04x\\%s",
3976
+ trans[0].lang, trans[0].code_page,
3977
+ key);
3978
+ if (VerQueryValue(data, buf, &ptr, &len)) {
3979
+ if (len == 0) {
3980
+ continue;
3981
+ }
3982
+ infocb->env_getter(infocb->data,
3983
+ key, strlen(key),
3984
+ (char *)ptr, len);
3985
+ }
3986
+ }
3987
+ }
3988
+ }
3989
+
3990
+ free(data);
3991
+ return status;
3992
+ }