diff options
-rw-r--r-- | lib/system_win32.c | 2 | ||||
-rw-r--r-- | lib/version_win32.c | 51 | ||||
-rw-r--r-- | src/tool_doswin.c | 2 |
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; |