summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/base/win/windows_version.cc
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/chromium/base/win/windows_version.cc')
-rw-r--r--security/sandbox/chromium/base/win/windows_version.cc313
1 files changed, 313 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/win/windows_version.cc b/security/sandbox/chromium/base/win/windows_version.cc
new file mode 100644
index 0000000000..ef96f8796f
--- /dev/null
+++ b/security/sandbox/chromium/base/win/windows_version.cc
@@ -0,0 +1,313 @@
+// Copyright (c) 2012 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 <windows.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+
+#include "base/file_version_info_win.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+
+#if !defined(__clang__) && _MSC_FULL_VER < 191125507
+#error VS 2017 Update 3.2 or higher is required
+#endif
+
+#if !defined(NTDDI_WIN10_RS4)
+#error Windows 10.0.17134.0 SDK or higher required.
+#endif
+
+namespace base {
+namespace win {
+
+namespace {
+
+// The values under the CurrentVersion registry hive are mirrored under
+// the corresponding Wow6432 hive.
+constexpr wchar_t kRegKeyWindowsNTCurrentVersion[] =
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+
+// Returns the "UBR" (Windows 10 patch number) and "ReleaseId" (Windows 10
+// release number) from the registry. "UBR" is an undocumented value and will be
+// 0 if the value was not found. "ReleaseId" will be an empty string if the
+// value is not found.
+std::pair<int, std::string> GetVersionData() {
+ DWORD ubr = 0;
+ std::wstring release_id;
+ RegKey key;
+
+ if (key.Open(HKEY_LOCAL_MACHINE, kRegKeyWindowsNTCurrentVersion,
+ KEY_QUERY_VALUE) == ERROR_SUCCESS) {
+ key.ReadValueDW(L"UBR", &ubr);
+ key.ReadValue(L"ReleaseId", &release_id);
+ }
+
+ return std::make_pair(static_cast<int>(ubr), WideToUTF8(release_id));
+}
+
+const _SYSTEM_INFO& GetSystemInfoStorage() {
+ static const NoDestructor<_SYSTEM_INFO> system_info([] {
+ _SYSTEM_INFO info = {};
+ ::GetNativeSystemInfo(&info);
+ return info;
+ }());
+ return *system_info;
+}
+
+} // namespace
+
+// static
+OSInfo** OSInfo::GetInstanceStorage() {
+ // Note: we don't use the Singleton class because it depends on AtExitManager,
+ // and it's convenient for other modules to use this class without it.
+ static OSInfo* info = []() {
+ _OSVERSIONINFOEXW version_info = {sizeof(version_info)};
+ ::GetVersionEx(reinterpret_cast<_OSVERSIONINFOW*>(&version_info));
+
+ DWORD os_type = 0;
+ ::GetProductInfo(version_info.dwMajorVersion, version_info.dwMinorVersion,
+ 0, 0, &os_type);
+
+ return new OSInfo(version_info, GetSystemInfoStorage(), os_type);
+ }();
+
+ return &info;
+}
+
+// static
+OSInfo* OSInfo::GetInstance() {
+ return *GetInstanceStorage();
+}
+
+// static
+OSInfo::WindowsArchitecture OSInfo::GetArchitecture() {
+ switch (GetSystemInfoStorage().wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ return X86_ARCHITECTURE;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ return X64_ARCHITECTURE;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ return IA64_ARCHITECTURE;
+ case PROCESSOR_ARCHITECTURE_ARM64:
+ return ARM64_ARCHITECTURE;
+ default:
+ return OTHER_ARCHITECTURE;
+ }
+}
+
+OSInfo::OSInfo(const _OSVERSIONINFOEXW& version_info,
+ const _SYSTEM_INFO& system_info,
+ int os_type)
+ : version_(Version::PRE_XP),
+ wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) {
+ version_number_.major = version_info.dwMajorVersion;
+ version_number_.minor = version_info.dwMinorVersion;
+ version_number_.build = version_info.dwBuildNumber;
+ std::tie(version_number_.patch, release_id_) = GetVersionData();
+ version_ = MajorMinorBuildToVersion(
+ version_number_.major, version_number_.minor, version_number_.build);
+ service_pack_.major = version_info.wServicePackMajor;
+ service_pack_.minor = version_info.wServicePackMinor;
+ service_pack_str_ = WideToUTF8(version_info.szCSDVersion);
+
+ processors_ = system_info.dwNumberOfProcessors;
+ allocation_granularity_ = system_info.dwAllocationGranularity;
+
+ if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) {
+ // Only present on Vista+.
+ switch (os_type) {
+ case PRODUCT_CLUSTER_SERVER:
+ case PRODUCT_DATACENTER_SERVER:
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ case PRODUCT_ENTERPRISE_SERVER:
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ case PRODUCT_STANDARD_SERVER:
+ case PRODUCT_STANDARD_SERVER_CORE:
+ case PRODUCT_WEB_SERVER:
+ version_type_ = SUITE_SERVER;
+ break;
+ case PRODUCT_PROFESSIONAL:
+ case PRODUCT_ULTIMATE:
+ version_type_ = SUITE_PROFESSIONAL;
+ break;
+ case PRODUCT_ENTERPRISE:
+ case PRODUCT_ENTERPRISE_E:
+ case PRODUCT_ENTERPRISE_EVALUATION:
+ case PRODUCT_ENTERPRISE_N:
+ case PRODUCT_ENTERPRISE_N_EVALUATION:
+ case PRODUCT_ENTERPRISE_S:
+ case PRODUCT_ENTERPRISE_S_EVALUATION:
+ case PRODUCT_ENTERPRISE_S_N:
+ case PRODUCT_ENTERPRISE_S_N_EVALUATION:
+ case PRODUCT_BUSINESS:
+ case PRODUCT_BUSINESS_N:
+ version_type_ = SUITE_ENTERPRISE;
+ break;
+ case PRODUCT_EDUCATION:
+ case PRODUCT_EDUCATION_N:
+ version_type_ = SUITE_EDUCATION;
+ break;
+ case PRODUCT_HOME_BASIC:
+ case PRODUCT_HOME_PREMIUM:
+ case PRODUCT_STARTER:
+ default:
+ version_type_ = SUITE_HOME;
+ break;
+ }
+ } else if (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion == 2) {
+ if (version_info.wProductType == VER_NT_WORKSTATION &&
+ system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ version_type_ = SUITE_PROFESSIONAL;
+ } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER) {
+ version_type_ = SUITE_HOME;
+ } else {
+ version_type_ = SUITE_SERVER;
+ }
+ } else if (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion == 1) {
+ if (version_info.wSuiteMask & VER_SUITE_PERSONAL)
+ version_type_ = SUITE_HOME;
+ else
+ version_type_ = SUITE_PROFESSIONAL;
+ } else {
+ // Windows is pre XP so we don't care but pick a safe default.
+ version_type_ = SUITE_HOME;
+ }
+}
+
+OSInfo::~OSInfo() = default;
+
+Version OSInfo::Kernel32Version() const {
+ static const Version kernel32_version =
+ MajorMinorBuildToVersion(Kernel32BaseVersion().components()[0],
+ Kernel32BaseVersion().components()[1],
+ Kernel32BaseVersion().components()[2]);
+ return kernel32_version;
+}
+
+Version OSInfo::UcrtVersion() const {
+ auto ucrt_version_info = FileVersionInfoWin::CreateFileVersionInfoWin(
+ FilePath(FILE_PATH_LITERAL("ucrtbase.dll")));
+ if (ucrt_version_info) {
+ auto ucrt_components = ucrt_version_info->GetFileVersion().components();
+ if (ucrt_components.size() == 4) {
+ return MajorMinorBuildToVersion(ucrt_components[0], ucrt_components[1],
+ ucrt_components[2]);
+ }
+ }
+ return Version();
+}
+
+// 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.
+base::Version OSInfo::Kernel32BaseVersion() const {
+ static const NoDestructor<base::Version> version([] {
+ std::unique_ptr<FileVersionInfoWin> file_version_info =
+ FileVersionInfoWin::CreateFileVersionInfoWin(
+ FilePath(FILE_PATH_LITERAL("kernel32.dll")));
+ if (!file_version_info) {
+ // crbug.com/912061: on some systems it seems kernel32.dll might be
+ // corrupted or not in a state to get version info. In this case try
+ // kernelbase.dll as a fallback.
+ file_version_info = FileVersionInfoWin::CreateFileVersionInfoWin(
+ FilePath(FILE_PATH_LITERAL("kernelbase.dll")));
+ }
+ CHECK(file_version_info);
+ return file_version_info->GetFileVersion();
+ }());
+ return *version;
+}
+
+std::string OSInfo::processor_model_name() {
+ if (processor_model_name_.empty()) {
+ const wchar_t kProcessorNameString[] =
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
+ RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ);
+ std::wstring value;
+ key.ReadValue(L"ProcessorNameString", &value);
+ processor_model_name_ = WideToUTF8(value);
+ }
+ return processor_model_name_;
+}
+
+// static
+OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) {
+ BOOL is_wow64 = FALSE;
+ if (!::IsWow64Process(process_handle, &is_wow64))
+ return WOW64_UNKNOWN;
+ return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
+}
+
+// With the exception of Server 2003, server variants are treated the same as
+// the corresponding workstation release.
+// static
+Version OSInfo::MajorMinorBuildToVersion(int major, int minor, int build) {
+ if (major == 10) {
+ if (build >= 19041)
+ return Version::WIN10_20H1;
+ if (build >= 18362)
+ return Version::WIN10_19H1;
+ if (build >= 17763)
+ return Version::WIN10_RS5;
+ if (build >= 17134)
+ return Version::WIN10_RS4;
+ if (build >= 16299)
+ return Version::WIN10_RS3;
+ if (build >= 15063)
+ return Version::WIN10_RS2;
+ if (build >= 14393)
+ return Version::WIN10_RS1;
+ if (build >= 10586)
+ return Version::WIN10_TH2;
+ return Version::WIN10;
+ }
+
+ if (major > 6) {
+ // Hitting this likely means that it's time for a >10 block above.
+ NOTREACHED() << major << "." << minor << "." << build;
+ return Version::WIN_LAST;
+ }
+
+ if (major == 6) {
+ switch (minor) {
+ case 0:
+ return Version::VISTA;
+ case 1:
+ return Version::WIN7;
+ case 2:
+ return Version::WIN8;
+ default:
+ DCHECK_EQ(minor, 3);
+ return Version::WIN8_1;
+ }
+ }
+
+ 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;
+ }
+
+ // Win 2000 or older.
+ return Version::PRE_XP;
+}
+
+Version GetVersion() {
+ return OSInfo::GetInstance()->version();
+}
+
+} // namespace win
+} // namespace base