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