-
Notifications
You must be signed in to change notification settings - Fork 584
Utility::GetPlatform*(): on Windows query the registry for version info #9699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ | ||
|
||
#include "base/atomic-file.hpp" | ||
#include "base/defer.hpp" | ||
#include "base/utility.hpp" | ||
#include "base/convert.hpp" | ||
#include "base/application.hpp" | ||
|
@@ -54,6 +55,7 @@ | |
#ifdef _WIN32 | ||
# include <VersionHelpers.h> | ||
# include <windows.h> | ||
# include <winreg.h> | ||
# include <io.h> | ||
# include <msi.h> | ||
# include <shlobj.h> | ||
|
@@ -1584,28 +1586,58 @@ static String UnameHelper(char type) | |
} | ||
} | ||
#endif /* _WIN32 */ | ||
|
||
#ifdef _WIN32 | ||
struct RegistryString | ||
{ | ||
union { | ||
BYTE AsBytes[512]; | ||
char AsChars[1] = {0}; | ||
} Data; | ||
|
||
DWORD Size = sizeof(Data); | ||
}; | ||
|
||
static const char * const l_RegCurrentVersion = R"EOF(SOFTWARE\Microsoft\Windows NT\CurrentVersion)EOF"; | ||
#endif /* _WIN32 */ | ||
|
||
static bool ReleaseHelper(String *platformName, String *platformVersion) | ||
{ | ||
#ifdef _WIN32 | ||
if (platformName) | ||
*platformName = "Windows"; | ||
|
||
if (platformVersion) { | ||
*platformVersion = "Vista"; | ||
if (IsWindowsVistaSP1OrGreater()) | ||
*platformVersion = "Vista SP1"; | ||
if (IsWindowsVistaSP2OrGreater()) | ||
*platformVersion = "Vista SP2"; | ||
if (IsWindows7OrGreater()) | ||
*platformVersion = "7"; | ||
if (IsWindows7SP1OrGreater()) | ||
*platformVersion = "7 SP1"; | ||
if (IsWindows8OrGreater()) | ||
*platformVersion = "8"; | ||
if (IsWindows8Point1OrGreater()) | ||
*platformVersion = "8.1 or greater"; | ||
if (IsWindowsServer()) | ||
*platformVersion += " (Server)"; | ||
HKEY hKey; | ||
auto err (RegOpenKeyExA(HKEY_LOCAL_MACHINE, l_RegCurrentVersion, 0, KEY_READ, &hKey)); | ||
|
||
if (err == ERROR_SUCCESS) { | ||
Defer regCloseKey ([hKey]() { (void)RegCloseKey(hKey); }); | ||
RegistryString productName; | ||
auto err (RegQueryValueExA(hKey, "ProductName", nullptr, nullptr, productName.Data.AsBytes, &productName.Size)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you need another subkey to search for instead of
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's already way better than the master branch though: Platform version: 8 xD System information:
Platform: Windows
Platform version: 8
Kernel: Windows
Kernel version: 6.2
Architecture: x86_64 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, Windows 11 says "Windows 11" in one key, but "Windows 10" in another? Please could you screen your SOFTWARE\Microsoft\Windows NT\CurrentVersion in RegEdit?
That's the point.👍
Unfortunately there's no such thing in Server 2012 R2. |
||
|
||
if (err == ERROR_SUCCESS) { | ||
*platformVersion = productName.Data.AsChars; | ||
|
||
RegistryString displayVersion; | ||
|
||
if (RegQueryValueExA(hKey, "DisplayVersion", nullptr, nullptr, displayVersion.Data.AsBytes, &displayVersion.Size) == ERROR_SUCCESS) { | ||
*platformVersion += " "; | ||
*platformVersion += displayVersion.Data.AsChars; | ||
} else { | ||
RegistryString releaseId; | ||
|
||
if (RegQueryValueExA(hKey, "ReleaseId", nullptr, nullptr, releaseId.Data.AsBytes, &releaseId.Size) == ERROR_SUCCESS) { | ||
*platformVersion += " "; | ||
*platformVersion += releaseId.Data.AsChars; | ||
} | ||
} | ||
} else { | ||
*platformVersion = "Unknown (Can't query HKEY_LOCAL_MACHINE\\" + (l_RegCurrentVersion + ("\\ProductName: " + Utility::FormatErrorNumber(err))) + ")"; | ||
} | ||
} else { | ||
*platformVersion = "Unknown (Can't open HKEY_LOCAL_MACHINE\\" + (l_RegCurrentVersion + (": " + Utility::FormatErrorNumber(err))) + ")"; | ||
} | ||
} | ||
|
||
return true; | ||
|
@@ -1703,14 +1735,28 @@ String Utility::GetPlatformKernel() | |
String Utility::GetPlatformKernelVersion() | ||
{ | ||
#ifdef _WIN32 | ||
OSVERSIONINFO info; | ||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | ||
GetVersionEx(&info); | ||
HKEY hKey; | ||
auto err (RegOpenKeyExA(HKEY_LOCAL_MACHINE, l_RegCurrentVersion, 0, KEY_READ, &hKey)); | ||
|
||
std::ostringstream msgbuf; | ||
msgbuf << info.dwMajorVersion << "." << info.dwMinorVersion; | ||
if (err == ERROR_SUCCESS) { | ||
Defer regCloseKey ([hKey]() { (void)RegCloseKey(hKey); }); | ||
RegistryString currentVersion; | ||
auto err (RegQueryValueExA(hKey, "CurrentVersion", nullptr, nullptr, currentVersion.Data.AsBytes, ¤tVersion.Size)); | ||
|
||
return msgbuf.str(); | ||
if (err == ERROR_SUCCESS) { | ||
RegistryString currentBuildNumber; | ||
|
||
if (RegQueryValueExA(hKey, "CurrentBuildNumber", nullptr, nullptr, currentBuildNumber.Data.AsBytes, ¤tBuildNumber.Size) == ERROR_SUCCESS) { | ||
return String(currentVersion.Data.AsChars) + "." + currentBuildNumber.Data.AsChars; | ||
} else { | ||
return currentVersion.Data.AsChars; | ||
} | ||
} else { | ||
return "Unknown (Can't query HKEY_LOCAL_MACHINE\\" + (l_RegCurrentVersion + ("\\CurrentVersion: " + Utility::FormatErrorNumber(err))) + ")"; | ||
} | ||
} else { | ||
return "Unknown (Can't open HKEY_LOCAL_MACHINE\\" + (l_RegCurrentVersion + (": " + Utility::FormatErrorNumber(err))) + ")"; | ||
} | ||
#else /* _WIN32 */ | ||
return UnameHelper('r'); | ||
#endif /* _WIN32 */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have documentation on what this type is used for. I was struggling to wrap my head around this until I found the term
type punning
about union types :).