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. 4 5 #include "base/win/windows_version.h" 6 7 #include <windows.h> 8 9 #include "base/logging.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/win/registry.h" 12 13 namespace { 14 typedef BOOL (WINAPI *GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD); 15 } 16 17 namespace base { 18 namespace win { 19 20 // static 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. 25 static OSInfo* info; 26 if (!info) { 27 OSInfo* new_info = new OSInfo(); 28 if (InterlockedCompareExchangePointer( 29 reinterpret_cast<PVOID*>(&info), new_info, NULL)) { 30 delete new_info; 31 } 32 } 33 return info; 34 } 35 36 OSInfo::OSInfo() 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) { 50 case 0: 51 // Treat Windows Server 2008 the same as Windows Vista. 52 version_ = VERSION_VISTA; 53 break; 54 case 1: 55 // Treat Windows Server 2008 R2 the same as Windows 7. 56 version_ = VERSION_WIN7; 57 break; 58 case 2: 59 // Treat Windows Server 2012 the same as Windows 8. 60 version_ = VERSION_WIN8; 61 break; 62 default: 63 DCHECK_EQ(version_number_.minor, 3); 64 version_ = VERSION_WIN8_1; 65 break; 66 } 67 } else if (version_number_.major > 6) { 68 NOTREACHED(); 69 version_ = VERSION_WIN_LAST; 70 } 71 service_pack_.major = version_info.wServicePackMajor; 72 service_pack_.minor = version_info.wServicePackMinor; 73 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; 80 } 81 processors_ = system_info.dwNumberOfProcessors; 82 allocation_granularity_ = system_info.dwAllocationGranularity; 83 84 GetProductInfoPtr get_product_info; 85 DWORD os_type; 86 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")); 91 92 get_product_info(version_info.dwMajorVersion, version_info.dwMinorVersion, 93 0, 0, &os_type); 94 switch (os_type) { 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; 107 break; 108 case PRODUCT_PROFESSIONAL: 109 case PRODUCT_ULTIMATE: 110 case PRODUCT_ENTERPRISE: 111 case PRODUCT_BUSINESS: 112 version_type_ = SUITE_PROFESSIONAL; 113 break; 114 case PRODUCT_HOME_BASIC: 115 case PRODUCT_HOME_PREMIUM: 116 case PRODUCT_STARTER: 117 default: 118 version_type_ = SUITE_HOME; 119 break; 120 } 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; 128 } else { 129 version_type_ = SUITE_SERVER; 130 } 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; 135 else 136 version_type_ = SUITE_PROFESSIONAL; 137 } else { 138 // Windows is pre XP so we don't care but pick a safe default. 139 version_type_ = SUITE_HOME; 140 } 141 } 142 143 OSInfo::~OSInfo() { 144 } 145 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); 151 string16 value; 152 key.ReadValue(L"ProcessorNameString", &value); 153 processor_model_name_ = UTF16ToUTF8(value); 154 } 155 return processor_model_name_; 156 } 157 158 // static 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; 169 } 170 171 Version GetVersion() { 172 return OSInfo::GetInstance()->version(); 173 } 174 175 } // namespace win 176 } // namespace base 177