xref: /aosp_15_r20/external/cronet/base/win/windows_version.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_version.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <memory>
10*6777b538SAndroid Build Coastguard Worker #include <tuple>
11*6777b538SAndroid Build Coastguard Worker #include <utility>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/file_version_info_win.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/win/registry.h"
23*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker #if !defined(__clang__) && _MSC_FULL_VER < 191125507
26*6777b538SAndroid Build Coastguard Worker #error VS 2017 Update 3.2 or higher is required
27*6777b538SAndroid Build Coastguard Worker #endif
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker #if !defined(NTDDI_WIN10_NI)
30*6777b538SAndroid Build Coastguard Worker #error Windows 10.0.22621.0 SDK or higher required.
31*6777b538SAndroid Build Coastguard Worker #endif
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker namespace base {
34*6777b538SAndroid Build Coastguard Worker namespace win {
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker namespace {
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker // The values under the CurrentVersion registry hive are mirrored under
39*6777b538SAndroid Build Coastguard Worker // the corresponding Wow6432 hive.
40*6777b538SAndroid Build Coastguard Worker constexpr wchar_t kRegKeyWindowsNTCurrentVersion[] =
41*6777b538SAndroid Build Coastguard Worker     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker // Returns the "UBR" (Windows 10 patch number) and "DisplayVersion" (or
44*6777b538SAndroid Build Coastguard Worker // "ReleaseId" on earlier versions) (Windows 10 release number) from registry.
45*6777b538SAndroid Build Coastguard Worker // "UBR" is an undocumented value and will be 0 if the value was not found.
46*6777b538SAndroid Build Coastguard Worker // "ReleaseId" will be an empty string if neither new nor old values are found.
GetVersionData()47*6777b538SAndroid Build Coastguard Worker std::pair<int, std::string> GetVersionData() {
48*6777b538SAndroid Build Coastguard Worker   DWORD ubr = 0;
49*6777b538SAndroid Build Coastguard Worker   std::wstring release_id;
50*6777b538SAndroid Build Coastguard Worker   RegKey key;
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker   if (key.Open(HKEY_LOCAL_MACHINE, kRegKeyWindowsNTCurrentVersion,
53*6777b538SAndroid Build Coastguard Worker                KEY_QUERY_VALUE) == ERROR_SUCCESS) {
54*6777b538SAndroid Build Coastguard Worker     key.ReadValueDW(L"UBR", &ubr);
55*6777b538SAndroid Build Coastguard Worker     // "DisplayVersion" has been introduced in Windows 10 2009
56*6777b538SAndroid Build Coastguard Worker     // when naming changed to mixed letters and numbers.
57*6777b538SAndroid Build Coastguard Worker     key.ReadValue(L"DisplayVersion", &release_id);
58*6777b538SAndroid Build Coastguard Worker     // Use discontinued "ReleaseId" instead, if the former is unavailable.
59*6777b538SAndroid Build Coastguard Worker     if (release_id.empty())
60*6777b538SAndroid Build Coastguard Worker       key.ReadValue(L"ReleaseId", &release_id);
61*6777b538SAndroid Build Coastguard Worker   }
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker   return std::make_pair(static_cast<int>(ubr), WideToUTF8(release_id));
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
GetSystemInfoStorage()66*6777b538SAndroid Build Coastguard Worker const _SYSTEM_INFO& GetSystemInfoStorage() {
67*6777b538SAndroid Build Coastguard Worker   static const _SYSTEM_INFO system_info = [] {
68*6777b538SAndroid Build Coastguard Worker     _SYSTEM_INFO info = {};
69*6777b538SAndroid Build Coastguard Worker     ::GetNativeSystemInfo(&info);
70*6777b538SAndroid Build Coastguard Worker     return info;
71*6777b538SAndroid Build Coastguard Worker   }();
72*6777b538SAndroid Build Coastguard Worker   return system_info;
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker }  // namespace
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker // static
GetInstanceStorage()78*6777b538SAndroid Build Coastguard Worker OSInfo** OSInfo::GetInstanceStorage() {
79*6777b538SAndroid Build Coastguard Worker   // Note: we don't use the Singleton class because it depends on AtExitManager,
80*6777b538SAndroid Build Coastguard Worker   // and it's convenient for other modules to use this class without it.
81*6777b538SAndroid Build Coastguard Worker   static OSInfo* info = []() {
82*6777b538SAndroid Build Coastguard Worker     _OSVERSIONINFOEXW version_info = {sizeof(version_info)};
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker #pragma clang diagnostic push
85*6777b538SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
86*6777b538SAndroid Build Coastguard Worker     // GetVersionEx() is deprecated, and the suggested replacement are
87*6777b538SAndroid Build Coastguard Worker     // the IsWindows*OrGreater() functions in VersionHelpers.h. We can't
88*6777b538SAndroid Build Coastguard Worker     // use that because:
89*6777b538SAndroid Build Coastguard Worker     // - For Windows 10, there's IsWindows10OrGreater(), but nothing more
90*6777b538SAndroid Build Coastguard Worker     //   granular. We need to be able to detect different Windows 10 releases
91*6777b538SAndroid Build Coastguard Worker     //   since they sometimes change behavior in ways that matter.
92*6777b538SAndroid Build Coastguard Worker     // - There is no IsWindows11OrGreater() function yet.
93*6777b538SAndroid Build Coastguard Worker     ::GetVersionEx(reinterpret_cast<_OSVERSIONINFOW*>(&version_info));
94*6777b538SAndroid Build Coastguard Worker #pragma clang diagnostic pop
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker     DWORD os_type = 0;
97*6777b538SAndroid Build Coastguard Worker     ::GetProductInfo(version_info.dwMajorVersion, version_info.dwMinorVersion,
98*6777b538SAndroid Build Coastguard Worker                      0, 0, &os_type);
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker     return new OSInfo(version_info, GetSystemInfoStorage(), os_type);
101*6777b538SAndroid Build Coastguard Worker   }();
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   return &info;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker // static
GetInstance()107*6777b538SAndroid Build Coastguard Worker OSInfo* OSInfo::GetInstance() {
108*6777b538SAndroid Build Coastguard Worker   return *GetInstanceStorage();
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker // static
GetArchitecture()112*6777b538SAndroid Build Coastguard Worker OSInfo::WindowsArchitecture OSInfo::GetArchitecture() {
113*6777b538SAndroid Build Coastguard Worker   switch (GetSystemInfoStorage().wProcessorArchitecture) {
114*6777b538SAndroid Build Coastguard Worker     case PROCESSOR_ARCHITECTURE_INTEL:
115*6777b538SAndroid Build Coastguard Worker       return X86_ARCHITECTURE;
116*6777b538SAndroid Build Coastguard Worker     case PROCESSOR_ARCHITECTURE_AMD64:
117*6777b538SAndroid Build Coastguard Worker       return X64_ARCHITECTURE;
118*6777b538SAndroid Build Coastguard Worker     case PROCESSOR_ARCHITECTURE_IA64:
119*6777b538SAndroid Build Coastguard Worker       return IA64_ARCHITECTURE;
120*6777b538SAndroid Build Coastguard Worker     case PROCESSOR_ARCHITECTURE_ARM64:
121*6777b538SAndroid Build Coastguard Worker       return ARM64_ARCHITECTURE;
122*6777b538SAndroid Build Coastguard Worker     default:
123*6777b538SAndroid Build Coastguard Worker       return OTHER_ARCHITECTURE;
124*6777b538SAndroid Build Coastguard Worker   }
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker // Returns true if this is an x86/x64 process running on ARM64 through
128*6777b538SAndroid Build Coastguard Worker // emulation.
129*6777b538SAndroid Build Coastguard Worker // static
IsRunningEmulatedOnArm64()130*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsRunningEmulatedOnArm64() {
131*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM64)
132*6777b538SAndroid Build Coastguard Worker   // If we're running native ARM64 then we aren't running emulated.
133*6777b538SAndroid Build Coastguard Worker   return false;
134*6777b538SAndroid Build Coastguard Worker #else
135*6777b538SAndroid Build Coastguard Worker   using IsWow64Process2Function = decltype(&IsWow64Process2);
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker   IsWow64Process2Function is_wow64_process2 =
138*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<IsWow64Process2Function>(::GetProcAddress(
139*6777b538SAndroid Build Coastguard Worker           ::GetModuleHandleA("kernel32.dll"), "IsWow64Process2"));
140*6777b538SAndroid Build Coastguard Worker   if (!is_wow64_process2) {
141*6777b538SAndroid Build Coastguard Worker     return false;
142*6777b538SAndroid Build Coastguard Worker   }
143*6777b538SAndroid Build Coastguard Worker   USHORT process_machine;
144*6777b538SAndroid Build Coastguard Worker   USHORT native_machine;
145*6777b538SAndroid Build Coastguard Worker   bool retval = is_wow64_process2(::GetCurrentProcess(), &process_machine,
146*6777b538SAndroid Build Coastguard Worker                                   &native_machine);
147*6777b538SAndroid Build Coastguard Worker   if (!retval) {
148*6777b538SAndroid Build Coastguard Worker     return false;
149*6777b538SAndroid Build Coastguard Worker   }
150*6777b538SAndroid Build Coastguard Worker   if (native_machine == IMAGE_FILE_MACHINE_ARM64) {
151*6777b538SAndroid Build Coastguard Worker     return true;
152*6777b538SAndroid Build Coastguard Worker   }
153*6777b538SAndroid Build Coastguard Worker   return false;
154*6777b538SAndroid Build Coastguard Worker #endif
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker 
OSInfo(const _OSVERSIONINFOEXW & version_info,const _SYSTEM_INFO & system_info,DWORD os_type)157*6777b538SAndroid Build Coastguard Worker OSInfo::OSInfo(const _OSVERSIONINFOEXW& version_info,
158*6777b538SAndroid Build Coastguard Worker                const _SYSTEM_INFO& system_info,
159*6777b538SAndroid Build Coastguard Worker                DWORD os_type)
160*6777b538SAndroid Build Coastguard Worker     : version_(Version::PRE_XP),
161*6777b538SAndroid Build Coastguard Worker       wow_process_machine_(WowProcessMachine::kUnknown),
162*6777b538SAndroid Build Coastguard Worker       wow_native_machine_(WowNativeMachine::kUnknown),
163*6777b538SAndroid Build Coastguard Worker       os_type_(os_type) {
164*6777b538SAndroid Build Coastguard Worker   version_number_.major = version_info.dwMajorVersion;
165*6777b538SAndroid Build Coastguard Worker   version_number_.minor = version_info.dwMinorVersion;
166*6777b538SAndroid Build Coastguard Worker   version_number_.build = version_info.dwBuildNumber;
167*6777b538SAndroid Build Coastguard Worker   std::tie(version_number_.patch, release_id_) = GetVersionData();
168*6777b538SAndroid Build Coastguard Worker   version_ = MajorMinorBuildToVersion(
169*6777b538SAndroid Build Coastguard Worker       version_number_.major, version_number_.minor, version_number_.build);
170*6777b538SAndroid Build Coastguard Worker   InitializeWowStatusValuesForProcess(GetCurrentProcess());
171*6777b538SAndroid Build Coastguard Worker   service_pack_.major = version_info.wServicePackMajor;
172*6777b538SAndroid Build Coastguard Worker   service_pack_.minor = version_info.wServicePackMinor;
173*6777b538SAndroid Build Coastguard Worker   service_pack_str_ = WideToUTF8(version_info.szCSDVersion);
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   processors_ = static_cast<int>(system_info.dwNumberOfProcessors);
176*6777b538SAndroid Build Coastguard Worker   allocation_granularity_ = system_info.dwAllocationGranularity;
177*6777b538SAndroid Build Coastguard Worker 
178*6777b538SAndroid Build Coastguard Worker   if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) {
179*6777b538SAndroid Build Coastguard Worker     // Only present on Vista+.
180*6777b538SAndroid Build Coastguard Worker     switch (os_type) {
181*6777b538SAndroid Build Coastguard Worker       case PRODUCT_CLUSTER_SERVER:
182*6777b538SAndroid Build Coastguard Worker       case PRODUCT_DATACENTER_SERVER:
183*6777b538SAndroid Build Coastguard Worker       case PRODUCT_DATACENTER_SERVER_CORE:
184*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_SERVER:
185*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_SERVER_CORE:
186*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_SERVER_IA64:
187*6777b538SAndroid Build Coastguard Worker       case PRODUCT_SMALLBUSINESS_SERVER:
188*6777b538SAndroid Build Coastguard Worker       case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
189*6777b538SAndroid Build Coastguard Worker       case PRODUCT_STANDARD_SERVER:
190*6777b538SAndroid Build Coastguard Worker       case PRODUCT_STANDARD_SERVER_CORE:
191*6777b538SAndroid Build Coastguard Worker       case PRODUCT_WEB_SERVER:
192*6777b538SAndroid Build Coastguard Worker         version_type_ = SUITE_SERVER;
193*6777b538SAndroid Build Coastguard Worker         break;
194*6777b538SAndroid Build Coastguard Worker       case PRODUCT_PROFESSIONAL:
195*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ULTIMATE:
196*6777b538SAndroid Build Coastguard Worker         version_type_ = SUITE_PROFESSIONAL;
197*6777b538SAndroid Build Coastguard Worker         break;
198*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE:
199*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_E:
200*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_EVALUATION:
201*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_N:
202*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_N_EVALUATION:
203*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_S:
204*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_S_EVALUATION:
205*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_S_N:
206*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_S_N_EVALUATION:
207*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_SUBSCRIPTION:
208*6777b538SAndroid Build Coastguard Worker       case PRODUCT_ENTERPRISE_SUBSCRIPTION_N:
209*6777b538SAndroid Build Coastguard Worker       case PRODUCT_BUSINESS:
210*6777b538SAndroid Build Coastguard Worker       case PRODUCT_BUSINESS_N:
211*6777b538SAndroid Build Coastguard Worker       case PRODUCT_IOTENTERPRISE:
212*6777b538SAndroid Build Coastguard Worker       case PRODUCT_IOTENTERPRISES:
213*6777b538SAndroid Build Coastguard Worker         version_type_ = SUITE_ENTERPRISE;
214*6777b538SAndroid Build Coastguard Worker         break;
215*6777b538SAndroid Build Coastguard Worker       case PRODUCT_PRO_FOR_EDUCATION:
216*6777b538SAndroid Build Coastguard Worker       case PRODUCT_PRO_FOR_EDUCATION_N:
217*6777b538SAndroid Build Coastguard Worker         version_type_ = SUITE_EDUCATION_PRO;
218*6777b538SAndroid Build Coastguard Worker         break;
219*6777b538SAndroid Build Coastguard Worker       case PRODUCT_EDUCATION:
220*6777b538SAndroid Build Coastguard Worker       case PRODUCT_EDUCATION_N:
221*6777b538SAndroid Build Coastguard Worker         version_type_ = SUITE_EDUCATION;
222*6777b538SAndroid Build Coastguard Worker         break;
223*6777b538SAndroid Build Coastguard Worker       case PRODUCT_HOME_BASIC:
224*6777b538SAndroid Build Coastguard Worker       case PRODUCT_HOME_PREMIUM:
225*6777b538SAndroid Build Coastguard Worker       case PRODUCT_STARTER:
226*6777b538SAndroid Build Coastguard Worker       default:
227*6777b538SAndroid Build Coastguard Worker         version_type_ = SUITE_HOME;
228*6777b538SAndroid Build Coastguard Worker         break;
229*6777b538SAndroid Build Coastguard Worker     }
230*6777b538SAndroid Build Coastguard Worker   } else if (version_info.dwMajorVersion == 5 &&
231*6777b538SAndroid Build Coastguard Worker              version_info.dwMinorVersion == 2) {
232*6777b538SAndroid Build Coastguard Worker     if (version_info.wProductType == VER_NT_WORKSTATION &&
233*6777b538SAndroid Build Coastguard Worker         system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
234*6777b538SAndroid Build Coastguard Worker       version_type_ = SUITE_PROFESSIONAL;
235*6777b538SAndroid Build Coastguard Worker     } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER) {
236*6777b538SAndroid Build Coastguard Worker       version_type_ = SUITE_HOME;
237*6777b538SAndroid Build Coastguard Worker     } else {
238*6777b538SAndroid Build Coastguard Worker       version_type_ = SUITE_SERVER;
239*6777b538SAndroid Build Coastguard Worker     }
240*6777b538SAndroid Build Coastguard Worker   } else if (version_info.dwMajorVersion == 5 &&
241*6777b538SAndroid Build Coastguard Worker              version_info.dwMinorVersion == 1) {
242*6777b538SAndroid Build Coastguard Worker     if (version_info.wSuiteMask & VER_SUITE_PERSONAL)
243*6777b538SAndroid Build Coastguard Worker       version_type_ = SUITE_HOME;
244*6777b538SAndroid Build Coastguard Worker     else
245*6777b538SAndroid Build Coastguard Worker       version_type_ = SUITE_PROFESSIONAL;
246*6777b538SAndroid Build Coastguard Worker   } else {
247*6777b538SAndroid Build Coastguard Worker     // Windows is pre XP so we don't care but pick a safe default.
248*6777b538SAndroid Build Coastguard Worker     version_type_ = SUITE_HOME;
249*6777b538SAndroid Build Coastguard Worker   }
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker OSInfo::~OSInfo() = default;
253*6777b538SAndroid Build Coastguard Worker 
Kernel32Version()254*6777b538SAndroid Build Coastguard Worker Version OSInfo::Kernel32Version() {
255*6777b538SAndroid Build Coastguard Worker   static const Version kernel32_version =
256*6777b538SAndroid Build Coastguard Worker       MajorMinorBuildToVersion(Kernel32BaseVersion().components()[0],
257*6777b538SAndroid Build Coastguard Worker                                Kernel32BaseVersion().components()[1],
258*6777b538SAndroid Build Coastguard Worker                                Kernel32BaseVersion().components()[2]);
259*6777b538SAndroid Build Coastguard Worker   return kernel32_version;
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker 
Kernel32VersionNumber()262*6777b538SAndroid Build Coastguard Worker OSInfo::VersionNumber OSInfo::Kernel32VersionNumber() {
263*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(Kernel32BaseVersion().components().size(), 4u);
264*6777b538SAndroid Build Coastguard Worker   static const VersionNumber version = {
265*6777b538SAndroid Build Coastguard Worker       .major = Kernel32BaseVersion().components()[0],
266*6777b538SAndroid Build Coastguard Worker       .minor = Kernel32BaseVersion().components()[1],
267*6777b538SAndroid Build Coastguard Worker       .build = Kernel32BaseVersion().components()[2],
268*6777b538SAndroid Build Coastguard Worker       .patch = Kernel32BaseVersion().components()[3]};
269*6777b538SAndroid Build Coastguard Worker   return version;
270*6777b538SAndroid Build Coastguard Worker }
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker // Retrieve a version from kernel32. This is useful because when running in
273*6777b538SAndroid Build Coastguard Worker // compatibility mode for a down-level version of the OS, the file version of
274*6777b538SAndroid Build Coastguard Worker // kernel32 will still be the "real" version.
Kernel32BaseVersion()275*6777b538SAndroid Build Coastguard Worker base::Version OSInfo::Kernel32BaseVersion() {
276*6777b538SAndroid Build Coastguard Worker   static const NoDestructor<base::Version> version([] {
277*6777b538SAndroid Build Coastguard Worker     // Allow the calls to `Kernel32BaseVersion()` to block, as they only happen
278*6777b538SAndroid Build Coastguard Worker     // once (after which the result is cached in `version`), and reading from
279*6777b538SAndroid Build Coastguard Worker     // kernel32.dll is fast in practice because it is used by all processes and
280*6777b538SAndroid Build Coastguard Worker     // therefore likely to be in the OS's file cache.
281*6777b538SAndroid Build Coastguard Worker     base::ScopedAllowBlocking allow_blocking;
282*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<FileVersionInfoWin> file_version_info =
283*6777b538SAndroid Build Coastguard Worker         FileVersionInfoWin::CreateFileVersionInfoWin(
284*6777b538SAndroid Build Coastguard Worker             FilePath(FILE_PATH_LITERAL("kernel32.dll")));
285*6777b538SAndroid Build Coastguard Worker     if (!file_version_info) {
286*6777b538SAndroid Build Coastguard Worker       // crbug.com/912061: on some systems it seems kernel32.dll might be
287*6777b538SAndroid Build Coastguard Worker       // corrupted or not in a state to get version info. In this case try
288*6777b538SAndroid Build Coastguard Worker       // kernelbase.dll as a fallback.
289*6777b538SAndroid Build Coastguard Worker       file_version_info = FileVersionInfoWin::CreateFileVersionInfoWin(
290*6777b538SAndroid Build Coastguard Worker           FilePath(FILE_PATH_LITERAL("kernelbase.dll")));
291*6777b538SAndroid Build Coastguard Worker     }
292*6777b538SAndroid Build Coastguard Worker     CHECK(file_version_info);
293*6777b538SAndroid Build Coastguard Worker     return file_version_info->GetFileVersion();
294*6777b538SAndroid Build Coastguard Worker   }());
295*6777b538SAndroid Build Coastguard Worker   return *version;
296*6777b538SAndroid Build Coastguard Worker }
297*6777b538SAndroid Build Coastguard Worker 
IsWowDisabled() const298*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsWowDisabled() const {
299*6777b538SAndroid Build Coastguard Worker   return (wow_process_machine_ == WowProcessMachine::kDisabled);
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker 
IsWowX86OnAMD64() const302*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsWowX86OnAMD64() const {
303*6777b538SAndroid Build Coastguard Worker   return (wow_process_machine_ == WowProcessMachine::kX86 &&
304*6777b538SAndroid Build Coastguard Worker           wow_native_machine_ == WowNativeMachine::kAMD64);
305*6777b538SAndroid Build Coastguard Worker }
306*6777b538SAndroid Build Coastguard Worker 
IsWowX86OnARM64() const307*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsWowX86OnARM64() const {
308*6777b538SAndroid Build Coastguard Worker   return (wow_process_machine_ == WowProcessMachine::kX86 &&
309*6777b538SAndroid Build Coastguard Worker           wow_native_machine_ == WowNativeMachine::kARM64);
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker 
IsWowAMD64OnARM64() const312*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsWowAMD64OnARM64() const {
313*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64)
314*6777b538SAndroid Build Coastguard Worker   // An AMD64 process running on an ARM64 device results in the incorrect
315*6777b538SAndroid Build Coastguard Worker   // identification of the device architecture (AMD64 is reported). However,
316*6777b538SAndroid Build Coastguard Worker   // IsWow64Process2 will return the correct device type for the native
317*6777b538SAndroid Build Coastguard Worker   // machine, even though the OS doesn't consider an AMD64 process on an ARM64
318*6777b538SAndroid Build Coastguard Worker   // processor a classic Windows-on-Windows setup.
319*6777b538SAndroid Build Coastguard Worker   return (wow_process_machine_ == WowProcessMachine::kDisabled &&
320*6777b538SAndroid Build Coastguard Worker           wow_native_machine_ == WowNativeMachine::kARM64);
321*6777b538SAndroid Build Coastguard Worker #else
322*6777b538SAndroid Build Coastguard Worker   return false;
323*6777b538SAndroid Build Coastguard Worker #endif
324*6777b538SAndroid Build Coastguard Worker }
325*6777b538SAndroid Build Coastguard Worker 
IsWowX86OnOther() const326*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsWowX86OnOther() const {
327*6777b538SAndroid Build Coastguard Worker   return (wow_process_machine_ == WowProcessMachine::kX86 &&
328*6777b538SAndroid Build Coastguard Worker           wow_native_machine_ == WowNativeMachine::kOther);
329*6777b538SAndroid Build Coastguard Worker }
330*6777b538SAndroid Build Coastguard Worker 
processor_model_name()331*6777b538SAndroid Build Coastguard Worker std::string OSInfo::processor_model_name() {
332*6777b538SAndroid Build Coastguard Worker   if (processor_model_name_.empty()) {
333*6777b538SAndroid Build Coastguard Worker     const wchar_t kProcessorNameString[] =
334*6777b538SAndroid Build Coastguard Worker         L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
335*6777b538SAndroid Build Coastguard Worker     RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ);
336*6777b538SAndroid Build Coastguard Worker     std::wstring value;
337*6777b538SAndroid Build Coastguard Worker     key.ReadValue(L"ProcessorNameString", &value);
338*6777b538SAndroid Build Coastguard Worker     processor_model_name_ = WideToUTF8(value);
339*6777b538SAndroid Build Coastguard Worker   }
340*6777b538SAndroid Build Coastguard Worker   return processor_model_name_;
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker 
IsWindowsNSku() const343*6777b538SAndroid Build Coastguard Worker bool OSInfo::IsWindowsNSku() const {
344*6777b538SAndroid Build Coastguard Worker   switch (os_type_) {
345*6777b538SAndroid Build Coastguard Worker     case PRODUCT_BUSINESS_N:
346*6777b538SAndroid Build Coastguard Worker     case PRODUCT_CORE_N:
347*6777b538SAndroid Build Coastguard Worker     case PRODUCT_CORE_CONNECTED_N:
348*6777b538SAndroid Build Coastguard Worker     case PRODUCT_EDUCATION_N:
349*6777b538SAndroid Build Coastguard Worker     case PRODUCT_ENTERPRISE_N:
350*6777b538SAndroid Build Coastguard Worker     case PRODUCT_ENTERPRISE_S_N:
351*6777b538SAndroid Build Coastguard Worker     case PRODUCT_ENTERPRISE_SUBSCRIPTION_N:
352*6777b538SAndroid Build Coastguard Worker     case PRODUCT_HOME_BASIC_N:
353*6777b538SAndroid Build Coastguard Worker     case PRODUCT_HOME_PREMIUM_N:
354*6777b538SAndroid Build Coastguard Worker     case PRODUCT_PRO_FOR_EDUCATION_N:
355*6777b538SAndroid Build Coastguard Worker     case PRODUCT_PRO_WORKSTATION_N:
356*6777b538SAndroid Build Coastguard Worker     case PRODUCT_PROFESSIONAL_N:
357*6777b538SAndroid Build Coastguard Worker     case PRODUCT_PROFESSIONAL_S_N:
358*6777b538SAndroid Build Coastguard Worker     case PRODUCT_PROFESSIONAL_STUDENT_N:
359*6777b538SAndroid Build Coastguard Worker     case PRODUCT_STARTER_N:
360*6777b538SAndroid Build Coastguard Worker     case PRODUCT_ULTIMATE_N:
361*6777b538SAndroid Build Coastguard Worker       return true;
362*6777b538SAndroid Build Coastguard Worker     default:
363*6777b538SAndroid Build Coastguard Worker       return false;
364*6777b538SAndroid Build Coastguard Worker   }
365*6777b538SAndroid Build Coastguard Worker }
366*6777b538SAndroid Build Coastguard Worker 
367*6777b538SAndroid Build Coastguard Worker // With the exception of Server 2003, server variants are treated the same as
368*6777b538SAndroid Build Coastguard Worker // the corresponding workstation release.
369*6777b538SAndroid Build Coastguard Worker // static
MajorMinorBuildToVersion(uint32_t major,uint32_t minor,uint32_t build)370*6777b538SAndroid Build Coastguard Worker Version OSInfo::MajorMinorBuildToVersion(uint32_t major,
371*6777b538SAndroid Build Coastguard Worker                                          uint32_t minor,
372*6777b538SAndroid Build Coastguard Worker                                          uint32_t build) {
373*6777b538SAndroid Build Coastguard Worker   if (major == 11) {
374*6777b538SAndroid Build Coastguard Worker     // We know nothing about this version of Windows or even if it exists.
375*6777b538SAndroid Build Coastguard Worker     // Known Windows 11 versions have a major number 10 and are thus handled by
376*6777b538SAndroid Build Coastguard Worker     // the == 10 block below.
377*6777b538SAndroid Build Coastguard Worker     return Version::WIN11;
378*6777b538SAndroid Build Coastguard Worker   }
379*6777b538SAndroid Build Coastguard Worker 
380*6777b538SAndroid Build Coastguard Worker   if (major == 10) {
381*6777b538SAndroid Build Coastguard Worker     if (build >= 22631) {
382*6777b538SAndroid Build Coastguard Worker       return Version::WIN11_23H2;
383*6777b538SAndroid Build Coastguard Worker     }
384*6777b538SAndroid Build Coastguard Worker     if (build >= 22621) {
385*6777b538SAndroid Build Coastguard Worker       return Version::WIN11_22H2;
386*6777b538SAndroid Build Coastguard Worker     }
387*6777b538SAndroid Build Coastguard Worker     if (build >= 22000) {
388*6777b538SAndroid Build Coastguard Worker       return Version::WIN11;
389*6777b538SAndroid Build Coastguard Worker     }
390*6777b538SAndroid Build Coastguard Worker     if (build >= 20348) {
391*6777b538SAndroid Build Coastguard Worker       return Version::SERVER_2022;
392*6777b538SAndroid Build Coastguard Worker     }
393*6777b538SAndroid Build Coastguard Worker     if (build >= 19045) {
394*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_22H2;
395*6777b538SAndroid Build Coastguard Worker     }
396*6777b538SAndroid Build Coastguard Worker     if (build >= 19044) {
397*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_21H2;
398*6777b538SAndroid Build Coastguard Worker     }
399*6777b538SAndroid Build Coastguard Worker     if (build >= 19043) {
400*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_21H1;
401*6777b538SAndroid Build Coastguard Worker     }
402*6777b538SAndroid Build Coastguard Worker     if (build >= 19042) {
403*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_20H2;
404*6777b538SAndroid Build Coastguard Worker     }
405*6777b538SAndroid Build Coastguard Worker     if (build >= 19041) {
406*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_20H1;
407*6777b538SAndroid Build Coastguard Worker     }
408*6777b538SAndroid Build Coastguard Worker     if (build >= 18363) {
409*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_19H2;
410*6777b538SAndroid Build Coastguard Worker     }
411*6777b538SAndroid Build Coastguard Worker     if (build >= 18362) {
412*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_19H1;
413*6777b538SAndroid Build Coastguard Worker     }
414*6777b538SAndroid Build Coastguard Worker     if (build >= 17763) {
415*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_RS5;
416*6777b538SAndroid Build Coastguard Worker     }
417*6777b538SAndroid Build Coastguard Worker     if (build >= 17134) {
418*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_RS4;
419*6777b538SAndroid Build Coastguard Worker     }
420*6777b538SAndroid Build Coastguard Worker     if (build >= 16299) {
421*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_RS3;
422*6777b538SAndroid Build Coastguard Worker     }
423*6777b538SAndroid Build Coastguard Worker     if (build >= 15063) {
424*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_RS2;
425*6777b538SAndroid Build Coastguard Worker     }
426*6777b538SAndroid Build Coastguard Worker     if (build >= 14393) {
427*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_RS1;
428*6777b538SAndroid Build Coastguard Worker     }
429*6777b538SAndroid Build Coastguard Worker     if (build >= 10586) {
430*6777b538SAndroid Build Coastguard Worker       return Version::WIN10_TH2;
431*6777b538SAndroid Build Coastguard Worker     }
432*6777b538SAndroid Build Coastguard Worker     return Version::WIN10;
433*6777b538SAndroid Build Coastguard Worker   }
434*6777b538SAndroid Build Coastguard Worker 
435*6777b538SAndroid Build Coastguard Worker   if (major > 6) {
436*6777b538SAndroid Build Coastguard Worker     // Hitting this likely means that it's time for a >11 block above.
437*6777b538SAndroid Build Coastguard Worker     NOTREACHED() << major << "." << minor << "." << build;
438*6777b538SAndroid Build Coastguard Worker     return Version::WIN_LAST;
439*6777b538SAndroid Build Coastguard Worker   }
440*6777b538SAndroid Build Coastguard Worker 
441*6777b538SAndroid Build Coastguard Worker   if (major == 6) {
442*6777b538SAndroid Build Coastguard Worker     switch (minor) {
443*6777b538SAndroid Build Coastguard Worker       case 0:
444*6777b538SAndroid Build Coastguard Worker         return Version::VISTA;
445*6777b538SAndroid Build Coastguard Worker       case 1:
446*6777b538SAndroid Build Coastguard Worker         return Version::WIN7;
447*6777b538SAndroid Build Coastguard Worker       case 2:
448*6777b538SAndroid Build Coastguard Worker         return Version::WIN8;
449*6777b538SAndroid Build Coastguard Worker       default:
450*6777b538SAndroid Build Coastguard Worker         DCHECK_EQ(minor, 3u);
451*6777b538SAndroid Build Coastguard Worker         return Version::WIN8_1;
452*6777b538SAndroid Build Coastguard Worker     }
453*6777b538SAndroid Build Coastguard Worker   }
454*6777b538SAndroid Build Coastguard Worker 
455*6777b538SAndroid Build Coastguard Worker   if (major == 5 && minor != 0) {
456*6777b538SAndroid Build Coastguard Worker     // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
457*6777b538SAndroid Build Coastguard Worker     return minor == 1 ? Version::XP : Version::SERVER_2003;
458*6777b538SAndroid Build Coastguard Worker   }
459*6777b538SAndroid Build Coastguard Worker 
460*6777b538SAndroid Build Coastguard Worker   // Win 2000 or older.
461*6777b538SAndroid Build Coastguard Worker   return Version::PRE_XP;
462*6777b538SAndroid Build Coastguard Worker }
463*6777b538SAndroid Build Coastguard Worker 
GetVersion()464*6777b538SAndroid Build Coastguard Worker Version GetVersion() {
465*6777b538SAndroid Build Coastguard Worker   return OSInfo::GetInstance()->version();
466*6777b538SAndroid Build Coastguard Worker }
467*6777b538SAndroid Build Coastguard Worker 
GetWowProcessMachineArchitecture(const int process_machine)468*6777b538SAndroid Build Coastguard Worker OSInfo::WowProcessMachine OSInfo::GetWowProcessMachineArchitecture(
469*6777b538SAndroid Build Coastguard Worker     const int process_machine) {
470*6777b538SAndroid Build Coastguard Worker   switch (process_machine) {
471*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_UNKNOWN:
472*6777b538SAndroid Build Coastguard Worker       return OSInfo::WowProcessMachine::kDisabled;
473*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_I386:
474*6777b538SAndroid Build Coastguard Worker       return OSInfo::WowProcessMachine::kX86;
475*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_ARM:
476*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_THUMB:
477*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_ARMNT:
478*6777b538SAndroid Build Coastguard Worker       return OSInfo::WowProcessMachine::kARM32;
479*6777b538SAndroid Build Coastguard Worker   }
480*6777b538SAndroid Build Coastguard Worker   return OSInfo::WowProcessMachine::kOther;
481*6777b538SAndroid Build Coastguard Worker }
482*6777b538SAndroid Build Coastguard Worker 
GetWowNativeMachineArchitecture(const int native_machine)483*6777b538SAndroid Build Coastguard Worker OSInfo::WowNativeMachine OSInfo::GetWowNativeMachineArchitecture(
484*6777b538SAndroid Build Coastguard Worker     const int native_machine) {
485*6777b538SAndroid Build Coastguard Worker   switch (native_machine) {
486*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_ARM64:
487*6777b538SAndroid Build Coastguard Worker       return OSInfo::WowNativeMachine::kARM64;
488*6777b538SAndroid Build Coastguard Worker     case IMAGE_FILE_MACHINE_AMD64:
489*6777b538SAndroid Build Coastguard Worker       return OSInfo::WowNativeMachine::kAMD64;
490*6777b538SAndroid Build Coastguard Worker   }
491*6777b538SAndroid Build Coastguard Worker   return OSInfo::WowNativeMachine::kOther;
492*6777b538SAndroid Build Coastguard Worker }
493*6777b538SAndroid Build Coastguard Worker 
InitializeWowStatusValuesFromLegacyApi(HANDLE process_handle)494*6777b538SAndroid Build Coastguard Worker void OSInfo::InitializeWowStatusValuesFromLegacyApi(HANDLE process_handle) {
495*6777b538SAndroid Build Coastguard Worker   BOOL is_wow64 = FALSE;
496*6777b538SAndroid Build Coastguard Worker   if (!::IsWow64Process(process_handle, &is_wow64))
497*6777b538SAndroid Build Coastguard Worker     return;
498*6777b538SAndroid Build Coastguard Worker   if (is_wow64) {
499*6777b538SAndroid Build Coastguard Worker     wow_process_machine_ = WowProcessMachine::kX86;
500*6777b538SAndroid Build Coastguard Worker     wow_native_machine_ = WowNativeMachine::kAMD64;
501*6777b538SAndroid Build Coastguard Worker   } else {
502*6777b538SAndroid Build Coastguard Worker     wow_process_machine_ = WowProcessMachine::kDisabled;
503*6777b538SAndroid Build Coastguard Worker   }
504*6777b538SAndroid Build Coastguard Worker }
505*6777b538SAndroid Build Coastguard Worker 
InitializeWowStatusValuesForProcess(HANDLE process_handle)506*6777b538SAndroid Build Coastguard Worker void OSInfo::InitializeWowStatusValuesForProcess(HANDLE process_handle) {
507*6777b538SAndroid Build Coastguard Worker   static const auto is_wow64_process2 =
508*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<decltype(&IsWow64Process2)>(::GetProcAddress(
509*6777b538SAndroid Build Coastguard Worker           ::GetModuleHandle(L"kernel32.dll"), "IsWow64Process2"));
510*6777b538SAndroid Build Coastguard Worker   if (!is_wow64_process2) {
511*6777b538SAndroid Build Coastguard Worker     InitializeWowStatusValuesFromLegacyApi(process_handle);
512*6777b538SAndroid Build Coastguard Worker     return;
513*6777b538SAndroid Build Coastguard Worker   }
514*6777b538SAndroid Build Coastguard Worker 
515*6777b538SAndroid Build Coastguard Worker   USHORT process_machine = IMAGE_FILE_MACHINE_UNKNOWN;
516*6777b538SAndroid Build Coastguard Worker   USHORT native_machine = IMAGE_FILE_MACHINE_UNKNOWN;
517*6777b538SAndroid Build Coastguard Worker   if (!is_wow64_process2(process_handle, &process_machine, &native_machine)) {
518*6777b538SAndroid Build Coastguard Worker     return;
519*6777b538SAndroid Build Coastguard Worker   }
520*6777b538SAndroid Build Coastguard Worker   wow_process_machine_ = GetWowProcessMachineArchitecture(process_machine);
521*6777b538SAndroid Build Coastguard Worker   wow_native_machine_ = GetWowNativeMachineArchitecture(native_machine);
522*6777b538SAndroid Build Coastguard Worker }
523*6777b538SAndroid Build Coastguard Worker 
524*6777b538SAndroid Build Coastguard Worker }  // namespace win
525*6777b538SAndroid Build Coastguard Worker }  // namespace base
526