]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
version_win32: use actual version instead of manifested version
authorJay Satiro <raysatiro@yahoo.com>
Mon, 4 Oct 2021 19:52:01 +0000 (15:52 -0400)
committerJay Satiro <raysatiro@yahoo.com>
Thu, 7 Oct 2021 07:18:22 +0000 (03:18 -0400)
- 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

lib/system_win32.c
lib/version_win32.c
src/tool_doswin.c

index 2939fd0d74b9b33fcb2990b7ecfa3a26da6223b1..d4e194831fc0f253c05e435aa71b75a627995906 100644 (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;
index b8157e98936671be27f2f4846e328ee2c59598ba..9df921fd617f170c48d2a0a61c815a0926a64c10 100644 (file)
 
 #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;
index 98e13bc099198425ba7cd235acc775f29bf5377f..1ad9cddc3f8f0d734e98ee7a0e38584a2b33ff0f 100644 (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;