From 7733912ae289440497e0cbdcfca0a373880d025a Mon Sep 17 00:00:00 2001 From: icex2 Date: Fri, 21 Aug 2020 17:53:32 +0200 Subject: [PATCH] util: Add OS module to get version information of Windows Data we always need when things go wrong, log it on boot. --- src/main/util/Module.mk | 1 + src/main/util/os.c | 130 ++++++++++++++++++++++++++++++++++++++++ src/main/util/os.h | 25 ++++++++ 3 files changed, 156 insertions(+) create mode 100644 src/main/util/os.c create mode 100644 src/main/util/os.h diff --git a/src/main/util/Module.mk b/src/main/util/Module.mk index f6b42ff..74c508a 100644 --- a/src/main/util/Module.mk +++ b/src/main/util/Module.mk @@ -13,6 +13,7 @@ src_util := \ mem.c \ msg-thread.c \ net.c \ + os.c \ signal.c \ str.c \ thread.c \ diff --git a/src/main/util/os.c b/src/main/util/os.c new file mode 100644 index 0000000..4609881 --- /dev/null +++ b/src/main/util/os.c @@ -0,0 +1,130 @@ +#define LOG_MODULE "util-os" + +#include + +#include + +#include + +#include "util/log.h" +#include "util/os.h" +#include "util/str.h" + +#define STATUS_SUCCESS (0x00000000) + +typedef LONG NTSTATUS, *PNTSTATUS; +typedef NTSTATUS (WINAPI* RtlGetVersion_t)(PRTL_OSVERSIONINFOW); + +static const char* human_readable_version(DWORD major, DWORD minor) +{ + if (IsWindowsServer()) { + if (major == 5 && minor == 2) { + return "Windows Server 2003 (R2)"; + } else if (major == 6 && minor == 0) { + return "Windows Server 2008"; + } else if (major == 6 && minor == 1) { + return "Windows Server 2008 R2"; + } else if (major == 6 && minor == 2) { + return "Windows Server 2012"; + } else if (major == 6 && minor == 3) { + return "Windows Server 2012 R2"; + } else if (major == 10 && minor == 0) { + return "Windows Server 2016/2019"; + } else { + return "Unknown server version"; + } + } else { + if (major == 5 && minor == 0) { + return "Windows 2000"; + } else if (major == 5 && minor == 1) { + return "Windows XP"; + } else if (major == 5 && minor == 2 ) { + return "Windows XP 64-bit"; + } else if (major == 6 && minor == 0) { + return "Windows Vista"; + } else if (major == 6 && minor == 1) { + return "Windows 7"; + } else if (major == 6 && minor == 2) { + return "Windows 8"; + } else if (major == 6 && minor == 3) { + return "Windows 8.1"; + } else if (major == 10 && minor == 0) { + return "Windows 10"; + } else { + return "Unknown client version"; + } + } +} + +static bool os_get_real_win_version(PRTL_OSVERSIONINFOW version) +{ + HMODULE module; + RtlGetVersion_t rtl_get_version; + + module = GetModuleHandleA("ntdll.dll"); + + if (!module) { + return false; + } + + rtl_get_version = (RtlGetVersion_t) GetProcAddress(module, "RtlGetVersion"); + + if (!rtl_get_version) { + return false; + } + + return rtl_get_version(version) == STATUS_SUCCESS; +} + +bool os_version_get(struct os_version* version) +{ + log_assert(version); + + RTL_OSVERSIONINFOW rovi; + char* version_str; + const char* readable_version; + + memset(&rovi, 0, sizeof(RTL_OSVERSIONINFOW)); + rovi.dwOSVersionInfoSize = sizeof(rovi); + + version_str = NULL; + + if (!os_get_real_win_version(&rovi)) { + return false; + } + + // Contains additional version info, e.g. "Service Pack 3" for XP + wstr_narrow(rovi.szCSDVersion, &version_str); + + readable_version = human_readable_version(rovi.dwMajorVersion, rovi.dwMinorVersion); + + strcpy(version->name, readable_version); + version->major = rovi.dwMajorVersion; + version->minor = rovi.dwMinorVersion; + version->build = rovi.dwBuildNumber; + version->platform_id = rovi.dwPlatformId; + strcpy(version->extension, version_str); + + if (version_str) { + free(version_str); + } + + return true; +} + +void os_version_log() +{ + struct os_version version; + + if (!os_version_get(&version)) { + log_warning("Could not detect OS version"); + } else { + log_info("OS version: %s - %d.%d.%d.%d - %s", + version.name, + version.major, + version.minor, + version.build, + version.platform_id, + version.extension); + } +} \ No newline at end of file diff --git a/src/main/util/os.h b/src/main/util/os.h new file mode 100644 index 0000000..8df0686 --- /dev/null +++ b/src/main/util/os.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +struct os_version { + char name[128]; + uint32_t major; + uint32_t minor; + uint32_t build; + uint32_t platform_id; + char extension[256]; +}; + +/** + * Get the (real) version information of the Windows OS. + * + * @param verison Pointer to version structure. This will be filled in. + * @return true on success, false on failure. + */ +bool os_version_get(struct os_version* version); + +/** + * Log the version information of the current Windows OS. + */ +void os_version_log(); \ No newline at end of file