-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsystem.cpp
More file actions
386 lines (348 loc) · 13.2 KB
/
system.cpp
File metadata and controls
386 lines (348 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
//**********************************************************************
// Copyright (c) 2009-2014 Daniel D Miller
// derbar.exe - Another WinBar application
// system.cpp: functions for gathering system information
//
// Written by: Daniel D. Miller
//
// Last Update: 04/10/09 09:50
//**********************************************************************
//lint -esym(767, _WIN32_WINNT)
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h> // for sprintf, for %f support
#include <time.h>
#include <tchar.h>
#include <iphlpapi.h>
#include <pdh.h>
// #ifdef _lint
// #include <stdlib.h> // atoi()
// #endif
#include "common.h"
#include "commonw.h"
#include "derbar.h"
#include "ip_iface.h"
#include "PdhMsg.h"
//********************************************************
static uint RxBytes = 0 ;
static uint TxBytes = 0 ;
uint RxBytesPerSec = 0 ;
uint TxBytesPerSec = 0 ;
static DWORD PrevTickCount = 0 ;
DWORD SampleMsec = 0 ;
u64 freemem = 0 ;
u64 min_freemem = 0 ;
u64 totalmem = 0 ;
static ip_iface_entry_p itable_top = NULL ;
static ip_iface_entry_p itable_tail ;
//*******************************************************************
void update_memory_readings(void)
{
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
GlobalMemoryStatusEx(&statex);
// DWORDLONG
// printf ("%ld percent of memory is in use.\n",
// statex.dwMemoryLoad);
// printf ("There are %*I64d total %sbytes of physical memory.\n",
// WIDTH, statex.ullTotalPhys/DIV, divisor);
// printf ("There are %*I64d free %sbytes of physical memory.\n",
// WIDTH, statex.ullAvailPhys/DIV, divisor);
// printf ("There are %*I64d total %sbytes of paging file.\n",
// WIDTH, statex.ullTotalPageFile/DIV, divisor);
// printf ("There are %*I64d free %sbytes of paging file.\n",
// WIDTH, statex.ullAvailPageFile/DIV, divisor);
// printf ("There are %*I64x total %sbytes of virtual memory.\n",
// WIDTH, statex.ullTotalVirtual/DIV, divisor);
// printf ("There are %*I64x free %sbytes of virtual memory.\n",
// WIDTH, statex.ullAvailVirtual/DIV, divisor);
//
// // Show the amount of extended memory available.
// printf ("There are %*I64x free %sbytes of extended memory.\n",
// WIDTH, statex.ullAvailExtendedVirtual/DIV, divisor);
freemem = statex.ullAvailPhys ;
totalmem = statex.ullTotalPhys ;
if (min_freemem == 0 || min_freemem > freemem) {
min_freemem = freemem ;
}
}
//***********************************************************************
static int build_IPAddress_table(void)
{
PMIB_IPADDRTABLE pIpAddrTable ;
DWORD dwSize = 0;
int dwRet;
// Figure out how much memory we need
dwRet = GetIpAddrTable(NULL, &dwSize, TRUE);
if (dwRet != ERROR_INSUFFICIENT_BUFFER) {
return dwRet;
}
pIpAddrTable = (PMIB_IPADDRTABLE) new TCHAR[dwSize]; //lint !e433 !e826
if (pIpAddrTable == NULL) {
return ERROR_NOT_ENOUGH_MEMORY;
}
// Actually get the IP address table.
dwRet = GetIpAddrTable(pIpAddrTable, &dwSize, TRUE);
if (dwRet != ERROR_SUCCESS) {
goto error_cleanup ;
}
// printf("Number of IP address entries: %u\n", (unsigned) pIpAddrTable->dwNumEntries) ;
for (DWORD dwLoopIndex = 0; dwLoopIndex < pIpAddrTable->dwNumEntries; dwLoopIndex++) {
ip_iface_entry_p iptr = new ip_iface_entry_t ;
ZeroMemory((TCHAR *) iptr, sizeof(ip_iface_entry_t)) ;
iptr->dwAddr = pIpAddrTable->table[dwLoopIndex].dwAddr ;
iptr->dwIndex = pIpAddrTable->table[dwLoopIndex].dwIndex ;
iptr->dwMask = pIpAddrTable->table[dwLoopIndex].dwMask ;
iptr->dwBCastAddr = pIpAddrTable->table[dwLoopIndex].dwBCastAddr ;
iptr->dwReasmSize = pIpAddrTable->table[dwLoopIndex].dwReasmSize ;
if (itable_top == NULL)
itable_top = iptr ;
else
itable_tail->next = iptr ;
itable_tail = iptr ;
// syslog(_T("Adding index %u: 0x%08X\n"), iptr->dwIndex, iptr->dwAddr) ;
}
puts("") ;
error_cleanup:
if (pIpAddrTable != NULL)
delete[] pIpAddrTable ;
return dwRet;
}
//***********************************************************************
// WARNING: Everyone who calls this function, needs to delete
// the return value when they're done with it!!
//***********************************************************************
static PMIB_IFROW get_iface_entry(DWORD idx)
{
PMIB_IFROW pIfRow = new MIB_IFROW ;
ZeroMemory(pIfRow, sizeof(MIB_IFROW));
pIfRow->dwIndex = idx ;
DWORD result = GetIfEntry(pIfRow) ;
if (result == NO_ERROR) {
return pIfRow ;
}
delete pIfRow ;
return NULL;
}
//***********************************************************************
static void build_iface_table(void)
{
ip_iface_entry_p iptr ;
// uint cbox_row = 1 ;
uint lview_row = 0 ;
for (iptr = itable_top; iptr != NULL; iptr = iptr->next) {
// syslog(_T("found index %u: %s\n"), iptr->dwIndex, iptr->ipaddr_str) ;
PMIB_IFROW pIfRow = get_iface_entry(iptr->dwIndex) ;
if (pIfRow != NULL) {
ul2uc_t uconv ;
uconv.ul = iptr->dwAddr ;
_stprintf(iptr->ipaddr_str, _T("%u.%u.%u.%u"),
(u8) uconv.uc[0], (u8) uconv.uc[1], (u8) uconv.uc[2], (u8) uconv.uc[3]) ;
// syslog(_T("found index %u: %s\n"), iptr->dwIndex, iptr->ipaddr_str) ;
// WideCharToMultiByte(CP_ACP, 0, pIfRow->wszName, -1, SomeAsciiStr, MAX_INTERFACE_NAME_LEN, NULL, NULL);
// printf("Index[%u]: %s\n", (unsigned) pIfRow->dwIndex, (TCHAR *) SomeAsciiStr);
// memcpy(iptr->iface_name, pIfRow->bDescr, pIfRow->dwDescrLen) ;
// iptr->iface_name[pIfRow->dwDescrLen] = 0 ;
// \DEVICE\TCPIP_{E0EC89D8-2A3A-11EB-BA6E-806E6F6E6963}
// \DEVICE\TCPIP_{D029C36D-06CF-4093-A60C-D7DF971E87D7}
// \DEVICE\TCPIP_{6FA7BCC6-6B01-4D83-8B5A-CB85A1B0B6B8}
// WCHAR *ascii2unicode(pIfRow->bDescr, pIfRow->dwDescrLen)
_tcscpy(iptr->iface_name, ascii2unicode((char *)pIfRow->bDescr, pIfRow->dwDescrLen)) ;
// iptr->cbox_row = cbox_row++ ;
iptr->lview_row = lview_row++ ;
delete pIfRow ;
}
}
}
//***********************************************************************
static void enable_if_row(TCHAR *cfg_str)
{
uint idx = (unsigned) _ttoi(cfg_str) ;
for (ip_iface_entry_p iptr = itable_top; iptr != NULL; iptr = iptr->next) {
if (iptr->lview_row == idx) {
iptr->if_active = true ;
break;
}
}
}
//***********************************************************************
static void disable_all_ifaces(void)
{
for (ip_iface_entry_p iptr = itable_top; iptr != NULL; iptr = iptr->next)
iptr->if_active = false ;
}
//***********************************************************************
void update_iface_flags(TCHAR *cfg_str)
{
disable_all_ifaces() ;
while (LOOP_FOREVER) {
if (cfg_str == 0)
break;
enable_if_row(cfg_str) ;
TCHAR *tl = _tcschr(cfg_str, _T(',')) ;
if (tl == NULL)
break;
cfg_str = tl+1 ;
}
}
//***********************************************************************
void write_iface_enables(FILE *fd)
{
TCHAR bfr[81] ;
int slen = 0 ;
for (ip_iface_entry_p iptr = itable_top; iptr != NULL; iptr = iptr->next) {
if (iptr->if_active) {
if (slen > 0)
slen += wsprintf(bfr+slen, L",") ;
slen += wsprintf(bfr+slen, L"%u", iptr->lview_row) ;
}
}
if (slen > 0) {
_ftprintf(fd, _T("ip_iface=%s\n"), bfr) ; //lint !e559
}
}
//***********************************************************************
// this is called once, at program startup
//***********************************************************************
void build_iface_tables(void)
{
build_IPAddress_table() ;
build_iface_table() ;
}
//***********************************************************************
// let listview iterate over interface list,
// without actually knowing about our internal data
//***********************************************************************
ip_iface_entry_p get_next_ip_iface(ip_iface_entry_p prev)
{
if (prev == NULL)
return itable_top ;
return prev->next ;
}
//***********************************************************************
void update_iface_counters(void)
{
uint txb = 0 ;
uint rxb = 0 ;
ip_iface_entry_p iptr ;
for (iptr = itable_top; iptr != NULL; iptr = iptr->next) {
// if program is set to any interface other than "Read All",
// skip all entries except for the chosen interface.
// if (ip_iface_idx != 0 && ip_iface_idx != iptr->cbox_row)
// continue;
if (!iptr->if_active)
continue;
PMIB_IFROW pIfRow = get_iface_entry(iptr->dwIndex) ;
if (pIfRow != NULL) {
iptr->dwInOctets = pIfRow->dwInOctets ;
iptr->dwOutOctets = pIfRow->dwOutOctets ;
iptr->dwInErrors = pIfRow->dwInErrors ;
iptr->dwOutErrors = pIfRow->dwOutErrors ;
// syslog(_T("[%u/%u] %s\n"), iptr->dwInOctets, iptr->dwOutOctets, iptr->iface_name) ;
rxb += pIfRow->dwInOctets ;
txb += pIfRow->dwOutOctets ;
delete pIfRow ;
}
}
if (PrevTickCount == 0) {
PrevTickCount = GetTickCount() ;
SampleMsec = 1000 ;
} else {
DWORD CurrTickCount = GetTickCount() ;
if (CurrTickCount > PrevTickCount) {
SampleMsec = CurrTickCount - PrevTickCount ;
} else {
// handle counter wrap
SampleMsec = CurrTickCount + (0xFFFFFFFF - PrevTickCount) + 1 ;
}
PrevTickCount = CurrTickCount ;
}
if (RxBytes == 0) {
RxBytes = rxb ;
RxBytesPerSec = 0 ;
} else if (rxb < RxBytes) {
// try to deal with counter wrap
RxBytes = rxb ;
RxBytesPerSec = 0 ;
} else {
RxBytesPerSec = rxb - RxBytes ;
RxBytes = rxb ;
}
if (TxBytes == 0) {
TxBytes = txb ;
TxBytesPerSec = 0 ;
} else if (txb < TxBytes) {
// try to deal with counter wrap
TxBytes = txb ;
TxBytesPerSec = 0 ;
} else {
TxBytesPerSec = txb - TxBytes ;
TxBytes = txb ;
}
}
//*********************************************************************
static HQUERY hQuery;
static HCOUNTER hCounter;
void cpu_usage_setup(void)
{
PDH_STATUS presult ;
presult = PdhOpenQuery(NULL, 0, &hQuery);
if (presult != ERROR_SUCCESS) {
syslog(_T("PdhOpenQuery: 0x%08X\n"), (uint) presult) ;
return ;
}
presult = PdhAddCounter(hQuery, _T("\\Processor(_Total)\\% Processor Time"), 0, &hCounter);
if (presult != ERROR_SUCCESS) {
syslog(_T("PdhAddCounter: 0x%08X\n"), (uint) presult) ;
return ;
}
}
//*********************************************************************
double cpu_usage_report(void)
{
PDH_FMT_COUNTERVALUE FmtValue;
static bool first_query_done = false ;
PDH_STATUS presult = PdhCollectQueryData(hQuery);
if (presult != ERROR_SUCCESS) {
syslog(_T("PdhCollectQueryData1: 0x%08X\n"), (uint) presult) ;
return 0.0 ;
}
// this returns PDH_INVALID_DATA:
// The specified counter does not contain valid data or a successful status code.
if (!first_query_done) {
first_query_done = true ;
return 0.0 ;
}
//*****************************************************************
// MessageId: PDH_CALC_NEGATIVE_DENOMINATOR
//
// MessageText:
//
// A counter with a negative denominator value was detected.
//*****************************************************************
// #define PDH_CALC_NEGATIVE_DENOMINATOR ((DWORD)0x800007D6L)
// [3628] PdhGetFormattedCounterValue: 0x800007D6
// https://www.netiq.com/support/kb/doc.php?id=7010545
// The return values like PDH_CALC_NEGATIVE_DENOMINATOR can occur because of
// either a bug in the provider or overflow of values in data storage. In these
// situations, you have an option to ignore this return value and retry a bit
// later like 1 second to get the new values. This is not a fatal error that
// application cant continue correctly, like INVALID_HANDLE or INVALID_DATA.
//
// 08/20/14 - adding PDH_FMT_NOCAP100 to the function call did NOT solve this
// issue. BTW, this mostly occurs on WinXP systems, I think.
//**********************************************************************************
presult = PdhGetFormattedCounterValue(hCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, NULL, &FmtValue);
if (presult != ERROR_SUCCESS) {
if ((uint) presult != PDH_CALC_NEGATIVE_DENOMINATOR)
syslog(_T("PdhGetFormattedCounterValue: 0x%08X\n"), (uint) presult) ;
return 0.0 ;
}
// printf("The cpu usage is : %f%%\n", FmtValue.doubleValue);
return FmtValue.doubleValue ;
}
//*********************************************************************
void cpu_usage_release(void)
{
PdhCloseQuery(hQuery);
}