sigar-test 0.7.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }