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 3624e70508
commit 46a20470fa

View File

@ -49,6 +49,18 @@
# include <io.h>
#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 "gthreadprivate.h"
@ -516,8 +528,6 @@ g_win32_get_package_installation_subdirectory (const gchar *package,
#endif
#define gwin32condmask(base,var) VerSetConditionMask (base, var, VER_GREATER_EQUAL)
/**
* g_win32_check_windows_version:
* @major: major version of Windows
@ -550,42 +560,75 @@ g_win32_check_windows_version (const gint major,
const GWin32OSType os_type)
{
OSVERSIONINFOEXW osverinfo;
gboolean test_os_type;
const DWORDLONG conds = gwin32condmask (gwin32condmask (gwin32condmask (0, VER_MAJORVERSION), VER_MINORVERSION), VER_SERVICEPACKMAJOR);
gboolean is_ver_checked = FALSE;
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));
osverinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
osverinfo.dwPlatformId = VER_PLATFORM_WIN32_NT;
osverinfo.dwMajorVersion = major;
osverinfo.dwMinorVersion = minor;
osverinfo.wServicePackMajor = spver;
RtlGetVersion (&osverinfo);
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:
osverinfo.wProductType = VER_NT_WORKSTATION;
test_os_type = TRUE;
break;
case G_WIN32_OS_SERVER:
osverinfo.wProductType = VER_NT_SERVER;
test_os_type = TRUE;
break;
default:
test_os_type = FALSE;
break;
switch (os_type)
{
case G_WIN32_OS_ANY:
is_type_checked = TRUE;
break;
case G_WIN32_OS_WORKSTATION:
if (osverinfo.wProductType == VER_NT_WORKSTATION)
is_type_checked = TRUE;
break;
case G_WIN32_OS_SERVER:
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)
return VerifyVersionInfoW (&osverinfo,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_PRODUCT_TYPE,
gwin32condmask (conds, VER_PRODUCT_TYPE));
else
return VerifyVersionInfoW (&osverinfo,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
conds);
}
#if WINAPI_FAMILY != MODERN_API_FAMILY
FreeLibrary (hmodule);
#endif
#undef gwin32condmask
return is_ver_checked && is_type_checked;
}
/**
* g_win32_get_windows_version: