summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/system_win32.c2
-rw-r--r--lib/version_win32.c51
-rw-r--r--src/tool_doswin.c2
3 files changed, 50 insertions, 5 deletions
diff --git a/lib/system_win32.c b/lib/system_win32.c
index 2939fd0d7..d4e194831 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -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;
diff --git a/lib/version_win32.c b/lib/version_win32.c
index b8157e989..9df921fd6 100644
--- a/lib/version_win32.c
+++ b/lib/version_win32.c
@@ -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;
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index 98e13bc09..1ad9cddc3 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -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;