1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_WindowsVersion_h
8 #define mozilla_WindowsVersion_h
9 
10 #include "mozilla/Atomics.h"
11 #include "mozilla/Attributes.h"
12 #include <stdint.h>
13 #include <windows.h>
14 
15 namespace mozilla {
16 
IsWindowsVersionOrLater(uint32_t aVersion)17 inline bool IsWindowsVersionOrLater(uint32_t aVersion) {
18   static Atomic<uint32_t> minVersion(0);
19   static Atomic<uint32_t> maxVersion(UINT32_MAX);
20 
21   if (minVersion >= aVersion) {
22     return true;
23   }
24 
25   if (aVersion >= maxVersion) {
26     return false;
27   }
28 
29   OSVERSIONINFOEX info;
30   ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
31   info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
32   info.dwMajorVersion = aVersion >> 24;
33   info.dwMinorVersion = (aVersion >> 16) & 0xFF;
34   info.wServicePackMajor = (aVersion >> 8) & 0xFF;
35   info.wServicePackMinor = aVersion & 0xFF;
36 
37   DWORDLONG conditionMask = 0;
38   VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
39   VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
40   VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
41   VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
42 
43   if (VerifyVersionInfo(&info,
44                         VER_MAJORVERSION | VER_MINORVERSION |
45                             VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
46                         conditionMask)) {
47     minVersion = aVersion;
48     return true;
49   }
50 
51   maxVersion = aVersion;
52   return false;
53 }
54 
IsWindowsBuildOrLater(uint32_t aBuild)55 inline bool IsWindowsBuildOrLater(uint32_t aBuild) {
56   static Atomic<uint32_t> minBuild(0);
57   static Atomic<uint32_t> maxBuild(UINT32_MAX);
58 
59   if (minBuild >= aBuild) {
60     return true;
61   }
62 
63   if (aBuild >= maxBuild) {
64     return false;
65   }
66 
67   OSVERSIONINFOEX info;
68   ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
69   info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
70   info.dwBuildNumber = aBuild;
71 
72   DWORDLONG conditionMask = 0;
73   VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
74 
75   if (VerifyVersionInfo(&info, VER_BUILDNUMBER, conditionMask)) {
76     minBuild = aBuild;
77     return true;
78   }
79 
80   maxBuild = aBuild;
81   return false;
82 }
83 
IsWindows10BuildOrLater(uint32_t aBuild)84 inline bool IsWindows10BuildOrLater(uint32_t aBuild) {
85   static Atomic<uint32_t> minBuild(0);
86   static Atomic<uint32_t> maxBuild(UINT32_MAX);
87 
88   if (minBuild >= aBuild) {
89     return true;
90   }
91 
92   if (aBuild >= maxBuild) {
93     return false;
94   }
95 
96   OSVERSIONINFOEX info;
97   ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
98   info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
99   info.dwMajorVersion = 10;
100   info.dwBuildNumber = aBuild;
101 
102   DWORDLONG conditionMask = 0;
103   VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
104   VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
105   VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
106   VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
107   VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
108 
109   if (VerifyVersionInfo(&info,
110                         VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER |
111                             VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
112                         conditionMask)) {
113     minBuild = aBuild;
114     return true;
115   }
116 
117   maxBuild = aBuild;
118   return false;
119 }
120 
IsWin7SP1OrLater()121 MOZ_ALWAYS_INLINE bool IsWin7SP1OrLater() {
122   return IsWindowsVersionOrLater(0x06010100ul);
123 }
124 
IsWin8OrLater()125 MOZ_ALWAYS_INLINE bool IsWin8OrLater() {
126   return IsWindowsVersionOrLater(0x06020000ul);
127 }
128 
IsWin8Point1OrLater()129 MOZ_ALWAYS_INLINE bool IsWin8Point1OrLater() {
130   return IsWindowsVersionOrLater(0x06030000ul);
131 }
132 
IsWin10OrLater()133 MOZ_ALWAYS_INLINE bool IsWin10OrLater() {
134   return IsWindowsVersionOrLater(0x0a000000ul);
135 }
136 
IsWin10CreatorsUpdateOrLater()137 MOZ_ALWAYS_INLINE bool IsWin10CreatorsUpdateOrLater() {
138   return IsWindows10BuildOrLater(15063);
139 }
140 
IsNotWin7PreRTM()141 MOZ_ALWAYS_INLINE bool IsNotWin7PreRTM() {
142   return IsWin7SP1OrLater() || IsWindowsBuildOrLater(7600);
143 }
144 
IsWin7AndPre2000Compatible()145 inline bool IsWin7AndPre2000Compatible() {
146   /*
147    * See Bug 1279171.
148    * We'd like to avoid using WMF on specific OS version when compatibility
149    * mode is in effect. The purpose of this function is to check if FF runs on
150    * Win7 OS with application compatibility mode being set to 95/98/ME.
151    * Those compatibility mode options (95/98/ME) can only display and
152    * be selected for 32-bit application.
153    * If the compatibility mode is in effect, the GetVersionEx function will
154    * report the OS as it identifies itself, which may not be the OS that is
155    * installed.
156    * Note : 1) We only target for Win7 build number greater than 7600.
157    *        2) GetVersionEx may be altered or unavailable for release after
158    *           Win8.1. Set pragma to avoid build warning as error.
159    */
160   bool isWin7 = IsNotWin7PreRTM() && !IsWin8OrLater();
161   if (!isWin7) {
162     return false;
163   }
164 
165   OSVERSIONINFOEX info;
166   ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
167 
168   info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
169 #pragma warning(push)
170 #pragma warning(disable : 4996)
171   bool success = GetVersionEx((LPOSVERSIONINFO)&info);
172 #pragma warning(pop)
173   if (!success) {
174     return false;
175   }
176   return info.dwMajorVersion < 5;
177 }
178 
179 }  // namespace mozilla
180 
181 #endif /* mozilla_WindowsVersion_h */
182