version_win32: use actual version instead of manifested version

- Use RtlVerifyVersionInfo instead of VerifyVersionInfo, when possible.

Later versions of Windows have normal version functions that compare and
return versions based on the way the application is manifested, instead
of the actual version of Windows the application is running on. We
prefer the actual version of Windows so we'll now call the Rtl variant
of version functions (RtlVerifyVersionInfo) which does a proper
comparison of the actual version.

Reported-by: Wyatt O'Day

Ref: https://github.com/curl/curl/pull/7727

Fixes https://github.com/curl/curl/issues/7742
Closes https://github.com/curl/curl/pull/7810
This commit is contained in:
Jay Satiro 2021-10-04 15:52:01 -04:00
parent a031614a84
commit 5044909ca2
3 changed files with 50 additions and 5 deletions

View File

@ -102,6 +102,8 @@ CURLcode Curl_win32_init(long flags)
Curl_if_nametoindex = pIfNameToIndex;
}
/* curlx_verify_windows_version must be called during init at least once
because it has its own initialization routine. */
if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
Curl_isVistaOrGreater = TRUE;

View File

@ -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()
*
@ -152,12 +169,23 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
}
#else
ULONGLONG cm = 0;
OSVERSIONINFOEX osver;
struct OUR_OSVERSIONINFOEXW osver;
BYTE majorCondition;
BYTE minorCondition;
BYTE spMajorCondition;
BYTE spMinorCondition;
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;
@ -214,10 +242,23 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
if(platform != PLATFORM_DONT_CARE)
cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
cm))
matched = TRUE;
/* 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,
(VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
cm);
}
else {
matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver,
(VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
cm);
}
#endif
return matched;

View File

@ -766,6 +766,8 @@ bool tool_isVistaOrGreater;
CURLcode win32_init(void)
{
/* curlx_verify_windows_version must be called during init at least once
because it has its own initialization routine. */
if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL))
tool_isVistaOrGreater = true;