summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/version_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/version_win32.c')
-rw-r--r--Utilities/cmcurl/lib/version_win32.c113
1 files changed, 101 insertions, 12 deletions
diff --git a/Utilities/cmcurl/lib/version_win32.c b/Utilities/cmcurl/lib/version_win32.c
index b8157e9893..79a2aa6ab4 100644
--- a/Utilities/cmcurl/lib/version_win32.c
+++ b/Utilities/cmcurl/lib/version_win32.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2016 - 2021, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,11 +26,28 @@
#include <curl/curl.h>
#include "version_win32.h"
+#include "warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
+/* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW)
+ and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */
+struct OUR_OSVERSIONINFOEXW {
+ ULONG dwOSVersionInfoSize;
+ ULONG dwMajorVersion;
+ ULONG dwMinorVersion;
+ ULONG dwBuildNumber;
+ ULONG dwPlatformId;
+ WCHAR szCSDVersion[128];
+ USHORT wServicePackMajor;
+ USHORT wServicePackMinor;
+ USHORT wSuiteMask;
+ UCHAR wProductType;
+ UCHAR wReserved;
+};
+
/*
* curlx_verify_windows_version()
*
@@ -40,6 +57,8 @@
*
* majorVersion [in] - The major version number.
* minorVersion [in] - The minor version number.
+ * buildVersion [in] - The build version number. If 0, this parameter is
+ * ignored.
* platform [in] - The optional platform identifier.
* condition [in] - The test condition used to specifier whether we are
* checking a version less then, equal to or greater than
@@ -50,6 +69,7 @@
*/
bool curlx_verify_windows_version(const unsigned int majorVersion,
const unsigned int minorVersion,
+ const unsigned int buildVersion,
const PlatformIdentifier platform,
const VersionCondition condition)
{
@@ -101,34 +121,52 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
case VERSION_LESS_THAN:
if(osver.dwMajorVersion < majorVersion ||
(osver.dwMajorVersion == majorVersion &&
- osver.dwMinorVersion < minorVersion))
+ osver.dwMinorVersion < minorVersion) ||
+ (buildVersion != 0 &&
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion == minorVersion &&
+ osver.dwBuildNumber < buildVersion)))
matched = TRUE;
break;
case VERSION_LESS_THAN_EQUAL:
if(osver.dwMajorVersion < majorVersion ||
(osver.dwMajorVersion == majorVersion &&
- osver.dwMinorVersion <= minorVersion))
+ osver.dwMinorVersion < minorVersion) ||
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion == minorVersion &&
+ (buildVersion == 0 ||
+ osver.dwBuildNumber <= buildVersion)))
matched = TRUE;
break;
case VERSION_EQUAL:
if(osver.dwMajorVersion == majorVersion &&
- osver.dwMinorVersion == minorVersion)
+ osver.dwMinorVersion == minorVersion &&
+ (buildVersion == 0 ||
+ osver.dwBuildNumber == buildVersion))
matched = TRUE;
break;
case VERSION_GREATER_THAN_EQUAL:
if(osver.dwMajorVersion > majorVersion ||
(osver.dwMajorVersion == majorVersion &&
- osver.dwMinorVersion >= minorVersion))
+ osver.dwMinorVersion > minorVersion) ||
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion == minorVersion &&
+ (buildVersion == 0 ||
+ osver.dwBuildNumber >= buildVersion)))
matched = TRUE;
break;
case VERSION_GREATER_THAN:
if(osver.dwMajorVersion > majorVersion ||
(osver.dwMajorVersion == majorVersion &&
- osver.dwMinorVersion > minorVersion))
+ osver.dwMinorVersion > minorVersion) ||
+ (buildVersion != 0 &&
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion == minorVersion &&
+ osver.dwBuildNumber > buildVersion)))
matched = TRUE;
break;
}
@@ -144,6 +182,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
case PLATFORM_WINNT:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
matched = FALSE;
+ break;
default: /* like platform == PLATFORM_DONT_CARE */
break;
@@ -152,16 +191,31 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
}
#else
ULONGLONG cm = 0;
- OSVERSIONINFOEX osver;
+ struct OUR_OSVERSIONINFOEXW osver;
BYTE majorCondition;
BYTE minorCondition;
+ BYTE buildCondition;
BYTE spMajorCondition;
BYTE spMinorCondition;
+ DWORD dwTypeMask = VER_MAJORVERSION | VER_MINORVERSION |
+ VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
+
+ typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN)
+ (struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG);
+ static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo;
+ static bool onetime = true; /* safe because first call is during init */
+
+ if(onetime) {
+ pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN,
+ (GetProcAddress(GetModuleHandleA("ntdll"), "RtlVerifyVersionInfo")));
+ onetime = false;
+ }
switch(condition) {
case VERSION_LESS_THAN:
majorCondition = VER_LESS;
minorCondition = VER_LESS;
+ buildCondition = VER_LESS;
spMajorCondition = VER_LESS_EQUAL;
spMinorCondition = VER_LESS_EQUAL;
break;
@@ -169,6 +223,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
case VERSION_LESS_THAN_EQUAL:
majorCondition = VER_LESS_EQUAL;
minorCondition = VER_LESS_EQUAL;
+ buildCondition = VER_LESS_EQUAL;
spMajorCondition = VER_LESS_EQUAL;
spMinorCondition = VER_LESS_EQUAL;
break;
@@ -176,6 +231,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
case VERSION_EQUAL:
majorCondition = VER_EQUAL;
minorCondition = VER_EQUAL;
+ buildCondition = VER_EQUAL;
spMajorCondition = VER_GREATER_EQUAL;
spMinorCondition = VER_GREATER_EQUAL;
break;
@@ -183,6 +239,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
case VERSION_GREATER_THAN_EQUAL:
majorCondition = VER_GREATER_EQUAL;
minorCondition = VER_GREATER_EQUAL;
+ buildCondition = VER_GREATER_EQUAL;
spMajorCondition = VER_GREATER_EQUAL;
spMinorCondition = VER_GREATER_EQUAL;
break;
@@ -190,6 +247,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
case VERSION_GREATER_THAN:
majorCondition = VER_GREATER;
minorCondition = VER_GREATER;
+ buildCondition = VER_GREATER;
spMajorCondition = VER_GREATER_EQUAL;
spMinorCondition = VER_GREATER_EQUAL;
break;
@@ -202,6 +260,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
osver.dwOSVersionInfoSize = sizeof(osver);
osver.dwMajorVersion = majorVersion;
osver.dwMinorVersion = minorVersion;
+ osver.dwBuildNumber = buildVersion;
if(platform == PLATFORM_WINDOWS)
osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
else if(platform == PLATFORM_WINNT)
@@ -211,13 +270,43 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
- if(platform != PLATFORM_DONT_CARE)
+
+ if(platform != PLATFORM_DONT_CARE) {
cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
+ dwTypeMask |= VER_PLATFORMID;
+ }
+
+ /* Later versions of Windows have version functions that may not return the
+ real version of Windows unless the application is so manifested. We prefer
+ the real version always, so we use the Rtl variant of the function when
+ possible. Note though the function signatures have underlying fundamental
+ types that are the same, the return values are different. */
+ if(pRtlVerifyVersionInfo)
+ matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
+ else
+ matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, dwTypeMask, cm);
+
+ /* Compare the build number separately. VerifyVersionInfo normally compares
+ major.minor in hierarchical order (eg 1.9 is less than 2.0) but does not
+ do the same for build (eg 1.9 build 222 is not less than 2.0 build 111).
+ Build comparison is only needed when build numbers are equal (eg 1.9 is
+ always less than 2.0 so build comparison is not needed). */
+ if(matched && buildVersion &&
+ (condition == VERSION_EQUAL ||
+ ((condition == VERSION_GREATER_THAN_EQUAL ||
+ condition == VERSION_LESS_THAN_EQUAL) &&
+ curlx_verify_windows_version(majorVersion, minorVersion, 0,
+ platform, VERSION_EQUAL)))) {
+
+ cm = VerSetConditionMask(0, VER_BUILDNUMBER, buildCondition);
+ dwTypeMask = VER_BUILDNUMBER;
+ if(pRtlVerifyVersionInfo)
+ matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
+ else
+ matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver,
+ dwTypeMask, cm);
+ }
- if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
- VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
- cm))
- matched = TRUE;
#endif
return matched;