gwin32.c: Avoid deprecated Win32 API usage

The VerifyVersionInfo() Win32 API has been deprecated in Windows 10, and
there is no direct replacement for it, except by using a lower-level
RtlGetVersion() that we aquire from the Windows DDK or from ntdll.dll.

Switch g_win32_check_windows_version() to use RtlGetVersion(), and
compare its results with the input parameters.

https://bugzilla.gnome.org/show_bug.cgi?id=756179
This commit is contained in:
Chun-wei Fan 2015-10-07 20:00:50 +08:00
parent 597438f5a2
commit 2b8b9361f9

View File

@ -49,6 +49,18 @@
# include <io.h> # include <io.h>
#endif /* _MSC_VER || __DMC__ */ #endif /* _MSC_VER || __DMC__ */
#define MODERN_API_FAMILY 2
#if WINAPI_FAMILY == MODERN_API_FAMILY
/* This is for modern UI Builds, where we can't use LoadLibraryW()/GetProcAddress() */
/* ntddk.h is found in the WDK, and MinGW */
#include <ntddk.h>
#ifdef _MSC_VER
#pragma comment (lib, "ntoskrnl.lib")
#endif
#endif
#include "glib.h" #include "glib.h"
#include "gthreadprivate.h" #include "gthreadprivate.h"
@ -516,8 +528,6 @@ g_win32_get_package_installation_subdirectory (const gchar *package,
#endif #endif
#define gwin32condmask(base,var) VerSetConditionMask (base, var, VER_GREATER_EQUAL)
/** /**
* g_win32_check_windows_version: * g_win32_check_windows_version:
* @major: major version of Windows * @major: major version of Windows
@ -550,42 +560,75 @@ g_win32_check_windows_version (const gint major,
const GWin32OSType os_type) const GWin32OSType os_type)
{ {
OSVERSIONINFOEXW osverinfo; OSVERSIONINFOEXW osverinfo;
gboolean test_os_type; gboolean is_ver_checked = FALSE;
const DWORDLONG conds = gwin32condmask (gwin32condmask (gwin32condmask (0, VER_MAJORVERSION), VER_MINORVERSION), VER_SERVICEPACKMAJOR); gboolean is_type_checked = FALSE;
#if WINAPI_FAMILY != MODERN_API_FAMILY
/* For non-modern UI Apps, use the LoadLibraryW()/GetProcAddress() thing */
typedef NTSTATUS fRtlGetVersion (PRTL_OSVERSIONINFOEXW);
fRtlGetVersion *RtlGetVersion;
HMODULE hmodule;
#endif
/* We Only Support Checking for XP or later */
g_return_val_if_fail (major >= 5 && (major <=6 || major == 10), FALSE);
g_return_val_if_fail ((major >= 5 && minor >= 1) || major >= 6, FALSE);
/* Check for Service Pack Version >= 0 */
g_return_val_if_fail (spver >= 0, FALSE);
#if WINAPI_FAMILY != MODERN_API_FAMILY
hmodule = LoadLibraryW (L"ntdll.dll");
g_return_val_if_fail (hmodule != NULL, FALSE);
RtlGetVersion = (fRtlGetVersion *) GetProcAddress (hmodule, "RtlGetVersion");
g_return_val_if_fail (RtlGetVersion != NULL, FALSE);
#endif
memset (&osverinfo, 0, sizeof (OSVERSIONINFOEXW)); memset (&osverinfo, 0, sizeof (OSVERSIONINFOEXW));
osverinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); osverinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
osverinfo.dwPlatformId = VER_PLATFORM_WIN32_NT; RtlGetVersion (&osverinfo);
osverinfo.dwMajorVersion = major;
osverinfo.dwMinorVersion = minor;
osverinfo.wServicePackMajor = spver;
switch (os_type) /* check the OS and Service Pack Versions */
if (osverinfo.dwMajorVersion > major)
is_ver_checked = TRUE;
else if (osverinfo.dwMajorVersion == major)
if (osverinfo.dwMinorVersion > minor)
is_ver_checked = TRUE;
else if (osverinfo.dwMinorVersion == minor)
if (osverinfo.wServicePackMajor >= spver)
is_ver_checked = TRUE;
/* Check OS Type */
if (is_ver_checked)
{ {
case G_WIN32_OS_WORKSTATION: switch (os_type)
osverinfo.wProductType = VER_NT_WORKSTATION; {
test_os_type = TRUE; case G_WIN32_OS_ANY:
break; is_type_checked = TRUE;
case G_WIN32_OS_SERVER: break;
osverinfo.wProductType = VER_NT_SERVER; case G_WIN32_OS_WORKSTATION:
test_os_type = TRUE; if (osverinfo.wProductType == VER_NT_WORKSTATION)
break; is_type_checked = TRUE;
default: break;
test_os_type = FALSE; case G_WIN32_OS_SERVER:
break; if (osverinfo.wProductType == VER_NT_SERVER ||
osverinfo.wProductType == VER_NT_DOMAIN_CONTROLLER)
is_type_checked = TRUE;
break;
default:
/* shouldn't get here normally */
g_warning ("Invalid os_type specified");
break;
}
} }
if (test_os_type) #if WINAPI_FAMILY != MODERN_API_FAMILY
return VerifyVersionInfoW (&osverinfo, FreeLibrary (hmodule);
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_PRODUCT_TYPE, #endif
gwin32condmask (conds, VER_PRODUCT_TYPE));
else
return VerifyVersionInfoW (&osverinfo,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
conds);
}
#undef gwin32condmask return is_ver_checked && is_type_checked;
}
/** /**
* g_win32_get_windows_version: * g_win32_get_windows_version: