summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/BUILD.gn1
-rw-r--r--base/base.gyp1
-rw-r--r--base/win/windows_version.cc110
-rw-r--r--base/win/windows_version.h24
-rw-r--r--base/win/windows_version_unittest.cc22
-rw-r--r--chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc10
-rw-r--r--tools/metrics/histograms/histograms.xml33
7 files changed, 159 insertions, 42 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0b41b0e..b3e2707 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1851,6 +1851,7 @@ test("base_unittests") {
"win/shortcut_unittest.cc",
"win/startup_information_unittest.cc",
"win/win_util_unittest.cc",
+ "win/windows_version_unittest.cc",
"win/wrapped_window_proc_unittest.cc",
]
diff --git a/base/base.gyp b/base/base.gyp
index 5b20cfe..52adb62 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -599,6 +599,7 @@
'win/shortcut_unittest.cc',
'win/startup_information_unittest.cc',
'win/win_util_unittest.cc',
+ 'win/windows_version_unittest.cc',
'win/wrapped_window_proc_unittest.cc',
'<@(trace_event_test_sources)',
],
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc
index 7a8b8fd..d2f766e 100644
--- a/base/win/windows_version.cc
+++ b/base/win/windows_version.cc
@@ -6,17 +6,81 @@
#include <windows.h>
+#include "base/file_version_info_win.h"
+#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
namespace {
typedef BOOL (WINAPI *GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD);
-}
+} // namespace
namespace base {
namespace win {
+namespace {
+
+// Helper to map a major.minor.x.build version (e.g. 6.1) to a Windows release.
+Version MajorMinorBuildToVersion(int major, int minor, int build) {
+ if ((major == 5) && (minor > 0)) {
+ // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
+ return (minor == 1) ? VERSION_XP : VERSION_SERVER_2003;
+ } else if (major == 6) {
+ switch (minor) {
+ case 0:
+ // Treat Windows Server 2008 the same as Windows Vista.
+ return VERSION_VISTA;
+ case 1:
+ // Treat Windows Server 2008 R2 the same as Windows 7.
+ return VERSION_WIN7;
+ case 2:
+ // Treat Windows Server 2012 the same as Windows 8.
+ return VERSION_WIN8;
+ default:
+ DCHECK_EQ(minor, 3);
+ return VERSION_WIN8_1;
+ }
+ } else if (major == 10) {
+ if (build < 10586) {
+ return VERSION_WIN10;
+ } else {
+ return VERSION_WIN10_TH2;
+ }
+ } else if (major > 6) {
+ NOTREACHED();
+ return VERSION_WIN_LAST;
+ }
+
+ NOTREACHED();
+ return VERSION_WIN_LAST;
+}
+
+// Retrieve a version from kernel32. This is useful because when running in
+// compatibility mode for a down-level version of the OS, the file version of
+// kernel32 will still be the "real" version.
+Version GetVersionFromKernel32() {
+ scoped_ptr<FileVersionInfoWin> file_version_info(
+ static_cast<FileVersionInfoWin*>(
+ FileVersionInfoWin::CreateFileVersionInfo(
+ base::FilePath(FILE_PATH_LITERAL("kernel32.dll")))));
+ if (file_version_info) {
+ const int major =
+ HIWORD(file_version_info->fixed_file_info()->dwFileVersionMS);
+ const int minor =
+ LOWORD(file_version_info->fixed_file_info()->dwFileVersionMS);
+ const int build =
+ HIWORD(file_version_info->fixed_file_info()->dwFileVersionLS);
+ return MajorMinorBuildToVersion(major, minor, build);
+ }
+
+ NOTREACHED();
+ return VERSION_WIN_LAST;
+}
+
+} // namespace
+
// static
OSInfo* OSInfo::GetInstance() {
// Note: we don't use the Singleton class because it depends on AtExitManager,
@@ -35,6 +99,8 @@ OSInfo* OSInfo::GetInstance() {
OSInfo::OSInfo()
: version_(VERSION_PRE_XP),
+ kernel32_version_(VERSION_PRE_XP),
+ got_kernel32_version_(false),
architecture_(OTHER_ARCHITECTURE),
wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) {
OSVERSIONINFOEX version_info = { sizeof version_info };
@@ -42,38 +108,8 @@ OSInfo::OSInfo()
version_number_.major = version_info.dwMajorVersion;
version_number_.minor = version_info.dwMinorVersion;
version_number_.build = version_info.dwBuildNumber;
- if ((version_number_.major == 5) && (version_number_.minor > 0)) {
- // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
- version_ = (version_number_.minor == 1) ? VERSION_XP : VERSION_SERVER_2003;
- } else if (version_number_.major == 6) {
- switch (version_number_.minor) {
- case 0:
- // Treat Windows Server 2008 the same as Windows Vista.
- version_ = VERSION_VISTA;
- break;
- case 1:
- // Treat Windows Server 2008 R2 the same as Windows 7.
- version_ = VERSION_WIN7;
- break;
- case 2:
- // Treat Windows Server 2012 the same as Windows 8.
- version_ = VERSION_WIN8;
- break;
- default:
- DCHECK_EQ(version_number_.minor, 3);
- version_ = VERSION_WIN8_1;
- break;
- }
- } else if (version_number_.major == 10) {
- if (version_number_.build < 10586) {
- version_ = VERSION_WIN10;
- } else {
- version_ = VERSION_WIN10_TH2;
- }
- } else if (version_number_.major > 6) {
- NOTREACHED();
- version_ = VERSION_WIN_LAST;
- }
+ version_ = MajorMinorBuildToVersion(
+ version_number_.major, version_number_.minor, version_number_.build);
service_pack_.major = version_info.wServicePackMajor;
service_pack_.minor = version_info.wServicePackMinor;
@@ -149,6 +185,14 @@ OSInfo::OSInfo()
OSInfo::~OSInfo() {
}
+Version OSInfo::Kernel32Version() const {
+ if (!got_kernel32_version_) {
+ kernel32_version_ = GetVersionFromKernel32();
+ got_kernel32_version_ = true;
+ }
+ return kernel32_version_;
+}
+
std::string OSInfo::processor_model_name() {
if (processor_model_name_.empty()) {
const wchar_t kProcessorNameString[] =
diff --git a/base/win/windows_version.h b/base/win/windows_version.h
index 676bd97..7bc8b6f 100644
--- a/base/win/windows_version.h
+++ b/base/win/windows_version.h
@@ -21,17 +21,20 @@ namespace win {
// syntactic sugar reasons; see the declaration of GetVersion() below.
// NOTE: Keep these in order so callers can do things like
// "if (base::win::GetVersion() >= base::win::VERSION_VISTA) ...".
+//
+// This enum is used in metrics histograms, so they shouldn't be reordered or
+// removed. New values can be added before VERSION_WIN_LAST.
enum Version {
VERSION_PRE_XP = 0, // Not supported.
- VERSION_XP,
- VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2.
- VERSION_VISTA, // Also includes Windows Server 2008.
- VERSION_WIN7, // Also includes Windows Server 2008 R2.
- VERSION_WIN8, // Also includes Windows Server 2012.
- VERSION_WIN8_1, // Also includes Windows Server 2012 R2.
- VERSION_WIN10, // Also includes Windows 10 Server.
- VERSION_WIN10_TH2, // Threshold 2: Version 1511, Build 10586.
- VERSION_WIN_LAST, // Indicates error condition.
+ VERSION_XP = 1,
+ VERSION_SERVER_2003 = 2, // Also includes XP Pro x64 and Server 2003 R2.
+ VERSION_VISTA = 3, // Also includes Windows Server 2008.
+ VERSION_WIN7 = 4, // Also includes Windows Server 2008 R2.
+ VERSION_WIN8 = 5, // Also includes Windows Server 2012.
+ VERSION_WIN8_1 = 6, // Also includes Windows Server 2012 R2.
+ VERSION_WIN10 = 7, // Also includes Windows 10 Server.
+ VERSION_WIN10_TH2 = 8, // Threshold 2: Version 1511, Build 10586.
+ VERSION_WIN_LAST, // Indicates error condition.
};
// A rough bucketing of the available types of versions of Windows. This is used
@@ -86,6 +89,7 @@ class BASE_EXPORT OSInfo {
static OSInfo* GetInstance();
Version version() const { return version_; }
+ Version Kernel32Version() const;
// The next two functions return arrays of values, [major, minor(, build)].
VersionNumber version_number() const { return version_number_; }
VersionType version_type() const { return version_type_; }
@@ -105,6 +109,8 @@ class BASE_EXPORT OSInfo {
~OSInfo();
Version version_;
+ mutable Version kernel32_version_;
+ mutable bool got_kernel32_version_;
VersionNumber version_number_;
VersionType version_type_;
ServicePack service_pack_;
diff --git a/base/win/windows_version_unittest.cc b/base/win/windows_version_unittest.cc
new file mode 100644
index 0000000..f0d6d96
--- /dev/null
+++ b/base/win/windows_version_unittest.cc
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/windows_version.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+namespace {
+
+TEST(WindowsVersion, GetVersionExAndKernelVersionMatch) {
+ // If this fails, we're running in compatibility mode, or need to update the
+ // application manifest.
+ EXPECT_EQ(OSInfo::GetInstance()->version(),
+ OSInfo::GetInstance()->Kernel32Version());
+}
+
+} // namespace
+} // namespace win
+} // namespace base
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index 11b1c17..58f4af4 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -51,6 +51,7 @@
#endif // defined(USE_OZONE) || defined(USE_X11)
#if defined(OS_WIN)
+#include "base/win/windows_version.h"
#include "chrome/installer/util/google_update_settings.h"
#endif // defined(OS_WIN)
@@ -140,6 +141,15 @@ void RecordMicroArchitectureStats() {
void RecordStartupMetricsOnBlockingPool() {
#if defined(OS_WIN)
GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms();
+
+ const base::win::OSInfo& os_info = *base::win::OSInfo::GetInstance();
+ UMA_HISTOGRAM_ENUMERATION("Windows.GetVersionExVersion", os_info.version(),
+ base::win::VERSION_WIN_LAST);
+ UMA_HISTOGRAM_ENUMERATION("Windows.Kernel32Version",
+ os_info.Kernel32Version(),
+ base::win::VERSION_WIN_LAST);
+ UMA_HISTOGRAM_BOOLEAN("Windows.InCompatibilityMode",
+ os_info.version() != os_info.Kernel32Version());
#endif // defined(OS_WIN)
#if defined(OS_MACOSX)
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4540b38..1cd4a80 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -58501,6 +58501,31 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary>
</histogram>
+<histogram name="Windows.GetVersionExVersion" enum="WindowsVersion">
+ <owner>scottmg@chromium.org</owner>
+ <summary>
+ The Windows version (base::win::Version) as reported by GetVersionEx(). This
+ is queried shortly after startup.
+ </summary>
+</histogram>
+
+<histogram name="Windows.InCompatibilityMode" enum="BooleanCompatibilityMode">
+ <owner>scottmg@chromium.org</owner>
+ <summary>
+ A boolean used to indicate when the Windows version reported by
+ GetVersionEx() and the Windows version reported by VerQueryValue() on
+ kernel32 do not match. This is queried shortly after startup.
+ </summary>
+</histogram>
+
+<histogram name="Windows.Kernel32Version" enum="WindowsVersion">
+ <owner>scottmg@chromium.org</owner>
+ <summary>
+ The Windows version (base::win::Version) as reported by VeryQueryValue() on
+ kernel32.dll. This is queried shortly after startup.
+ </summary>
+</histogram>
+
<histogram name="Windows.Tablet" enum="BooleanTablet">
<owner>zturner@chromium.org</owner>
<summary>Count of browser launches from a Windows tablet pc.</summary>
@@ -60190,6 +60215,11 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="1" label="Common Name used"/>
</enum>
+<enum name="BooleanCompatibilityMode" type="int">
+ <int value="0" label="Not in compatibility mode"/>
+ <int value="1" label="In compatibility mode"/>
+</enum>
+
<enum name="BooleanCompleted" type="int">
<int value="0" label="Not Completed"/>
<int value="1" label="Completed"/>
@@ -84218,6 +84248,9 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="3" label="Vista"/>
<int value="4" label="Windows 7"/>
<int value="5" label="Windows 8"/>
+ <int value="6" label="Windows 8.1"/>
+ <int value="7" label="Windows 10"/>
+ <int value="8" label="Windows 10 TH2"/>
</enum>
<enum name="WindowType" type="int">