#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <psapi.h>
#include <powrprof.h>
#include "info.h"
#define LEN 20
#define MAXPROCESSES 1024
static const char *os_type = "Windows";
static double calculate_cpu_load(unsigned long long, unsigned long long);
static unsigned long long file_time_to_ull(const FILETIME);
const char *get_os_type(void) {
return os_type;
}
const char *get_os_release(void) {
OSVERSIONINFO osvi;
char *s = malloc(LEN);
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (GetVersionEx(&osvi))
snprintf(s, LEN, "%ld.%ld.%ld",
osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber);
else
strncpy(s, "unknown", LEN);
s[LEN - 1] = '\0';
return s;
}
unsigned int get_cpu_num(void) {
unsigned int num;
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
num = sys_info.dwNumberOfProcessors;
return num;
}
typedef struct _PROCESSOR_POWER_INFORMATION
{
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION;
unsigned long get_cpu_speed(void) {
unsigned int num = get_cpu_num();
unsigned int power_info_len = num * sizeof(PROCESSOR_POWER_INFORMATION);
PROCESSOR_POWER_INFORMATION *power_info = malloc(power_info_len);
CallNtPowerInformation(ProcessorInformation, NULL, 0, power_info, power_info_len);
unsigned int speed = 0;
for (unsigned int i = 0; i < num; i++) {
if (speed < power_info[i].MaxMhz) {
speed = power_info[i].MaxMhz;
}
}
free(power_info);
return speed;
}
LoadAvg get_loadavg(void) {
FILETIME idle_time, kernel_time, user_time;
LoadAvg la;
double load = GetSystemTimes(&idle_time, &kernel_time, &user_time) ?
calculate_cpu_load(file_time_to_ull(idle_time),
file_time_to_ull(kernel_time) +
file_time_to_ull(user_time)) :
-1.0;
la.one = load;
la.five = load;
la.fifteen = load;
return la;
}
unsigned long get_proc_total(void) {
DWORD aprocesses[MAXPROCESSES], cb_needed, cprocesses;
if (!EnumProcesses(aprocesses, sizeof(aprocesses), &cb_needed))
cprocesses = 0;
else
cprocesses = cb_needed / sizeof(unsigned long);
return cprocesses;
}
MemInfo get_mem_info(void) {
MEMORYSTATUSEX stat;
MemInfo mi;
stat.dwLength = sizeof(stat);
if (GlobalMemoryStatusEx(&stat)) {
mi.total = stat.ullTotalPhys / 1024;
mi.avail = 0;
mi.free = stat.ullAvailPhys / 1024;
mi.cached = 0;
mi.buffers = 0;
mi.swap_total = (stat.ullTotalPageFile - stat.ullTotalPhys) / 1024;
mi.swap_free = (stat.ullAvailPageFile - stat.ullAvailPhys) / 1024;
if (mi.swap_free > mi.swap_total) {
mi.swap_free = mi.swap_total;
}
} else {
memset(&mi, 0, sizeof(mi));
}
return mi;
}
DiskInfo get_disk_info(void) {
DWORD cluser, sector, free, total;
double tmp;
DiskInfo di;
if (GetDiskFreeSpace(NULL, &cluser, §or, &free, &total)) {
tmp = cluser * sector;
di.total = tmp * total / 1024;
di.free = tmp * free / 1024;
} else {
di.total = 0;
di.free = 0;
}
return di;
}
double calculate_cpu_load(unsigned long long idle_ticks,
unsigned long long total_ticks) {
static unsigned long long _prev_total_ticks = 0;
static unsigned long long _prev_idle_ticks = 0;
unsigned long long total_ticks_since_last_time = total_ticks -
_prev_total_ticks;
unsigned long long idle_ticks_since_last_time = idle_ticks -
_prev_idle_ticks;
double ret = 1.0 - ((total_ticks_since_last_time > 0) ?
((double)idle_ticks_since_last_time) /
total_ticks_since_last_time :
0);
_prev_total_ticks = total_ticks;
_prev_idle_ticks = idle_ticks;
return ret;
}
unsigned long long file_time_to_ull(const FILETIME ft) {
return (((unsigned long long)(ft.dwHighDateTime)) << 32) |
((unsigned long long)ft.dwLowDateTime);
}