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  */
curlx_verify_windows_version(const unsigned int majorVersion,const unsigned int minorVersion,const PlatformIdentifier platform,const VersionCondition condition)51 bool 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