Index: runtime/bin/platform_win.cc |
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc |
index d8e0a434542b117febef0c9a4e0e643ed4916bd6..5568af08081d1a98a8e2f0124aeb4c8df136483d 100644 |
--- a/runtime/bin/platform_win.cc |
+++ b/runtime/bin/platform_win.cc |
@@ -213,6 +213,89 @@ const char* Platform::OperatingSystem() { |
return "windows"; |
} |
+// We pull the version number, and other version information out of the |
+// registry because GetVersionEx() and friends lie about the OS version after |
+// Windows 8.1. See: |
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx |
+static const wchar_t* kCurrentVersion = |
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; |
+ |
+static bool GetCurrentVersionDWord(const wchar_t* field, DWORD* value) { |
+ DWORD value_size = sizeof(*value); |
+ LONG err = RegGetValue(HKEY_LOCAL_MACHINE, kCurrentVersion, field, |
+ RRF_RT_REG_DWORD, NULL, value, &value_size); |
+ return err == ERROR_SUCCESS; |
+} |
+ |
+static bool GetCurrentVersionString(const wchar_t* field, const char** value) { |
+ wchar_t wversion[256]; |
+ DWORD wversion_size = sizeof(wversion); |
+ LONG err = RegGetValue(HKEY_LOCAL_MACHINE, kCurrentVersion, field, |
+ RRF_RT_REG_SZ, NULL, wversion, &wversion_size); |
+ if (err != ERROR_SUCCESS) { |
+ return false; |
+ } |
+ *value = StringUtilsWin::WideToUtf8(wversion); |
+ return true; |
+} |
+ |
+static const char* VersionNumber() { |
+ // Try to get CurrentMajorVersionNumber. If that fails, fall back on |
+ // CurrentVersion. If it succeeds also get CurrentMinorVersionNumber. |
+ DWORD major; |
+ if (!GetCurrentVersionDWord(L"CurrentMajorVersionNumber", &major)) { |
+ const char* version; |
+ if (!GetCurrentVersionString(L"CurrentVersion", &version)) { |
+ return NULL; |
+ } |
+ return version; |
+ } |
+ |
+ DWORD minor; |
+ if (!GetCurrentVersionDWord(L"CurrentMinorVersionNumber", &minor)) { |
+ return NULL; |
+ } |
+ const char* kFormat = "%d.%d"; |
+ int len = snprintf(NULL, 0, kFormat, major, minor); |
+ if (len < 0) { |
+ return NULL; |
+ } |
+ char* result = DartUtils::ScopedCString(len + 1); |
+ ASSERT(result != NULL); |
+ len = snprintf(result, len + 1, kFormat, major, minor); |
+ if (len < 0) { |
+ return NULL; |
+ } |
+ return result; |
+} |
+ |
+const char* Platform::OperatingSystemVersion() { |
+ // Get the product name, e.g. "Windows 10 Home". |
+ const char* name; |
+ if (!GetCurrentVersionString(L"ProductName", &name)) { |
+ return NULL; |
+ } |
+ |
+ // Get the version number, e.g. "10.0". |
+ const char* version_number = VersionNumber(); |
+ if (version_number == NULL) { |
+ return NULL; |
+ } |
+ |
+ // Get the build number. |
+ const char* build; |
+ if (!GetCurrentVersionString(L"CurrentBuild", &build)) { |
+ return NULL; |
+ } |
+ |
+ // Put it all together. |
+ const char* kFormat = "\"%s\" %s (Build %s)"; |
+ int len = snprintf(NULL, 0, kFormat, name, version_number, build); |
+ char* result = DartUtils::ScopedCString(len + 1); |
+ len = snprintf(result, len + 1, kFormat, name, version_number, build); |
+ return result; |
+} |
+ |
const char* Platform::LibraryPrefix() { |
return ""; |
} |