1/*
2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "SystemInfo.h"
28
29#include <windows.h>
30#include <wtf/text/StringConcatenate.h>
31
32namespace WebCore {
33
34WindowsVersion windowsVersion(int* major, int* minor)
35{
36    static bool initialized = false;
37    static WindowsVersion version;
38    static int majorVersion, minorVersion;
39
40    if (!initialized) {
41        initialized = true;
42#if OS(WINCE)
43        OSVERSIONINFO versionInfo;
44#else
45        OSVERSIONINFOEX versionInfo;
46#endif
47        ZeroMemory(&versionInfo, sizeof(versionInfo));
48        versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
49        GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&versionInfo));
50        majorVersion = versionInfo.dwMajorVersion;
51        minorVersion = versionInfo.dwMinorVersion;
52
53#if OS(WINCE)
54        if (majorVersion >= 1 && majorVersion <= 7)
55            version = static_cast<WindowsVersion>(WindowsCE1 + (majorVersion - 1));
56        else
57            version = (majorVersion < 1) ? WindowsCE1 : WindowsCE7;
58#else
59        if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32s)
60            version = Windows3_1;
61        else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
62            if (!minorVersion)
63                version = Windows95;
64            else
65                version = (minorVersion == 10) ? Windows98 : WindowsME;
66        } else {
67            if (majorVersion == 5) {
68                if (!minorVersion)
69                    version = Windows2000;
70                else
71                    version = (minorVersion == 1) ? WindowsXP : WindowsServer2003;
72            } else if (majorVersion >= 6) {
73                if (versionInfo.wProductType == VER_NT_WORKSTATION)
74                    version = (majorVersion == 6 && !minorVersion) ? WindowsVista : Windows7;
75                else
76                    version = WindowsServer2008;
77            } else
78                version = (majorVersion == 4) ? WindowsNT4 : WindowsNT3;
79        }
80#endif
81    }
82
83    if (major)
84        *major = majorVersion;
85    if (minor)
86        *minor = minorVersion;
87    return version;
88}
89
90static String osVersionForUAString()
91{
92    int major, minor;
93    WindowsVersion version = windowsVersion(&major, &minor);
94    switch (version) {
95    case WindowsCE1:
96    case WindowsCE2:
97    case WindowsCE3:
98        return "Windows CE";
99    case WindowsCE4:
100        return "Windows CE .NET";
101    case Windows3_1:
102        return "Windows 3.1";
103    case Windows95:
104        return "Windows 95";
105    case Windows98:
106        return "Windows 98";
107    case WindowsME:
108        return "Windows 98; Win 9x 4.90";
109    case WindowsNT4:
110        return "WinNT4.0";
111    }
112
113    const char* familyName = (version >= WindowsNT3) ? "Windows NT " : "Windows CE ";
114    return makeString(familyName, String::number(major), '.', String::number(minor));
115}
116
117#if !OS(WINCE)
118static bool isWOW64()
119{
120    static bool initialized = false;
121    static bool wow64 = false;
122
123    if (!initialized) {
124        initialized = true;
125        HMODULE kernel32Module = GetModuleHandleA("kernel32.dll");
126        if (!kernel32Module)
127            return wow64;
128        typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL);
129        IsWow64ProcessFunc isWOW64Process = reinterpret_cast<IsWow64ProcessFunc>(GetProcAddress(kernel32Module, "IsWow64Process"));
130        if (isWOW64Process) {
131            BOOL result = FALSE;
132            wow64 = isWOW64Process(GetCurrentProcess(), &result) && result;
133        }
134    }
135
136    return wow64;
137}
138
139static WORD processorArchitecture()
140{
141    static bool initialized = false;
142    static WORD architecture = PROCESSOR_ARCHITECTURE_INTEL;
143
144    if (!initialized) {
145        initialized = true;
146        HMODULE kernel32Module = GetModuleHandleA("kernel32.dll");
147        if (!kernel32Module)
148            return architecture;
149        typedef VOID (WINAPI* GetNativeSystemInfoFunc)(LPSYSTEM_INFO);
150        GetNativeSystemInfoFunc getNativeSystemInfo = reinterpret_cast<GetNativeSystemInfoFunc>(GetProcAddress(kernel32Module, "GetNativeSystemInfo"));
151        if (getNativeSystemInfo) {
152            SYSTEM_INFO systemInfo;
153            ZeroMemory(&systemInfo, sizeof(systemInfo));
154            getNativeSystemInfo(&systemInfo);
155            architecture = systemInfo.wProcessorArchitecture;
156        }
157    }
158
159    return architecture;
160}
161#endif
162
163static String architectureTokenForUAString()
164{
165#if !OS(WINCE)
166    if (isWOW64())
167        return "; WOW64";
168    if (processorArchitecture() == PROCESSOR_ARCHITECTURE_AMD64)
169        return "; Win64; x64";
170    if (processorArchitecture() == PROCESSOR_ARCHITECTURE_IA64)
171        return "; Win64; IA64";
172#endif
173    return String();
174}
175
176String windowsVersionForUAString()
177{
178    return makeString(osVersionForUAString(), architectureTokenForUAString());
179}
180
181} // namespace WebCore
182