15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)typedef BOOL (WINAPI *GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD);
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSInfo* OSInfo::GetInstance() {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: we don't use the Singleton class because it depends on AtExitManager,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and it's convenient for other modules to use this classs without it. This
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pattern is copied from gurl.cc.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static OSInfo* info;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSInfo* new_info = new OSInfo();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (InterlockedCompareExchangePointer(
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<PVOID*>(&info), new_info, NULL)) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete new_info;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return info;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSInfo::OSInfo()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : version_(VERSION_PRE_XP),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      architecture_(OTHER_ARCHITECTURE),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSVERSIONINFOEX version_info = { sizeof version_info };
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_number_.major = version_info.dwMajorVersion;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_number_.minor = version_info.dwMinorVersion;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_number_.build = version_info.dwBuildNumber;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((version_number_.major == 5) && (version_number_.minor > 0)) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    version_ = (version_number_.minor == 1) ? VERSION_XP : VERSION_SERVER_2003;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (version_number_.major == 6) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (version_number_.minor) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 0:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Treat Windows Server 2008 the same as Windows Vista.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        version_ = VERSION_VISTA;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Treat Windows Server 2008 R2 the same as Windows 7.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        version_ = VERSION_WIN7;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      case 2:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Treat Windows Server 2012 the same as Windows 8.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        version_ = VERSION_WIN8;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      default:
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        DCHECK_EQ(version_number_.minor, 3);
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        version_ = VERSION_WIN8_1;
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        break;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (version_number_.major > 6) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    version_ = VERSION_WIN_LAST;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_pack_.major = version_info.wServicePackMajor;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_pack_.minor = version_info.wServicePackMinor;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SYSTEM_INFO system_info = { 0 };
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ::GetNativeSystemInfo(&system_info);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (system_info.wProcessorArchitecture) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PROCESSOR_ARCHITECTURE_INTEL: architecture_ = X86_ARCHITECTURE; break;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PROCESSOR_ARCHITECTURE_AMD64: architecture_ = X64_ARCHITECTURE; break;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PROCESSOR_ARCHITECTURE_IA64:  architecture_ = IA64_ARCHITECTURE; break;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  processors_ = system_info.dwNumberOfProcessors;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allocation_granularity_ = system_info.dwAllocationGranularity;
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetProductInfoPtr get_product_info;
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DWORD os_type;
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (version_info.dwMajorVersion == 6) {
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Only present on Vista+.
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    get_product_info = reinterpret_cast<GetProductInfoPtr>(
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "GetProductInfo"));
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    get_product_info(version_info.dwMajorVersion, version_info.dwMinorVersion,
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     0, 0, &os_type);
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switch (os_type) {
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_CLUSTER_SERVER:
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_DATACENTER_SERVER:
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_DATACENTER_SERVER_CORE:
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_ENTERPRISE_SERVER:
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_ENTERPRISE_SERVER_CORE:
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_ENTERPRISE_SERVER_IA64:
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_SMALLBUSINESS_SERVER:
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_STANDARD_SERVER:
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_STANDARD_SERVER_CORE:
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_WEB_SERVER:
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        version_type_ = SUITE_SERVER;
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_PROFESSIONAL:
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_ULTIMATE:
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_ENTERPRISE:
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_BUSINESS:
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        version_type_ = SUITE_PROFESSIONAL;
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_HOME_BASIC:
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_HOME_PREMIUM:
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PRODUCT_STARTER:
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      default:
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        version_type_ = SUITE_HOME;
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else if (version_info.dwMajorVersion == 5 &&
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             version_info.dwMinorVersion == 2) {
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (version_info.wProductType == VER_NT_WORKSTATION &&
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      version_type_ = SUITE_PROFESSIONAL;
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER ) {
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      version_type_ = SUITE_HOME;
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else {
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      version_type_ = SUITE_SERVER;
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else if (version_info.dwMajorVersion == 5 &&
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             version_info.dwMinorVersion == 1) {
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if(version_info.wSuiteMask & VER_SUITE_PERSONAL)
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      version_type_ = SUITE_HOME;
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    else
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      version_type_ = SUITE_PROFESSIONAL;
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Windows is pre XP so we don't care but pick a safe default.
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    version_type_ = SUITE_HOME;
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSInfo::~OSInfo() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string OSInfo::processor_model_name() {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (processor_model_name_.empty()) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t kProcessorNameString[] =
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 value;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key.ReadValue(L"ProcessorNameString", &value);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    processor_model_name_ = UTF16ToUTF8(value);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return processor_model_name_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_wow64_process)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WOW64_DISABLED;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL is_wow64 = FALSE;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(*is_wow64_process)(process_handle, &is_wow64))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WOW64_UNKNOWN;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Version GetVersion() {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OSInfo::GetInstance()->version();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
177