diff --git a/src/Makefile b/src/Makefile index c24e5d0..ae36df2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,6 +22,11 @@ INSTALL ?= install LINK_FLAGS ?= -Wl,-E SMC_LIBS ?= -L/usr/X11R6/lib -lSM -lICE +SHARED_PATH = ../shared +# Make GNU Make search for sources somewhere else as well +VPATH = $(SHARED_PATH) + + ifeq ($(without-gnutls),1) CONFIGURE_ARGS += --without-gnutls endif @@ -40,8 +45,6 @@ endif ifeq ($(without-libsensors),1) CONFIGURE_ARGS += --without-libsensors endif - - DUMMY_VAR := $(shell ./configure $(CONFIGURE_ARGS)) HAVE_GNUTLS = $(shell grep -c HAVE_GNUTLS configure.h) @@ -65,14 +68,13 @@ endif CC ?= gcc STRIP ?= -s -GKRELLM_INCLUDES = gkrellm.h gkrellm-public-proto.h +GKRELLM_INCLUDES = gkrellm.h gkrellm-public-proto.h $(SHARED_PATH)/log.h PKG_INCLUDE = `$(PKG_CONFIG) --cflags gtk+-2.0 gthread-2.0` - PKG_LIB = `$(PKG_CONFIG) --libs gtk+-2.0 gthread-2.0` -FLAGS = -O2 -I.. $(PKG_INCLUDE) $(GTOP_INCLUDE) -FLAGS+= $(PTHREAD_INC) +FLAGS = -O2 -I.. -I$(SHARED_PATH) $(PKG_INCLUDE) $(GTOP_INCLUDE) $(PTHREAD_INC) \ + -DGKRELLM_CLIENT LIBS = $(PKG_LIB) $(GTOP_LIBS) $(SMC_LIBS) $(SYS_LIBS) $(SSL_LIBS) $(SENSORS_LIBS) @@ -83,6 +85,13 @@ ifeq ($(debug),yes) FLAGS += -g endif +ifeq ($(profile),1) + FLAGS += -g -pg +endif +ifeq ($(profile),yes) + FLAGS += -g -pg +endif + ifeq ($(enable_nls),1) FLAGS += -DENABLE_NLS -DLOCALEDIR=\"$(LOCALEDIR)\" endif @@ -91,7 +100,7 @@ ifeq ($(enable_nls),yes) endif ifneq ($(PACKAGE),gkrellm) - FLAGS += -DPACKAGE=\"$(PACKAGE)\" + FLAGS += -DPACKAGE=\"$(PACKAGE)\" endif ifeq ($(HAVE_GETADDRINFO),1) @@ -105,9 +114,9 @@ OBJS = main.o alerts.o battery.o base64.o clock.o cpu.o disk.o fs.o \ hostname.o inet.o mail.o mem.o net.o proc.o sensors.o uptime.o \ chart.o panel.o config.o gui.o krell.o plugins.o pixops.o \ smbdes.o smbencrypt.o smbmd4.o smbutil.o \ - client.o utils.o deprecated.o + client.o utils.o sysdeps-unix.o deprecated.o log.o -UNIXOBJS = winops-x11.o sysdeps-unix.o +UNIXOBJS = winops-x11.o all: gkrellm @@ -170,13 +179,13 @@ solaris: windows: libgkrellm.a $(MAKE) \ - CFLAGS="${CFLAGS} -DWIN32_CLIENT -D_WIN32_WINNT=0x0500 -DWINVER=0x0500" \ - LINK_FLAGS="${LINK_FLAGS} -mwindows" \ - EXTRAOBJS="${EXTRAOBJS} winops-win32.o sysdeps/win32.o win32-plugin.o win32-resource.o" \ - SYS_LIBS=" -llargeint -lws2_32 -lpdh -lnetapi32 -liphlpapi -lntdll -lintl" \ - SMC_LIBS="" \ - UNIXOBJS="" \ - gkrellm + CFLAGS="${CFLAGS} -D_WIN32_WINNT=0x0500 -DWINVER=0x0500" \ + LINK_FLAGS="${LINK_FLAGS} -mwindows" \ + EXTRAOBJS="${EXTRAOBJS} winops-win32.o win32-plugin.o win32-resource.o" \ + SYS_LIBS=" -llargeint -lws2_32 -lpdh -lnetapi32 -liphlpapi -lntdll -lintl" \ + SMC_LIBS="" \ + UNIXOBJS="" \ + gkrellm install: install_bin install_inc install_man @@ -320,14 +329,17 @@ pixops.o: pixops.c $(GKRELLM_H) client.o: client.c $(GKRELLM_H) utils.o: utils.c $(GKRELLM_H) sysdeps-unix.o: sysdeps-unix.c $(GKRELLM_H_SYS) $(SYSDEPS_SRC) +log.o: $(SHARED_PATH)/log.c $(SHARED_PATH)/log.h $(GKRELLM_H) +deprecated.o: deprecated.c $(GKRELLM_H) + winops-x11.o: winops-x11.c $(GKRELLM_H) winops-gtk-mac.o: winops-gtk-mac.c $(GKRELLM_H) -deprecated.o: deprecated.c $(GKRELLM_H) -sysdeps/win32.o: sysdeps/win32.c $(GKRELLM_H_SYS) -winops-win32.o: winops-win32.c $(GKRELLM_H) +winops-win32.o: winops-win32.c $(GKRELLM_H) + win32-plugin.o: win32-plugin.c win32-plugin.h win32-libgkrellm.o: win32-libgkrellm.c win32-plugin.h win32-resource.o: win32-resource.rc win32-resource.h windres -I.. -o win32-resource.o win32-resource.rc + libgkrellm.a: win32-libgkrellm.o ar -cr libgkrellm.a win32-libgkrellm.o diff --git a/src/gkrellm.h b/src/gkrellm.h index ec5975a..40210aa 100644 --- a/src/gkrellm.h +++ b/src/gkrellm.h @@ -25,7 +25,8 @@ #if defined(HAVE_CONFIG_H) #include "config.h" -#endif +#endif +#include "log.h" #if !defined(WIN32) #include @@ -84,7 +85,7 @@ # define gettext(String) (String) # define dgettext(Domain,String) (String) # define dcgettext(Domain,String,Type) (String) -# define bindtextdomain(Domain,Directory) (Domain) +# define bindtextdomain(Domain,Directory) (Domain) #endif /* ENABLE_NLS */ @@ -269,7 +270,7 @@ typedef struct GdkBitmap *stencil; gint y_src; /* Offset into pixmap if a vertical stack */ gint w, h; /* Size of the decal */ - gint x, y; /* Position of decal in a drawable */ + gint x, y; /* Position of decal in a drawable */ gshort flags, state; gint value; /* Index into stack, text value, etc */ @@ -1050,13 +1051,13 @@ typedef struct _GkrellmMonitor void (*save_user_config)(FILE *); void (*load_user_config)(gchar *); gchar *config_keyword; - + void (*undef2)(void); void (*undef1)(void); GkrellmMonprivate *privat; gint insert_before_id; /* If plugin, insert before this mon*/ - + void *handle; /* If monitor is a plugin. */ gchar *path; /* " */ } diff --git a/src/main.c b/src/main.c index a75d210..4caea5a 100644 --- a/src/main.c +++ b/src/main.c @@ -22,6 +22,7 @@ #include "gkrellm.h" #include "gkrellm-private.h" #include "gkrellm-sysdeps.h" +#include "log-private.h" #if GTK_CHECK_VERSION(2,4,0) #include "icon.xpm" @@ -133,17 +134,15 @@ load_font(gchar *font_string, PangoFontDescription **gk_font, if (font_string) font_desc = pango_font_description_from_string(font_string); - if (_GK.debug_level & DEBUG_GUI) - printf("load_font: %s %p\n", font_string, font_desc); + gkrellm_debug(DEBUG_GUI, "load_font: %s %p\n", font_string, font_desc); if (!font_desc) { for (i = 0; !font_desc && i < N_FALLBACK_FONTS; ++i) { font_desc = pango_font_description_from_string(fallback_fonts[i]); - if (_GK.debug_level & DEBUG_GUI) - printf("load_font trying fallback: %s\n", - fallback_fonts[i]); + gkrellm_debug(DEBUG_GUI, "load_font trying fallback: %s\n", + fallback_fonts[i]); } } if (*gk_font) @@ -222,7 +221,7 @@ setup_colors() /* Set up the depth 1 GCs */ - /* printf("white pixel = %ld\n", _GK.white_color.pixel); */ + /* g_print("white pixel = %ld\n", _GK.white_color.pixel); */ if (_GK.bit1_GC == NULL) { GdkBitmap *dummy_bitmap; @@ -274,8 +273,7 @@ set_or_save_position(gint save) y_last = _GK.y_position; fprintf(f, "%d %d\n", _GK.x_position, _GK.y_position); fclose(f); - if (_GK.debug_level & DEBUG_POSITION) - printf("save_position: %d %d\n", x_last, y_last); + gkrellm_debug(DEBUG_POSITION, "save_position: %d %d\n", x_last, y_last); } save_position_countdown = 0; } @@ -295,8 +293,7 @@ set_or_save_position(gint save) _GK.y_position = y_last = y; _GK.position_valid = TRUE; gdk_window_move(gtree.window->window, x, y); - if (_GK.debug_level & DEBUG_POSITION) - printf("startup_position moveto %d %d (valid)\n", x, y); + gkrellm_debug(DEBUG_POSITION, "startup_position moveto %d %d (valid)\n", x, y); } } } @@ -602,8 +599,7 @@ top_frame_button_release(GtkWidget *widget, GdkEventButton *ev, gpointer data) if (!no_transparency) gkrellm_winop_apply_rootpixmap_transparency(); moving_gkrellm = FALSE; - if (_GK.debug_level & DEBUG_POSITION) - printf("gkrellm moveto: x_pos=%d y_pos=%d\n", + gkrellm_debug(DEBUG_POSITION, "gkrellm moveto: x_pos=%d y_pos=%d\n", _GK.x_position, _GK.y_position); } @@ -1179,7 +1175,7 @@ gkrellm_pack_side_frames(void) { rf_image = gtk_image_new_from_pixmap(gtree.frame_right_pixmap, NULL); gtk_box_pack_start(GTK_BOX(gtree.right_vbox), rf_image, - FALSE, FALSE, 0); + FALSE, FALSE, 0); gtk_widget_show(rf_image); } else @@ -1199,9 +1195,9 @@ gkrellm_pack_side_frames(void) { gdk_window_move(gtree.window->window, _GK.x_position, _GK.y_position); - if (_GK.debug_level & DEBUG_POSITION) - printf("pack moveto %d %d=y_position (y_gkrell=%d y_bot=%d)\n", - _GK.x_position, _GK.y_position, y_gkrell, y_bottom); + gkrellm_debug(DEBUG_POSITION, + "pack moveto %d %d=y_position (y_gkrell=%d y_bot=%d)\n", + _GK.x_position, _GK.y_position, y_gkrell, y_bottom); } y_pack = -1; } @@ -1218,9 +1214,9 @@ gkrellm_pack_side_frames(void) if (_GK.position_valid) { gdk_window_move(gtree.window->window, _GK.x_position, y_pack); - if (_GK.debug_level & DEBUG_POSITION) - printf("pack moveto %d %d=y_pack (y_gkrell=%d y_bot=%d)\n", - _GK.x_position, y_pack, y_gkrell, y_bottom); + gkrellm_debug(DEBUG_POSITION, + "pack moveto %d %d=y_pack (y_gkrell=%d y_bot=%d)\n", + _GK.x_position, y_pack, y_gkrell, y_bottom); } } /* If GKrellM bottom edge was <= screen bottom, then move to make @@ -1233,9 +1229,9 @@ gkrellm_pack_side_frames(void) if (_GK.position_valid) { gdk_window_move(gtree.window->window, _GK.x_position, y_pack); - if (_GK.debug_level & DEBUG_POSITION) - printf("pack moveto %d %d=y_pack (y_gkrell=%d on_bottom)\n", - _GK.x_position, y_pack, y_gkrell); + gkrellm_debug(DEBUG_POSITION, + "pack moveto %d %d=y_pack (y_gkrell=%d on_bottom)\n", + _GK.x_position, y_pack, y_gkrell); } } } @@ -1293,8 +1289,8 @@ fix_edges() gdk_window_move(gtree.window->window, x, y); if (y != _GK.y_position) y_pack = y; - if (_GK.debug_level & DEBUG_POSITION) - printf("fix_edges: %d %d (y_pos=%d)\n", x, y, _GK.y_position); + gkrellm_debug(DEBUG_POSITION, + "fix_edges: %d %d (y_pos=%d)\n", x, y, _GK.y_position); } } @@ -1319,7 +1315,7 @@ gkrellm_render_spacer(GkrellmSpacer *spacer, gint y_src, gint h_src, ) { if (spacer->height > 0) - fprintf(stderr, "Bad image size for spacer or bg_chart.\n"); + g_warning("Bad image size for spacer or bg_chart.\n"); return FALSE; } piximage.border = spacer->piximage->border; @@ -1573,7 +1569,7 @@ cb_client_event(GtkWidget *widget, GdkEventClient *event, gpointer data) if (!atom_gkrellm_read_theme) atom_gkrellm_read_theme = gdk_atom_intern("_GKRELLM_READ_THEME",FALSE); - if (event->message_type == atom_gkrellm_read_theme) + if (event->message_type == atom_gkrellm_read_theme) gkrellm_read_theme_event(NULL); return FALSE; } @@ -1673,12 +1669,16 @@ cb_configure_notify(GtkWidget *widget, GdkEventConfigure *ev, gpointer data) if (y >= 0 && y < _GK.h_display - 5 && y != y_pack) _GK.y_position = y; _GK.position_valid = TRUE; - if (!moving_gkrellm && (_GK.debug_level & DEBUG_POSITION)) - printf("configure-event: x_pos=%d y_pos=%d x=%d y=%d y_pack=%d\n", - _GK.x_position, _GK.y_position, x, y, y_pack); + if (!moving_gkrellm) + gkrellm_debug(DEBUG_POSITION, + "configure-event: x_pos=%d y_pos=%d x=%d y=%d y_pack=%d\n", + _GK.x_position, _GK.y_position, x, y, y_pack); + } + else + { + gkrellm_debug(DEBUG_POSITION, + "locked configure-event: x=%d y=%d\n", x, y); } - else if (_GK.debug_level & DEBUG_POSITION) - printf("locked configure-event: x=%d y=%d\n", x, y); if (size_change || position_change) gkrellm_winop_update_struts(); @@ -1948,26 +1948,11 @@ load_builtin_monitors() add_builtin(gkrellm_init_uptime_monitor()); } - -void -gkrellm_print(const gchar *string) - { - gchar *s; - - s = g_locale_from_utf8(string, -1, NULL, NULL, NULL); - if (s) - { - fputs(s, stdout); - g_free(s); - } - else - fputs(string, stdout); - } - static void gkrellm_exit(gint exit_code) { gkrellm_sys_main_cleanup(); + gkrellm_log_cleanup(); exit(exit_code); } @@ -2051,22 +2036,40 @@ main(gint argc, gchar **argv) gint i; gchar *s; - gkrellm_sys_main_init(); + //gkrellm_sys_main_init(); #ifdef ENABLE_NLS gtk_set_locale(); #endif - g_thread_init(NULL); - gtk_init(&argc, &argv); /* Will call gdk_init() */ - + gkrellm_log_init(); gtk_widget_push_colormap(gdk_rgb_get_colormap()); #ifdef ENABLE_NLS #ifdef LOCALEDIR +#if defined(WIN32) + /* + Prepend app install path to relative locale dir, don't rely on CWD being correct + */ + if (!G_IS_DIR_SEPARATOR(LOCALEDIR[0])) + { + gchar* locale_dir; + locale_dir = g_win32_get_package_installation_subdirectory(NULL, NULL, LOCALEDIR); + if (locale_dir != NULL) + { + bindtextdomain(PACKAGE, locale_dir); + g_free(locale_dir); + } + } + else + { + bindtextdomain(PACKAGE, LOCALEDIR); + } +#else bindtextdomain(PACKAGE, LOCALEDIR); -#endif +#endif /* !WIN32 */ +#endif /* LOCALEDIR */ textdomain(PACKAGE); bind_textdomain_codeset(PACKAGE, "UTF-8"); #endif /* ENABLE_NLS */ @@ -2080,8 +2083,6 @@ main(gint argc, gchar **argv) signal(SIGSEGV, gkrellm_abort); signal(SIGABRT, gkrellm_abort); - g_set_print_handler(gkrellm_print); - for (i = 1; i < argc; ++i) { s = argv[i]; @@ -2128,6 +2129,8 @@ main(gint argc, gchar **argv) _GK.no_config = TRUE; else if ((!strcmp(s, "debug-level") || !strcmp(s, "d")) && i < argc-1) _GK.debug_level = (gint) strtoul(argv[++i], NULL, 0); + else if ((!strcmp(s, "logfile") || !strcmp(s, "l")) && i < argc-1) + gkrellm_log_set_filename(argv[++i]); else if (!strncmp(s, "debug", 5)) { if (s[5] != '\0') @@ -2150,7 +2153,7 @@ main(gint argc, gchar **argv) _GK.test += 1; else if (!strcmp(s, "version") || !strcmp(s, "v")) { - printf("%s %d.%d.%d%s\n", PACKAGE, GKRELLM_VERSION_MAJOR, + g_print("%s %d.%d.%d%s\n", PACKAGE, GKRELLM_VERSION_MAJOR, GKRELLM_VERSION_MINOR, GKRELLM_VERSION_REV, GKRELLM_EXTRAVERSION); exit(0); @@ -2168,17 +2171,19 @@ main(gint argc, gchar **argv) } } + gkrellm_sys_main_init(); //FIXME: call this later or earlier? + _GK.w_display = gdk_screen_get_width(gdk_screen_get_default()); _GK.h_display = gdk_screen_get_height(gdk_screen_get_default()); - if (_GK.debug_level) - printf("--- GKrellM %d.%d.%d ---\n", GKRELLM_VERSION_MAJOR, - GKRELLM_VERSION_MINOR, GKRELLM_VERSION_REV); + if (_GK.debug_level > 0) + g_debug("--- GKrellM %d.%d.%d ---\n", GKRELLM_VERSION_MAJOR, + GKRELLM_VERSION_MINOR, GKRELLM_VERSION_REV); if (_GK.server && !gkrellm_client_mode_connect()) exit(0); check_gkrellm_directories(); - gkrellm_load_user_config(NULL, FALSE); + gkrellm_load_user_config(NULL, FALSE); decorated = (_GK.command_line_decorated || _GK.decorated); if ( _GK.command_line_plugin || _GK.command_line_theme || _GK.debug_level > 0 || _GK.debug > 0 || _GK.nolock @@ -2252,33 +2257,10 @@ main(gint argc, gchar **argv) gkrellm_start_timer(_GK.update_HZ); setup_signal_handler(); - gtk_main (); + gtk_main(); + gkrellm_save_all(); gkrellm_exit(0); return 0; } - - -#if defined(WIN32) && defined(_WINDOWS) -int APIENTRY WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) - { - int argc; - gint i, ret; - gchar *s, *sm; - gchar **argv; - gchar *cmd; - - // need to get exe too - cmd = GetCommandLine(); - g_shell_parse_argv(cmd, &argc, &argv, NULL); - - ret = main(argc, argv); - g_strfreev(argv); - return ret; - } -#endif - diff --git a/src/sysdeps-unix.c b/src/sysdeps-unix.c index eddc178..98ec015 100644 --- a/src/sysdeps-unix.c +++ b/src/sysdeps-unix.c @@ -68,9 +68,15 @@ #include "sysdeps/gtop.c" #endif -#include +#if defined(WIN32) +#include "sysdeps/win32.c" +#endif -#ifndef SENSORS_COMMON +#if !defined(WIN32) +#include +#endif + +#if !defined(SENSORS_COMMON) && !defined(WIN32) static gboolean (*mbmon_check_func)(); #endif @@ -86,6 +92,7 @@ gkrellm_sys_get_host_name(void) return buf; } +#if !defined(WIN32) gchar * gkrellm_sys_get_system_name(void) { @@ -98,12 +105,13 @@ gkrellm_sys_get_system_name(void) sname = g_strdup("unknown name"); return sname; } +#endif gboolean gkrellm_sys_sensors_mbmon_port_change(gint port) { gboolean result = FALSE; - +#if !defined(WIN32) _GK.mbmon_port = port; /* mbmon_check_func will be set if sysdep code has included @@ -116,11 +124,16 @@ gkrellm_sys_sensors_mbmon_port_change(gint port) gkrellm_sensors_model_update(); gkrellm_sensors_rebuild(TRUE, TRUE, TRUE); } +#endif return result; } gboolean gkrellm_sys_sensors_mbmon_supported(void) { +#if !defined(WIN32) return mbmon_check_func ? TRUE : FALSE; +#else + return FALSE; +#endif } diff --git a/src/sysdeps/win32.c b/src/sysdeps/win32.c index 8966fb2..8274b3d 100644 --- a/src/sysdeps/win32.c +++ b/src/sysdeps/win32.c @@ -1,10 +1,11 @@ - /* GKrellM -| Copyright (C) 1999-2007 Bill Wilson +/* GKrellM +| Copyright (C) 1999-2008 Bill Wilson | | Author: Bill Wilson billw@gkrellm.net | Latest versions might be found at: http://gkrellm.net | -| win32.c code is Copyright (C) Bill Nalen bill@nalens.com +| win32.c code is Copyright (C) Bill Nalen bill@nalens.com +| Stefan Gehn stefan.gkrellm@srcbox.net | | | GKrellM is free software: you can redistribute it and/or modify it @@ -21,53 +22,36 @@ | along with this program. If not, see http://www.gnu.org/licenses/ */ -#if defined(WIN32_CLIENT) -#include "../gkrellm.h" -#include "../gkrellm-sysdeps.h" -#include "../gkrellm-private.h" -#include "../win32-plugin.h" - #include -#else +#include "../inet.h" // For struct ActiveTCP +#if defined(GKRELLM_SERVER) #include "../../server/win32-plugin.h" +#else + #include "../win32-plugin.h" #endif -// we use struct ActiveTCP -#include "../inet.h" - -#include -#include -#include -#include -#include -#include - +#include // For disk space calculation +#include // For cdrom eject +#include // For tcp connection stats +// Following two are for cpu, proc, disk and network stats +// which are queried via "performance data counters" #include #include -#include -#include -#include -#include - +// Following two are used to determine number of logged in users and +// pagefile usage via NT-APIs #include +#include -#if defined(UNICODE) ^ defined(_UNICODE) -#error Inconsistent UNICODE and _UNICODE definition -#endif -#if !defined(ARRAYSIZE) -#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0])) -#endif - -// *************************************************************************** +// ---------------------------------------------------------------------------- // Needed to determine pagefile usage -// definitions were taken from MinGW include/ddk/ntapi.h because you cannot -// mix ddk includes with normal windows includes. +// +// These definitions were taken from MinGW include/ddk/ntapi.h because you +// cannot mix ddk includes with normal windows includes although you can call +// these functions without being a driver. #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define SystemPagefileInformation 18 -NTSTATUS -NTAPI -ZwQuerySystemInformation( +NTSTATUS NTAPI ZwQuerySystemInformation( /*IN*/ UINT SystemInformationClass, /*IN OUT*/ PVOID SystemInformation, /*IN*/ ULONG SystemInformationLength, @@ -81,166 +65,315 @@ typedef struct _SYSTEM_PAGEFILE_INFORMATION { UNICODE_STRING FileName; } SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; -// *************************************************************************** -// Max length of device names -// value taken from net.c load_net_config() and disk.c load_disk_config()) +// ---------------------------------------------------------------------------- +// Structs and typedefs used to determine the number of logged in users. +// These should be in ntsecapi.h but are missing in MinGW currently. +// Docs: http://msdn.microsoft.com/en-us/library/aa378290(VS.85).aspx + +typedef struct _SECURITY_LOGON_SESSION_DATA { + ULONG Size; + LUID LogonId; + LSA_UNICODE_STRING UserName; + LSA_UNICODE_STRING LogonDomain; + LSA_UNICODE_STRING AuthenticationPackage; + ULONG LogonType; + ULONG Session; + PSID Sid; + LARGE_INTEGER LogonTime; + LSA_UNICODE_STRING LogonServer; + LSA_UNICODE_STRING DnsDomainName; + LSA_UNICODE_STRING Upn; +} SECURITY_LOGON_SESSION_DATA, *PSECURITY_LOGON_SESSION_DATA; + +// Definitions for function pointers (functions resolved manually at runtime) +typedef NTSTATUS (NTAPI *pfLsaEnumerateLogonSessions)( + PULONG LogonSessionCount, PLUID *LogonSessionList); +typedef NTSTATUS (NTAPI *pfLsaGetLogonSessionData)( + PLUID LogonId, PSECURITY_LOGON_SESSION_DATA *ppLogonSessionData); +typedef NTSTATUS (NTAPI *pfLsaFreeReturnBuffer)(PVOID Buffer); + + +// ---------------------------------------------------------------------------- +// Max len of device names returned by clean_dev_name(). +// Value taken from net.c load_net_config() and disk.c load_disk_config(). #define MAX_DEV_NAME 31 -#define PerfKeysSize 12 -typedef enum PerfKey_T -{ - CpuStart = 0, - CpuTime = 1, - CpuSysTime = 2, - NumProcesses = 3, - NumThreads = 4, - Uptime = 5, - NetDevStart = 6, - NetDevRecv = 7, - NetDevSend = 8, - DiskStart = 9, - DiskRead = 10, - DiskWrite = 11 -} PerfKey; +static PDH_HQUERY pdhQueryHandle = NULL; -//****************************************************************** - -/// List of perflib counter strings, they are i18ned inside windows -/// so we have to fetch them by index at startup (readPerfKeys()) -static TCHAR* perfKeyList[PerfKeysSize]; - -static HQUERY pdhQueryHandle = 0; -static HCOUNTER processCounter = NULL; -static HCOUNTER threadCounter = NULL; -static HCOUNTER uptimeCounter = NULL; - -static PDH_STATUS status; +static const wchar_t* PDHDLL = L"PDH.DLL"; +static const wchar_t* NTDLL = L"NTDLL.DLL"; // ---------------------------------------------------------------------------- -// CPU structures and variables -typedef struct _GK_CPU +// Own cleanup functions, called in gkrellm_sys_main_cleanup() to cleanup +// resources allocated by gkrellm_sys_*_init() + +static void gkrellm_sys_cpu_cleanup(void); +static void gkrellm_sys_disk_cleanup(void); +static void gkrellm_sys_mem_cleanup(void); +static void gkrellm_sys_net_cleanup(void); +static void gkrellm_sys_proc_cleanup(void); + + +// ---------------------------------------------------------------------------- + +//! print a warning and (if possible) decode a windows error number +static void +win32_warning(const wchar_t *dll_name, DWORD status, const gchar *format, ...) { - HCOUNTER total_pdh_counter; // total cpu = user cpu + sys cpu - HCOUNTER sys_pdh_counter; - gulong user; - gulong sys; - gulong idle; - } GK_CPU; -static GPtrArray *s_cpu_ptr_array = NULL; // ptr list of GK_CPU + va_list varargs; + wchar_t *status_msg = NULL; + gchar *formatted_msg = NULL; + HMODULE dll_handle = NULL; + DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS; -static -GK_CPU *gk_cpu_new() -{ - return g_new0(GK_CPU, 1); -} + va_start(varargs, format); + // Format passed message string + formatted_msg = g_strdup_vprintf(format, varargs); + va_end(varargs); -static -void gk_cpu_free(GK_CPU *cpu) -{ - g_free(cpu); -} - - -// ---------------------------------------------------------------------------- -// Disk structures and variables -typedef struct _GK_DISK + // Load library for message strings if one was passed + if (dll_name != NULL) { - HCOUNTER read_pdh_counter; - HCOUNTER write_pdh_counter; - gchar *name; - gulong read; - gulong write; - } GK_DISK; -static GPtrArray *s_disk_ptr_array = NULL; + dll_handle = LoadLibraryW(dll_name); + if (dll_handle != NULL) + flags |= FORMAT_MESSAGE_FROM_HMODULE; + } -static -GK_DISK *gk_disk_new() -{ - return g_new0(GK_DISK, 1); -} + if (FormatMessageW( + flags // dwFlags + , dll_handle // lpSource + , status // dwMessageId + , MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) // dwLanguageId + , (LPWSTR)&status_msg // lpBuffer + , 0 // nSize + , NULL // varargs + ) > 0) + { + g_log(NULL, G_LOG_LEVEL_WARNING, "%s; Error 0x%lX: %ls", + formatted_msg, status, status_msg); + LocalFree(status_msg); + } + else + { + g_log(NULL, G_LOG_LEVEL_WARNING, "%s; Error 0x%lX\n", + formatted_msg, status); + } -static -void gk_disk_free(GK_DISK *disk) -{ - g_free(disk->name); - g_free(disk); -} + g_free(formatted_msg); + if (dll_handle != NULL) + FreeLibrary(dll_handle); + } // ---------------------------------------------------------------------------- -// Network structures and variables -typedef struct _GK_NET +// Simple wrapper around PdhAddCounter with error/debug handling +static gboolean +add_counter(const wchar_t *counter_path, PDH_HCOUNTER *counter_handle) { - HCOUNTER recv_pdh_counter; - HCOUNTER send_pdh_counter; - gchar *name; - gulong recv; - gulong send; - } GK_NET; + PDH_STATUS st; -static GPtrArray *s_net_ptr_array = NULL; + if (pdhQueryHandle == NULL || !counter_path || !counter_handle) + return FALSE; + + st = PdhAddCounterW(pdhQueryHandle, counter_path, 0, counter_handle); + if (st != ERROR_SUCCESS) + { + win32_warning(PDHDLL, st, "Failed adding pdh-counter for path '%ls'", + counter_path); + return FALSE; + } + + gkrellm_debug(DEBUG_SYSDEP, "Added pdh-counter for path '%ls'\n", + counter_path); + return TRUE; + } + +static gboolean +get_formatted_counter_value( + PDH_HCOUNTER counter_handle, const gchar *counter_name, + DWORD format, PDH_FMT_COUNTERVALUE *val) + { + PDH_STATUS st; + + st = PdhGetFormattedCounterValue(counter_handle, format, NULL, val); + if ((st != ERROR_SUCCESS) || (val->CStatus != PDH_CSTATUS_VALID_DATA)) + { + win32_warning(PDHDLL, st, + "Getting pdh-counter (%s) failed; CStatus %lX", + counter_name, val->CStatus); + return FALSE; + } + return TRUE; + } + +// Simple wrapper around PdhLookupPerfNameByIndex with error handling +static gboolean +lookup_perfname(DWORD index, wchar_t *perfname, DWORD perfname_max_len) + { + PDH_STATUS st; + + st = PdhLookupPerfNameByIndexW(NULL, index, perfname, &perfname_max_len); + if (st != ERROR_SUCCESS) + { + win32_warning(PDHDLL, st, "Could not lookup perfname for index %d", + index); + return FALSE; + } + + gkrellm_debug(DEBUG_SYSDEP, "Looked up perfname '%ls' for index %d\n", + perfname, index); + return TRUE; + } + +typedef void (*add_counter_cb) (wchar_t *name, PDH_HCOUNTER *c1, PDH_HCOUNTER *c2); + +static void +add_counter_list(guint object_index, + guint counter_index1, guint counter_index2, + add_counter_cb cb) + { + PDH_STATUS st; + wchar_t obj_name[128]; + wchar_t c1_name[128]; + wchar_t c2_name[128]; + wchar_t * obj_list = NULL; + DWORD obj_list_size = 0; + wchar_t * inst_list = NULL; + DWORD inst_list_size = 0; + // Holds counter path, length is 128 + 128 + 4 + strlen(instance) + wchar_t counter_path[768]; + wchar_t * inst = NULL; + PDH_HCOUNTER c1; + PDH_HCOUNTER c2; + + gkrellm_debug(DEBUG_SYSDEP, "add_counter_list()\n"); + if (pdhQueryHandle == NULL) + return; + + // Get translated name for object_index + if (!lookup_perfname(object_index, obj_name, 128)) + return; + + if (!lookup_perfname(counter_index1, c1_name, 128)) + return; + + if (!lookup_perfname(counter_index2, c2_name, 128)) + return; + + // Get number of counters/instances that can be queried + st = PdhEnumObjectItemsW(NULL, NULL, obj_name, + NULL, &obj_list_size, + NULL, &inst_list_size, + PERF_DETAIL_WIZARD, 0); + + if ((st != PDH_MORE_DATA) && (st != ERROR_SUCCESS)) + { + // Either no data at all or other error + win32_warning(PDHDLL, st, + "Failed to get pdh-counter count for object '%ls'", obj_name); + return; + } + + // Do nothing if there's no counters + if (inst_list_size == 0) + return; + + // Allocate buffers to hold object and instance names + ++obj_list_size; + obj_list = (wchar_t *)malloc(sizeof(wchar_t) * obj_list_size); + + ++inst_list_size; + inst_list = (wchar_t *)malloc(sizeof(wchar_t) * inst_list_size); + + // Get actual information about counters + st = PdhEnumObjectItemsW(NULL, NULL, obj_name, + obj_list, &obj_list_size, + inst_list, &inst_list_size, + PERF_DETAIL_WIZARD, 0); + if (st != ERROR_SUCCESS) + { + // Either no data at all or other error + win32_warning(PDHDLL, st, + "Failed to enumerate pdh-counters for object '%ls'", obj_name); + } + else + { + for (inst = inst_list; *inst != 0; inst += wcslen(inst) + 1) + { + // Ignore total counter, gkrellm provides that functionality + if (wcsnicmp(L"_Total", inst, 6) == 0) + continue; + + // "\Disks(DiskOne)\ReadBytes" + _snwprintf(counter_path, sizeof(counter_path) / sizeof(wchar_t), + L"\\%ls(%ls)\\%ls", + obj_name, inst, c1_name); + add_counter(counter_path, &c1); + + // "\Disks(DiskOne)\WriteBytes" + _snwprintf(counter_path, sizeof(counter_path) / sizeof(wchar_t), + L"\\%ls(%ls)\\%ls", + obj_name, inst, c2_name); + add_counter(counter_path, &c2); + + if (c1 && c2) + cb(inst, &c1, &c2); + } + } + free(obj_list); + free(inst_list); + } static -GK_NET *gk_net_new() +gchar *clean_dev_name(const wchar_t *name) { - return g_new0(GK_NET, 1); + gchar *clean_name; + gchar *p; + + clean_name = g_utf16_to_utf8(name, -1, NULL, NULL, NULL); + //FIXME: handle clean_name being NULL + + p = clean_name; + while (*p) + { + p = g_utf8_next_char(p); + if (*p == ' ' || *p == '\t') + *p = '_'; + } + + // limit length of device name, gkrellm can't handle longer names :( + if (strlen(clean_name) > MAX_DEV_NAME) + clean_name[MAX_DEV_NAME] = '\0'; + + return clean_name; } -static -void gk_net_free(GK_NET *net) -{ - g_free(net->name); - g_free(net); -} - - -// ---------------------------------------------------------------------------- -// local function prototypes -static void initPerfKeyList(void); - -static void placePerfKeysFromReg(const PerfKey key, unsigned int index1, - unsigned int index2); - -static void placePerfKeyFromReg(const PerfKey key, unsigned int index, - const TCHAR* prefix, const TCHAR* suffix); - -static void placePerfKey(const PerfKey key, const TCHAR* value); - // ---------------------------------------------------------------------------- void gkrellm_sys_main_init(void) { + PDH_STATUS st; WSADATA wsdata; int err; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Starting Winsock\n"); + gkrellm_debug(DEBUG_SYSDEP, "Starting Winsock\n"); err = WSAStartup(MAKEWORD(1,1), &wsdata); if (err != 0) - { - g_printerr("Starting Winsock failed with error code %i\n", err); - return; - } + g_warning("Starting Winsock failed with error code %d\n", err); - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Opening PDH query\n"); - status = PdhOpenQuery(NULL, 0, &pdhQueryHandle); - if (status != ERROR_SUCCESS || pdhQueryHandle == 0) + gkrellm_debug(DEBUG_SYSDEP, "Opening PDH query\n"); + st = PdhOpenQueryW(NULL, 0, &pdhQueryHandle); + if ((st != ERROR_SUCCESS) || (pdhQueryHandle == NULL)) { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Opening pdh-query failed with error code %lu\n", status); + win32_warning(PDHDLL, st, "Opening PDH query failed"); pdhQueryHandle = 0; } - // get perflib localized key names - initPerfKeyList(); - - s_cpu_ptr_array = g_ptr_array_new(); - s_disk_ptr_array = g_ptr_array_new(); - s_net_ptr_array = g_ptr_array_new(); // we don't have local mail on Windows (yet?) gkrellm_mail_local_unsupported(); @@ -251,78 +384,56 @@ void gkrellm_sys_main_init(void) void gkrellm_sys_main_cleanup(void) -{ - int i; -#if defined(WIN32_CLIENT) - NOTIFYICONDATA nid; - // remove system tray icon - nid.cbSize = sizeof(NOTIFYICONDATA); - nid.hWnd = GDK_WINDOW_HWND(gkrellm_get_top_window()->window); - nid.uID = 1; - Shell_NotifyIcon(NIM_DELETE, &nid); -#endif // WIN32_CLIENT + { + int i; + PDH_STATUS st; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Waiting for mail checking thread to end.\n"); + gkrellm_debug(DEBUG_SYSDEP, "Waiting for mail checking thread to end.\n"); + i = 0; + while (gkrellm_mail_get_active_thread() != NULL && (i++ < 120)) + { + // wait here till it finishes + // in case we are trying to get mail info + g_usleep(G_USEC_PER_SEC); // 1 second wait + } - while (gkrellm_mail_get_active_thread() != NULL) - { - // wait here till it finishes - // in case we are trying to get mail info - g_usleep(G_USEC_PER_SEC / 2); // 500msec wait - } + // Close PDH query-handle + gkrellm_debug(DEBUG_SYSDEP, "Closing PDH query\n"); + st = PdhCloseQuery(pdhQueryHandle); + if (st != ERROR_SUCCESS) + win32_warning(PDHDLL, st, "Closing PDH query handle failed"); + pdhQueryHandle = NULL; - // Close PDH query-handle - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Closing PDH query\n"); - PdhCloseQuery(pdhQueryHandle); + gkrellm_sys_cpu_cleanup(); + gkrellm_sys_disk_cleanup(); + gkrellm_sys_net_cleanup(); + gkrellm_sys_proc_cleanup(); + gkrellm_sys_mem_cleanup(); - // free up these strings - for (i = 0; i < PerfKeysSize; i++) - free(perfKeyList[i]); - - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Freeing counters for %u cpus\n", s_cpu_ptr_array->len); - for (i = 0; i < s_cpu_ptr_array->len; i++) - gk_cpu_free(g_ptr_array_index(s_cpu_ptr_array, i)); - g_ptr_array_free(s_cpu_ptr_array, TRUE); - - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Freeing counters for %u disks\n", s_disk_ptr_array->len); - for (i = 0; i < s_disk_ptr_array->len; i++) - gk_disk_free(g_ptr_array_index(s_disk_ptr_array, i)); - g_ptr_array_free(s_disk_ptr_array, TRUE); - - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Freeing counters for %u network adapters\n", s_net_ptr_array->len); - for (i = 0; i < s_net_ptr_array->len; i++) - gk_net_free(g_ptr_array_index(s_net_ptr_array, i)); - g_ptr_array_free(s_net_ptr_array, TRUE); - - // stop winsock - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Closing Winsock\n"); - WSACleanup(); -} + gkrellm_debug(DEBUG_SYSDEP, "Closing Winsock\n"); + i = WSACleanup(); + if (i != 0) + g_warning("Stopping Winsock failed, error %d\n", i); + } // only need to collect pdhQueryHandle data once for all those monitors that use it -static void win32_read_proc_stat(void) +static +void win32_read_proc_stat(void) { - static gint data_read_tick = -1; + static gint s_data_read_tick = -1; + PDH_STATUS st; - if (pdhQueryHandle == 0) + if (pdhQueryHandle == NULL) return; - if (data_read_tick == gkrellm_get_timer_ticks()) /* One read per tick */ + if (s_data_read_tick == gkrellm_get_timer_ticks()) // One read per tick return; - data_read_tick = gkrellm_get_timer_ticks(); + s_data_read_tick = gkrellm_get_timer_ticks(); - /*if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Collecting PDH query data\n");*/ - - status = PdhCollectQueryData(pdhQueryHandle); - if (status != ERROR_SUCCESS) - g_print("Collecting PDH query data failed with status %lu\n", status); + gkrellm_debug(DEBUG_SYSDEP, "Collecting PDH query data\n"); + st = PdhCollectQueryData(pdhQueryHandle); + if (st != ERROR_SUCCESS) + win32_warning(PDHDLL, st, "Failed to collect PDH query data"); } @@ -330,23 +441,58 @@ static void win32_read_proc_stat(void) /* Sensor interface */ /* ===================================================================== */ -// interface to work with shared memory for MBM5 +#define MBM_INTERFACE 1 /* MotherBoardMonitor 5 */ +#define SF_INTERFACE 2 /* SpeedFan */ +#define CT_INTERFACE 3 /* CoreTemp */ + +static +HANDLE gkrellm_sys_sensors_open_shm_helper(const wchar_t *shm_name, + const gchar *app_name) +{ + HANDLE hData = NULL; + gboolean ret; + GError *err = NULL; + + // Try to open shm-file and return if successful + hData = OpenFileMappingW(FILE_MAP_READ, FALSE, shm_name); + if (hData != 0) + return hData; + + // shm-file could not be opened, try to start sensor-app + ret = g_spawn_command_line_async(app_name, &err); + if (!ret && err) + { + g_warning("Could not start sensor-app %s: %s\n", + app_name, err->message); + g_error_free(err); + } + else + { + gkrellm_debug(DEBUG_SYSDEP, + "Started sensor-app %s, waiting for it to initialize\n", + app_name); + // 5 second wait to allow sensor-app init + g_usleep(5 * G_USEC_PER_SEC); + // Retry open of shm-file + hData = OpenFileMappingW(FILE_MAP_READ, FALSE, shm_name); + } + return hData; +} // --------------------------------------------------------------------------- -// --------------------------------------- Copyright 2001 A@majland.org ------ -// --------------------------------------- Alteration for use in Visual C ---- -// --------------------------------------- By Chris Zahrt techn0@iastate.edu - -// --------------------------------------------------------------------------- +// Interface to work with shared memory for MBM5 +// +// Copyright 2001 A@majland.org +// Alteration for use in Visual C by Chris Zahrt techn0@iastate.edu // // Version : 0.1 // Date : 02-27-2002 -// // MBM : version 5.1 // -// Author : Chris Zahrt techn0@iastate.edu (visual c alterations) -// http://techn0.dhs.org/programming/vcmbmsm.html -// Anders@Majland.org (author of original c code) -// http://www.majland.org/sw/mbmcaf +// Author : - Anders@Majland.org (author of original c code) +// http://www.majland.org/sw/mbmcaf +// - Chris Zahrt techn0@iastate.edu (visual c alterations) +// http://techn0.dhs.org/programming/vcmbmsm.html // // Licence : Cardware. (Send me a note/email if you find it usefull.) // Basically you may use it as you see fit as long as the origin @@ -354,155 +500,176 @@ static void win32_read_proc_stat(void) // // History : // 0.1 02-27-2002 conversion of 0.3 borland to this version - +// // Update for MBM 5.1.9 by Bill Nalen bill@nalens.com - // --------------------------------------------------------------------------- -#define NrTemperature 32 -#define NrVoltage 16 -#define NrFan 16 -#define NrCPU 4 - -static double temperatures[NrTemperature]; -static int tempCount; -static double voltages[NrVoltage]; -static int voltCount; -static double fans[NrFan]; -static int fanCount; - -#define BusType char +#define BusType char #define SMBType char - #define SensorType char -#define stUnknown 0 -#define stTemperature 1 -#define stVoltage 2 -#define stFan 3 -#define stMhz 4 -#define stPercentage 5 +#define stUnknown (char)(0) +#define stTemperature (char)(1) +#define stVoltage (char)(2) +#define stFan (char)(3) +//#define stMhz (char)(4) +//#define stPercentage (char)(5) typedef struct { - SensorType iType; // type of sensor - int Count; // number of sensor for that type -} SharedIndex; + SensorType iType; // type of sensor + int Count; // number of sensor for that type +} MBMSharedIndex; typedef struct { - SensorType ssType; // type of sensor - unsigned char ssName[12]; // name of sensor - char sspadding1[3]; // padding of 3 byte - double ssCurrent; // current value - double ssLow; // lowest readout - double ssHigh; // highest readout - long ssCount; // total number of readout - char sspadding2[4]; // padding of 4 byte - long double ssTotal; // total amout of all readouts - char sspadding3[6]; // padding of 6 byte - double ssAlarm1; // temp & fan: high alarm; voltage: % off; - double ssAlarm2; // temp: low alarm -} SharedSensor; + SensorType ssType; // type of sensor + unsigned char ssName[12]; // name of sensor + char sspadding1[3]; // padding of 3 byte + double ssCurrent; // current value + double ssLow; // lowest readout + double ssHigh; // highest readout + long ssCount; // total number of readout + char sspadding2[4]; // padding of 4 byte + long double ssTotal; // total amout of all readouts + char sspadding3[6]; // padding of 6 byte + double ssAlarm1; // temp & fan: high alarm; voltage: % off; + double ssAlarm2; // temp: low alarm +} MBMSharedSensor; typedef struct { - short siSMB_Base; // SMBus base address - BusType siSMB_Type; // SMBus/Isa bus used to access chip - SMBType siSMB_Code; // SMBus sub type, Intel, AMD or ALi - char siSMB_Addr; // Address of sensor chip on SMBus - unsigned char siSMB_Name[41]; // Nice name for SMBus - short siISA_Base; // ISA base address of sensor chip on ISA - int siChipType; // Chip nr, connects with Chipinfo.ini - char siVoltageSubType; // Subvoltage option selected -} SharedInfo; + short siSMB_Base; // SMBus base address + BusType siSMB_Type; // SMBus/Isa bus used to access chip + SMBType siSMB_Code; // SMBus sub type, Intel, AMD or ALi + char siSMB_Addr; // Address of sensor chip on SMBus + unsigned char siSMB_Name[41]; // Nice name for SMBus + short siISA_Base; // ISA base address of sensor chip on ISA + int siChipType; // Chip nr, connects with Chipinfo.ini + char siVoltageSubType; // Subvoltage option selected +} MBMSharedInfo; typedef struct { - double sdVersion; // version number (example: 51090) - SharedIndex sdIndex[10]; // Sensor index - SharedSensor sdSensor[100]; // sensor info - SharedInfo sdInfo; // misc. info - unsigned char sdStart[41]; // start time - unsigned char sdCurrent[41]; // current time - unsigned char sdPath[256]; // MBM path -} SharedData; + double sdVersion; // version number (example: 51090) + MBMSharedIndex sdIndex[10]; // Sensor index + MBMSharedSensor sdSensor[100]; // sensor info + MBMSharedInfo sdInfo; // misc. info + unsigned char sdStart[41]; // start time + unsigned char sdCurrent[41]; // current time + unsigned char sdPath[256]; // MBM path +} MBMSharedData; +static const wchar_t* MBM_SHM_NAME = L"$M$B$M$5$S$D$"; +static const gchar* MBM_EXE_NAME = "MBM5.exe"; -static gboolean ReadMBMSharedData(void); -static gboolean ReadSFSharedData(void); - - -static gboolean ReadSharedData(void) - { - static gint sens_data_read_tick = -1; - static gboolean sens_data_valid = FALSE; - - if (sens_data_read_tick == gkrellm_get_timer_ticks()) /* One read per tick */ - return sens_data_valid; - sens_data_read_tick = gkrellm_get_timer_ticks(); - - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Reading MBM or SpeedFan data\n"); - - // Try getting data from MBM - sens_data_valid = ReadMBMSharedData(); - - // Try SpeedFan in case MBM is absent - if (!sens_data_valid) - sens_data_valid = ReadSFSharedData(); - - return sens_data_valid; - } // ReadSharedData() - - -static gboolean ReadMBMSharedData(void) +static SensorType gkrellm_sensor_type_to_mbm(gint type) { - SharedData *ptr; - SharedSensor *sens; - HANDLE hSData; - int i, j; - int totalCount; + if (type == SENSOR_TEMPERATURE) + return stTemperature; + if (type == SENSOR_VOLTAGE) + return stVoltage; + if (type == SENSOR_FAN) + return stFan; + return stUnknown; +} - hSData=OpenFileMapping(FILE_MAP_READ, FALSE, _T("$M$B$M$5$S$D$")); - if (hSData == 0) - return FALSE; +static gboolean +gkrellm_sys_sensors_mbm_get_value(gint sensor_id, gint sensor_type, gfloat *value) +{ + HANDLE hData; + MBMSharedData *pData; + MBMSharedSensor *pSensor; + gboolean ret = FALSE; + SensorType st = gkrellm_sensor_type_to_mbm(sensor_type); - ptr = (SharedData *)MapViewOfFile(hSData, FILE_MAP_READ, 0, 0, 0); - if (ptr == 0) - { - CloseHandle(hSData); + if (st == stUnknown || sensor_id < 0 || sensor_id > 99) + return FALSE; // id out of range + + hData = OpenFileMappingW(FILE_MAP_READ, FALSE, MBM_SHM_NAME); + if (hData == 0) return FALSE; + pData = (MBMSharedData *)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (pData != NULL) + { + gkrellm_debug(DEBUG_SYSDEP, "Fetching sensor value %d from MBM\n", sensor_id); + pSensor = &(pData->sdSensor[sensor_id]); + if (pSensor->ssType == st) + { + *value = pSensor->ssCurrent; + ret = TRUE; + } + UnmapViewOfFile(pData); + } + CloseHandle(hData); + return ret; } - totalCount = 0; - for (i = 0; i < 5; i++) - { - totalCount += ptr->sdIndex[i].Count; - } +static gboolean +gkrellm_sys_sensors_mbm_init(void) +{ + HANDLE hData; + MBMSharedData *pData; + MBMSharedSensor *pSensor; + gboolean ret = FALSE; + gint i, sensorCount, tempCount, voltCount, fanCount; + gchar *id_name; - tempCount = 0; - voltCount = 0; - fanCount = 0; - for (j = 0; j < totalCount; j++) + hData = gkrellm_sys_sensors_open_shm_helper(MBM_SHM_NAME, MBM_EXE_NAME); + if (hData == 0) + return FALSE; + pData = (MBMSharedData *)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (pData != NULL) { - sens = &(ptr->sdSensor[j]); - switch (sens->ssType) + ret = TRUE; // MBM available, return TRUE + + sensorCount = 0; + for (i = 0; i < 9; i++) + sensorCount += pData->sdIndex[i].Count; + + tempCount = 0; + voltCount = 0; + fanCount = 0; + for (i = 0; i < sensorCount; i++) { - case stTemperature: - temperatures[tempCount] = sens->ssCurrent; - ++tempCount; - break; - case stVoltage: - voltages[voltCount] = sens->ssCurrent; - ++voltCount; - break; - case stFan: - fans[fanCount] = sens->ssCurrent; - ++fanCount; - break; - default: - break; - } + pSensor = &(pData->sdSensor[i]); + switch (pSensor->ssType) + { + case stTemperature: + id_name = g_strdup_printf("mbm-temp-%d", tempCount); + + gkrellm_sensors_add_sensor(SENSOR_TEMPERATURE, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/i, /*iodev*/0, + /*inter*/MBM_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/pSensor->ssName); + + g_free(id_name); + ++tempCount; + break; + case stVoltage: + id_name = g_strdup_printf("mbm-volt-%d", voltCount); + + gkrellm_sensors_add_sensor(SENSOR_VOLTAGE, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/i, /*iodev*/0, + /*inter*/MBM_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/pSensor->ssName); + + g_free(id_name); + ++voltCount; + break; + case stFan: + id_name = g_strdup_printf("mbm-fan-%d", fanCount); + + gkrellm_sensors_add_sensor(SENSOR_FAN, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/i, /*iodev*/0, + /*inter*/MBM_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/pSensor->ssName); + + g_free(id_name); + fanCount++; + break; + } /* switch() */ + } /* for() */ + + UnmapViewOfFile(pData); } - UnmapViewOfFile(ptr); - CloseHandle(hSData); - return TRUE; + CloseHandle(hData); + return ret; } @@ -526,128 +693,288 @@ typedef struct } SFSharedMemory; #pragma pack(pop) +static const wchar_t* SPEEDFAN_SHM_NAME = L"SFSharedMemory_ALM"; +static const gchar* SPEEDFAN_EXE_NAME = "speedfan.exe"; -static gboolean ReadSFSharedData(void) - { - SFSharedMemory *ptr; - HANDLE hSData; - int i; +static gboolean +gkrellm_sys_sensors_sf_get_value(gint sensor_id, gint sensor_type, gfloat *value) +{ + HANDLE hData; + SFSharedMemory *pData; + gboolean ret = FALSE; - hSData = OpenFileMapping(FILE_MAP_READ, FALSE, TEXT("SFSharedMemory_ALM")); - if (hSData == 0) - return FALSE; - - ptr = (SFSharedMemory *)MapViewOfFile(hSData, FILE_MAP_READ, 0, 0, 0); - if (ptr == 0) - { - g_printerr("Could not map SpeedFan SHM data\n"); - CloseHandle(hSData); + if (sensor_id < 0 || sensor_id > 31) + return FALSE; // id out of range + + hData = OpenFileMappingW(FILE_MAP_READ, FALSE, SPEEDFAN_SHM_NAME); + if (hData == 0) return FALSE; + pData = (SFSharedMemory *)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (pData != NULL) + { + gkrellm_debug(DEBUG_SYSDEP, "Fetching sensor value %d from SpeedFan\n", sensor_id); + switch(sensor_type) + { + case SENSOR_TEMPERATURE: + if (sensor_id < pData->NumTemps) + { + *value = pData->temps[sensor_id] / 100.0; + ret = TRUE; + } + break; + case SENSOR_VOLTAGE: + if (sensor_id < pData->NumVolts) + { + *value = pData->volts[sensor_id] / 100.0; + ret = TRUE; + } + break; + case SENSOR_FAN: + if (sensor_id < pData->NumFans) + { + *value = pData->fans[sensor_id]; + ret = TRUE; + } + break; + } + UnmapViewOfFile(pData); + } + CloseHandle(hData); + return ret; } - tempCount = min(NrTemperature, ptr->NumTemps); - for (i = 0; i < tempCount; i++) - temperatures[i] = ptr->temps[i] / 100.0; +static gboolean +gkrellm_sys_sensors_sf_init(void) + { + HANDLE hData; + SFSharedMemory *pData; + gboolean ret = FALSE; + gint i; + gchar *id_name; + gchar *default_label; - voltCount = min(NrVoltage, ptr->NumVolts); - for (i = 0; i < voltCount; i++) - voltages[i] = ptr->volts[i] / 100.0; + hData = gkrellm_sys_sensors_open_shm_helper(SPEEDFAN_SHM_NAME, SPEEDFAN_EXE_NAME); + if (hData == 0) + return FALSE; + pData = (SFSharedMemory *)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (pData != NULL) + { + ret = TRUE; // Mark SpeedFan as available - fanCount = min(NrFan, ptr->NumFans); - for (i = 0; i < fanCount; i++) - fans[i] = ptr->fans[i]; + for (i = 0; i < pData->NumTemps; i++) + { + id_name = g_strdup_printf("speedfan-temp-%d", i); + default_label = g_strdup_printf("Temp %d", i+1); - UnmapViewOfFile(ptr); - CloseHandle(hSData); - return TRUE; + gkrellm_sensors_add_sensor(SENSOR_TEMPERATURE, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/i, /*iodev*/0, + /*inter*/SF_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/default_label); + + g_free(id_name); + g_free(default_label); + } + + for (i = 0; i < pData->NumVolts; i++) + { + id_name = g_strdup_printf("speedfan-volt-%d", i); + default_label = g_strdup_printf("Voltage %d", i+1); + + gkrellm_sensors_add_sensor(SENSOR_VOLTAGE, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/i, /*iodev*/0, + /*inter*/SF_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/default_label); + + g_free(id_name); + g_free(default_label); + } + + for (i = 0; i < pData->NumFans; i++) + { + id_name = g_strdup_printf("speedfan-fan-%d", i); + default_label = g_strdup_printf("Fan %d", i+1); + + gkrellm_sensors_add_sensor(SENSOR_FAN, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/i, /*iodev*/0, + /*inter*/SF_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/default_label); + + g_free(id_name); + g_free(default_label); + } + + UnmapViewOfFile(pData); + } + CloseHandle(hData); + return ret; + } + + +/* ======================================================================== */ +// CoreTemp + +/** + * ucFahrenheit and ucDeltaToTjMax represent boolean values. 0 = false, 1 = true. + * If ucFahrenheit is set, the temperature is reported in Fahrenheit. + * If ucDeltaToTjMax is set, the temperature reported respresents the distance + * from TjMax. + * + * Information and struct taken from + * http://www.alcpu.com/CoreTemp/developers.html +**/ +typedef struct core_temp_shared_data +{ + unsigned int uiLoad[256]; + unsigned int uiTjMax[128]; + unsigned int uiCoreCnt; + unsigned int uiCPUCnt; + float fTemp[256]; + float fVID; + float fCPUSpeed; + float fFSBSpeed; + float fMultipier; + char sCPUName[100]; + unsigned char ucFahrenheit; + unsigned char ucDeltaToTjMax; +} CORE_TEMP_SHARED_DATA; + +static const wchar_t* CORE_TEMP_SHM_NAME = L"CoreTempMappingObject"; +static const gchar* CORE_TEMP_EXE_NAME = "CoreTemp.exe"; + +static gboolean +gkrellm_sys_sensors_ct_get_temp(guint core_index, guint cpu_index, gfloat *temp) + { + HANDLE hData; + CORE_TEMP_SHARED_DATA *pData; + gboolean ret = FALSE; + guint temp_index; + + if (core_index < 0 || core_index > 255 || cpu_index < 0 || cpu_index > 127) + return FALSE; // core or cpu index out of range + + hData = OpenFileMappingW(FILE_MAP_READ, FALSE, CORE_TEMP_SHM_NAME); + if (hData == 0) + return FALSE; + pData = (CORE_TEMP_SHARED_DATA *)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (pData != NULL) + { + gkrellm_debug(DEBUG_SYSDEP, + "Fetching temp for core %d, cpu %d from CoreTemp\n", core_index, + cpu_index); + + // 'core index' + ( 'cpu index' * 'number of cores per cpu' ) + temp_index = core_index + (cpu_index * pData->uiCoreCnt); + + // make absolute value from delta + if (pData->ucDeltaToTjMax == '\1') + *temp = pData->uiTjMax[cpu_index] - pData->fTemp[temp_index]; + else + *temp = pData->fTemp[temp_index]; + + // Convert Fahrenheit to Celsius + if (pData->ucFahrenheit == '\1') + *temp = (*temp - 32) * 5 / 9; + + UnmapViewOfFile(pData); + } + CloseHandle(hData); + return ret; + } + +static gboolean +gkrellm_sys_sensors_ct_init(void) + { + HANDLE hData; + CORE_TEMP_SHARED_DATA *pData; + gboolean ret = FALSE; + guint uiCpu; + guint uiCore; + gchar *id_name; + gchar *default_label; + + hData = gkrellm_sys_sensors_open_shm_helper(CORE_TEMP_SHM_NAME, CORE_TEMP_EXE_NAME); + if (hData == 0) + return FALSE; + pData = (CORE_TEMP_SHARED_DATA *)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (pData != NULL) + { + ret = TRUE; // Mark CoreTemp as available + + for (uiCpu = 0; uiCpu < pData->uiCPUCnt; uiCpu++) + { + for (uiCore = 0; uiCore < pData->uiCoreCnt; uiCore++) + { + id_name = g_strdup_printf("coretemp-cpu%u-core%u", uiCpu, uiCore); + if (pData->uiCPUCnt == 1) + default_label = g_strdup_printf("CPU Core %u", uiCore+1); + else + default_label = g_strdup_printf("CPU %u, Core %u", uiCpu+1, uiCore+1); + + gkrellm_sensors_add_sensor(SENSOR_TEMPERATURE, /*sensor_path*/NULL, + /*id_name*/id_name, /*id*/uiCore, /*iodev*/uiCpu, + /*inter*/CT_INTERFACE, /*factor*/1, /*offset*/0, + /*vref*/NULL, /*default_label*/default_label); + + g_free(id_name); + g_free(default_label); + } + } + UnmapViewOfFile(pData); + } + CloseHandle(hData); + return ret; } /* ======================================================================== */ - -gboolean gkrellm_sys_sensors_get_voltage(gchar *device_name, gint id, +gboolean +gkrellm_sys_sensors_get_voltage(gchar *device_name, gint id, gint iodev, gint inter, gfloat *volt) { - *volt = 0; - if (iodev < 0 || iodev >= NrVoltage) - return FALSE; - if (ReadSharedData() == FALSE) - return FALSE; - *volt = voltages[iodev]; - return TRUE; + if (inter == MBM_INTERFACE) + return gkrellm_sys_sensors_mbm_get_value(id, SENSOR_VOLTAGE, volt); + if (inter == SF_INTERFACE) + return gkrellm_sys_sensors_sf_get_value(id, SENSOR_VOLTAGE, volt); + return FALSE; } -gboolean gkrellm_sys_sensors_get_fan(gchar *device_name, gint id, +gboolean +gkrellm_sys_sensors_get_fan(gchar *device_name, gint id, gint iodev, gint inter, gfloat *fan) { - *fan = 0; - if (iodev >= NrFan || iodev < 0) - return FALSE; - if (ReadSharedData() == FALSE) - return FALSE; - *fan = fans[iodev]; - return TRUE; + if (inter == MBM_INTERFACE) + return gkrellm_sys_sensors_mbm_get_value(id, SENSOR_FAN, fan); + if (inter == SF_INTERFACE) + return gkrellm_sys_sensors_sf_get_value(id, SENSOR_FAN, fan); + return FALSE; } -gboolean gkrellm_sys_sensors_get_temperature(gchar *device_name, gint id, +gboolean +gkrellm_sys_sensors_get_temperature(gchar *device_name, gint id, gint iodev, gint inter, gfloat *temp) { - *temp = 0; - if (iodev >= NrTemperature || iodev < 0) - return FALSE; - if (ReadSharedData() == FALSE) - return FALSE; - *temp = temperatures[iodev]; - return TRUE; + if (inter == MBM_INTERFACE) + return gkrellm_sys_sensors_mbm_get_value(id, SENSOR_TEMPERATURE, temp); + if (inter == SF_INTERFACE) + return gkrellm_sys_sensors_sf_get_value(id, SENSOR_TEMPERATURE, temp); + if (inter == CT_INTERFACE) + return gkrellm_sys_sensors_ct_get_temp((guint)id, (guint)iodev, temp); + return FALSE; } -gboolean gkrellm_sys_sensors_init(void) +gboolean +gkrellm_sys_sensors_init(void) { - char buf[25]; - int i; + gboolean init_ok = FALSE; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT sensors\n"); + gkrellm_debug(DEBUG_SYSDEP, "INIT sensors\n"); + init_ok |= gkrellm_sys_sensors_sf_init(); + init_ok |= gkrellm_sys_sensors_ct_init(); + init_ok |= gkrellm_sys_sensors_mbm_init(); - //TODO: determine number of sensors at startup? This could cause - // user confusion in case mbm/speedfan is started after gkrellm - tempCount = 0; - voltCount = 0; - fanCount = 0; - - for (i = 0; i < NrTemperature; i++) - { - //TODO: i18n? - snprintf(buf, sizeof(buf), "Temp %i", i); - gkrellm_sensors_add_sensor(SENSOR_TEMPERATURE, NULL, buf, tempCount, - tempCount, 0, 1, 0, NULL, buf); - ++tempCount; - } - - for (i = 0; i < NrVoltage; i++) - { - snprintf(buf, sizeof(buf), "Volt %i", i); - gkrellm_sensors_add_sensor(SENSOR_VOLTAGE, NULL, buf, voltCount, - voltCount, 0, 1, 0, NULL, buf); - ++voltCount; - } - - for (i = 0; i < NrFan; i++) - { - snprintf(buf, sizeof(buf), "Fan %i", i); - gkrellm_sensors_add_sensor(SENSOR_FAN, NULL, buf, fanCount, fanCount, - 0, 1, 0, NULL, buf); - ++fanCount; - } - - if (_GK.debug_level & DEBUG_SYSDEP) - { - g_print("Initialized sensors for %i temps, %i volts and %i fans.\n", - tempCount, voltCount, fanCount); - } - - return TRUE; + // returns true if at least one sensors interface has been found + return init_ok; } @@ -655,284 +982,268 @@ gboolean gkrellm_sys_sensors_init(void) /* CPU monitor interface */ /* ===================================================================== */ - -void gkrellm_sys_cpu_read_data(void) +typedef struct _GK_CPU { - //DWORD type; - PDH_FMT_COUNTERVALUE userVal; - PDH_FMT_COUNTERVALUE sysVal; + PDH_HCOUNTER total_pdh_counter; + PDH_HCOUNTER sys_pdh_counter; + gulong user; + gulong sys; + gulong idle; + } GK_CPU; + +static GPtrArray *s_cpu_ptr_array = NULL; + +void +gkrellm_sys_cpu_read_data(void) + { + PDH_FMT_COUNTERVALUE tot; + PDH_FMT_COUNTERVALUE sys; gint i; GK_CPU *cpu; - if (pdhQueryHandle == 0) + if (pdhQueryHandle == NULL) return; - win32_read_proc_stat(); // eventually fetch new pdh data + gkrellm_debug(DEBUG_SYSDEP, "Reading cpu data for %d CPUs\n", + s_cpu_ptr_array->len); for (i = 0; i < s_cpu_ptr_array->len; i++) { - cpu = g_ptr_array_index(s_cpu_ptr_array, i); + cpu = (GK_CPU *)g_ptr_array_index(s_cpu_ptr_array, i); - status = PdhGetFormattedCounterValue(cpu->total_pdh_counter, PDH_FMT_LONG, NULL, &userVal); - if (status != ERROR_SUCCESS) - { - g_print("Getting PDH-counter (cpu total time) failed with status %lu\n", status); + if (!get_formatted_counter_value(cpu->total_pdh_counter, "cpu total time", PDH_FMT_LONG, &tot)) return; - } - status = PdhGetFormattedCounterValue(cpu->sys_pdh_counter, PDH_FMT_LONG, NULL, &sysVal); - if (status != ERROR_SUCCESS) - { - g_print("Getting PDH-counter (cpu sys time) failed with status %lu\n", status); + if (!get_formatted_counter_value(cpu->sys_pdh_counter, "cpu system time", PDH_FMT_LONG, &sys)) return; - } - // user time defined as total - system - userVal.longValue -= sysVal.longValue; - - cpu->user += userVal.longValue; - cpu->sys += sysVal.longValue; - cpu->idle += (100 - userVal.longValue - sysVal.longValue); + // user time = (total time - system time) + cpu->user += (tot.longValue - sys.longValue); + cpu->sys += sys.longValue; + // idle time = 100% - total time - system time + cpu->idle += (100 - tot.longValue - sys.longValue); gkrellm_cpu_assign_data(i, cpu->user, 0 /*nice*/, cpu->sys, cpu->idle); } - } /* gkrellm_sys_cpu_read_data() */ + } +static void +gkrellm_sys_cpu_add_cb(wchar_t *name, PDH_HCOUNTER *total, PDH_HCOUNTER *sys) +{ + GK_CPU *cpu; -gboolean gkrellm_sys_cpu_init(void) + gkrellm_debug(DEBUG_SYSDEP, "Adding CPU '%ls'\n", name); + + cpu = g_new0(GK_CPU, 1); + cpu->total_pdh_counter = *total; + cpu->sys_pdh_counter = *sys; + g_ptr_array_add(s_cpu_ptr_array, cpu); +} + +gboolean +gkrellm_sys_cpu_init(void) { - SYSTEM_INFO sysInfo; - DWORD i; - TCHAR pdh_path[PDH_MAX_COUNTER_PATH]; - TCHAR num_str[11]; - GK_CPU* cpu; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT cpu monitoring\n"); + gkrellm_debug(DEBUG_SYSDEP, "INIT CPU Monitoring\n"); + + s_cpu_ptr_array = g_ptr_array_new(); gkrellm_cpu_nice_time_unsupported(); - GetSystemInfo(&sysInfo); // fetch number of processors/cores - if (pdhQueryHandle != 0 && perfKeyList[CpuStart] != NULL && perfKeyList[CpuTime] != NULL) - { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Allocating counters for %ld CPUs\n", sysInfo.dwNumberOfProcessors); - for (i = 0; i < sysInfo.dwNumberOfProcessors; i++) - { - cpu = gk_cpu_new(); - _itot(i, num_str, 10); + add_counter_list( + 238 // object_index + , 6 // counter_index1, cpu time + , 144 // counter_index2, system time + , gkrellm_sys_cpu_add_cb); - _tcscpy(pdh_path, perfKeyList[CpuStart]); - _tcscat(pdh_path, num_str); - _tcscat(pdh_path, perfKeyList[CpuTime]); - status = PdhAddCounter(pdhQueryHandle, pdh_path, 0, &(cpu->total_pdh_counter)); - if (status != ERROR_SUCCESS) - g_print("Failed adding cpu user-time pdh-counter for path '%s', status %ld\n", pdh_path, status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added cpu user-time pdh-counter for path '%s'\n", pdh_path); - - _tcscpy(pdh_path, perfKeyList[CpuStart]); - _tcscat(pdh_path, num_str); - _tcscat(pdh_path, perfKeyList[CpuSysTime]); - status = PdhAddCounter(pdhQueryHandle, pdh_path, 0, &(cpu->sys_pdh_counter)); - if (status != ERROR_SUCCESS) - g_print("Failed adding cpu sys-time pdh-counter for path '%s', status %ld\n", pdh_path, status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added cpu sys-time pdh-counter for path '%s'\n", pdh_path); - - // only add to cpu-list if we got both counters - if (cpu->total_pdh_counter && cpu->sys_pdh_counter) - g_ptr_array_add(s_cpu_ptr_array, cpu); - else - gk_cpu_free(cpu); - } - } + gkrellm_debug(DEBUG_SYSDEP, "Found %i CPUs for monitoring.\n", + s_cpu_ptr_array->len); gkrellm_cpu_set_number_of_cpus(s_cpu_ptr_array->len); - return (s_cpu_ptr_array->len > 0 ? TRUE : FALSE); - } /* gkrellm_sys_cpu_init() */ + return (s_cpu_ptr_array->len == 0 ? FALSE : TRUE); + } +static void +gkrellm_sys_cpu_cleanup(void) + { + guint i; + if (!s_cpu_ptr_array) + return; + gkrellm_debug(DEBUG_SYSDEP, "Freeing counters for %u cpu(s)\n", + s_cpu_ptr_array->len); + for (i = 0; i < s_cpu_ptr_array->len; i++) + g_free(g_ptr_array_index(s_cpu_ptr_array, i)); + g_ptr_array_free(s_cpu_ptr_array, TRUE); + s_cpu_ptr_array = NULL; + } /* ===================================================================== */ /* Net monitor interface */ /* ===================================================================== */ +typedef struct + { + PDH_HCOUNTER recv_pdh_counter; + PDH_HCOUNTER send_pdh_counter; + gchar *name; + gulong recv; + gulong send; + } + GK_NET; -void gkrellm_sys_net_read_data(void) +static GPtrArray *s_net_ptr_array = NULL; + +static GK_NET * +gk_net_new() +{ + return g_new0(GK_NET, 1); +} + +static void +gk_net_free(GK_NET *net) +{ + g_free(net->name); + g_free(net); +} + +void +gkrellm_sys_net_read_data(void) { gint i; GK_NET *net; PDH_FMT_COUNTERVALUE recvVal; PDH_FMT_COUNTERVALUE sendVal; - if (pdhQueryHandle == 0) + if (pdhQueryHandle == NULL) return; - win32_read_proc_stat(); + gkrellm_debug(DEBUG_SYSDEP, "Reading net data for %d network devices\n", + s_net_ptr_array->len); for (i = 0; i < s_net_ptr_array->len; i++) { - net = g_ptr_array_index(s_net_ptr_array, i); + net = (GK_NET *)g_ptr_array_index(s_net_ptr_array, i); - status = PdhGetFormattedCounterValue(net->recv_pdh_counter, PDH_FMT_LONG, NULL, &recvVal); - if (status != ERROR_SUCCESS) - { - g_print("Getting pdh-counter (net recv counter) failed with status %lu\n", status); - return; - } + if (!get_formatted_counter_value(net->recv_pdh_counter, "net recv", PDH_FMT_LONG, &recvVal)) + continue; - status = PdhGetFormattedCounterValue(net->send_pdh_counter, PDH_FMT_LONG, NULL, &sendVal); - if (status != ERROR_SUCCESS) - { - g_print("Getting pdh-counter (net send counter) failed with status %lu\n", status); - return; - } + if (!get_formatted_counter_value(net->send_pdh_counter, "net send", PDH_FMT_LONG, &sendVal)) + continue; net->recv += recvVal.longValue / _GK.update_HZ; net->send += sendVal.longValue / _GK.update_HZ; + gkrellm_net_assign_data(net->name, net->recv, net->send); } } -void gkrellm_sys_net_check_routes(void) +void +gkrellm_sys_net_check_routes(void) { - //TODO + //TODO: Implement if possible, detects enable/disable of network-interfaces } -gboolean gkrellm_sys_net_isdn_online(void) +gboolean +gkrellm_sys_net_isdn_online(void) { - return FALSE; /* ISDN is off line */ + return FALSE; //TODO: Implement if possible } - -static -gchar *clean_dev_name(const gchar *name) +static void +gkrellm_sys_net_add_cb(wchar_t *name, PDH_HCOUNTER *recv, PDH_HCOUNTER *send) { - gchar *clean_name; - size_t i; - size_t len; - - clean_name = g_strndup(name, MAX_DEV_NAME); - len = strlen(clean_name); - - for (i = 0; i < len; i++) - { - if (clean_name[i] == ' ') - clean_name[i] = '_'; - } - return clean_name; -} - -gboolean gkrellm_sys_net_init(void) - { - DWORD objectSize = 0; - DWORD instanceSize = 0; GK_NET *net; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT network monitoring\n"); + net = gk_net_new(); + net->name = clean_dev_name(name); + net->recv_pdh_counter = *recv; + net->send_pdh_counter = *send; - if (pdhQueryHandle != 0) - { - TCHAR pdhIface[128]; - DWORD pdhIfaceSz = sizeof(pdhIface) / sizeof(TCHAR); - PDH_STATUS stat; + gkrellm_debug(DEBUG_SYSDEP, "Adding network interface %s\n", net->name); - stat = PdhLookupPerfNameByIndex(NULL, 510, pdhIface, &pdhIfaceSz); - if (stat != ERROR_SUCCESS) // fall back to non-translated pdh string - _tcscpy(pdhIface, _T("Network Interface")); + // TODO: determine network type + gkrellm_net_add_timer_type_ppp(net->name); - stat = PdhEnumObjectItems(NULL, NULL, pdhIface, NULL, &objectSize, NULL, - &instanceSize, PERF_DETAIL_WIZARD, 0); - if (stat != PDH_MORE_DATA && stat != ERROR_SUCCESS) - { - g_print("Could not enumerate net pdh-counters for path '%s', error %lu\n", pdhIface, stat); - } - else if (instanceSize > 0) - { - TCHAR buf[1024]; - LPTSTR objects = NULL; - LPTSTR instances = NULL; - LPTSTR instance = NULL; + g_ptr_array_add(s_net_ptr_array, net); +} - ++instanceSize; - ++objectSize; +gboolean +gkrellm_sys_net_init(void) + { + gkrellm_debug(DEBUG_SYSDEP, "INIT network monitoring\n"); - objects = (LPTSTR) malloc(sizeof(TCHAR) * objectSize); - instances = (LPTSTR) malloc(sizeof(TCHAR) * instanceSize); + s_net_ptr_array = g_ptr_array_new(); - PdhEnumObjectItems(NULL, NULL, pdhIface, objects, &objectSize, - instances, &instanceSize, PERF_DETAIL_WIZARD, 0); + add_counter_list( + 510 // object_index + , 264 // counter_index1 + , 896 // counter_index2 + , gkrellm_sys_net_add_cb); - for (instance = instances; *instance != 0; instance += lstrlen(instance) + 1) - { - net = gk_net_new(); - net->name = clean_dev_name(instance); - - // TODO: determine network type - gkrellm_net_add_timer_type_ppp(net->name); - - _tcscpy(buf, perfKeyList[NetDevStart]); - _tcscat(buf, instance); - _tcscat(buf, perfKeyList[NetDevRecv]); - status = PdhAddCounter(pdhQueryHandle, buf, 0, &(net->recv_pdh_counter)); - if (status != ERROR_SUCCESS) - g_print("Failed adding net recv pdh-counter for path '%s', status %ld\n", buf, status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added net recv pdh-counter for path '%s'\n", buf); - - _tcscpy(buf, perfKeyList[NetDevStart]); - _tcscat(buf, instance); - _tcscat(buf, perfKeyList[NetDevSend]); - status = PdhAddCounter(pdhQueryHandle, buf, 0, &(net->send_pdh_counter)); - if (status != ERROR_SUCCESS) - g_print("Failed adding net send pdh-counter for path '%s', status %ld\n", buf, status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added net send pdh-counter for path '%s'\n", buf); - - if (net->recv_pdh_counter && net->send_pdh_counter) - g_ptr_array_add(s_net_ptr_array, net); - else - gk_net_free(net); - } // for() - - free(objects); - free(instances); - } - } - - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Found %i network adapters for monitoring.\n", s_net_ptr_array->len); + gkrellm_debug(DEBUG_SYSDEP, "Found %i network adapters for monitoring.\n", + s_net_ptr_array->len); return (s_net_ptr_array->len == 0 ? FALSE : TRUE); } +static void +gkrellm_sys_net_cleanup(void) + { + guint i; + if (!s_net_ptr_array) + return; + gkrellm_debug(DEBUG_SYSDEP, "Freeing counters for %u network adapter(s)\n", + s_net_ptr_array->len); + for (i = 0; i < s_net_ptr_array->len; i++) + gk_net_free(g_ptr_array_index(s_net_ptr_array, i)); + g_ptr_array_free(s_net_ptr_array, TRUE); + } /* ===================================================================== */ /* Disk monitor interface */ /* ===================================================================== */ -//static gint numDisks = 0; -//static long diskread[MAX_DISKS], diskwrite[MAX_DISKS]; +typedef struct _GK_DISK + { + PDH_HCOUNTER read_pdh_counter; + PDH_HCOUNTER write_pdh_counter; + gchar *name; + gulong read; + gulong write; + } GK_DISK; -gchar * gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number, +static GPtrArray *s_disk_ptr_array = NULL; + +static GK_DISK * +gk_disk_new() +{ + return g_new0(GK_DISK, 1); +} + +static void +gk_disk_free(GK_DISK *disk) +{ + g_free(disk->name); + g_free(disk); +} + +gchar *gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number, gint *order) { static gchar name[37]; GK_DISK *disk; disk = g_ptr_array_index(s_disk_ptr_array, device_number); - //TODO: i18n? snprintf(name, sizeof(name), "Disk%s", disk->name); *order = device_number; - + return name; } gint gkrellm_sys_disk_order_from_name(gchar *name) { - return 0; /* Disk by name not implemented in Windows */ + return 0; // Disk by name not implemented in Windows } void gkrellm_sys_disk_read_data(void) @@ -942,274 +1253,436 @@ void gkrellm_sys_disk_read_data(void) PDH_FMT_COUNTERVALUE readVal; PDH_FMT_COUNTERVALUE writeVal; - if (pdhQueryHandle == 0) + if (pdhQueryHandle == NULL) return; - win32_read_proc_stat(); + gkrellm_debug(DEBUG_SYSDEP, "Reading disk data\n"); for (i = 0; i < s_disk_ptr_array->len; i++) { disk = g_ptr_array_index(s_disk_ptr_array, i); - - status = PdhGetFormattedCounterValue(disk->read_pdh_counter, PDH_FMT_DOUBLE, NULL, &readVal); - if (status != ERROR_SUCCESS) - { - g_print("Getting PDH-counter (disk read cnt) failed with status %lu\n", status); - break; - } - status = PdhGetFormattedCounterValue(disk->write_pdh_counter, PDH_FMT_DOUBLE, NULL, &writeVal); - if (status != ERROR_SUCCESS) - { - g_print("Getting PDH-counter (disk write cnt) failed with status %lu\n", status); - break; - } + + if (!get_formatted_counter_value(disk->read_pdh_counter, "disk read", PDH_FMT_DOUBLE, &readVal)) + continue; + + if (!get_formatted_counter_value(disk->write_pdh_counter, "disk write", PDH_FMT_DOUBLE, &writeVal)) + continue; disk->read += readVal.doubleValue / _GK.update_HZ; disk->write += writeVal.doubleValue / _GK.update_HZ; gkrellm_disk_assign_data_by_device(i, 0, disk->read, disk->write, FALSE); } - } /* gkrellm_sys_disk_read_data() */ + } -gboolean gkrellm_sys_disk_init(void) - { - DWORD size = 0; - DWORD isize = 0; - TCHAR buf[1024]; +static +void gkrellm_sys_disk_add_cb(wchar_t *name, PDH_HCOUNTER *read, PDH_HCOUNTER *write) +{ GK_DISK *disk; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT disk monitoring\n"); + disk = gk_disk_new(); + disk->name = clean_dev_name(name); + disk->read_pdh_counter = *read; + disk->write_pdh_counter = *write; - if (pdhQueryHandle != 0) - { - TCHAR pdhDisk[128]; - DWORD pdhDiskSz = 128; - PDH_STATUS stat; - - stat = PdhLookupPerfNameByIndex(NULL, 234, pdhDisk, &pdhDiskSz); - if (stat != ERROR_SUCCESS) // Fall back to non-translated pdh string - _tcscpy(pdhDisk, TEXT("PhysicalDisk")); + gkrellm_debug(DEBUG_SYSDEP, "Adding disk %s\n", disk->name); - // Get number of disks that can be queried - stat = PdhEnumObjectItems(NULL, NULL, pdhDisk, NULL, &size, NULL, &isize, PERF_DETAIL_WIZARD, 0); - if (stat != PDH_MORE_DATA && stat != ERROR_SUCCESS) - { - g_print("Could not enumerate disk pdh-counters for path '%s', error %lu\n", pdhDisk, stat); - } - else if (size > 0) - { - LPTSTR objects = NULL; - LPTSTR instances = NULL; - LPTSTR instance = NULL; + g_ptr_array_add(s_disk_ptr_array, disk); +} - ++isize; - ++size; +gboolean +gkrellm_sys_disk_init(void) + { + gkrellm_debug(DEBUG_SYSDEP, "INIT disk monitoring\n"); - objects = (LPTSTR) malloc(sizeof(TCHAR) * size); - instances = (LPTSTR) malloc(sizeof(TCHAR) * isize); + s_disk_ptr_array = g_ptr_array_new(); - // get information about disks - PdhEnumObjectItems(NULL, NULL, pdhDisk, objects, &size, instances, &isize, PERF_DETAIL_WIZARD, 0); - for (instance = instances; *instance != 0; instance += lstrlen(instance) + 1) - { - // Ignore total counter, gkrellm provides that functionality - if (_strnicmp(_T("_Total"), instance, 6) == 0) - continue; + add_counter_list( + 234 // object_index + , 220 // counter_index1 + , 222 // counter_index2 + , gkrellm_sys_disk_add_cb); - disk = gk_disk_new(); - disk->name = clean_dev_name(instance); - // assemble object name to pdhQueryHandle - _tcscpy(buf, perfKeyList[DiskStart]); - _tcscat(buf, instance); - _tcscat(buf, perfKeyList[DiskRead]); - status = PdhAddCounter(pdhQueryHandle, buf, 0, &(disk->read_pdh_counter)); - if (status != ERROR_SUCCESS) - g_print("Failed adding disk read pdh-counter for path '%s', status %ld\n", buf, status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added disk read pdh-counter for path '%s'\n", buf); - - _tcscpy(buf, perfKeyList[DiskStart]); - _tcscat(buf, instance); - _tcscat(buf, perfKeyList[DiskWrite]); - status = PdhAddCounter(pdhQueryHandle, buf, 0, &(disk->write_pdh_counter)); - if (status != ERROR_SUCCESS) - g_print("Failed adding disk write pdh-counter for path '%s', status %ld\n", buf, status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added disk write pdh-counter for path '%s'\n", buf); - - if (disk->read_pdh_counter && disk->write_pdh_counter) - g_ptr_array_add(s_disk_ptr_array, disk); - else - gk_disk_free(disk); - } - - free(objects); - free(instances); - } - } - - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Found %i disks for monitoring.\n", s_disk_ptr_array->len); + gkrellm_debug(DEBUG_SYSDEP, "Found %i disk(s) for monitoring.\n", + s_disk_ptr_array->len); return (s_disk_ptr_array->len == 0 ? FALSE : TRUE); } +static void +gkrellm_sys_disk_cleanup(void) + { + guint i; + if (!s_disk_ptr_array) + return; + gkrellm_debug(DEBUG_SYSDEP, "Freeing counters for %u disk(s)\n", + s_disk_ptr_array->len); + for (i = 0; i < s_disk_ptr_array->len; i++) + gk_disk_free(g_ptr_array_index(s_disk_ptr_array, i)); + g_ptr_array_free(s_disk_ptr_array, TRUE); + } /* ===================================================================== */ /* Proc monitor interface */ /* ===================================================================== */ -void gkrellm_sys_proc_read_data(void) - { - static gulong last_n_forks = 0; - static gfloat fload = 0; +// Counters for proc monitor interface +static PDH_HCOUNTER processCounter = NULL; +static PDH_HCOUNTER waitQueueCounter = NULL; +// Library handle for secur32.dll, lib is loaded at runtime +static HANDLE hSecur32 = NULL; +// Function pointers to various functions from secur32.dll +static pfLsaEnumerateLogonSessions pfLELS = NULL; +static pfLsaFreeReturnBuffer pfLFRB = NULL; +static pfLsaGetLogonSessionData pfLGLSD = NULL; + +#if 0 +// We need to subtract 1 on Win2k, the "idle process" seems to be counted +// as waiting on win2k (not on winxp though) +// TODO: check on vista, win2k3, win2k8 etc. +static long proc_load_correction_val = 0; +#endif + +void +gkrellm_sys_proc_read_data(void) + { + static gulong last_num_processes = 0; + static gfloat fload = 0; - DWORD type; PDH_FMT_COUNTERVALUE value; - gint n_running = 0, n_processes = 0; - gulong n_forks = 0; - gulong new_forks; + LONG num_processes; + LONG num_forks = 0; + LONG num_waiting; gfloat a; - if (pdhQueryHandle == 0) + if (pdhQueryHandle == NULL) return; - win32_read_proc_stat(); + gkrellm_debug(DEBUG_SYSDEP, "Reading proc data\n"); - status = PdhGetFormattedCounterValue(processCounter, PDH_FMT_LONG, &type, &value); - if (status != ERROR_SUCCESS) - { - g_print("Getting PDH-counter (process cnt) failed with status %ld\n", status); + if (!get_formatted_counter_value(processCounter, "process count", + PDH_FMT_LONG, &value)) return; - } - n_processes = value.longValue; - - status = PdhGetFormattedCounterValue(threadCounter, PDH_FMT_LONG, &type, &value); - if (status != ERROR_SUCCESS) - { - g_print("Getting PDH-counter (thread cnt) failed with status %ld\n", status); - return; - } - n_forks = value.longValue; + num_processes = value.longValue; + if ((last_num_processes) > 0 && (last_num_processes < num_processes)) + num_forks = num_processes - last_num_processes; + last_num_processes = num_processes; - n_running = n_processes; + if (!get_formatted_counter_value(waitQueueCounter, "wait queue size", + PDH_FMT_LONG, &value)) + return; +#if 0 + num_waiting = (value.longValue + proc_load_correction_val); +#else + num_waiting = value.longValue; +#endif - //fload - is the system load average, an exponential moving average over a period - // of a minute of n_running. It measures how heavily a system is loaded - // with processes or threads competing for cpu time slices. + //fload - is the system load average, an exponential moving average over a + //period of a minute of n_running. It measures how heavily a system is + //loaded with processes or threads competing for cpu time slices. + // + //All the unix OSs have a system call for getting the load average. But if + //you don't and can get a n_running number, you can calculate fload. An + //exponential moving average (ema) is done like: + // + // a = 2 / (period + 1) + // ema = ema + a * (new_value - ema) + // + // See also + // http://en.wikipedia.org/wiki/Load_(computing) + a = 2.0 / ((_GK.update_HZ * 60.) + 1.); + fload += a * (num_waiting - fload); + if (fload < 0) + fload = 0; - //All the unix OSs have a system call for getting the load average. But if - //you don't and can get a n_running number, you can calculate fload. An - //exponential moving average (ema) is done like: + gkrellm_debug(DEBUG_SYSDEP, "num_forks %ld; num_waiting %ld; a %f; fload %f\n", + num_forks, num_waiting, a, fload); - // a = 2 / (period + 1) - // ema = ema + a * (new_value - ema) - - - a = 2. / ((_GK.update_HZ * 60.) + 1.); - new_forks = n_forks - last_n_forks; - if (new_forks < 0) - new_forks = 0; - fload = fload + a * (new_forks - fload); - if (fload < 0) - fload = 0; - - gkrellm_proc_assign_data(n_processes, n_running, n_forks, fload); - - last_n_forks = n_forks; + gkrellm_proc_assign_data(num_processes, 0 /*n_running*/, + num_forks /*n_forks*/, fload); } - -void gkrellm_sys_proc_read_users(void) +void +gkrellm_sys_proc_read_users(void) { - gint n_users = 1; - DWORD entriesRead; - DWORD totalEntries; - LPBYTE ptr; - NET_API_STATUS nerr; + gint i; + // Number of interactive users + gint n_users = 0; + // Return value for Lsa functions + NTSTATUS ntstatus; + // Arguments for LsaEnumerateLogonSessions() + ULONG numSessions = 0; + PLUID pSessions = NULL; + // Argument for LsaGetLogonSessionData() + PSECURITY_LOGON_SESSION_DATA pSessionData; + wchar_t acc_name[256]; + wchar_t acc_dom[256]; + DWORD dwSize; + SID_NAME_USE sid_type; - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Getting number of logged in users.\n"); + /* Silently fail if secur32.dll is missing functions that we use */ + if ((pfLELS == NULL) || (pfLFRB == NULL) || (pfLGLSD == NULL)) + return; - nerr = NetWkstaUserEnum(NULL, 0, &ptr, MAX_PREFERRED_LENGTH, &entriesRead, - &totalEntries, NULL); - if (nerr == NERR_Success) - n_users = entriesRead; + gkrellm_debug(DEBUG_SYSDEP, "Getting number of logged in users\n"); - NetApiBufferFree(ptr); + ntstatus = pfLELS(&numSessions, &pSessions); + if (NT_SUCCESS(ntstatus)) + { + gkrellm_debug(DEBUG_SYSDEP, "Found %lu user-sessions\n", numSessions); + for (i = 0; i < (int)numSessions; i++) + { + //gkrellm_debug(DEBUG_SYSDEP, "Fetching session-data for session %d\n", i); + pSessionData = NULL; + + ntstatus = pfLGLSD(&pSessions[i], &pSessionData); + if (NT_SUCCESS(ntstatus) && (pSessionData != NULL)) + { + if ((SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive + && (pSessionData->UserName.Buffer != NULL)) + { + gkrellm_debug(DEBUG_SYSDEP, "Interactive User %d; '%ls'\n", + i, pSessionData->UserName.Buffer); + + dwSize = 256; + if (LookupAccountSidW(NULL, pSessionData->Sid, + acc_name, &dwSize, + acc_dom, &dwSize, + &sid_type)) + { + if (sid_type == 1) + { + n_users++; + } + else + { + gkrellm_debug(DEBUG_SYSDEP, + "SID type %d is not a normal account\n", + (int)sid_type); + } + } + else + { + win32_warning(NTDLL, + GetLastError(), + "Looking up user account id failed"); + } + } + } + else + { + win32_warning(NTDLL, ntstatus, + "Could not get session-data for session %d", i); + } + + // Free session-data provided by OS, even if function returned + // an error before + pfLFRB(pSessionData); + } + } + else + { + win32_warning(NTDLL, ntstatus, "Could not enumerate user-sessions\n"); + } + + // Free LUID list provided by OS, even if function returned an error before + pfLFRB(pSessions); gkrellm_proc_assign_users(n_users); } - -gboolean gkrellm_sys_proc_init(void) +gboolean +gkrellm_sys_proc_init(void) { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT process monitoring\n"); + wchar_t system_name[128]; + wchar_t counter_name[128]; + wchar_t counter_path[128+128+3]; +#if 0 + OSVERSIONINFOEXW vi; +#endif - if (pdhQueryHandle == 0) + gkrellm_debug(DEBUG_SYSDEP, "INIT process monitoring\n"); + + if (pdhQueryHandle == NULL) return FALSE; - status = PdhAddCounter(pdhQueryHandle, perfKeyList[NumProcesses], 0, &processCounter); - if (status != ERROR_SUCCESS) - g_print("Failed adding process pdh-counter for path '%s', status %ld\n", perfKeyList[NumProcesses], status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added process pdh-counter for path '%s'\n", perfKeyList[NumProcesses]); + // Fetch prefix for both counter paths ("System" index is 2) + if (!lookup_perfname(2, system_name, 128)) + return FALSE; - status = PdhAddCounter(pdhQueryHandle, perfKeyList[NumThreads], 0, &threadCounter); - if (status != ERROR_SUCCESS) - g_print("Failed adding thread pdh-counter for path '%s', status %ld\n", perfKeyList[NumThreads], status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added thread pdh-counter for path '%s'\n", perfKeyList[NumThreads]); + // Add counter for number of processes (index is 248) + if (!lookup_perfname(248, counter_name, 128)) + return FALSE; + _snwprintf(counter_path, sizeof(counter_path) / sizeof(wchar_t), + L"\\%ls\\%ls", + system_name, counter_name); + if (!add_counter(counter_path, &processCounter)) + return FALSE; + + // --- Add counter for waiting queue size (index is 44) + if (!lookup_perfname(44, counter_name, 128)) + return FALSE; + _snwprintf(counter_path, sizeof(counter_path) / sizeof(wchar_t), + L"\\%ls\\%ls", + system_name, counter_name); + if (!add_counter(counter_path, &waitQueueCounter)) + return FALSE; + + // Dynamically load secur32.dll and lookup functions. + // Needed to determine number of logged in users + hSecur32 = LoadLibraryW(L"secur32.dll"); + if (hSecur32 != NULL) + { + gkrellm_debug(DEBUG_SYSDEP, "Loaded secur32.dll\n"); + + pfLELS = (pfLsaEnumerateLogonSessions)GetProcAddress(hSecur32, + "LsaEnumerateLogonSessions"); + if (pfLELS == NULL) + { + g_warning("Could not get address for " \ + "LsaEnumerateLogonSessions() in secur32.dll\n"); + } + + pfLFRB = (pfLsaFreeReturnBuffer)GetProcAddress(hSecur32, + "LsaFreeReturnBuffer"); + if (pfLFRB == NULL) + { + g_warning("Could not get address for " \ + "LsaFreeReturnBuffer() in secur32.dll\n"); + } + + pfLGLSD = (pfLsaGetLogonSessionData)GetProcAddress(hSecur32, + "LsaGetLogonSessionData"); + if (pfLGLSD == NULL) + { + g_warning("Could not get address for " \ + "LsaGetLogonSessionData() in secur32.dll\n"); + } + } + else + { + win32_warning(NULL, GetLastError(), + "Could not load secur32.dll, number of logged in " \ + "users will not be detected\n"); + } + + + // Determine OS for proper load-average computation + // (wait-queue value on win2k is off by one) + +#if 0 + memset(&vi, 0, sizeof(OSVERSIONINFOEXW)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + if (GetVersionExW((OSVERSIONINFOW *)(&vi))) + { + gkrellm_debug(DEBUG_SYSDEP, "major %ld; minor %ld\n", + vi.dwMajorVersion, vi.dwMinorVersion); + if ((vi.dwMajorVersion == 5) && (vi.dwMinorVersion == 0)) + proc_load_correction_val = -1; + } +#endif return TRUE; } +static void +gkrellm_sys_proc_cleanup(void) + { + // Unload secur32.dll and invalidate function pointers + pfLELS = NULL; + pfLFRB = NULL; + pfLGLSD = NULL; + if (hSecur32 != NULL) + FreeLibrary(hSecur32); + hSecur32 = NULL; + } + /* ===================================================================== */ /* Memory/Swap monitor interface */ /* ===================================================================== */ -void gkrellm_sys_mem_read_data(void) -{ - MEMORYSTATUSEX memStatus; - memStatus.dwLength = sizeof(memStatus); +typedef struct { + DWORD cb; + SIZE_T CommitTotal; + SIZE_T CommitLimit; + SIZE_T CommitPeak; + SIZE_T PhysicalTotal; + SIZE_T PhysicalAvailable; + SIZE_T SystemCache; + SIZE_T KernelTotal; + SIZE_T KernelPaged; + SIZE_T KernelNonpaged; + SIZE_T PageSize; + DWORD HandleCount; + DWORD ProcessCount; + DWORD ThreadCount; +} PERFORMANCE_INFORMATION; - if (GlobalMemoryStatusEx(&memStatus) != 0) +typedef BOOL (WINAPI *pfGetPerformanceInfo)(PERFORMANCE_INFORMATION *, DWORD); + +static HINSTANCE psapi_instance = NULL; +static pfGetPerformanceInfo pGPI = NULL; +static DWORD page_size = 1; + +void +gkrellm_sys_mem_read_data(void) { - guint64 physUsed; - guint64 shared; - guint64 buffers; - DWORDLONG physAvail, physTot; - DWORDLONG cached; + gkrellm_debug(DEBUG_SYSDEP, "Checking memory utilization\n"); - physTot = memStatus.ullTotalPhys; - physAvail = memStatus.ullAvailPhys; + guint64 total = 0; + guint64 used = 0; + guint64 avail = 0; + guint64 cache = 0; - shared = 0; //TODO: how to determine? - buffers = 0; //TODO: how to determine? - // TODO: don't know if this is correct (update: no, it's not) - cached = 0; //(virtTot - virtAvail) - (pageTot - pageAvail); - //if (cached < 0) - // cached = 0; + if (pGPI) + { + PERFORMANCE_INFORMATION pi; - physUsed = (physTot - physAvail) - buffers - cached; + // See http://msdn.microsoft.com/en-us/library/ms684824(VS.85).aspx + // for the confusing description of PERFORMANCE_INFORMATION + // + // total = PhysicalTotal + // used = PhysicalTotal - PhysicalAvailable + // NOTE: (avail value is not exactly correct but we can't know better) + // avail = PhysicalAvailable - SystemCache + // cache = SystemCache - gkrellm_mem_assign_data(physTot, physUsed, physAvail, shared, buffers, cached); + if (pGPI(&pi, sizeof(PERFORMANCE_INFORMATION))) + { + total = pi.PhysicalTotal * pi.PageSize; + used = (pi.PhysicalTotal - pi.PhysicalAvailable) * pi.PageSize; + avail = (pi.PhysicalAvailable - pi.SystemCache) * pi.PageSize; + cache = pi.SystemCache * pi.PageSize; + } + } + else + { + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + + if (GlobalMemoryStatusEx(&ms)) + { + total = ms.ullTotalPhys; + used = ms.ullTotalPhys - ms.ullAvailPhys; + avail = ms.ullAvailPhys; + } + } + + gkrellm_mem_assign_data(total, used, avail, 0, 0, cache); } -} - -void gkrellm_sys_swap_read_data(void) +void +gkrellm_sys_swap_read_data(void) { - SYSTEM_INFO si; - GetSystemInfo(&si); - + guint64 swapTotal = 0; + guint64 swapUsed = 0; NTSTATUS ntstatus; ULONG szBuf = 3*sizeof(SYSTEM_PAGEFILE_INFORMATION); - LPVOID pBuf = NULL; + LPVOID pBuf = NULL; + + gkrellm_debug(DEBUG_SYSDEP, "Checking swap utilization\n"); // it is difficult to determine beforehand which size of the // buffer will be enough to retrieve all information, so we @@ -1217,72 +1690,101 @@ void gkrellm_sys_swap_read_data(void) // the information successfully do { - pBuf = malloc(szBuf); - if (pBuf == NULL) - break; + pBuf = g_malloc(szBuf); - ntstatus = ZwQuerySystemInformation(SystemPagefileInformation, pBuf, szBuf, NULL); + ntstatus = ZwQuerySystemInformation(SystemPagefileInformation, pBuf, + szBuf, NULL); if (ntstatus == STATUS_INFO_LENGTH_MISMATCH) { - free(pBuf); + // Buffer was too small, double its size and try again + g_free(pBuf); szBuf *= 2; } else if (!NT_SUCCESS(ntstatus)) - { // give up - break; + { + win32_warning(NTDLL, ntstatus, "Could not determine swap usage"); + g_free(pBuf); + // Some other error occured, give up + return; } } while (ntstatus == STATUS_INFO_LENGTH_MISMATCH); - guint64 swapTotal = 0; - guint64 swapUsed = 0; - gulong swapIn = 0; //TODO: calculate value - gulong swapOut = 0; //TODO: calculate value + if (pBuf != NULL) + { + // iterate over information for all pagefiles + PSYSTEM_PAGEFILE_INFORMATION pInfo = (PSYSTEM_PAGEFILE_INFORMATION)pBuf; + for (;;) + { + swapTotal += pInfo->CurrentSize * page_size; + swapUsed += pInfo->TotalUsed * page_size; + if (pInfo->NextEntryOffset == 0) + break; // end of list + // get pointer to next struct + pInfo = (PSYSTEM_PAGEFILE_INFORMATION)((PBYTE)pInfo + + pInfo->NextEntryOffset); + } + g_free(pBuf); - // iterate over information for all pagefiles - PSYSTEM_PAGEFILE_INFORMATION pInfo = (PSYSTEM_PAGEFILE_INFORMATION)pBuf; - for (;;) - { - swapTotal += pInfo->CurrentSize * si.dwPageSize; - swapUsed += pInfo->TotalUsed * si.dwPageSize; - if (pInfo->NextEntryOffset == 0) - break; - // get pointer to next struct - pInfo = (PSYSTEM_PAGEFILE_INFORMATION)((PBYTE)pInfo + - pInfo->NextEntryOffset); - } - free(pBuf); - - gkrellm_swap_assign_data(swapTotal, swapUsed, swapIn, swapOut); + // TODO: calculate swapin/swapout values + gkrellm_swap_assign_data(swapTotal, swapUsed, 0, 0); + } } - -gboolean gkrellm_sys_mem_init(void) +gboolean +gkrellm_sys_mem_init(void) { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT memory monitoring\n"); + SYSTEM_INFO si; + + gkrellm_debug(DEBUG_SYSDEP, "INIT memory monitoring\n"); + + GetSystemInfo(&si); + page_size = si.dwPageSize; + + psapi_instance = LoadLibraryW(L"PSAPI.DLL"); + if (psapi_instance) + { + pGPI = GetProcAddress(psapi_instance, "GetPerformanceInfo"); + if (pGPI == NULL) + { + gkrellm_debug(DEBUG_SYSDEP, "No GetPerformanceInfo() in " \ + "PSAPI.DLL, cache-memory will stay at 0!\n"); + } + } + else + { + win32_warning(NULL, GetLastError(), "Could not load PSAPI.DLL"); + } + return TRUE; } +static void +gkrellm_sys_mem_cleanup(void) + { + pGPI = NULL; + if (psapi_instance) + FreeLibrary(psapi_instance); + psapi_instance = NULL; + } + + /* ===================================================================== */ /* Battery monitor interface */ /* ===================================================================== */ -#define L_NO_BATTERY 0x80 -#define L_ON_LINE 1 -#define L_CHARGING 8 -#define L_UNKNOWN 0xFF - void gkrellm_sys_battery_read_data(void) { gboolean available, on_line, charging; gint percent, time_left; SYSTEM_POWER_STATUS power; + gkrellm_debug(DEBUG_SYSDEP, "Checking battery state\n"); + GetSystemPowerStatus(&power); - if ( (power.BatteryFlag & L_NO_BATTERY) == L_NO_BATTERY - || (power.BatteryFlag & L_UNKNOWN) == L_UNKNOWN + if ( (power.BatteryFlag & BATTERY_FLAG_NO_BATTERY) == BATTERY_FLAG_NO_BATTERY + || (power.BatteryFlag & BATTERY_FLAG_UNKNOWN) == BATTERY_FLAG_UNKNOWN ) { available = FALSE; @@ -1292,25 +1794,23 @@ void gkrellm_sys_battery_read_data(void) available = TRUE; } - on_line = ((power.ACLineStatus & L_ON_LINE) == L_ON_LINE) ? TRUE : FALSE; - charging= ((power.BatteryFlag & L_CHARGING) == L_CHARGING) ? TRUE : FALSE; - + on_line = ((power.ACLineStatus & AC_LINE_ONLINE) == AC_LINE_ONLINE) ? TRUE : FALSE; + charging = ((power.BatteryFlag & BATTERY_FLAG_CHARGING) == BATTERY_FLAG_CHARGING) ? TRUE : FALSE; time_left = power.BatteryLifeTime; - percent = power.BatteryLifePercent; + percent = power.BatteryLifePercent; - gkrellm_battery_assign_data(0, available, on_line, charging, percent, time_left); + gkrellm_battery_assign_data(0, available, on_line, charging, percent, + time_left); } - gboolean gkrellm_sys_battery_init() { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT battery monitoring\n"); + gkrellm_debug(DEBUG_SYSDEP, "INIT battery monitoring\n"); return TRUE; } -/* ============================================== */ +/* ===================================================================== */ /* FS monitor interfaces */ /* ===================================================================== */ @@ -1319,24 +1819,22 @@ gboolean gkrellm_sys_fs_fstab_modified(void) return FALSE; } - +static void eject_win32_cdrom(gchar *device) { HANDLE hFile; BOOL err; - TCHAR devPath[MAX_PATH]; + char device_path[MAX_PATH]; DWORD numBytes; - if (!device || device[0] == 0) + if (!device || *device == '\0') return; - /* FIXME: This assumes device names like "D:" */ - _sntprintf(devPath, ARRAYSIZE(devPath), _T("\\\\.\\%c:"), device[0]); - devPath[ARRAYSIZE(devPath) - 1] = 0; + // FIXME: This assumes device names like "D:" + snprintf(device_path, MAX_PATH, "\\\\.\\%c:", device[0]); - hFile = CreateFile(devPath, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, - NULL); + hFile = CreateFileA(device_path, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL); if (hFile != 0 && hFile != INVALID_HANDLE_VALUE) { // this should be safe for non-removable drives @@ -1351,93 +1849,122 @@ void eject_win32_cdrom(gchar *device) } } - -gboolean gkrellm_sys_fs_init(void) +gboolean gkrellm_sys_fs_init(void) { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT filesystem monitoring\n"); + gkrellm_debug(DEBUG_SYSDEP, "INIT filesystem monitoring\n"); + gkrellm_fs_mounting_unsupported(); gkrellm_fs_setup_eject(NULL, NULL, eject_win32_cdrom, NULL); return TRUE; } - void gkrellm_sys_fs_get_fsusage(gpointer fs, gchar *dir) { BOOL err = 0; - - if (!dir || dir[0] == 0) - return; - - ULARGE_INTEGER freeAvailableToCaller; + ULARGE_INTEGER availToCaller; ULARGE_INTEGER totalBytes; ULARGE_INTEGER freeBytes; - gulong total, freeCaller, free; + gunichar2 *w_dir = NULL; - /* TODO: Unicode support? */ - err = GetDiskFreeSpaceExA(dir, &freeAvailableToCaller, &totalBytes, &freeBytes); + if (!dir || *dir == '\0') + return; + gkrellm_debug(DEBUG_SYSDEP, "Checking fs usage for %s\n", dir); + + w_dir = g_utf8_to_utf16(dir, -1, NULL, NULL, NULL); + if (!w_dir) + return; + + err = GetDiskFreeSpaceExW(w_dir, &availToCaller, &totalBytes, &freeBytes); if (err != 0) { - total = EnlargedUnsignedDivide(totalBytes, 1024, 0); - freeCaller = EnlargedUnsignedDivide(freeAvailableToCaller, 1024, 0); - free = EnlargedUnsignedDivide(freeBytes, 1024, 0); // fs, blocks, avail, free, size - gkrellm_fs_assign_fsusage_data(fs, total, freeCaller, free, 1024); + gkrellm_fs_assign_fsusage_data(fs + , EnlargedUnsignedDivide(totalBytes, 1024, 0) /* total */ + , EnlargedUnsignedDivide(availToCaller, 1024, 0) /* free to caller */ + , EnlargedUnsignedDivide(freeBytes, 1024, 0) /* free */ + , 1024 /* block size */ + ); } else { - /* TODO: This may happen on cd/dvd drives, ignore for now */ - /* - g_print("GetDiskFreeSpaceEx() failed on drive %c:, error %d\n", *dir, err); - */ + /* This may happen on cd/dvd drives, ignore error silently */ } + g_free(w_dir); } void gkrellm_sys_fs_get_mounts_list(void) { - char driveStrings[512]; - char *drive; + wchar_t drive_list[4*26]; + wchar_t *drive; + gchar *drive_utf8; DWORD ret; - /* TODO: Unicode support? */ - ret = GetLogicalDriveStringsA(ARRAYSIZE(driveStrings) - 1, driveStrings); - if (ret > 0) + DWORD sz; + UINT drive_type; + + gkrellm_debug(DEBUG_SYSDEP, "Getting list of mounted drives\n"); + + drive_list[0] = '\0'; + sz = (sizeof(drive_list) / sizeof(wchar_t)) - sizeof(wchar_t); + ret = GetLogicalDriveStringsW(sz, drive_list); + if (ret == 0 || ret > sz) + { + win32_warning(NULL, GetLastError(), "Failed enumerating mounted drives"); + return; + } + + for (drive = drive_list; (*drive) != '\0'; drive += wcslen(drive) + 1) { - for (drive = driveStrings; *drive != 0; drive += lstrlenA(drive) + 1) - { - if (_strnicmp("A:\\", drive, 3) != 0 - && _strnicmp("B:\\", drive, 3) != 0 - ) - { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Found mounted drive '%s'\n", drive); - gkrellm_fs_add_to_mounts_list(drive, drive, ""); - } - } + drive_type = GetDriveTypeW(drive); + + if ( (drive_type == DRIVE_REMOVABLE) + && (!wcsncmp(drive, L"A:\\", 3) || !wcsncmp(drive, L"B:\\", 3))) + continue; + + gkrellm_debug(DEBUG_SYSDEP, "Found mounted drive '%ls' of type %u\n", + drive, drive_type); + drive_utf8 = g_utf16_to_utf8(drive, -1, NULL, NULL, NULL); + gkrellm_fs_add_to_mounts_list(drive_utf8, drive_utf8, + (drive_type == DRIVE_REMOTE ? "smbfs" : "")); + g_free(drive_utf8); } } - void gkrellm_sys_fs_get_fstab_list(void) { - char driveStrings[512]; - char *drive; + wchar_t drive_list[4*26]; + wchar_t *drive; + gchar *drive_utf8; DWORD ret; - /* TODO: Unicode support? */ - ret = GetLogicalDriveStringsA(ARRAYSIZE(driveStrings) - 1, driveStrings); - if (ret > 0) + DWORD sz; + UINT drive_type; + + gkrellm_debug(DEBUG_SYSDEP, "Getting list of drives in fstab\n"); + + drive_list[0] = '\0'; + sz = (sizeof(drive_list) / sizeof(wchar_t)) - sizeof(wchar_t); + ret = GetLogicalDriveStringsW(sz, drive_list); + if (ret == 0 || ret > sz) + { + win32_warning(NULL, GetLastError(), "Failed enumerating fstab drives"); + return; + } + + for (drive = drive_list; (*drive) != '\0'; drive += wcslen(drive) + 1) { - for (drive = driveStrings; *drive != 0; drive += lstrlenA(drive) + 1) - { - if (_strnicmp("A:\\", drive, 3) != 0 - && _strnicmp("B:\\", drive, 3) != 0 - ) - { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Found fstab drive '%s'\n", drive); - gkrellm_fs_add_to_fstab_list(drive, drive, "", ""); - } - } + drive_type = GetDriveTypeW(drive); + + if ( (drive_type == DRIVE_REMOVABLE) + && (!wcsncmp(drive, L"A:\\", 3) || !wcsncmp(drive, L"B:\\", 3))) + continue; + + gkrellm_debug(DEBUG_SYSDEP, "Found fstab drive '%ls' of type %u\n", + drive, drive_type); + + drive_utf8 = g_utf16_to_utf8(drive, -1, NULL, NULL, NULL); + gkrellm_fs_add_to_fstab_list(drive_utf8, drive_utf8, + (drive_type == DRIVE_REMOTE ? "smbfs" : ""), ""); + g_free(drive_utf8); } } @@ -1448,47 +1975,70 @@ void gkrellm_sys_fs_get_fstab_list(void) gboolean gkrellm_sys_inet_init(void) { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT inet port monitoring\n"); + gkrellm_debug(DEBUG_SYSDEP, "INIT inet port monitoring\n"); return TRUE; } void gkrellm_sys_inet_read_tcp_data(void) { + // TODO: Make use of GetTcp6Table() by loading it at runtime + // (only available on vista and newer) PMIB_TCPTABLE pTcpTable = NULL; DWORD dwTableSize = 0; + DWORD dwStatus; + MIB_TCPROW *tcprow; + ActiveTCP tcp; + DWORD i; + + gkrellm_debug(DEBUG_SYSDEP, "Fetching list of TCP connections\n"); // Make an initial call to GetTcpTable to // get the necessary size into the dwSize variable - if (GetTcpTable(NULL, &dwTableSize, FALSE) == ERROR_INSUFFICIENT_BUFFER - && dwTableSize > 0 - ) + dwStatus = GetTcpTable(NULL, &dwTableSize, FALSE); + + if ((dwStatus == ERROR_INSUFFICIENT_BUFFER) && (dwTableSize > 0)) { - pTcpTable = (MIB_TCPTABLE *)malloc(dwTableSize); + pTcpTable = (MIB_TCPTABLE *)g_malloc(dwTableSize); // Make a second call to GetTcpTable to get // the actual data we require - if (GetTcpTable(pTcpTable, &dwTableSize, FALSE) == NO_ERROR) + dwStatus = GetTcpTable(pTcpTable, &dwTableSize, FALSE); + + if (dwStatus == NO_ERROR) { - ActiveTCP tcp; - DWORD i; for (i = 0; i < pTcpTable->dwNumEntries; i++) { - MIB_TCPROW *row = &pTcpTable->table[i]; + tcprow = &pTcpTable->table[i]; - if (row->dwState != MIB_TCP_STATE_ESTAB) + // Skip connections that are not fully established + if (tcprow->dwState != MIB_TCP_STATE_ESTAB) continue; tcp.family = AF_INET; - tcp.local_port = htons(row->dwLocalPort); - tcp.remote_port = htons(row->dwRemotePort); - tcp.remote_addr.s_addr = row->dwRemoteAddr; + tcp.local_port = htons(tcprow->dwLocalPort); + tcp.remote_addr.s_addr = tcprow->dwRemoteAddr; +#if defined(INET6) + tcp.in6_addr = 0; +#endif + tcp.remote_port = htons(tcprow->dwRemotePort); + tcp.is_udp = FALSE; gkrellm_inet_log_tcp_port_data(&tcp); } } - free(pTcpTable); + else + { + win32_warning(NULL, dwStatus, + "Could not fetch list of TCP connections"); + } + + g_free(pTcpTable); + } + else + { + win32_warning(NULL, dwStatus, + "Could not fetch list of TCP connections"); } } @@ -1497,60 +2047,49 @@ void gkrellm_sys_inet_read_tcp_data(void) /* Uptime monitor interface */ /* ===================================================================== */ +static PDH_HCOUNTER uptimeCounter = NULL; + time_t gkrellm_sys_uptime_read_uptime(void) { - DWORD type; - PDH_FMT_COUNTERVALUE value; - long l = 0; + PDH_FMT_COUNTERVALUE val; + if (pdhQueryHandle == NULL) + return (time_t)0; win32_read_proc_stat(); + gkrellm_debug(DEBUG_SYSDEP, "Reading system uptime\n"); - if (pdhQueryHandle != 0) - { - status = PdhGetFormattedCounterValue(uptimeCounter, PDH_FMT_LONG, &type, &value); - if (status != ERROR_SUCCESS) - { - g_print("Getting uptime pdh-counter failed, status %ld\n", status); - return (time_t)0; - } - l = value.longValue; - } - - return (time_t) l; + if (!get_formatted_counter_value(uptimeCounter, "uptime", PDH_FMT_LONG, &val)) + return (time_t)0; + return (time_t)val.longValue; } - gboolean gkrellm_sys_uptime_init(void) { - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("INIT uptime monitoring\n"); + wchar_t system_name[128]; + wchar_t uptime_name[128]; + wchar_t counter_path[128+128+3]; - if (pdhQueryHandle == 0) + gkrellm_debug(DEBUG_SYSDEP, "INIT uptime monitoring\n"); + + if (pdhQueryHandle == NULL) return FALSE; - - status = PdhAddCounter(pdhQueryHandle, perfKeyList[Uptime], 0, &uptimeCounter); - if (status != ERROR_SUCCESS) - g_print("Failed adding uptime pdh-counter for path '%s', status %ld\n", perfKeyList[Uptime], status); - else if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Added uptime pdh-counter for path '%s'\n", perfKeyList[Uptime]); - return (status == ERROR_SUCCESS ? TRUE : FALSE); - } + // Fetch prefix for counter ("System" index is 2) + if (!lookup_perfname(2, system_name, 128)) + return FALSE; + // Fetch name for uptime ("Uptime" index is 674) + if (!lookup_perfname(674, uptime_name, 128)) + return FALSE; -/* ===================================================================== */ -/* hostname interface */ -/* ===================================================================== */ + _snwprintf(counter_path, sizeof(counter_path) / sizeof(wchar_t), + L"\\%ls\\%ls", + system_name, uptime_name); -gchar *gkrellm_sys_get_host_name(void) - { - static gboolean have_it; - static gchar buf[128]; + if (!add_counter(counter_path, &uptimeCounter)) + return FALSE; - if (!have_it && gethostname(buf, sizeof(buf)) != 0) - strcpy(buf, "unknown"); - have_it = TRUE; - return buf; + return TRUE; } @@ -1558,197 +2097,94 @@ gchar *gkrellm_sys_get_host_name(void) /* System name interface */ /* ===================================================================== */ + +typedef void (WINAPI *PGetNativeSystemInfo)(SYSTEM_INFO *); + gchar *gkrellm_sys_get_system_name(void) { - static gboolean have_sys_name; - static gchar sysname[24]; + static gboolean have_sys_name; + static gchar sysname[32]; + OSVERSIONINFOEXW vi; + SYSTEM_INFO si; + PGetNativeSystemInfo pGNSI; - if (!have_sys_name) + if (have_sys_name) + return sysname; + + gkrellm_debug(DEBUG_SYSDEP, "Retrieving system name\n"); + + // Default value for sysname + g_strlcpy(sysname, "Unknown", sizeof(sysname)); + + // Query version info + memset(&vi, 0, sizeof(OSVERSIONINFOEXW)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + if (!GetVersionExW((OSVERSIONINFOW *)(&vi))) + return sysname; + + // We actually only support decoding NT-based version info + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + return sysname; + + // Try to call native version first, as this allows detecting + // 64bit hosts from within a 32bit process. + pGNSI = (PGetNativeSystemInfo)GetProcAddress( + GetModuleHandleW(L"kernel32.dll"), "GetNativeSystemInfo"); + + if (pGNSI != NULL) + pGNSI(&si); + else + GetSystemInfo(&si); + + if (vi.dwMajorVersion == 6 && vi.dwMinorVersion == 0) { - OSVERSIONINFOEX info; - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + // Windows 6.0 aka Vista or Server 2008 - if (_GK.debug_level & DEBUG_SYSDEP) - g_print("Retrieving system name.\n"); - - GetVersionEx((OSVERSIONINFO *)(&info)); - - g_strlcpy(sysname, "Unknown", sizeof(sysname)); - if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - if (info.dwMajorVersion == 6 && info.dwMinorVersion == 0) - { // Windows 6.0 aka Vista or Server 2008 - if (info.wProductType == VER_NT_WORKSTATION) - g_strlcpy(sysname, "Windows Vista", sizeof(sysname)); - else - g_strlcpy(sysname, "Windows Server 2008", sizeof(sysname)); - } - else if (info.dwMajorVersion == 5) - { // Windows 5.x aka 2000, XP, Server 2003 - if (info.dwMinorVersion == 0) - g_strlcpy(sysname, "Windows 2000", sizeof(sysname)); - else if (info.dwMinorVersion == 1) - g_strlcpy(sysname, "Windows XP", sizeof(sysname)); - else if (info.dwMinorVersion == 2) - g_strlcpy(sysname, "Windows Server 2003", sizeof(sysname)); - } - else if (info.dwMajorVersion == 4) - { // NT4 - g_strlcpy(sysname, "Windows NT 4.0", sizeof(sysname)); - } - } // winnt + if (vi.wProductType == VER_NT_WORKSTATION) + g_strlcpy(sysname, "Windows Vista", sizeof(sysname)); + else + g_strlcpy(sysname, "Windows Server 2008", sizeof(sysname)); } + else if (vi.dwMajorVersion == 5) + { + // Windows 5.x aka 2000, XP, Server 2003 + + if (vi.dwMinorVersion == 0) + { + if (vi.wProductType == VER_NT_WORKSTATION) + g_strlcpy(sysname, "Windows 2000 Professional", sizeof(sysname)); + else + g_strlcpy(sysname, "Windows 2000 Server", sizeof(sysname)); + } + else if (vi.dwMinorVersion == 1) + { + if (vi.wSuiteMask & VER_SUITE_PERSONAL) + g_strlcpy(sysname, "Windows XP Home Edition", sizeof(sysname)); + else + g_strlcpy(sysname, "Windows XP Professional", sizeof(sysname)); + } + else if (vi.dwMinorVersion == 2) + { + if (GetSystemMetrics(SM_SERVERR2)) + g_strlcpy(sysname, "Windows Server 2003 R2", sizeof(sysname)); + else if (vi.wSuiteMask == VER_SUITE_STORAGE_SERVER) + g_strlcpy(sysname, "Windows Storage Server 2003", sizeof(sysname)); + else if ( vi.wProductType == VER_NT_WORKSTATION + && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + g_strlcpy(sysname, "Windows XP Professional x64", sizeof(sysname)); + else + g_strlcpy(sysname, "Windows Server 2003", sizeof(sysname)); + } + } + return sysname; - } /* gkrellm_sys_get_system_name() */ - - -/* ===================================================================== */ -/* MBMON interface */ -/* ===================================================================== */ - -gboolean gkrellm_sys_sensors_mbmon_port_change(gint port) -{ - return FALSE; -} - -gboolean gkrellm_sys_sensors_mbmon_supported(void) -{ - return FALSE; -} + } /* ===================================================================== */ /* Misc functions */ /* ===================================================================== */ - -static void -initPerfKeyList(void) - { - int i; - for (i = 0; i < PerfKeysSize; i++) - { - perfKeyList[i] = NULL; - } - - if (pdhQueryHandle == 0) - return; - - placePerfKeysFromReg(NumProcesses , 2 , 248); - placePerfKeysFromReg(NumThreads , 2 , 250); - placePerfKeysFromReg(Uptime , 2 , 674); - - placePerfKeyFromReg(CpuStart , 238, _T("\\") , _T("(")); - placePerfKeyFromReg(CpuTime , 6 , _T(")\\"), NULL); - placePerfKeyFromReg(CpuSysTime , 144, _T(")\\"), NULL); - placePerfKeyFromReg(NetDevStart , 510, _T("\\") , _T("(")); - placePerfKeyFromReg(NetDevRecv , 264, _T(")\\"), NULL); - placePerfKeyFromReg(NetDevSend , 896, _T(")\\"), NULL); - placePerfKeyFromReg(DiskStart , 234, _T("\\") , _T("(")); - placePerfKeyFromReg(DiskRead , 220, _T(")\\"), NULL); - placePerfKeyFromReg(DiskWrite , 222, _T(")\\"), NULL); - } - - -static void -placePerfKeysFromReg(const PerfKey key, unsigned int index1, unsigned int index2) - { - TCHAR buf[512]; - TCHAR perfName[512]; - PDH_STATUS stat; - DWORD size = 512; - - stat = PdhLookupPerfNameByIndex(NULL, index1, perfName, &size); - if (stat == ERROR_SUCCESS) - { - _tcsncpy(buf, _T("\\"), 512); - _tcsncat(buf, perfName, 512); - _tcsncat(buf, _T("\\"), 512); - - size = 512; - stat = PdhLookupPerfNameByIndex(NULL, index2, perfName, &size); - if (stat == ERROR_SUCCESS) - { - _tcsncat(buf, perfName, 512); - placePerfKey(key, buf); - } - else - { - g_print("could not find perflib index %d in registry\n", index2); - placePerfKey(key, NULL); - } - } - else - { - g_print("Could not find perflib index %d in registry\n", index1); - placePerfKey(key, NULL); - } - } - - -static void -placePerfKeyFromReg(const PerfKey key, unsigned int index, const TCHAR* prefix, - const TCHAR* suffix) - { - TCHAR buf[512]; - TCHAR perfName[512]; - PDH_STATUS stat; - DWORD size = 512; - - stat = PdhLookupPerfNameByIndex(NULL, index, perfName, &size); - if (stat == ERROR_SUCCESS) - { - if (prefix) - { - _tcsncpy(buf, prefix, 512); - _tcsncat(buf, perfName, 512); - } - else - { - _tcsncpy(buf, perfName, 512); - } - - if (suffix) - { - _tcsncat(buf, suffix, 512); - } - placePerfKey(key, buf); - } - else - { - g_print("could not find index %d in registry\n", index); - placePerfKey(key, NULL); - } - } - - -static void -placePerfKey(const PerfKey key, const TCHAR* value) - { - size_t strSize; - if (((int)key > -1) && ((int)key < PerfKeysSize)) - { - free(perfKeyList[key]); - if (value != NULL) - { - strSize = _tcsclen(value); - perfKeyList[key] = malloc(sizeof(TCHAR) * strSize + 1); - _tcscpy(perfKeyList[key], value); - } - else - { - perfKeyList[key] = NULL; - } - //g_print("perfKeyList[ %d ] = '%s'\n", key, perfKeyList[key]); - } - else - { - g_print("Invalid placement for key %d; value was '%s'\n", key, value); - } - } - - - /* * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. diff --git a/src/winops-win32.c b/src/winops-win32.c index a0c4ffa..a2a5952 100644 --- a/src/winops-win32.c +++ b/src/winops-win32.c @@ -24,234 +24,157 @@ #include "win32-resource.h" #include -static UINT WM_GKRELLMCALLBACK; -static WNDPROC oldWndProc = 0; static GdkGC *trans_gc = NULL; static GdkColor trans_color; - -void gkrellm_winop_reset(void) +void +gkrellm_winop_reset(void) { } - -LRESULT CALLBACK newWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - if (Msg == WM_GKRELLMCALLBACK) +void +gkrellm_winop_options(gint argc, gchar **argv) { - if (lParam == WM_LBUTTONUP) - SetForegroundWindow(GDK_WINDOW_HWND(gkrellm_get_top_window()->window)); - else if (lParam == WM_RBUTTONUP) - gkrellm_menu_popup(); - } - /*else if (Msg == WM_SIZE && _GK.withdrawn) - { - HWND slitHwnd = FindWindowEx(NULL, NULL, "BControl", "BSlitWindow"); - if (slitHwnd != NULL) - PostMessage(slitHwnd, BM_SLITMESSAGE, BSM_UPDATEPOSITIONS, 0); - InvalidateRgn(GDK_WINDOW_HWND(gkrellm_get_top_window()->window), NULL, FALSE); - }*/ - - return CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam); -} - -void gkrellm_winop_options(gint argc, gchar **argv) -{ - NOTIFYICONDATA nid; HWND hWnd = GDK_WINDOW_HWND(gkrellm_get_top_window()->window); - // get gtk window procedure and set new one - oldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC); - SetWindowLong(hWnd, GWL_WNDPROC, (LONG)newWndProc); - // Get rid of task list icon SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW); - // Create System Tray Icon - WM_GKRELLMCALLBACK = RegisterWindowMessage(TEXT("GKrellMCallback")); - - nid.cbSize = sizeof(NOTIFYICONDATA); - nid.hWnd = hWnd; - nid.uID = 1; - nid.uFlags = (NIF_ICON | NIF_TIP | NIF_MESSAGE); - nid.uCallbackMessage = WM_GKRELLMCALLBACK; - - strcpy(nid.szTip, g_locale_from_utf8(_("GKrellM for Windows"), -1, NULL, NULL, NULL)); - - nid.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON3)); - Shell_NotifyIcon(NIM_ADD, &nid); - + // Set stay-on-top flag if requested if (_GK.on_top) - { - // set stay on top flag if requested SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - } - - /*if (_GK.withdrawn) - { - // put in slit in bluebox - HWND slithWnd = FindWindowEx(NULL, NULL, "BControl", "BSlitWindow"); - SetProp(hWnd, "BSlitControl", (HANDLE)1); - - if (IsWindow(slithWnd)) - { - SendMessage(slithWnd, BM_SLITMESSAGE, BSM_ADDWINDOW, (LPARAM) hWnd); - SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); - gdk_window_move(gkrellm_get_top_window()->window, 0, 0); - _GK.x_position = 0; - _GK.y_position = 0; - _GK.position_valid = TRUE; - - SetWindowLong(hWnd, GWL_USERDATA, 0x49474541); - - PostMessage(slithWnd, BM_SLITMESSAGE, BSM_UPDATEPOSITIONS, 0); - InvalidateRgn(hWnd, NULL, FALSE); - } - }*/ -} - - -void gkrellm_winop_withdrawn(void) - { } -void gkrellm_winop_place_gkrellm(gchar *geom) - { - gint newX = _GK.x_position; - gint newY = _GK.y_position; +void +gkrellm_winop_withdrawn(void) + { + } - // parse the command line - // +x+y or -x+y or +x-y or -x-y +void +gkrellm_winop_place_gkrellm(gchar *geom) + { + gint newX = _GK.x_position; + gint newY = _GK.y_position; - gint startx = -1, starty = -1, endx = -1, endy = -1; - gint w_gkrell, h_gkrell; - gint stringSize = strlen(geom); - gint i; - gint xsign = 1, ysign = 1; - gchar* part; + // parse the command line + // +x+y or -x+y or +x-y or -x-y + + gint startx = -1, starty = -1, endx = -1, endy = -1; + gint w_gkrell, h_gkrell; + gint stringSize = strlen(geom); + gint i; + gint xsign = 1, ysign = 1; + gchar* part; for (i = 0; i < stringSize; i++) - { - if (geom[i] != '+' && geom[i] != '-') { + if (geom[i] != '+' && geom[i] != '-') + { if (startx == -1) - { - startx = i; - } + startx = i; if (starty == -1 && endx != -1) - { - starty = i; - } + starty = i; } else - { - if (startx != -1 && endx == -1) { - endx = i - 1; - if (geom[i] == '-') + if (startx != -1 && endx == -1) { - xsign = -1; - } + endx = i - 1; + if (geom[i] == '-') + xsign = -1; } if (starty != -1 && endy == -1) - { - endy = i - 1; - if (geom[i] == '-') { - ysign = -1; - } + endy = i - 1; + if (geom[i] == '-') + ysign = -1; } } } if (starty != -1 && endy == -1) - { - endy = stringSize - 1; - } + endy = stringSize - 1; - w_gkrell = _GK.chart_width + _GK.frame_left_width + _GK.frame_right_width; - h_gkrell = _GK.monitor_height + _GK.total_frame_height; + w_gkrell = _GK.chart_width + _GK.frame_left_width + _GK.frame_right_width; + h_gkrell = _GK.monitor_height + _GK.total_frame_height; if (startx >= 0 && startx <= endx && endx >= 0) - { - part = malloc(sizeof(gchar) * (endx - startx + 1 + 1)); + { + part = malloc(sizeof(gchar) * (endx - startx + 1 + 1)); for (i = 0; i < endx - startx + 1; i++) - { - part[i] = geom[i + startx]; - } - part[i] = '\0'; - newX = atoi(part); + part[i] = geom[i + startx]; + part[i] = '\0'; + newX = atoi(part); if (xsign == -1) - { - newX = _GK.w_display - w_gkrell + newX; - } - free(part); - } - if (starty >= 0 && starty <= endy && endy >= 0) - { - part = malloc(sizeof(gchar) * (endy - starty + 1 + 1)); - for (i = 0; i < endy - starty + 1; i++) - { - part[i] = geom[i + starty]; - } - part[i] = '\0'; - newY = atoi(part); - if (ysign == -1) - { - newY = _GK.h_display - h_gkrell + newY; - } + newX = _GK.w_display - w_gkrell + newX; + free(part); } - if (newX >= 0 && newX < _GK.w_display - 10 - && newY >= 0 && newY < _GK.h_display - 25) - { - gdk_window_move(gkrellm_get_top_window()->window, newX, newY); - _GK.y_position = newY; - _GK.x_position = newX; + if (starty >= 0 && starty <= endy && endy >= 0) + { + part = malloc(sizeof(gchar) * (endy - starty + 1 + 1)); + for (i = 0; i < endy - starty + 1; i++) + part[i] = geom[i + starty]; + part[i] = '\0'; + newY = atoi(part); + if (ysign == -1) + newY = _GK.h_display - h_gkrell + newY; } + + if ( newX >= 0 && newX < _GK.w_display - 10 + && newY >= 0 && newY < _GK.h_display - 25) + { + gdk_window_move(gkrellm_get_top_window()->window, newX, newY); + _GK.y_position = newY; + _GK.x_position = newX; + } + _GK.position_valid = TRUE; } -void gkrellm_winop_flush_motion_events(void) +void +gkrellm_winop_flush_motion_events(void) { } -gboolean gkrellm_winop_updated_background(void) +gboolean +gkrellm_winop_updated_background(void) { return TRUE; } -void gkrellm_winop_update_struts(void) +void +gkrellm_winop_update_struts(void) { } - -gboolean gkrellm_winop_draw_rootpixmap_onto_transparent_chart(GkrellmChart *p) +gboolean +gkrellm_winop_draw_rootpixmap_onto_transparent_chart(GkrellmChart *p) { - if (!p->transparency || !p->drawing_area || !p->drawing_area->window || trans_gc == NULL) - return FALSE; - + if (!p->transparency || !p->drawing_area || !p->drawing_area->window || !trans_gc) + return FALSE; + // Fill the panel with transparency color gdk_draw_rectangle(p->bg_src_pixmap, trans_gc, TRUE, 0, 0, p->w, p->h); // If mode permits, stencil on non transparent parts of bg_clean_pixmap. if (p->transparency == 2 && p->bg_mask) - { - gdk_gc_set_clip_mask(_GK.text_GC, p->bg_mask); - gdk_draw_drawable(p->bg_src_pixmap, _GK.text_GC, p->bg_clean_pixmap, 0, 0, 0, 0, p->w, p->h); - } + { + gdk_gc_set_clip_mask(_GK.text_GC, p->bg_mask); + gdk_draw_drawable(p->bg_src_pixmap, _GK.text_GC, p->bg_clean_pixmap, + 0, 0, 0, 0, p->w, p->h); + } gdk_gc_set_clip_mask(_GK.text_GC, NULL); p->bg_sequence_id += 1; return TRUE; } - - -gboolean gkrellm_winop_draw_rootpixmap_onto_transparent_panel(GkrellmPanel *p) +gboolean +gkrellm_winop_draw_rootpixmap_onto_transparent_panel(GkrellmPanel *p) { - if (!p->transparency || !p->drawing_area || !p->drawing_area->window || trans_gc == NULL) + if (!p->transparency || !p->drawing_area || !p->drawing_area->window || !trans_gc) return FALSE; gdk_gc_set_fill(trans_gc, GDK_SOLID); @@ -262,16 +185,17 @@ gboolean gkrellm_winop_draw_rootpixmap_onto_transparent_panel(GkrellmPanel *p) // If mode permits, stencil on non transparent parts of bg_clean_pixmap. if (p->transparency == 2 && p->bg_mask) - { + { gdk_gc_set_clip_mask(_GK.text_GC, p->bg_mask); - gdk_draw_drawable(p->bg_pixmap, _GK.text_GC, p->bg_clean_pixmap, 0, 0, 0, 0, p->w, p->h); + gdk_draw_drawable(p->bg_pixmap, _GK.text_GC, p->bg_clean_pixmap, + 0, 0, 0, 0, p->w, p->h); gdk_gc_set_clip_mask(_GK.text_GC, NULL); - } + } return TRUE; } - -static void draw_rootpixmap_onto_transparent_spacers(GkrellmMonitor *mon) +static void +draw_rootpixmap_onto_transparent_spacers(GkrellmMonitor *mon) { GkrellmMonprivate *mp = mon->privat; @@ -312,36 +236,36 @@ static void draw_rootpixmap_onto_transparent_spacers(GkrellmMonitor *mon) } } - -void gkrellm_winop_apply_rootpixmap_transparency(void) +void +gkrellm_winop_apply_rootpixmap_transparency(void) { static gboolean isTransparent = FALSE; - GList *list; + GList *list; GkrellmChart *cp; GkrellmPanel *p; - HWND w; + HWND w; w = GDK_WINDOW_HWND(gkrellm_get_top_window()->window); if (!_GK.any_transparency && isTransparent) - { // make opaque + { // make opaque SetWindowLong(w, GWL_EXSTYLE, GetWindowLong(w, GWL_EXSTYLE) & ~WS_EX_LAYERED); isTransparent = FALSE; return; - } + } else if (_GK.any_transparency && !isTransparent) - { // make transparent + { // make transparent if (trans_gc == NULL) - { + { GdkColormap *cm = gtk_widget_get_colormap(gkrellm_get_top_window()); trans_gc = gdk_gc_new(gkrellm_get_top_window()->window); if (trans_gc == NULL) - { - printf("ERROR: could not create trans_gc!\n"); + { + g_warning("Could not create trans_gc!\n"); return; - } - + } + gdk_gc_copy(trans_gc, _GK.draw1_GC); gdk_gc_set_fill(trans_gc, GDK_SOLID); @@ -350,65 +274,64 @@ void gkrellm_winop_apply_rootpixmap_transparency(void) trans_color.blue = 65535; if (!gdk_colormap_alloc_color(cm , &trans_color, FALSE, TRUE)) - { - printf("ERROR: could not allocate trans_color!\n"); - g_object_unref(trans_gc); - trans_gc = NULL; - return; - } + { + g_warning("Could not allocate trans_color!\n"); + g_object_unref(trans_gc); + trans_gc = NULL; + return; + } gdk_gc_set_foreground(trans_gc, &trans_color); - } - + } SetWindowLong(w, GWL_EXSTYLE, GetWindowLong(w, GWL_EXSTYLE) | WS_EX_LAYERED); SetLayeredWindowAttributes(w, RGB(255, 0, 255), 0, LWA_COLORKEY); isTransparent = TRUE; - } - + } if (isTransparent) - { - for (list = gkrellm_get_chart_list(); list; list = list->next) { + for (list = gkrellm_get_chart_list(); list; list = list->next) + { cp = (GkrellmChart *) list->data; if (!cp->transparency || !cp->shown) continue; gkrellm_winop_draw_rootpixmap_onto_transparent_chart(cp); gkrellm_refresh_chart(cp); - } + } for (list = gkrellm_get_panel_list(); list; list = list->next) - { + { p = (GkrellmPanel *) list->data; if (!p->transparency || !p->shown) continue; gkrellm_draw_panel_label(p); - } + } for (list = gkrellm_monitor_list; list; list = list->next) - { + { draw_rootpixmap_onto_transparent_spacers((GkrellmMonitor *)list->data); - } + } gdk_gc_set_clip_mask(_GK.text_GC, NULL); - } + } } - -void gkrellm_winop_state_skip_taskbar(gboolean state) +void +gkrellm_winop_state_skip_taskbar(gboolean state) { } - -void gkrellm_winop_state_skip_pager(gboolean state) +void +gkrellm_winop_state_skip_pager(gboolean state) { } -void gkrellm_winop_state_above(gboolean state) +void +gkrellm_winop_state_above(gboolean state) { } - -void gkrellm_winop_state_below(gboolean state) +void +gkrellm_winop_state_below(gboolean state) { }