summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/HPM.c2
-rw-r--r--src/common/Makefile.in24
-rw-r--r--src/common/console.c15
-rw-r--r--src/common/core.c151
-rw-r--r--src/common/core.h2
-rw-r--r--src/common/malloc.c8
-rw-r--r--src/common/sysinfo.c1022
-rw-r--r--src/common/sysinfo.h62
8 files changed, 1131 insertions, 155 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 971eb83bd..6d2c45641 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -703,8 +703,6 @@ void hplugins_share_defaults(void) {
HPM->share(&arg_c,"arg_c");
HPM->share(SERVER_NAME,"SERVER_NAME");
HPM->share(&SERVER_TYPE,"SERVER_TYPE");
- HPM->share((void*)get_svn_revision,"get_svn_revision");
- HPM->share((void*)get_git_hash,"get_git_hash");
HPM->share(DB, "DB");
HPM->share(HPMiMalloc, "iMalloc");
/* socket */
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index 7bb9ae630..623c59c2e 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -1,3 +1,5 @@
+# Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+# See the LICENSE file
CONFIG_D = ../config
CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h)
@@ -15,8 +17,8 @@ MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
MT19937AR_INCLUDE = -I$(MT19937AR_D)
COMMON_SHARED_C = conf.c db.c des.c ers.c grfio.c HPM.c mapindex.c md5calc.c \
- mutex.c nullpo.c random.c showmsg.c strlib.c thread.c \
- timer.c utils.c
+ mutex.c nullpo.c random.c showmsg.c strlib.c sysinfo.c \
+ thread.c timer.c utils.c
COMMON_C = $(COMMON_SHARED_C)
COMMON_SHARED_OBJ = $(patsubst %.c,%.o,$(COMMON_SHARED_C))
COMMON_OBJ = $(addprefix obj_all/, $(COMMON_SHARED_OBJ) \
@@ -27,11 +29,12 @@ COMMON_C += console.c core.c malloc.c socket.c
COMMON_H = atomic.h cbasetypes.h conf.h console.h core.h db.h des.h ers.h \
grfio.h HPM.h HPMi.h malloc.h mapindex.h md5calc.h mmo.h mutex.h \
nullpo.h random.h showmsg.h socket.h spinlock.h sql.h strlib.h \
- thread.h timer.h utils.h winapi.h
+ sysinfo.h thread.h timer.h utils.h winapi.h
COMMON_SQL_OBJ = obj_sql/sql.o
COMMON_SQL_H = sql.h
COMMON_C += sql.c
+SYSINFO_INC = sysinfo.inc
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
@@ -54,7 +57,7 @@ sql: $(SQL_DEPENDS)
buildclean:
@echo " CLEAN common (build temp files)"
- @rm -rf *.o obj_all obj_sql
+ @rm -rf *.o obj_all obj_sql sysinfo.inc
clean: buildclean
@echo " CLEAN common"
@@ -71,6 +74,10 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/common/Makefile
+$(SYSINFO_INC): $(COMMON_C) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+ @echo " MAKE $@"
+ @$(MAKE) -C ../.. sysinfo
+
needs_mysql:
@echo "MySQL not found or disabled by the configure script"
@exit 1
@@ -103,19 +110,20 @@ common_mini: $(COMMON_MINI_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) obj_all/common
common_sql: $(COMMON_SQL_OBJ) obj_sql/common_sql.a Makefile
-obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_all
+obj_all/sysinfo.o: sysinfo.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(SYSINFO_INC) | obj_all
+
+obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all
@echo " CC $<"
@$(CC) @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-obj_all/mini%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_all
+obj_all/mini%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all
@echo " CC $<"
@$(CC) @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) $(CONFIG_H) $(LIBCONFIG_H) | obj_sql
+obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) $(CONFIG_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_sql
@echo " CC $<"
@$(CC) @CFLAGS@ $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-
# missing object files
$(MT19937AR_OBJ):
@echo " MAKE $@"
diff --git a/src/common/console.c b/src/common/console.c
index ec228b563..d8f352c8a 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -5,6 +5,7 @@
#include "../common/cbasetypes.h"
#include "../common/showmsg.h"
#include "../common/core.h"
+#include "../common/sysinfo.h"
#include "../config/core.h"
#include "console.h"
@@ -41,8 +42,7 @@ struct console_interface console_s;
* CORE : Display title
*--------------------------------------*/
void display_title(void) {
- const char* svn = get_svn_revision();
- const char* git = get_git_hash();
+ const char *vcstype = sysinfo->vcstype();
ShowMessage("\n");
ShowMessage(""CL_BG_RED""CL_BT_WHITE" "CL_CLL""CL_NORMAL"\n");
@@ -57,10 +57,13 @@ void display_title(void) {
ShowMessage(""CL_BG_RED""CL_BT_WHITE" http://hercules.ws/board/ "CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_BG_RED""CL_BT_WHITE" "CL_CLL""CL_NORMAL"\n");
- if( git[0] != HERC_UNKNOWN_VER )
- ShowInfo("Git Hash: '"CL_WHITE"%s"CL_RESET"'\n", git);
- else if( svn[0] != HERC_UNKNOWN_VER )
- ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'\n", svn);
+ ShowInfo("Hercules %d-bit for %s\n", sysinfo->is64bit() ? 64 : 32, sysinfo->platform());
+ ShowInfo("%s revision (src): '"CL_WHITE"%s"CL_RESET"'\n", vcstype, sysinfo->vcsrevision_src());
+ ShowInfo("%s revision (scripts): '"CL_WHITE"%s"CL_RESET"'\n", vcstype, sysinfo->vcsrevision_scripts());
+ ShowInfo("OS version: '"CL_WHITE"%s"CL_RESET" [%s]'\n", sysinfo->osversion(), sysinfo->arch());
+ ShowInfo("CPU: '"CL_WHITE"%s [%d]"CL_RESET"'\n", sysinfo->cpu(), sysinfo->cpucores());
+ ShowInfo("Compiled with %s\n", sysinfo->compiler());
+ ShowInfo("Compile Flags: %s\n", sysinfo->cflags());
}
#ifdef CONSOLE_INPUT
#if defined(WIN32)
diff --git a/src/common/core.c b/src/common/core.c
index c6075da40..798c832f0 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -9,6 +9,7 @@
#include "core.h"
#include "../common/console.h"
#include "../common/random.h"
+#include "../common/sysinfo.h"
#ifndef MINICORE
#include "../common/db.h"
@@ -78,7 +79,7 @@ sigfunc *compat_signal(int signo, sigfunc *func) {
*--------------------------------------*/
#ifdef _WIN32
static BOOL WINAPI console_handler(DWORD c_event) {
- switch(c_event) {
+ switch(c_event) {
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
@@ -89,8 +90,8 @@ static BOOL WINAPI console_handler(DWORD c_event) {
break;
default:
return FALSE;
- }
- return TRUE;
+ }
+ return TRUE;
}
static void cevents_init() {
@@ -152,134 +153,21 @@ void signals_init (void) {
}
#endif
-const char* get_svn_revision(void) {
- static char svn_version_buffer[16] = "";
- FILE *fp;
-
- if( svn_version_buffer[0] != '\0' )
- return svn_version_buffer;
-
- // subversion 1.7 uses a sqlite3 database
- // FIXME this is hackish at best...
- // - ignores database file structure
- // - assumes the data in NODES.dav_cache column ends with "!svn/ver/<revision>/<path>)"
- // - since it's a cache column, the data might not even exist
- if( (fp = fopen(".svn"PATHSEP_STR"wc.db", "rb")) != NULL || (fp = fopen(".."PATHSEP_STR".svn"PATHSEP_STR"wc.db", "rb")) != NULL )
- {
- #ifndef SVNNODEPATH
- //not sure how to handle branches, so i'll leave this overridable define until a better solution comes up
- #define SVNNODEPATH trunk
- #endif
- const char* prefix = "!svn/ver/";
- const char* postfix = "/"EXPAND_AND_QUOTE(SVNNODEPATH)")"; // there should exist only 1 entry like this
- size_t prefix_len = strlen(prefix);
- size_t postfix_len = strlen(postfix);
- size_t i,j,len;
- char* buffer;
-
- // read file to buffer
- fseek(fp, 0, SEEK_END);
- len = ftell(fp);
- buffer = (char*)aMalloc(len + 1);
- fseek(fp, 0, SEEK_SET);
- len = fread(buffer, 1, len, fp);
- buffer[len] = '\0';
- fclose(fp);
-
- // parse buffer
- for( i = prefix_len + 1; i + postfix_len <= len; ++i ) {
- if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 )
- continue; // postfix missmatch
- for( j = i; j > 0; --j ) {// skip digits
- if( !ISDIGIT(buffer[j - 1]) )
- break;
- }
- if( memcmp(buffer + j - prefix_len, prefix, prefix_len) != 0 )
- continue; // prefix missmatch
- // done
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(buffer + j));
- break;
- }
- aFree(buffer);
-
- if( svn_version_buffer[0] != '\0' )
- return svn_version_buffer;
- }
-
- // subversion 1.6 and older?
- if ((fp = fopen(".svn/entries", "r")) != NULL) {
- char line[1024];
- int rev;
- // Check the version
- if (fgets(line, sizeof(line), fp)) {
- if(!ISDIGIT(line[0])) {
- // XML File format
- while (fgets(line,sizeof(line),fp))
- if (strstr(line,"revision=")) break;
- if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) {
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", rev);
- }
- } else {
- // Bin File format
- if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get bin name\n"); } // Get the name
- if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get entries kind\n"); } // Get the entries kind
- if(fgets(line, sizeof(line), fp)) { // Get the rev numver
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(line));
- }
- }
- }
- fclose(fp);
-
- if( svn_version_buffer[0] != '\0' )
- return svn_version_buffer;
- }
-
- // fallback
- svn_version_buffer[0] = HERC_UNKNOWN_VER;
- return svn_version_buffer;
-}
-/* whats our origin */
-#define GIT_ORIGIN "refs/remotes/origin/master"
-/* Grabs the hash from the last time the user updated his working copy (last pull) */
-const char *get_git_hash (void) {
- static char HerculesGitHash[41] = "";//Sha(40) + 1
- FILE *fp;
-
- if( HerculesGitHash[0] != '\0' )
- return HerculesGitHash;
-
- if ( (fp = fopen (".git/"GIT_ORIGIN, "r")) != NULL) {
- char line[64];
- char *rev = malloc (sizeof (char) * 50);
-
- if (fgets (line, sizeof (line), fp) && sscanf (line, "%50s", rev))
- snprintf (HerculesGitHash, sizeof (HerculesGitHash), "%s", rev);
-
- free (rev);
- fclose (fp);
- } else {
- HerculesGitHash[0] = HERC_UNKNOWN_VER;
- }
-
- if (! (*HerculesGitHash)) {
- HerculesGitHash[0] = HERC_UNKNOWN_VER;
- }
-
- return HerculesGitHash;
-}
-// Warning if executed as superuser (root)
+/**
+ * Warns the user if executed as superuser (root)
+ */
void usercheck(void) {
-#ifndef _WIN32
- if (geteuid() == 0) {
- ShowWarning ("You are running Hercules with root privileges, it is not necessary.\n");
- }
-#endif
+ if (sysinfo->is_superuser()) {
+ ShowWarning("You are running Hercules with root privileges, it is not necessary.\n");
+ }
}
+
void core_defaults(void) {
#ifndef MINICORE
hpm_defaults();
HCache_defaults();
#endif
+ sysinfo_defaults();
console_defaults();
strlib_defaults();
malloc_defaults();
@@ -318,16 +206,18 @@ int main (int argc, char **argv) {
iMalloc->init();// needed for Show* in display_title() [FlavioJS]
+ sysinfo->init();
+
if (!(msg_silent&0x1))
console->display_title();
-
-#ifdef MINICORE // minimalist Core
+
usercheck();
+
+#ifdef MINICORE // minimalist Core
do_init(argc,argv);
do_final();
#else// not MINICORE
set_server_type();
- usercheck();
Sql_Init();
rathread_init();
@@ -348,10 +238,8 @@ int main (int argc, char **argv) {
HCache->init();
-#ifndef MINICORE
HPM->init();
-#endif
-
+
sockt->init();
do_init(argc,argv);
@@ -366,15 +254,14 @@ int main (int argc, char **argv) {
console->final();
do_final();
-#ifndef MINICORE
HPM->final();
-#endif
timer->final();
sockt->final();
DB->final();
rathread_final();
ers_final();
#endif
+ sysinfo->final();
iMalloc->final();
diff --git a/src/common/core.h b/src/common/core.h
index 72f956e1d..2cb623bc2 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -32,8 +32,6 @@ enum server_types {
enum server_types SERVER_TYPE;
-const char *get_svn_revision(void);
-const char *get_git_hash (void);
extern int do_init(int,char**);
extern void set_server_type(void);
extern void do_abort(void);
diff --git a/src/common/malloc.c b/src/common/malloc.c
index f7f108304..5b39cbab6 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -5,6 +5,7 @@
#include "../common/malloc.h"
#include "../common/core.h"
#include "../common/showmsg.h"
+#include "../common/sysinfo.h"
#include <stdio.h>
#include <stdlib.h>
@@ -574,17 +575,14 @@ static void memmgr_log (char *buf)
if( !log_fp ) {
time_t raw;
struct tm* t;
- const char* svn = get_svn_revision();
- const char* git = get_git_hash();
log_fp = fopen(memmer_logfile,"at");
if (!log_fp) log_fp = stdout;
time(&raw);
t = localtime(&raw);
- fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (rev %s).\n",
- (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
- git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown");
+ fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (%s rev '%s').\n",
+ (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, sysinfo->vcstype(), sysinfo->vcsrevision_src());
}
fprintf(log_fp, "%s", buf);
return;
diff --git a/src/common/sysinfo.c b/src/common/sysinfo.c
new file mode 100644
index 000000000..a56896458
--- /dev/null
+++ b/src/common/sysinfo.c
@@ -0,0 +1,1022 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Base Author: Haru @ http://hercules.ws
+
+/// See sysinfo.h for a description of this file
+
+#define _COMMON_SYSINFO_P_
+#include "sysinfo.h"
+#undef _COMMON_SYSINFO_P_
+
+#include "../common/cbasetypes.h"
+#include "../common/core.h"
+#include "../common/strlib.h"
+#include "../common/malloc.h"
+
+#ifdef WIN32
+#include <windows.h>
+#include <string.h> // strlen
+#else
+#include <unistd.h>
+#endif
+#include <stdio.h> // fopen
+#include <stdlib.h> // atoi
+
+/// sysinfo.c interface source
+struct sysinfo_interface sysinfo_s;
+struct sysinfo_private sysinfo_p;
+
+#define VCSTYPE_UNKNOWN 0
+#define VCSTYPE_GIT 1
+#define VCSTYPE_SVN 2
+#define VCSTYPE_NONE -1
+
+#ifdef WIN32
+/**
+ * Values to be used with GetProductInfo.
+ *
+ * These aren't defined in MSVC2008/WindowsXP, so we gotta define them here.
+ * Values from: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724358%28v=vs.85%29.aspx
+ */
+enum windows_product_type {
+ msPRODUCT_UNDEFINED = 0x00000000, ///< An unknown product
+ msPRODUCT_ULTIMATE = 0x00000001, ///< Ultimate
+ msPRODUCT_HOME_BASIC = 0x00000002, ///< Home Basic
+ msPRODUCT_HOME_PREMIUM = 0x00000003, ///< Home Premium
+ msPRODUCT_ENTERPRISE = 0x00000004, ///< Enterprise
+ msPRODUCT_HOME_BASIC_N = 0x00000005, ///< Home Basic N
+ msPRODUCT_BUSINESS = 0x00000006, ///< Business
+ msPRODUCT_STANDARD_SERVER = 0x00000007, ///< Server Standard
+ msPRODUCT_DATACENTER_SERVER = 0x00000008, ///< Server Datacenter (full installation)
+ msPRODUCT_SMALLBUSINESS_SERVER = 0x00000009, ///< Windows Small Business Server
+ msPRODUCT_ENTERPRISE_SERVER = 0x0000000A, ///< Server Enterprise (full installation)
+ msPRODUCT_STARTER = 0x0000000B, ///< Starter
+ msPRODUCT_DATACENTER_SERVER_CORE = 0x0000000C, ///< Server Datacenter (core installation)
+ msPRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E, ///< Server Enterprise (core installation)
+ msPRODUCT_STANDARD_SERVER_CORE = 0x0000000D, ///< Server Standard (core installation)
+ msPRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F, ///< Server Enterprise for Itanium-based Systems
+ msPRODUCT_BUSINESS_N = 0x00000010, ///< Business N
+ msPRODUCT_WEB_SERVER = 0x00000011, ///< Web Server (full installation)
+ msPRODUCT_CLUSTER_SERVER = 0x00000012, ///< HPC Edition
+ msPRODUCT_HOME_SERVER = 0x00000013, ///< Windows Storage Server 2008 R2 Essentials
+ msPRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014, ///< Storage Server Express
+ msPRODUCT_STORAGE_STANDARD_SERVER = 0x00000015, ///< Storage Server Standard
+ msPRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016, ///< Storage Server Workgroup
+ msPRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017, ///< Storage Server Enterprise
+ msPRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018, ///< Windows Server 2008 for Windows Essential Server Solutions
+ msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019, ///< Small Business Server Premium
+ msPRODUCT_HOME_PREMIUM_N = 0x0000001A, ///< Home Premium N
+ msPRODUCT_ENTERPRISE_N = 0x0000001B, ///< Enterprise N
+ msPRODUCT_ULTIMATE_N = 0x0000001C, ///< Ultimate N
+ msPRODUCT_WEB_SERVER_CORE = 0x0000001D, ///< Web Server (core installation)
+ msPRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E, ///< Windows Essential Business Server Management Server
+ msPRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F, ///< Windows Essential Business Server Security Server
+ msPRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020, ///< Windows Essential Business Server Messaging Server
+ msPRODUCT_SERVER_FOUNDATION = 0x00000021, ///< Server Foundation
+ msPRODUCT_HOME_PREMIUM_SERVER = 0x00000022, ///< Windows Home Server 2011
+ msPRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023, ///< Windows Server 2008 without Hyper-V for Windows Essential Server Solutions
+ msPRODUCT_STANDARD_SERVER_V = 0x00000024, ///< Server Standard without Hyper-V
+ msPRODUCT_DATACENTER_SERVER_V = 0x00000025, ///< Server Datacenter without Hyper-V (full installation)
+ msPRODUCT_ENTERPRISE_SERVER_V = 0x00000026, ///< Server Enterprise without Hyper-V (full installation)
+ msPRODUCT_DATACENTER_SERVER_CORE_V = 0x00000027, ///< Server Datacenter without Hyper-V (core installation)
+ msPRODUCT_STANDARD_SERVER_CORE_V = 0x00000028, ///< Server Standard without Hyper-V (core installation)
+ msPRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029, ///< Server Enterprise without Hyper-V (core installation)
+ msPRODUCT_HYPERV = 0x0000002A, ///< Microsoft Hyper-V Server
+ msPRODUCT_STORAGE_EXPRESS_SERVER_CORE = 0x0000002B, ///< Storage Server Express (core installation)
+ msPRODUCT_STORAGE_STANDARD_SERVER_CORE = 0x0000002C, ///< Storage Server Standard (core installation)
+ msPRODUCT_STORAGE_WORKGROUP_SERVER_CORE = 0x0000002D, ///< Storage Server Workgroup (core installation)
+ msPRODUCT_STORAGE_ENTERPRISE_SERVER_CORE = 0x0000002E, ///< Storage Server Enterprise (core installation)
+ msPRODUCT_STARTER_N = 0x0000002F, ///< Starter N
+ msPRODUCT_PROFESSIONAL = 0x00000030, ///< Professional
+ msPRODUCT_PROFESSIONAL_N = 0x00000031, ///< Professional N
+ msPRODUCT_SB_SOLUTION_SERVER = 0x00000032, ///< Windows Small Business Server 2011 Essentials
+ msPRODUCT_SERVER_FOR_SB_SOLUTIONS = 0x00000033, ///< Server For SB Solutions
+ msPRODUCT_STANDARD_SERVER_SOLUTIONS = 0x00000034, ///< Server Solutions Premium
+ msPRODUCT_STANDARD_SERVER_SOLUTIONS_CORE = 0x00000035, ///< Server Solutions Premium (core installation)
+ msPRODUCT_SB_SOLUTION_SERVER_EM = 0x00000036, ///< Server For SB Solutions EM
+ msPRODUCT_SERVER_FOR_SB_SOLUTIONS_EM = 0x00000037, ///< Server For SB Solutions EM
+ msPRODUCT_SOLUTION_EMBEDDEDSERVER = 0x00000038, ///< Windows MultiPoint Server
+ msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMT = 0x0000003B, ///< Windows Essential Server Solution Management
+ msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDL = 0x0000003C, ///< Windows Essential Server Solution Additional
+ msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC = 0x0000003D, ///< Windows Essential Server Solution Management SVC
+ msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC = 0x0000003E, ///< Windows Essential Server Solution Additional SVC
+ msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE = 0x0000003F, ///< Small Business Server Premium (core installation)
+ msPRODUCT_CLUSTER_SERVER_V = 0x00000040, ///< Server Hyper Core V
+ msPRODUCT_STARTER_E = 0x00000042, ///< Not supported
+ msPRODUCT_HOME_BASIC_E = 0x00000043, ///< Not supported
+ msPRODUCT_HOME_PREMIUM_E = 0x00000044, ///< Not supported
+ msPRODUCT_PROFESSIONAL_E = 0x00000045, ///< Not supported
+ msPRODUCT_ENTERPRISE_E = 0x00000046, ///< Not supported
+ msPRODUCT_ULTIMATE_E = 0x00000047, ///< Not supported
+ msPRODUCT_ENTERPRISE_EVALUATION = 0x00000048, ///< Server Enterprise (evaluation installation)
+ msPRODUCT_MULTIPOINT_STANDARD_SERVER = 0x0000004C, ///< Windows MultiPoint Server Standard (full installation)
+ msPRODUCT_MULTIPOINT_PREMIUM_SERVER = 0x0000004D, ///< Windows MultiPoint Server Premium (full installation)
+ msPRODUCT_STANDARD_EVALUATION_SERVER = 0x0000004F, ///< Server Standard (evaluation installation)
+ msPRODUCT_DATACENTER_EVALUATION_SERVER = 0x00000050, ///< Server Datacenter (evaluation installation)
+ msPRODUCT_ENTERPRISE_N_EVALUATION = 0x00000054, ///< Enterprise N (evaluation installation)
+ msPRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER = 0x0000005F, ///< Storage Server Workgroup (evaluation installation)
+ msPRODUCT_STORAGE_STANDARD_EVALUATION_SERVER = 0x00000060, ///< Storage Server Standard (evaluation installation)
+ msPRODUCT_CORE_N = 0x00000062, ///< Windows 8 N
+ msPRODUCT_CORE_COUNTRYSPECIFIC = 0x00000063, ///< Windows 8 China
+ msPRODUCT_CORE_SINGLELANGUAGE = 0x00000064, ///< Windows 8 Single Language
+ msPRODUCT_CORE = 0x00000065, ///< Windows 8
+ msPRODUCT_PROFESSIONAL_WMC = 0x00000067, ///< Professional with Media Center
+};
+
+/**
+ * Values to be used with GetSystemMetrics.
+ *
+ * Values from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx
+ */
+enum windows_metrics {
+ msSM_SERVERR2 = 89, ///< Obtains the build number if the system is Windows Server 2003 R2; otherwise, 0.
+};
+
+/**
+ * Values to be used with OSVERSIONINFOEX.wSuiteMask.
+ *
+ * Values from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724833%28v=vs.85%29.aspx
+ */
+enum windows_ver_suite {
+ msVER_SUITE_BLADE = 0x00000400, ///< Windows Server 2003, Web Edition is installed.
+ msVER_SUITE_STORAGE_SERVER = 0x00002000, ///< Windows Storage Server 2003 R2 or Windows Storage Server 2003 is installed.
+ msVER_SUITE_COMPUTE_SERVER = 0x00004000, ///< Windows Server 2003, Compute Cluster Edition is installed.
+ msVER_SUITE_WH_SERVER = 0x00008000, ///< Windows Home Server is installed.
+};
+
+#else // not WIN32
+// UNIX. Use build-time cached values
+#include "sysinfo.inc"
+#endif // WIN32
+
+// Compiler detection <http://sourceforge.net/p/predef/wiki/Compilers/>
+#if defined(__BORLANDC__)
+#define SYSINFO_COMPILER "Borland C++"
+#elif defined(__clang__)
+#define SYSINFO_COMPILER "Clang v" EXPAND_AND_QUOTE(__clang_major__) "." EXPAND_AND_QUOTE(__clang_minor__) "." EXPAND_AND_QUOTE(__clang_patchlevel__)
+#elif defined(__INTEL_COMPILER)
+#define SYSINFO_COMPILER "Intel CC v" EXPAND_AND_QUOTE(__INTEL_COMPILER)
+#elif defined(__MINGW32__)
+#if defined(__MINGW64__)
+#define SYSINFO_COMPILER "MinGW-w64 64 Bit v" EXPAND_AND_QUOTE(__MINGW64_VERSION_MAJOR) "." EXPAND_AND_QUOTE(__MINGW64_VERSION_MINOR) \
+ " (MinGW " EXPAND_AND_QUOTE(__MINGW32_MAJOR_VERSION) "." EXPAND_AND_QUOTE(__MINGW32_MINOR_VERSION) ")"
+#elif defined(__MINGW64_VERSION_MAJOR)
+#define SYSINFO_COMPILER "MinGW-w64 32 Bit v" EXPAND_AND_QUOTE(__MINGW64_VERSION_MAJOR) "." EXPAND_AND_QUOTE(__MINGW64_VERSION_MINOR) \
+ " (MinGW " EXPAND_AND_QUOTE(__MINGW32_MAJOR_VERSION) "." EXPAND_AND_QUOTE(__MINGW32_MINOR_VERSION) ")"
+#else
+#define SYSINFO_COMPILER "MinGW32 v" EXPAND_AND_QUOTE(__MINGW32_MAJOR_VERSION) "." EXPAND_AND_QUOTE(__MINGW32_MINOR_VERSION)
+#endif
+#elif defined(__GNUC__)
+#define SYSINFO_COMPILER "GCC v" EXPAND_AND_QUOTE(__GNUC__) "." EXPAND_AND_QUOTE(__GNUC_MINOR__) "." EXPAND_AND_QUOTE(__GNUC_PATCHLEVEL__)
+#elif defined(_MSC_VER)
+#if _MSC_VER >= 1300 && _MSC_VER < 1310
+#define SYSINFO_COMPILER "Microsoft Visual C++ 7.0 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#elif _MSC_VER >= 1310 && _MSC_VER < 1400
+#define SYSINFO_COMPILER "Microsoft Visual C++ 2003 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#elif _MSC_VER >= 1400 && _MSC_VER < 1500
+#define SYSINFO_COMPILER "Microsoft Visual C++ 2005 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#elif _MSC_VER >= 1500 && _MSC_VER < 1600
+#define SYSINFO_COMPILER "Microsoft Visual C++ 2008 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#elif _MSC_VER >= 1600 && _MSC_VER < 1700
+#define SYSINFO_COMPILER "Microsoft Visual C++ 2010 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#elif _MSC_VER >= 1700 && _MSC_VER < 1800
+#define SYSINFO_COMPILER "Microsoft Visual C++ 2012 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#elif _MSC_VER >= 1800 && _MSC_VER < 1900
+#define SYSINFO_COMPILER "Microsoft Visual C++ 2013 (v" EXPAND_AND_QUOTE(_MSC_VER) ")"
+#else // < 1300 || >= 1900
+#define SYSINFO_COMPILER "Microsoft Visual C++ v" EXPAND_AND_QUOTE(_MSC_VER)
+#endif
+#else
+#define SYSINFO_COMPILER "Unknown"
+#endif
+// end compiler detection
+
+/**
+ * Retrieves the current SVN revision.
+ *
+ * @param out[out] a string pointer to return the value (to be aFree()'d.)
+ * @retval true if a revision was correctly detected.
+ * @retval false if no revision was detected. out is set to NULL in this case.
+ */
+bool sysinfo_svn_get_revision(char **out) {
+ // Only include SVN support if detected it, or we're on MSVC
+#if !defined(SYSINFO_VCSTYPE) || SYSINFO_VCSTYPE == VCSTYPE_SVN || SYSINFO_VCSTYPE == VCSTYPE_UNKNOWN
+ FILE *fp;
+
+ // subversion 1.7 uses a sqlite3 database
+ // FIXME this is hackish at best...
+ // - ignores database file structure
+ // - assumes the data in NODES.dav_cache column ends with "!svn/ver/<revision>/<path>)"
+ // - since it's a cache column, the data might not even exist
+ if ((fp = fopen(".svn"PATHSEP_STR"wc.db", "rb")) != NULL || (fp = fopen(".."PATHSEP_STR".svn"PATHSEP_STR"wc.db", "rb")) != NULL) {
+
+#ifndef SVNNODEPATH //not sure how to handle branches, so i'll leave this overridable define until a better solution comes up
+#define SVNNODEPATH trunk
+#endif // SVNNODEPATH
+
+ const char* prefix = "!svn/ver/";
+ const char* postfix = "/"EXPAND_AND_QUOTE(SVNNODEPATH)")"; // there should exist only 1 entry like this
+ size_t prefix_len = strlen(prefix);
+ size_t postfix_len = strlen(postfix);
+ size_t i,j,flen;
+ char* buffer;
+
+ // read file to buffer
+ fseek(fp, 0, SEEK_END);
+ flen = ftell(fp);
+ buffer = (char*)aMalloc(flen + 1);
+ fseek(fp, 0, SEEK_SET);
+ flen = fread(buffer, 1, flen, fp);
+ buffer[flen] = '\0';
+ fclose(fp);
+
+ // parse buffer
+ for (i = prefix_len + 1; i + postfix_len <= flen; ++i) {
+ if (buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0)
+ continue; // postfix mismatch
+ for (j = i; j > 0; --j) { // skip digits
+ if (!ISDIGIT(buffer[j - 1]))
+ break;
+ }
+ if (memcmp(buffer + j - prefix_len, prefix, prefix_len) != 0)
+ continue; // prefix mismatch
+ // done
+ if (*out != NULL)
+ aFree(*out);
+ *out = aCalloc(1, 8);
+ snprintf(*out, 8, "%d", atoi(buffer + j));
+ break;
+ }
+ aFree(buffer);
+
+ if (*out != NULL)
+ return true;
+ }
+
+ // subversion 1.6 and older?
+ if ((fp = fopen(".svn/entries", "r")) != NULL) {
+ char line[1024];
+ int rev;
+ // Check the version
+ if (fgets(line, sizeof(line), fp)) {
+ if (!ISDIGIT(line[0])) {
+ // XML File format
+ while (fgets(line,sizeof(line),fp))
+ if (strstr(line,"revision=")) break;
+ if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) {
+ if (*out != NULL)
+ aFree(*out);
+ *out = aCalloc(1, 8);
+ snprintf(*out, 8, "%d", rev);
+ }
+ } else {
+ // Bin File format
+ if (fgets(line, sizeof(line), fp) == NULL) { printf("Can't get bin name\n"); } // Get the name
+ if (fgets(line, sizeof(line), fp) == NULL) { printf("Can't get entries kind\n"); } // Get the entries kind
+ if (fgets(line, sizeof(line), fp)) { // Get the rev numver
+ if (*out != NULL)
+ aFree(*out);
+ *out = aCalloc(1, 8);
+ snprintf(*out, 8, "%d", atoi(line));
+ }
+ }
+ }
+ fclose(fp);
+
+ if (*out != NULL)
+ return true;
+ }
+#endif
+ if (*out != NULL)
+ aFree(*out);
+ *out = NULL;
+ return false;
+}
+
+/**
+ * Retrieves the current Git revision.
+ *
+ * @param out[out] a string pointer to return the value (to be aFree()'d.)
+ * @retval true if a revision was correctly detected.
+ * @retval false if no revision was detected. out is set to NULL in this case.
+ */
+bool sysinfo_git_get_revision(char **out) {
+ // Only include Git support if we detected it, or we're on MSVC
+#if !defined(SYSINFO_VCSTYPE) || SYSINFO_VCSTYPE == VCSTYPE_GIT || SYSINFO_VCSTYPE == VCSTYPE_UNKNOWN
+ FILE *fp;
+ char ref[128], filepath[128], line[128];
+
+ strcpy(ref, "HEAD");
+
+ while (*ref) {
+ snprintf(filepath, sizeof(filepath), ".git/%s", ref);
+ if ((fp = fopen(filepath, "r")) != NULL) {
+ if (fgets(line, sizeof(line)-1, fp) == NULL) {
+ fclose(fp);
+ break;
+ }
+ fclose(fp);
+ if (sscanf(line, "ref: %127[^\n]", ref) == 1) {
+ continue;
+ } else if (sscanf(line, "%127[a-f0-9]", ref) == 1 && strlen(ref) == 40) {
+ if (*out != NULL)
+ aFree(*out);
+ *out = aStrdup(ref);
+ }
+ }
+ break;
+ }
+ if (*out != NULL)
+ return true;
+#else
+ if (*out != NULL)
+ aFree(*out);
+ *out = NULL;
+#endif
+ return false;
+}
+
+#ifdef WIN32
+
+/// Windows-specific runtime detection functions.
+
+typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
+/**
+ * Retrieves the Operating System version (Windows only).
+ *
+ * Once retrieved, the version string is stored into sysinfo->p->osversion.
+ */
+void sysinfo_osversion_retrieve(void) {
+ OSVERSIONINFOEX osvi;
+ StringBuf buf;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ StrBuf->Init(&buf);
+
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+ if (sysinfo->p->osversion != NULL) {
+ aFree(sysinfo->p->osversion);
+ sysinfo->p->osversion = NULL;
+ }
+
+ /*
+ * #pragma rantmode (on)
+ * Some engineer at Microsoft moronically decided that, since some applications use this information to do version checks and refuse to
+ * run if they detect a new, unknown version of Windows, now nobody will be able to rely on this information anymore, not even those who
+ * need it for reporting or logging.
+ * The correct fix was to let those applications break, and their developer fix them (and in the meanwhile let the users use the
+ * Compatibility settings to run them) but no, they decided they'd deprecate the API, and make it lie for those who use it, reporting
+ * windows 8 even if they're running on 8.1 or newer.
+ * The API wasn't broken, applications were. Now we have broken applications, and a broken API. Great move, Microsoft. Oh right,
+ * there's the Version API helper functions. Or maybe not, since you can only do 'are we running on at least version X?' checks with
+ * those, it's not what we need.
+ * You know what? I'll just silence your deprecation warning for the time being. Maybe by the time you release the next version of
+ * Windows, you'll have provided a less crippled API or something.
+ * #pragma rantmode (off)
+ */
+#pragma warning (push)
+#pragma warning (disable : 4996)
+ if (!GetVersionEx((OSVERSIONINFO*) &osvi)) {
+ sysinfo->p->osversion = aStrdup("Unknown Version");
+ return;
+ }
+#pragma warning (pop)
+
+ if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId // Windows NT Family
+ && ((osvi.dwMajorVersion > 4 && osvi.dwMajorVersion < 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 3)) // Between XP and 8.1
+ ) {
+ if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 3) { // Between Vista and 8.1
+ PGPI pGPI;
+ DWORD dwType;
+ if (osvi.dwMinorVersion == 0) {
+ StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows Server 2008");
+ } else if (osvi.dwMinorVersion == 1) {
+ StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows Server 2008 R2");
+ } else {
+ // If it's 2, it can be Windows 8, or any newer version (8.1 at the time of writing this) -- see above for the reason.
+ switch (osvi.dwMinorVersion) {
+ case 2:
+ {
+ ULONGLONG mask = 0;
+ OSVERSIONINFOEX osvi2;
+ ZeroMemory(&osvi2, sizeof(OSVERSIONINFOEX));
+ osvi2.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ osvi2.dwMajorVersion = 6;
+ osvi2.dwMinorVersion = 2;
+ VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_LESS_EQUAL);
+ VER_SET_CONDITION(mask, VER_MINORVERSION, VER_LESS_EQUAL);
+ if (VerifyVersionInfo(&osvi2, VER_MAJORVERSION | VER_MINORVERSION, mask)) {
+ StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows Server 2012");
+ break;
+ }
+ }
+ case 3:
+ StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2");
+ }
+ }
+
+ pGPI = (PGPI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
+
+ pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
+
+ switch (dwType) {
+ case msPRODUCT_ULTIMATE:
+ case msPRODUCT_ULTIMATE_N:
+ StrBuf->AppendStr(&buf, " Ultimate");
+ break;
+ case msPRODUCT_PROFESSIONAL:
+ case msPRODUCT_PROFESSIONAL_N:
+ case msPRODUCT_PROFESSIONAL_WMC:
+ StrBuf->AppendStr(&buf, " Professional");
+ break;
+ case msPRODUCT_HOME_PREMIUM:
+ case msPRODUCT_HOME_PREMIUM_N:
+ StrBuf->AppendStr(&buf, " Home Premium");
+ break;
+ case msPRODUCT_HOME_BASIC:
+ case msPRODUCT_HOME_BASIC_N:
+ StrBuf->AppendStr(&buf, " Home Basic");
+ break;
+ case msPRODUCT_ENTERPRISE:
+ case msPRODUCT_ENTERPRISE_N:
+ case msPRODUCT_ENTERPRISE_SERVER:
+ case msPRODUCT_ENTERPRISE_SERVER_CORE:
+ case msPRODUCT_ENTERPRISE_SERVER_IA64:
+ case msPRODUCT_ENTERPRISE_SERVER_V:
+ case msPRODUCT_ENTERPRISE_SERVER_CORE_V:
+ case msPRODUCT_ENTERPRISE_EVALUATION:
+ case msPRODUCT_ENTERPRISE_N_EVALUATION:
+ StrBuf->AppendStr(&buf, " Enterprise");
+ break;
+ case msPRODUCT_BUSINESS:
+ case msPRODUCT_BUSINESS_N:
+ StrBuf->AppendStr(&buf, " Business");
+ break;
+ case msPRODUCT_STARTER:
+ case msPRODUCT_STARTER_N:
+ StrBuf->AppendStr(&buf, " Starter");
+ break;
+ case msPRODUCT_CLUSTER_SERVER:
+ case msPRODUCT_CLUSTER_SERVER_V:
+ StrBuf->AppendStr(&buf, " Cluster Server");
+ break;
+ case msPRODUCT_DATACENTER_SERVER:
+ case msPRODUCT_DATACENTER_SERVER_CORE:
+ case msPRODUCT_DATACENTER_SERVER_V:
+ case msPRODUCT_DATACENTER_SERVER_CORE_V:
+ case msPRODUCT_DATACENTER_EVALUATION_SERVER:
+ StrBuf->AppendStr(&buf, " Datacenter");
+ break;
+ case msPRODUCT_SMALLBUSINESS_SERVER:
+ case msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ case msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE:
+ StrBuf->AppendStr(&buf, " Small Business Server");
+ break;
+ case PRODUCT_STANDARD_SERVER:
+ case PRODUCT_STANDARD_SERVER_CORE:
+ case msPRODUCT_STANDARD_SERVER_V:
+ case msPRODUCT_STANDARD_SERVER_CORE_V:
+ case msPRODUCT_STANDARD_EVALUATION_SERVER:
+ StrBuf->AppendStr(&buf, " Standard");
+ break;
+ case msPRODUCT_WEB_SERVER:
+ case msPRODUCT_WEB_SERVER_CORE:
+ StrBuf->AppendStr(&buf, " Web Server");
+ break;
+ case msPRODUCT_STORAGE_EXPRESS_SERVER:
+ case msPRODUCT_STORAGE_STANDARD_SERVER:
+ case msPRODUCT_STORAGE_WORKGROUP_SERVER:
+ case msPRODUCT_STORAGE_ENTERPRISE_SERVER:
+ case msPRODUCT_STORAGE_EXPRESS_SERVER_CORE:
+ case msPRODUCT_STORAGE_STANDARD_SERVER_CORE:
+ case msPRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
+ case msPRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
+ case msPRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER:
+ case msPRODUCT_STORAGE_STANDARD_EVALUATION_SERVER:
+ StrBuf->AppendStr(&buf, " Storage Server");
+ break;
+ case msPRODUCT_HOME_SERVER:
+ case msPRODUCT_SERVER_FOR_SMALLBUSINESS:
+ case msPRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
+ case msPRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
+ case msPRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
+ case msPRODUCT_SERVER_FOR_SMALLBUSINESS_V:
+ case msPRODUCT_SERVER_FOUNDATION:
+ case msPRODUCT_HOME_PREMIUM_SERVER:
+ case msPRODUCT_HYPERV:
+ case msPRODUCT_SB_SOLUTION_SERVER:
+ case msPRODUCT_SERVER_FOR_SB_SOLUTIONS:
+ case msPRODUCT_STANDARD_SERVER_SOLUTIONS:
+ case msPRODUCT_STANDARD_SERVER_SOLUTIONS_CORE:
+ case msPRODUCT_SB_SOLUTION_SERVER_EM:
+ case msPRODUCT_SERVER_FOR_SB_SOLUTIONS_EM:
+ case msPRODUCT_SOLUTION_EMBEDDEDSERVER:
+ case msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMT:
+ case msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDL:
+ case msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC:
+ case msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC:
+ case msPRODUCT_MULTIPOINT_STANDARD_SERVER:
+ case msPRODUCT_MULTIPOINT_PREMIUM_SERVER:
+ StrBuf->AppendStr(&buf, " Server (other)");
+ break;
+ case msPRODUCT_CORE_N:
+ case msPRODUCT_CORE_COUNTRYSPECIFIC:
+ case msPRODUCT_CORE_SINGLELANGUAGE:
+ case msPRODUCT_CORE:
+ StrBuf->AppendStr(&buf, " Workstation (other)");
+ break;
+ }
+
+ } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { // XP x64 and Server 2003
+ if (osvi.wProductType == VER_NT_WORKSTATION) {
+ StrBuf->AppendStr(&buf, "Windows XP Professional");
+ } else {
+ if (GetSystemMetrics(msSM_SERVERR2))
+ StrBuf->AppendStr(&buf, "Windows Server 2003 R2");
+ else if (osvi.wSuiteMask & msVER_SUITE_STORAGE_SERVER)
+ StrBuf->AppendStr(&buf, "Windows Storage Server 2003");
+ else if (osvi.wSuiteMask & msVER_SUITE_WH_SERVER)
+ StrBuf->AppendStr(&buf, "Windows Home Server");
+ else
+ StrBuf->AppendStr(&buf, "Windows Server 2003");
+
+ // Test for the server type.
+ if (osvi.wSuiteMask & msVER_SUITE_COMPUTE_SERVER)
+ StrBuf->AppendStr(&buf, " Compute Cluster");
+ else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ StrBuf->AppendStr(&buf, " Datacenter");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ StrBuf->AppendStr(&buf, " Enterprise");
+ else if (osvi.wSuiteMask & msVER_SUITE_BLADE)
+ StrBuf->AppendStr(&buf, " Web");
+ else
+ StrBuf->AppendStr(&buf, " Standard");
+ }
+ } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { // XP
+ StrBuf->AppendStr(&buf, "Windows XP");
+ if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT)
+ StrBuf->AppendStr(&buf, " Embedded");
+ else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
+ StrBuf->AppendStr(&buf, " Home");
+ else
+ StrBuf->AppendStr(&buf, " Professional");
+ } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { // 2000
+ StrBuf->AppendStr(&buf, "Windows 2000");
+
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ StrBuf->AppendStr(&buf, " Professional");
+ else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ StrBuf->AppendStr(&buf, " Datacenter Server");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ StrBuf->AppendStr(&buf, " Advanced Server");
+ else
+ StrBuf->AppendStr(&buf, " Server");
+ } else {
+ StrBuf->Printf(&buf, "Unknown Windows version %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
+ }
+ }
+
+ // Include service pack (if any) and build number.
+
+ if (strlen(osvi.szCSDVersion) > 0) {
+ StrBuf->Printf(&buf, " %s", osvi.szCSDVersion);
+ }
+
+ StrBuf->Printf(&buf, " (build %d)", osvi.dwBuildNumber);
+
+ sysinfo->p->osversion = aStrdup(StrBuf->Value(&buf));
+
+ StrBuf->Destroy(&buf);
+ return;
+}
+
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+/**
+ * Retrieves the CPU type (Windows only).
+ *
+ * Once retrieved, the name is stored into sysinfo->p->cpu and the
+ * number of cores in sysinfo->p->cpucores.
+ */
+void sysinfo_cpu_retrieve(void) {
+ StringBuf buf;
+ PGNSI pGNSI;
+ SYSTEM_INFO si;
+ ZeroMemory(&si, sizeof(SYSTEM_INFO));
+ StrBuf->Init(&buf);
+
+ if (sysinfo->p->cpu != NULL) {
+ aFree(sysinfo->p->cpu);
+ sysinfo->p->cpu = NULL;
+ }
+
+ // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
+ pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
+ if (NULL != pGNSI)
+ pGNSI(&si);
+ else
+ GetSystemInfo(&si);
+
+ if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL
+ || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
+ ) {
+ StrBuf->Printf(&buf, "%s CPU, Family %d, Model %d, Stepping %d",
+ si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ? "x86" : "x86_64",
+ si.wProcessorLevel,
+ (si.wProcessorRevision&0xff00)>>8,
+ (si.wProcessorRevision&0xff));
+ } else {
+ StrBuf->AppendStr(&buf, "Unknown");
+ }
+
+ sysinfo->p->cpu = aStrdup(StrBuf->Value(&buf));
+ sysinfo->p->cpucores = si.dwNumberOfProcessors;
+
+ StrBuf->Destroy(&buf);
+}
+
+/**
+ * Retrieves the OS architecture (Windows only).
+ *
+ * Once retrieved, the name is stored into sysinfo->p->arch.
+ */
+void sysinfo_arch_retrieve(void) {
+ PGNSI pGNSI;
+ SYSTEM_INFO si;
+ ZeroMemory(&si, sizeof(SYSTEM_INFO));
+
+ if (sysinfo->p->arch != NULL) {
+ aFree(sysinfo->p->arch);
+ sysinfo->p->arch = NULL;
+ }
+
+ // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
+ pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
+ if (NULL != pGNSI)
+ pGNSI(&si);
+ else
+ GetSystemInfo(&si);
+
+ if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) // x64
+ sysinfo->p->arch = aStrdup("x86_64");
+ else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) // x32
+ sysinfo->p->arch = aStrdup("x86");
+ else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM) // ARM
+ sysinfo->p->arch = aStrdup("ARM");
+ else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) // Itanium
+ sysinfo->p->arch = aStrdup("IA-64");
+ else
+ sysinfo->p->arch = aStrdup("Unknown");
+}
+
+/**
+ * Retrieves the startup-time VCS revision information.
+ *
+ * Once retrieved, the value is stored in sysinfo->p->vcsrevision_src.
+ */
+void sysinfo_vcsrevision_src_retrieve(void) {
+ if (sysinfo->p->vcsrevision_src != NULL) {
+ aFree(sysinfo->p->vcsrevision_src);
+ sysinfo->p->vcsrevision_src = NULL;
+ }
+ // Try Git, then SVN
+ if (sysinfo_git_get_revision(&sysinfo->p->vcsrevision_src)) {
+ sysinfo->p->vcstype = VCSTYPE_GIT;
+ return;
+ }
+ if (sysinfo_svn_get_revision(&sysinfo->p->vcsrevision_src)) {
+ sysinfo->p->vcstype = VCSTYPE_SVN;
+ return;
+ }
+ sysinfo->p->vcstype = VCSTYPE_NONE;
+ sysinfo->p->vcsrevision_src = aStrdup("Unknown");
+}
+#endif // WIN32
+
+/**
+ * Retrieevs the VCS type name.
+ *
+ * Once retrieved, the value is stored in sysinfo->p->vcstype_name.
+ */
+void sysinfo_vcstype_name_retrieve(void) {
+ if (sysinfo->p->vcstype_name != NULL) {
+ aFree(sysinfo->p->vcstype_name);
+ sysinfo->p->vcstype_name = NULL;
+ }
+ switch (sysinfo->p->vcstype) {
+ case VCSTYPE_GIT:
+ sysinfo->p->vcstype_name = aStrdup("Git");
+ break;
+ case VCSTYPE_SVN:
+ sysinfo->p->vcstype_name = aStrdup("SVN");
+ break;
+ default:
+ sysinfo->p->vcstype_name = aStrdup("Exported");
+ break;
+ }
+}
+
+/**
+ * Returns the platform (OS type) this application is running on.
+ *
+ * This information is cached at compile time, since it's unlikely to change.
+ *
+ * @return the OS platform name.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "Linux", "Darwin", "Windows", etc.
+ */
+const char *sysinfo_platform(void) {
+ return sysinfo->p->platform;
+}
+
+/**
+ * Returns the Operating System version the application is running on.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time, since it is uncommon that an application is compiled and runs
+ * on different machines.
+ *
+ * @return the OS name.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "Windows 2008 Small Business Server", "OS X 10.8 Mountain Lion",
+ * "Gentoo Base System Release 2.2", "Debian GNU/Linux 6.0.6 (squeeze)", etc.
+ */
+const char *sysinfo_osversion(void) {
+ return sysinfo->p->osversion;
+}
+
+/**
+ * Returns the CPU model the application is running on.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time, since it is uncommon that an application is compiled and runs
+ * on different machines.
+ *
+ * @return the CPU model name.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "Intel(R) Atom(TM) CPU D2500 @ 1.86GHz",
+ * "Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz", "Intel Core i7",
+ * "x86 CPU, Family 6, Model 54, Stepping 1", etc.
+ */
+const char *sysinfo_cpu(void) {
+ return sysinfo->p->cpu;
+}
+
+/**
+ * Returns the number of CPU cores available.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time, since it is uncommon that an application is compiled and runs
+ * on different machines.
+ *
+ * @return the number of CPU cores.
+ */
+int sysinfo_cpucores(void) {
+ return sysinfo->p->cpucores;
+}
+
+/**
+ * Returns the CPU architecture the application was compiled for.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time, since it is uncommon that an application is compiled and runs
+ * on different machines.
+ *
+ * @return the CPU architecture name.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "x86", "x86_64", "IA-64", "ARM", etc.
+ */
+const char *sysinfo_arch(void) {
+ return sysinfo->p->arch;
+}
+
+/**
+ * Returns info about the 32 or 64 bit build of Hercules.
+ *
+ * @retval true if this is a 64 bit build.
+ * @retval false if this isn't a 64 bit build (i.e. it is a 32 bit build).
+ */
+bool sysinfo_is64bit(void) {
+#ifdef _LP64
+ return true;
+#else
+ return false;
+#endif
+}
+
+/**
+ * Returns the compiler the application was compiled with.
+ *
+ * @return the compiler name.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "Microsoft Visual C++ 2012 (v170050727)",
+ * "Clang v5.0.0", "MinGW32 v3.20", "GCC v4.7.3", etc.
+ */
+const char *sysinfo_compiler(void) {
+ return sysinfo->p->compiler;
+}
+
+/**
+ * Returns the compiler flags the application was compiled with.
+ *
+ * On Windows (MSVC), an empty string is returned instead.
+ *
+ * @return the compiler flags.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "-ggdb -O2 -flto -pipe -ffast-math ..."
+ */
+const char *sysinfo_cflags(void) {
+ return sysinfo->p->cflags;
+}
+
+/**
+ * Returns the Version Control System the application was downloaded with.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time. On Windows (MSVC), it is cached when the function is first
+ * called (most likely on server startup).
+ *
+ * @return the VCS type (numerical).
+ *
+ * @see VCSTYPE_NONE, VCSTYPE_GIT, VCSTYPE_SVN, VCSTYPE_UNKNOWN
+ */
+int sysinfo_vcstypeid(void) {
+ return sysinfo->p->vcstype;
+}
+
+/**
+ * Returns the Version Control System the application was downloaded with.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time. On Windows (MSVC), it is cached when the function is first
+ * called (most likely on server startup).
+ *
+ * @return the VCS type.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: "Git", "SVN", "Exported"
+ */
+const char *sysinfo_vcstype(void) {
+ return sysinfo->p->vcstype_name;
+}
+
+/**
+ * Returns the Version Control System revision.
+ *
+ * On platforms other than Windows (MSVC), this information is cached at
+ * compile time for better reliability. On Windows (MSVC), it is cached when
+ * the function is first called (most likely on server startup), so it may
+ * diverge from the actual revision that was compiled.
+ *
+ * @return the VCS revision.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: Git: "9128feccf3bddda94a7f8a170305565416815b40", SVN: "17546"
+ */
+const char *sysinfo_vcsrevision_src(void) {
+ return sysinfo->p->vcsrevision_src;
+}
+
+/**
+ * Returns the Version Control System revision.
+ *
+ * This information is cached during a script reload, so that it matches the
+ * version of the loaded scripts.
+ *
+ * @return the VCS revision.
+ *
+ * Note: Ownership is NOT transferred, the value should not be freed.
+ *
+ * Output example: Git: "9128feccf3bddda94a7f8a170305565416815b40", SVN: "17546"
+ */
+const char *sysinfo_vcsrevision_scripts(void) {
+ return sysinfo->p->vcsrevision_scripts;
+}
+
+/**
+ * Reloads the run-time (scripts) VCS revision information. To be used during
+ * script reloads to refresh the cached version.
+ */
+void sysinfo_vcsrevision_reload(void) {
+ if (sysinfo->p->vcsrevision_scripts != NULL) {
+ aFree(sysinfo->p->vcsrevision_scripts);
+ sysinfo->p->vcsrevision_scripts = NULL;
+ }
+ // Try Git, then SVN
+ if (sysinfo_git_get_revision(&sysinfo->p->vcsrevision_scripts)) {
+ return;
+ }
+ if (sysinfo_svn_get_revision(&sysinfo->p->vcsrevision_scripts)) {
+ return;
+ }
+ sysinfo->p->vcsrevision_scripts = aStrdup("Unknown");
+}
+
+/**
+ * Checks if we're running (unnecessarily) as superuser.
+ *
+ * @retval true if the current process is running as UNIX super-user.
+ * @retval false if the current process is running as regular user, or
+ * in any case under Windows.
+ */
+bool sysinfo_is_superuser(void) {
+#ifndef _WIN32
+ if (geteuid() == 0)
+ return true;
+#endif
+ return false;
+}
+
+/**
+ * Interface runtime initialization.
+ */
+void sysinfo_init(void) {
+ sysinfo->p->compiler = SYSINFO_COMPILER;
+#ifdef WIN32
+ sysinfo->p->platform = "Windows";
+ sysinfo->p->cflags = "N/A";
+ sysinfo_osversion_retrieve();
+ sysinfo_cpu_retrieve();
+ sysinfo_arch_retrieve();
+ sysinfo_vcsrevision_src_retrieve();
+#else
+ sysinfo->p->platform = SYSINFO_PLATFORM;
+ sysinfo->p->osversion = SYSINFO_OSVERSION;
+ sysinfo->p->cpucores = SYSINFO_CPUCORES;
+ sysinfo->p->cpu = SYSINFO_CPU;
+ sysinfo->p->arch = SYSINFO_ARCH;
+ sysinfo->p->cflags = SYSINFO_CFLAGS;
+ sysinfo->p->vcstype = SYSINFO_VCSTYPE;
+ sysinfo->p->vcsrevision_src = SYSINFO_VCSREV;
+#endif
+ sysinfo->vcsrevision_reload();
+ sysinfo_vcstype_name_retrieve(); // Must be called after setting vcstype
+}
+
+/**
+ * Interface shutdown cleanup.
+ */
+void sysinfo_final(void) {
+#ifdef WIN32
+ // Only need to be free'd in win32, they're #defined elsewhere
+ if (sysinfo->p->osversion)
+ aFree(sysinfo->p->osversion);
+ if (sysinfo->p->cpu)
+ aFree(sysinfo->p->cpu);
+ if (sysinfo->p->arch)
+ aFree(sysinfo->p->arch);
+ if (sysinfo->p->vcsrevision_src)
+ aFree(sysinfo->p->vcsrevision_src);
+#endif
+ sysinfo->p->platform = NULL;
+ sysinfo->p->osversion = NULL;
+ sysinfo->p->cpu = NULL;
+ sysinfo->p->arch = NULL;
+ sysinfo->p->vcsrevision_src = NULL;
+ sysinfo->p->cflags = NULL;
+ if (sysinfo->p->vcsrevision_scripts)
+ aFree(sysinfo->p->vcsrevision_scripts);
+ sysinfo->p->vcsrevision_scripts = NULL;
+ if (sysinfo->p->vcstype_name)
+ aFree(sysinfo->p->vcstype_name);
+ sysinfo->p->vcstype_name = NULL;
+}
+
+/**
+ * Interface default values initialization.
+ */
+void sysinfo_defaults(void) {
+ sysinfo = &sysinfo_s;
+ memset(&sysinfo_p, '\0', sizeof(sysinfo_p));
+ sysinfo->p = &sysinfo_p;
+
+ sysinfo->platform = sysinfo_platform;
+ sysinfo->osversion = sysinfo_osversion;
+ sysinfo->cpu = sysinfo_cpu;
+ sysinfo->cpucores = sysinfo_cpucores;
+ sysinfo->arch = sysinfo_arch;
+ sysinfo->is64bit = sysinfo_is64bit;
+ sysinfo->compiler = sysinfo_compiler;
+ sysinfo->cflags = sysinfo_cflags;
+ sysinfo->vcstype = sysinfo_vcstype;
+ sysinfo->vcstypeid = sysinfo_vcstypeid;
+ sysinfo->vcsrevision_src = sysinfo_vcsrevision_src;
+ sysinfo->vcsrevision_scripts = sysinfo_vcsrevision_scripts;
+ sysinfo->vcsrevision_reload = sysinfo_vcsrevision_reload;
+ sysinfo->is_superuser = sysinfo_is_superuser;
+ sysinfo->init = sysinfo_init;
+ sysinfo->final = sysinfo_final;
+}
diff --git a/src/common/sysinfo.h b/src/common/sysinfo.h
new file mode 100644
index 000000000..17faac26b
--- /dev/null
+++ b/src/common/sysinfo.h
@@ -0,0 +1,62 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Base Author: Haru @ http://hercules.ws
+
+#ifndef _COMMON_SYSINFO_H_
+#define _COMMON_SYSINFO_H_
+
+/**
+ * Provides various bits of information about the system Hercules is running on
+ * (note: on unix systems, to avoid runtime detection, most of the data is
+ * cached at compile time)
+ */
+
+#include "../common/cbasetypes.h"
+
+#ifdef _COMMON_SYSINFO_P_
+struct sysinfo_private {
+ char *platform;
+ char *osversion;
+ char *cpu;
+ int cpucores;
+ char *arch;
+ char *compiler;
+ char *cflags;
+ char *vcstype_name;
+ int vcstype;
+ char *vcsrevision_src;
+ char *vcsrevision_scripts;
+};
+#else
+struct sysinfo_private;
+#endif
+
+/**
+ * sysinfo.c interface
+ **/
+struct sysinfo_interface {
+ struct sysinfo_private *p;
+
+ const char *(*platform) (void);
+ const char *(*osversion) (void);
+ const char *(*cpu) (void);
+ int (*cpucores) (void);
+ const char *(*arch) (void);
+ bool (*is64bit) (void);
+ const char *(*compiler) (void);
+ const char *(*cflags) (void);
+ const char *(*vcstype) (void);
+ int (*vcstypeid) (void);
+ const char *(*vcsrevision_src) (void);
+ const char *(*vcsrevision_scripts) (void);
+ void (*vcsrevision_reload) (void);
+ bool (*is_superuser) (void);
+ void (*init) (void);
+ void (*final) (void);
+};
+
+struct sysinfo_interface *sysinfo;
+
+void sysinfo_defaults(void);
+
+#endif /* _COMMON_SYSINFO_H_ */