1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#if defined(WIN32)
26
27#include <curl/curl.h>
28#include "version_win32.h"
29
30/* The last #include files should be: */
31#include "curl_memory.h"
32#include "memdebug.h"
33
34/*
35 * curlx_verify_windows_version()
36 *
37 * This is used to verify if we are running on a specific windows version.
38 *
39 * Parameters:
40 *
41 * majorVersion [in] - The major version number.
42 * minorVersion [in] - The minor version number.
43 * platform [in] - The optional platform identifier.
44 * condition [in] - The test condition used to specifier whether we are
45 * checking a version less then, equal to or greater than
46 * what is specified in the major and minor version
47 * numbers.
48 *
49 * Returns TRUE if matched; otherwise FALSE.
50 */
51bool curlx_verify_windows_version(const unsigned int majorVersion,
52 const unsigned int minorVersion,
53 const PlatformIdentifier platform,
54 const VersionCondition condition)
55{
56 bool matched = FALSE;
57
58#if defined(CURL_WINDOWS_APP)
59 /* We have no way to determine the Windows version from Windows apps,
60 so let's assume we're running on the target Windows version. */
61 const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
62 const WORD targetVersion = (WORD)_WIN32_WINNT;
63
64 switch(condition) {
65 case VERSION_LESS_THAN:
66 matched = targetVersion < fullVersion;
67 break;
68
69 case VERSION_LESS_THAN_EQUAL:
70 matched = targetVersion <= fullVersion;
71 break;
72
73 case VERSION_EQUAL:
74 matched = targetVersion == fullVersion;
75 break;
76
77 case VERSION_GREATER_THAN_EQUAL:
78 matched = targetVersion >= fullVersion;
79 break;
80
81 case VERSION_GREATER_THAN:
82 matched = targetVersion > fullVersion;
83 break;
84 }
85
86 if(matched && (platform == PLATFORM_WINDOWS)) {
87 /* we're always running on PLATFORM_WINNT */
88 matched = FALSE;
89 }
90#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
91 (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
92 OSVERSIONINFO osver;
93
94 memset(&osver, 0, sizeof(osver));
95 osver.dwOSVersionInfoSize = sizeof(osver);
96
97 /* Find out Windows version */
98 if(GetVersionEx(&osver)) {
99 /* Verify the Operating System version number */
100 switch(condition) {
101 case VERSION_LESS_THAN:
102 if(osver.dwMajorVersion < majorVersion ||
103 (osver.dwMajorVersion == majorVersion &&
104 osver.dwMinorVersion < minorVersion))
105 matched = TRUE;
106 break;
107
108 case VERSION_LESS_THAN_EQUAL:
109 if(osver.dwMajorVersion < majorVersion ||
110 (osver.dwMajorVersion == majorVersion &&
111 osver.dwMinorVersion <= minorVersion))
112 matched = TRUE;
113 break;
114
115 case VERSION_EQUAL:
116 if(osver.dwMajorVersion == majorVersion &&
117 osver.dwMinorVersion == minorVersion)
118 matched = TRUE;
119 break;
120
121 case VERSION_GREATER_THAN_EQUAL:
122 if(osver.dwMajorVersion > majorVersion ||
123 (osver.dwMajorVersion == majorVersion &&
124 osver.dwMinorVersion >= minorVersion))
125 matched = TRUE;
126 break;
127
128 case VERSION_GREATER_THAN:
129 if(osver.dwMajorVersion > majorVersion ||
130 (osver.dwMajorVersion == majorVersion &&
131 osver.dwMinorVersion > minorVersion))
132 matched = TRUE;
133 break;
134 }
135
136 /* Verify the platform identifier (if necessary) */
137 if(matched) {
138 switch(platform) {
139 case PLATFORM_WINDOWS:
140 if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
141 matched = FALSE;
142 break;
143
144 case PLATFORM_WINNT:
145 if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
146 matched = FALSE;
147
148 default: /* like platform == PLATFORM_DONT_CARE */
149 break;
150 }
151 }
152 }
153#else
154 ULONGLONG cm = 0;
155 OSVERSIONINFOEX osver;
156 BYTE majorCondition;
157 BYTE minorCondition;
158 BYTE spMajorCondition;
159 BYTE spMinorCondition;
160
161 switch(condition) {
162 case VERSION_LESS_THAN:
163 majorCondition = VER_LESS;
164 minorCondition = VER_LESS;
165 spMajorCondition = VER_LESS_EQUAL;
166 spMinorCondition = VER_LESS_EQUAL;
167 break;
168
169 case VERSION_LESS_THAN_EQUAL:
170 majorCondition = VER_LESS_EQUAL;
171 minorCondition = VER_LESS_EQUAL;
172 spMajorCondition = VER_LESS_EQUAL;
173 spMinorCondition = VER_LESS_EQUAL;
174 break;
175
176 case VERSION_EQUAL:
177 majorCondition = VER_EQUAL;
178 minorCondition = VER_EQUAL;
179 spMajorCondition = VER_GREATER_EQUAL;
180 spMinorCondition = VER_GREATER_EQUAL;
181 break;
182
183 case VERSION_GREATER_THAN_EQUAL:
184 majorCondition = VER_GREATER_EQUAL;
185 minorCondition = VER_GREATER_EQUAL;
186 spMajorCondition = VER_GREATER_EQUAL;
187 spMinorCondition = VER_GREATER_EQUAL;
188 break;
189
190 case VERSION_GREATER_THAN:
191 majorCondition = VER_GREATER;
192 minorCondition = VER_GREATER;
193 spMajorCondition = VER_GREATER_EQUAL;
194 spMinorCondition = VER_GREATER_EQUAL;
195 break;
196
197 default:
198 return FALSE;
199 }
200
201 memset(&osver, 0, sizeof(osver));
202 osver.dwOSVersionInfoSize = sizeof(osver);
203 osver.dwMajorVersion = majorVersion;
204 osver.dwMinorVersion = minorVersion;
205 if(platform == PLATFORM_WINDOWS)
206 osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
207 else if(platform == PLATFORM_WINNT)
208 osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
209
210 cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
211 cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
212 cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
213 cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
214 if(platform != PLATFORM_DONT_CARE)
215 cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
216
217 if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
218 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
219 cm))
220 matched = TRUE;
221#endif
222
223 return matched;
224}
225
226#endif /* WIN32 */
227