113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Steve Holme, <steve_holme@hotmail.com>. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#include "curl_setup.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#if defined(_WIN32) 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include <curl/curl.h> 3013498266Sopenharmony_ci#include "version_win32.h" 3113498266Sopenharmony_ci#include "warnless.h" 3213498266Sopenharmony_ci 3313498266Sopenharmony_ci/* The last #include files should be: */ 3413498266Sopenharmony_ci#include "curl_memory.h" 3513498266Sopenharmony_ci#include "memdebug.h" 3613498266Sopenharmony_ci 3713498266Sopenharmony_ci/* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW) 3813498266Sopenharmony_ci and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */ 3913498266Sopenharmony_cistruct OUR_OSVERSIONINFOEXW { 4013498266Sopenharmony_ci ULONG dwOSVersionInfoSize; 4113498266Sopenharmony_ci ULONG dwMajorVersion; 4213498266Sopenharmony_ci ULONG dwMinorVersion; 4313498266Sopenharmony_ci ULONG dwBuildNumber; 4413498266Sopenharmony_ci ULONG dwPlatformId; 4513498266Sopenharmony_ci WCHAR szCSDVersion[128]; 4613498266Sopenharmony_ci USHORT wServicePackMajor; 4713498266Sopenharmony_ci USHORT wServicePackMinor; 4813498266Sopenharmony_ci USHORT wSuiteMask; 4913498266Sopenharmony_ci UCHAR wProductType; 5013498266Sopenharmony_ci UCHAR wReserved; 5113498266Sopenharmony_ci}; 5213498266Sopenharmony_ci 5313498266Sopenharmony_ci/* 5413498266Sopenharmony_ci * curlx_verify_windows_version() 5513498266Sopenharmony_ci * 5613498266Sopenharmony_ci * This is used to verify if we are running on a specific windows version. 5713498266Sopenharmony_ci * 5813498266Sopenharmony_ci * Parameters: 5913498266Sopenharmony_ci * 6013498266Sopenharmony_ci * majorVersion [in] - The major version number. 6113498266Sopenharmony_ci * minorVersion [in] - The minor version number. 6213498266Sopenharmony_ci * buildVersion [in] - The build version number. If 0, this parameter is 6313498266Sopenharmony_ci * ignored. 6413498266Sopenharmony_ci * platform [in] - The optional platform identifier. 6513498266Sopenharmony_ci * condition [in] - The test condition used to specifier whether we are 6613498266Sopenharmony_ci * checking a version less then, equal to or greater than 6713498266Sopenharmony_ci * what is specified in the major and minor version 6813498266Sopenharmony_ci * numbers. 6913498266Sopenharmony_ci * 7013498266Sopenharmony_ci * Returns TRUE if matched; otherwise FALSE. 7113498266Sopenharmony_ci */ 7213498266Sopenharmony_cibool curlx_verify_windows_version(const unsigned int majorVersion, 7313498266Sopenharmony_ci const unsigned int minorVersion, 7413498266Sopenharmony_ci const unsigned int buildVersion, 7513498266Sopenharmony_ci const PlatformIdentifier platform, 7613498266Sopenharmony_ci const VersionCondition condition) 7713498266Sopenharmony_ci{ 7813498266Sopenharmony_ci bool matched = FALSE; 7913498266Sopenharmony_ci 8013498266Sopenharmony_ci#if defined(CURL_WINDOWS_APP) 8113498266Sopenharmony_ci (void)buildVersion; 8213498266Sopenharmony_ci 8313498266Sopenharmony_ci /* We have no way to determine the Windows version from Windows apps, 8413498266Sopenharmony_ci so let's assume we're running on the target Windows version. */ 8513498266Sopenharmony_ci const WORD fullVersion = MAKEWORD(minorVersion, majorVersion); 8613498266Sopenharmony_ci const WORD targetVersion = (WORD)_WIN32_WINNT; 8713498266Sopenharmony_ci 8813498266Sopenharmony_ci switch(condition) { 8913498266Sopenharmony_ci case VERSION_LESS_THAN: 9013498266Sopenharmony_ci matched = targetVersion < fullVersion; 9113498266Sopenharmony_ci break; 9213498266Sopenharmony_ci 9313498266Sopenharmony_ci case VERSION_LESS_THAN_EQUAL: 9413498266Sopenharmony_ci matched = targetVersion <= fullVersion; 9513498266Sopenharmony_ci break; 9613498266Sopenharmony_ci 9713498266Sopenharmony_ci case VERSION_EQUAL: 9813498266Sopenharmony_ci matched = targetVersion == fullVersion; 9913498266Sopenharmony_ci break; 10013498266Sopenharmony_ci 10113498266Sopenharmony_ci case VERSION_GREATER_THAN_EQUAL: 10213498266Sopenharmony_ci matched = targetVersion >= fullVersion; 10313498266Sopenharmony_ci break; 10413498266Sopenharmony_ci 10513498266Sopenharmony_ci case VERSION_GREATER_THAN: 10613498266Sopenharmony_ci matched = targetVersion > fullVersion; 10713498266Sopenharmony_ci break; 10813498266Sopenharmony_ci } 10913498266Sopenharmony_ci 11013498266Sopenharmony_ci if(matched && (platform == PLATFORM_WINDOWS)) { 11113498266Sopenharmony_ci /* we're always running on PLATFORM_WINNT */ 11213498266Sopenharmony_ci matched = FALSE; 11313498266Sopenharmony_ci } 11413498266Sopenharmony_ci#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ 11513498266Sopenharmony_ci (_WIN32_WINNT < _WIN32_WINNT_WIN2K) 11613498266Sopenharmony_ci OSVERSIONINFO osver; 11713498266Sopenharmony_ci 11813498266Sopenharmony_ci memset(&osver, 0, sizeof(osver)); 11913498266Sopenharmony_ci osver.dwOSVersionInfoSize = sizeof(osver); 12013498266Sopenharmony_ci 12113498266Sopenharmony_ci /* Find out Windows version */ 12213498266Sopenharmony_ci if(GetVersionEx(&osver)) { 12313498266Sopenharmony_ci /* Verify the Operating System version number */ 12413498266Sopenharmony_ci switch(condition) { 12513498266Sopenharmony_ci case VERSION_LESS_THAN: 12613498266Sopenharmony_ci if(osver.dwMajorVersion < majorVersion || 12713498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 12813498266Sopenharmony_ci osver.dwMinorVersion < minorVersion) || 12913498266Sopenharmony_ci (buildVersion != 0 && 13013498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 13113498266Sopenharmony_ci osver.dwMinorVersion == minorVersion && 13213498266Sopenharmony_ci osver.dwBuildNumber < buildVersion))) 13313498266Sopenharmony_ci matched = TRUE; 13413498266Sopenharmony_ci break; 13513498266Sopenharmony_ci 13613498266Sopenharmony_ci case VERSION_LESS_THAN_EQUAL: 13713498266Sopenharmony_ci if(osver.dwMajorVersion < majorVersion || 13813498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 13913498266Sopenharmony_ci osver.dwMinorVersion < minorVersion) || 14013498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 14113498266Sopenharmony_ci osver.dwMinorVersion == minorVersion && 14213498266Sopenharmony_ci (buildVersion == 0 || 14313498266Sopenharmony_ci osver.dwBuildNumber <= buildVersion))) 14413498266Sopenharmony_ci matched = TRUE; 14513498266Sopenharmony_ci break; 14613498266Sopenharmony_ci 14713498266Sopenharmony_ci case VERSION_EQUAL: 14813498266Sopenharmony_ci if(osver.dwMajorVersion == majorVersion && 14913498266Sopenharmony_ci osver.dwMinorVersion == minorVersion && 15013498266Sopenharmony_ci (buildVersion == 0 || 15113498266Sopenharmony_ci osver.dwBuildNumber == buildVersion)) 15213498266Sopenharmony_ci matched = TRUE; 15313498266Sopenharmony_ci break; 15413498266Sopenharmony_ci 15513498266Sopenharmony_ci case VERSION_GREATER_THAN_EQUAL: 15613498266Sopenharmony_ci if(osver.dwMajorVersion > majorVersion || 15713498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 15813498266Sopenharmony_ci osver.dwMinorVersion > minorVersion) || 15913498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 16013498266Sopenharmony_ci osver.dwMinorVersion == minorVersion && 16113498266Sopenharmony_ci (buildVersion == 0 || 16213498266Sopenharmony_ci osver.dwBuildNumber >= buildVersion))) 16313498266Sopenharmony_ci matched = TRUE; 16413498266Sopenharmony_ci break; 16513498266Sopenharmony_ci 16613498266Sopenharmony_ci case VERSION_GREATER_THAN: 16713498266Sopenharmony_ci if(osver.dwMajorVersion > majorVersion || 16813498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 16913498266Sopenharmony_ci osver.dwMinorVersion > minorVersion) || 17013498266Sopenharmony_ci (buildVersion != 0 && 17113498266Sopenharmony_ci (osver.dwMajorVersion == majorVersion && 17213498266Sopenharmony_ci osver.dwMinorVersion == minorVersion && 17313498266Sopenharmony_ci osver.dwBuildNumber > buildVersion))) 17413498266Sopenharmony_ci matched = TRUE; 17513498266Sopenharmony_ci break; 17613498266Sopenharmony_ci } 17713498266Sopenharmony_ci 17813498266Sopenharmony_ci /* Verify the platform identifier (if necessary) */ 17913498266Sopenharmony_ci if(matched) { 18013498266Sopenharmony_ci switch(platform) { 18113498266Sopenharmony_ci case PLATFORM_WINDOWS: 18213498266Sopenharmony_ci if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) 18313498266Sopenharmony_ci matched = FALSE; 18413498266Sopenharmony_ci break; 18513498266Sopenharmony_ci 18613498266Sopenharmony_ci case PLATFORM_WINNT: 18713498266Sopenharmony_ci if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT) 18813498266Sopenharmony_ci matched = FALSE; 18913498266Sopenharmony_ci break; 19013498266Sopenharmony_ci 19113498266Sopenharmony_ci default: /* like platform == PLATFORM_DONT_CARE */ 19213498266Sopenharmony_ci break; 19313498266Sopenharmony_ci } 19413498266Sopenharmony_ci } 19513498266Sopenharmony_ci } 19613498266Sopenharmony_ci#else 19713498266Sopenharmony_ci ULONGLONG cm = 0; 19813498266Sopenharmony_ci struct OUR_OSVERSIONINFOEXW osver; 19913498266Sopenharmony_ci BYTE majorCondition; 20013498266Sopenharmony_ci BYTE minorCondition; 20113498266Sopenharmony_ci BYTE buildCondition; 20213498266Sopenharmony_ci BYTE spMajorCondition; 20313498266Sopenharmony_ci BYTE spMinorCondition; 20413498266Sopenharmony_ci DWORD dwTypeMask = VER_MAJORVERSION | VER_MINORVERSION | 20513498266Sopenharmony_ci VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR; 20613498266Sopenharmony_ci 20713498266Sopenharmony_ci typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN) 20813498266Sopenharmony_ci (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG); 20913498266Sopenharmony_ci static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo; 21013498266Sopenharmony_ci static bool onetime = true; /* safe because first call is during init */ 21113498266Sopenharmony_ci 21213498266Sopenharmony_ci if(onetime) { 21313498266Sopenharmony_ci pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN, 21413498266Sopenharmony_ci (GetProcAddress(GetModuleHandleA("ntdll"), "RtlVerifyVersionInfo"))); 21513498266Sopenharmony_ci onetime = false; 21613498266Sopenharmony_ci } 21713498266Sopenharmony_ci 21813498266Sopenharmony_ci switch(condition) { 21913498266Sopenharmony_ci case VERSION_LESS_THAN: 22013498266Sopenharmony_ci majorCondition = VER_LESS; 22113498266Sopenharmony_ci minorCondition = VER_LESS; 22213498266Sopenharmony_ci buildCondition = VER_LESS; 22313498266Sopenharmony_ci spMajorCondition = VER_LESS_EQUAL; 22413498266Sopenharmony_ci spMinorCondition = VER_LESS_EQUAL; 22513498266Sopenharmony_ci break; 22613498266Sopenharmony_ci 22713498266Sopenharmony_ci case VERSION_LESS_THAN_EQUAL: 22813498266Sopenharmony_ci majorCondition = VER_LESS_EQUAL; 22913498266Sopenharmony_ci minorCondition = VER_LESS_EQUAL; 23013498266Sopenharmony_ci buildCondition = VER_LESS_EQUAL; 23113498266Sopenharmony_ci spMajorCondition = VER_LESS_EQUAL; 23213498266Sopenharmony_ci spMinorCondition = VER_LESS_EQUAL; 23313498266Sopenharmony_ci break; 23413498266Sopenharmony_ci 23513498266Sopenharmony_ci case VERSION_EQUAL: 23613498266Sopenharmony_ci majorCondition = VER_EQUAL; 23713498266Sopenharmony_ci minorCondition = VER_EQUAL; 23813498266Sopenharmony_ci buildCondition = VER_EQUAL; 23913498266Sopenharmony_ci spMajorCondition = VER_GREATER_EQUAL; 24013498266Sopenharmony_ci spMinorCondition = VER_GREATER_EQUAL; 24113498266Sopenharmony_ci break; 24213498266Sopenharmony_ci 24313498266Sopenharmony_ci case VERSION_GREATER_THAN_EQUAL: 24413498266Sopenharmony_ci majorCondition = VER_GREATER_EQUAL; 24513498266Sopenharmony_ci minorCondition = VER_GREATER_EQUAL; 24613498266Sopenharmony_ci buildCondition = VER_GREATER_EQUAL; 24713498266Sopenharmony_ci spMajorCondition = VER_GREATER_EQUAL; 24813498266Sopenharmony_ci spMinorCondition = VER_GREATER_EQUAL; 24913498266Sopenharmony_ci break; 25013498266Sopenharmony_ci 25113498266Sopenharmony_ci case VERSION_GREATER_THAN: 25213498266Sopenharmony_ci majorCondition = VER_GREATER; 25313498266Sopenharmony_ci minorCondition = VER_GREATER; 25413498266Sopenharmony_ci buildCondition = VER_GREATER; 25513498266Sopenharmony_ci spMajorCondition = VER_GREATER_EQUAL; 25613498266Sopenharmony_ci spMinorCondition = VER_GREATER_EQUAL; 25713498266Sopenharmony_ci break; 25813498266Sopenharmony_ci 25913498266Sopenharmony_ci default: 26013498266Sopenharmony_ci return FALSE; 26113498266Sopenharmony_ci } 26213498266Sopenharmony_ci 26313498266Sopenharmony_ci memset(&osver, 0, sizeof(osver)); 26413498266Sopenharmony_ci osver.dwOSVersionInfoSize = sizeof(osver); 26513498266Sopenharmony_ci osver.dwMajorVersion = majorVersion; 26613498266Sopenharmony_ci osver.dwMinorVersion = minorVersion; 26713498266Sopenharmony_ci osver.dwBuildNumber = buildVersion; 26813498266Sopenharmony_ci if(platform == PLATFORM_WINDOWS) 26913498266Sopenharmony_ci osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; 27013498266Sopenharmony_ci else if(platform == PLATFORM_WINNT) 27113498266Sopenharmony_ci osver.dwPlatformId = VER_PLATFORM_WIN32_NT; 27213498266Sopenharmony_ci 27313498266Sopenharmony_ci cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition); 27413498266Sopenharmony_ci cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition); 27513498266Sopenharmony_ci cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition); 27613498266Sopenharmony_ci cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition); 27713498266Sopenharmony_ci 27813498266Sopenharmony_ci if(platform != PLATFORM_DONT_CARE) { 27913498266Sopenharmony_ci cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); 28013498266Sopenharmony_ci dwTypeMask |= VER_PLATFORMID; 28113498266Sopenharmony_ci } 28213498266Sopenharmony_ci 28313498266Sopenharmony_ci /* Later versions of Windows have version functions that may not return the 28413498266Sopenharmony_ci real version of Windows unless the application is so manifested. We prefer 28513498266Sopenharmony_ci the real version always, so we use the Rtl variant of the function when 28613498266Sopenharmony_ci possible. Note though the function signatures have underlying fundamental 28713498266Sopenharmony_ci types that are the same, the return values are different. */ 28813498266Sopenharmony_ci if(pRtlVerifyVersionInfo) 28913498266Sopenharmony_ci matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm); 29013498266Sopenharmony_ci else 29113498266Sopenharmony_ci matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, dwTypeMask, cm); 29213498266Sopenharmony_ci 29313498266Sopenharmony_ci /* Compare the build number separately. VerifyVersionInfo normally compares 29413498266Sopenharmony_ci major.minor in hierarchical order (eg 1.9 is less than 2.0) but does not 29513498266Sopenharmony_ci do the same for build (eg 1.9 build 222 is not less than 2.0 build 111). 29613498266Sopenharmony_ci Build comparison is only needed when build numbers are equal (eg 1.9 is 29713498266Sopenharmony_ci always less than 2.0 so build comparison is not needed). */ 29813498266Sopenharmony_ci if(matched && buildVersion && 29913498266Sopenharmony_ci (condition == VERSION_EQUAL || 30013498266Sopenharmony_ci ((condition == VERSION_GREATER_THAN_EQUAL || 30113498266Sopenharmony_ci condition == VERSION_LESS_THAN_EQUAL) && 30213498266Sopenharmony_ci curlx_verify_windows_version(majorVersion, minorVersion, 0, 30313498266Sopenharmony_ci platform, VERSION_EQUAL)))) { 30413498266Sopenharmony_ci 30513498266Sopenharmony_ci cm = VerSetConditionMask(0, VER_BUILDNUMBER, buildCondition); 30613498266Sopenharmony_ci dwTypeMask = VER_BUILDNUMBER; 30713498266Sopenharmony_ci if(pRtlVerifyVersionInfo) 30813498266Sopenharmony_ci matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm); 30913498266Sopenharmony_ci else 31013498266Sopenharmony_ci matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, 31113498266Sopenharmony_ci dwTypeMask, cm); 31213498266Sopenharmony_ci } 31313498266Sopenharmony_ci 31413498266Sopenharmony_ci#endif 31513498266Sopenharmony_ci 31613498266Sopenharmony_ci return matched; 31713498266Sopenharmony_ci} 31813498266Sopenharmony_ci 31913498266Sopenharmony_ci#endif /* _WIN32 */ 320