sigar-test 0.7.3.1

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