1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/win/windows_version.h"
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/win/registry.h"
14 typedef BOOL (WINAPI
*GetProductInfoPtr
)(DWORD
, DWORD
, DWORD
, DWORD
, PDWORD
);
21 OSInfo
* OSInfo::GetInstance() {
22 // Note: we don't use the Singleton class because it depends on AtExitManager,
23 // and it's convenient for other modules to use this classs without it. This
24 // pattern is copied from gurl.cc.
27 OSInfo
* new_info
= new OSInfo();
28 if (InterlockedCompareExchangePointer(
29 reinterpret_cast<PVOID
*>(&info
), new_info
, NULL
)) {
37 : version_(VERSION_PRE_XP
),
38 architecture_(OTHER_ARCHITECTURE
),
39 wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) {
40 OSVERSIONINFOEX version_info
= { sizeof version_info
};
41 ::GetVersionEx(reinterpret_cast<OSVERSIONINFO
*>(&version_info
));
42 version_number_
.major
= version_info
.dwMajorVersion
;
43 version_number_
.minor
= version_info
.dwMinorVersion
;
44 version_number_
.build
= version_info
.dwBuildNumber
;
45 if ((version_number_
.major
== 5) && (version_number_
.minor
> 0)) {
46 // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
47 version_
= (version_number_
.minor
== 1) ? VERSION_XP
: VERSION_SERVER_2003
;
48 } else if (version_number_
.major
== 6) {
49 switch (version_number_
.minor
) {
51 // Treat Windows Server 2008 the same as Windows Vista.
52 version_
= VERSION_VISTA
;
55 // Treat Windows Server 2008 R2 the same as Windows 7.
56 version_
= VERSION_WIN7
;
59 // Treat Windows Server 2012 the same as Windows 8.
60 version_
= VERSION_WIN8
;
63 DCHECK_EQ(version_number_
.minor
, 3);
64 version_
= VERSION_WIN8_1
;
67 } else if (version_number_
.major
== 10) {
68 version_
= VERSION_WIN10
;
69 } else if (version_number_
.major
> 6) {
71 version_
= VERSION_WIN_LAST
;
73 service_pack_
.major
= version_info
.wServicePackMajor
;
74 service_pack_
.minor
= version_info
.wServicePackMinor
;
76 SYSTEM_INFO system_info
= { 0 };
77 ::GetNativeSystemInfo(&system_info
);
78 switch (system_info
.wProcessorArchitecture
) {
79 case PROCESSOR_ARCHITECTURE_INTEL
: architecture_
= X86_ARCHITECTURE
; break;
80 case PROCESSOR_ARCHITECTURE_AMD64
: architecture_
= X64_ARCHITECTURE
; break;
81 case PROCESSOR_ARCHITECTURE_IA64
: architecture_
= IA64_ARCHITECTURE
; break;
83 processors_
= system_info
.dwNumberOfProcessors
;
84 allocation_granularity_
= system_info
.dwAllocationGranularity
;
86 GetProductInfoPtr get_product_info
;
89 if (version_info
.dwMajorVersion
== 6 || version_info
.dwMajorVersion
== 10) {
90 // Only present on Vista+.
91 get_product_info
= reinterpret_cast<GetProductInfoPtr
>(
92 ::GetProcAddress(::GetModuleHandle(L
"kernel32.dll"), "GetProductInfo"));
94 get_product_info(version_info
.dwMajorVersion
, version_info
.dwMinorVersion
,
97 case PRODUCT_CLUSTER_SERVER
:
98 case PRODUCT_DATACENTER_SERVER
:
99 case PRODUCT_DATACENTER_SERVER_CORE
:
100 case PRODUCT_ENTERPRISE_SERVER
:
101 case PRODUCT_ENTERPRISE_SERVER_CORE
:
102 case PRODUCT_ENTERPRISE_SERVER_IA64
:
103 case PRODUCT_SMALLBUSINESS_SERVER
:
104 case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM
:
105 case PRODUCT_STANDARD_SERVER
:
106 case PRODUCT_STANDARD_SERVER_CORE
:
107 case PRODUCT_WEB_SERVER
:
108 version_type_
= SUITE_SERVER
;
110 case PRODUCT_PROFESSIONAL
:
111 case PRODUCT_ULTIMATE
:
112 case PRODUCT_ENTERPRISE
:
113 case PRODUCT_BUSINESS
:
114 version_type_
= SUITE_PROFESSIONAL
;
116 case PRODUCT_HOME_BASIC
:
117 case PRODUCT_HOME_PREMIUM
:
118 case PRODUCT_STARTER
:
120 version_type_
= SUITE_HOME
;
123 } else if (version_info
.dwMajorVersion
== 5 &&
124 version_info
.dwMinorVersion
== 2) {
125 if (version_info
.wProductType
== VER_NT_WORKSTATION
&&
126 system_info
.wProcessorArchitecture
== PROCESSOR_ARCHITECTURE_AMD64
) {
127 version_type_
= SUITE_PROFESSIONAL
;
128 } else if (version_info
.wSuiteMask
& VER_SUITE_WH_SERVER
) {
129 version_type_
= SUITE_HOME
;
131 version_type_
= SUITE_SERVER
;
133 } else if (version_info
.dwMajorVersion
== 5 &&
134 version_info
.dwMinorVersion
== 1) {
135 if(version_info
.wSuiteMask
& VER_SUITE_PERSONAL
)
136 version_type_
= SUITE_HOME
;
138 version_type_
= SUITE_PROFESSIONAL
;
140 // Windows is pre XP so we don't care but pick a safe default.
141 version_type_
= SUITE_HOME
;
148 std::string
OSInfo::processor_model_name() {
149 if (processor_model_name_
.empty()) {
150 const wchar_t kProcessorNameString
[] =
151 L
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
152 base::win::RegKey
key(HKEY_LOCAL_MACHINE
, kProcessorNameString
, KEY_READ
);
154 key
.ReadValue(L
"ProcessorNameString", &value
);
155 processor_model_name_
= UTF16ToUTF8(value
);
157 return processor_model_name_
;
161 OSInfo::WOW64Status
OSInfo::GetWOW64StatusForProcess(HANDLE process_handle
) {
162 typedef BOOL (WINAPI
* IsWow64ProcessFunc
)(HANDLE
, PBOOL
);
163 IsWow64ProcessFunc is_wow64_process
= reinterpret_cast<IsWow64ProcessFunc
>(
164 GetProcAddress(GetModuleHandle(L
"kernel32.dll"), "IsWow64Process"));
165 if (!is_wow64_process
)
166 return WOW64_DISABLED
;
167 BOOL is_wow64
= FALSE
;
168 if (!(*is_wow64_process
)(process_handle
, &is_wow64
))
169 return WOW64_UNKNOWN
;
170 return is_wow64
? WOW64_ENABLED
: WOW64_DISABLED
;
173 Version
GetVersion() {
174 return OSInfo::GetInstance()->version();