summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Graham <scottmg@chromium.org>2016-03-14 23:18:12 -0700
committerScott Graham <scottmg@chromium.org>2016-03-15 06:20:30 +0000
commit131230d025c9b31910e2f397e662625372fa264c (patch)
treeba203a002abbadb638f4755b189dbcd1b46def7b
parentd3cbefdeb2f21f56a24866318658cc16bbe23c0c (diff)
downloadchromium_src-131230d025c9b31910e2f397e662625372fa264c.zip
chromium_src-131230d025c9b31910e2f397e662625372fa264c.tar.gz
chromium_src-131230d025c9b31910e2f397e662625372fa264c.tar.bz2
Add histograms to compare GetVersionEx() with VerQueryValue() of kernel32
Checking VerQueryValue() of kernel32 reports the "real" OS, rather than the potentially shimmed one that GetVersionEx() reports. Normally it's better to use GetVersionEx() because that'll determine the APIs that are available and how they behave. However, we'd like to know if there are a substantial percentage of users in compatibility mode, as there have been complaints of users seeing the "XP and Vista are no longer supported" infobar on Windows 7. R=asvitkine@chromium.org, robliao@chromium.org, wfh@chromium.org, nick@chromium.org BUG=581499 Review URL: https://codereview.chromium.org/1784623003 Cr-Commit-Position: refs/heads/master@{#380793} (cherry picked from commit d68b1e1c89ab3d8055046883b1bf726084673959) Review URL: https://codereview.chromium.org/1799423002 . Cr-Commit-Position: refs/branch-heads/2623@{#623} Cr-Branched-From: 92d77538a86529ca35f9220bd3cd512cbea1f086-refs/heads/master@{#369907}
-rw-r--r--base/BUILD.gn1
-rw-r--r--base/base.gyp1
-rw-r--r--base/win/windows_version.cc106
-rw-r--r--base/win/windows_version.h23
-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, 37 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 1265df8..8f21b58 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1856,6 +1856,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 94a1d49..dc794be 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -669,6 +669,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 35cdbb3..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,34 +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) {
- version_ = VERSION_WIN10;
- } 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;
@@ -145,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 c9bbd4f..7bc8b6f 100644
--- a/base/win/windows_version.h
+++ b/base/win/windows_version.h
@@ -21,16 +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_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
@@ -85,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_; }
@@ -104,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 525ab33..b3f7405 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 f5c2eeb..1fd9085 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -56311,6 +56311,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>
@@ -57816,6 +57841,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"/>
@@ -81037,6 +81067,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">