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
> 6) {
69 version_
= VERSION_WIN_LAST
;
71 service_pack_
.major
= version_info
.wServicePackMajor
;
72 service_pack_
.minor
= version_info
.wServicePackMinor
;
74 SYSTEM_INFO system_info
= { 0 };
75 ::GetNativeSystemInfo(&system_info
);
76 switch (system_info
.wProcessorArchitecture
) {
77 case PROCESSOR_ARCHITECTURE_INTEL
: architecture_
= X86_ARCHITECTURE
; break;
78 case PROCESSOR_ARCHITECTURE_AMD64
: architecture_
= X64_ARCHITECTURE
; break;
79 case PROCESSOR_ARCHITECTURE_IA64
: architecture_
= IA64_ARCHITECTURE
; break;
81 processors_
= system_info
.dwNumberOfProcessors
;
82 allocation_granularity_
= system_info
.dwAllocationGranularity
;
84 GetProductInfoPtr get_product_info
;
87 if (version_info
.dwMajorVersion
== 6) {
88 // Only present on Vista+.
89 get_product_info
= reinterpret_cast<GetProductInfoPtr
>(
90 ::GetProcAddress(::GetModuleHandle(L
"kernel32.dll"), "GetProductInfo"));
92 get_product_info(version_info
.dwMajorVersion
, version_info
.dwMinorVersion
,
95 case PRODUCT_CLUSTER_SERVER
:
96 case PRODUCT_DATACENTER_SERVER
:
97 case PRODUCT_DATACENTER_SERVER_CORE
:
98 case PRODUCT_ENTERPRISE_SERVER
:
99 case PRODUCT_ENTERPRISE_SERVER_CORE
:
100 case PRODUCT_ENTERPRISE_SERVER_IA64
:
101 case PRODUCT_SMALLBUSINESS_SERVER
:
102 case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM
:
103 case PRODUCT_STANDARD_SERVER
:
104 case PRODUCT_STANDARD_SERVER_CORE
:
105 case PRODUCT_WEB_SERVER
:
106 version_type_
= SUITE_SERVER
;
108 case PRODUCT_PROFESSIONAL
:
109 case PRODUCT_ULTIMATE
:
110 case PRODUCT_ENTERPRISE
:
111 case PRODUCT_BUSINESS
:
112 version_type_
= SUITE_PROFESSIONAL
;
114 case PRODUCT_HOME_BASIC
:
115 case PRODUCT_HOME_PREMIUM
:
116 case PRODUCT_STARTER
:
118 version_type_
= SUITE_HOME
;
121 } else if (version_info
.dwMajorVersion
== 5 &&
122 version_info
.dwMinorVersion
== 2) {
123 if (version_info
.wProductType
== VER_NT_WORKSTATION
&&
124 system_info
.wProcessorArchitecture
== PROCESSOR_ARCHITECTURE_AMD64
) {
125 version_type_
= SUITE_PROFESSIONAL
;
126 } else if (version_info
.wSuiteMask
& VER_SUITE_WH_SERVER
) {
127 version_type_
= SUITE_HOME
;
129 version_type_
= SUITE_SERVER
;
131 } else if (version_info
.dwMajorVersion
== 5 &&
132 version_info
.dwMinorVersion
== 1) {
133 if(version_info
.wSuiteMask
& VER_SUITE_PERSONAL
)
134 version_type_
= SUITE_HOME
;
136 version_type_
= SUITE_PROFESSIONAL
;
138 // Windows is pre XP so we don't care but pick a safe default.
139 version_type_
= SUITE_HOME
;
146 std::string
OSInfo::processor_model_name() {
147 if (processor_model_name_
.empty()) {
148 const wchar_t kProcessorNameString
[] =
149 L
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
150 base::win::RegKey
key(HKEY_LOCAL_MACHINE
, kProcessorNameString
, KEY_READ
);
152 key
.ReadValue(L
"ProcessorNameString", &value
);
153 processor_model_name_
= UTF16ToUTF8(value
);
155 return processor_model_name_
;
159 OSInfo::WOW64Status
OSInfo::GetWOW64StatusForProcess(HANDLE process_handle
) {
160 typedef BOOL (WINAPI
* IsWow64ProcessFunc
)(HANDLE
, PBOOL
);
161 IsWow64ProcessFunc is_wow64_process
= reinterpret_cast<IsWow64ProcessFunc
>(
162 GetProcAddress(GetModuleHandle(L
"kernel32.dll"), "IsWow64Process"));
163 if (!is_wow64_process
)
164 return WOW64_DISABLED
;
165 BOOL is_wow64
= FALSE
;
166 if (!(*is_wow64_process
)(process_handle
, &is_wow64
))
167 return WOW64_UNKNOWN
;
168 return is_wow64
? WOW64_ENABLED
: WOW64_DISABLED
;
171 Version
GetVersion() {
172 return OSInfo::GetInstance()->version();