summaryrefslogtreecommitdiff
path: root/src/common/sysinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/sysinfo.c')
-rw-r--r--src/common/sysinfo.c1022
1 files changed, 1022 insertions, 0 deletions
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;
+}